Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
a0476e9
Implement viewing replays on the web (#39)
dowoge Mar 12, 2026
f6de006
wasm: Proper decompressing of lumps (Hi LZMA!!!!)
dowoge Mar 12, 2026
9eca607
Lock viewing replays behind being logged in lol
dowoge Mar 12, 2026
361e01d
wasm: support kz_ and surf_ maps
dowoge Mar 12, 2026
fd48c6a
Translucent rendering pipeline: separate opaque, translucent, and wat…
dowoge Mar 17, 2026
c9af37b
Fix opaque textures rendering as transparent, change FOV to 75, add s…
dowoge Mar 17, 2026
b4aed98
Use camera position instead of player position
dowoge Mar 17, 2026
9ecc2a7
Fix position
dowoge Mar 17, 2026
c1f9ce2
Fix project type errors (#41)
dowoge Mar 17, 2026
901a5ed
wasm: Fix maps rendering all black due to invalid/empty lighting data
dowoge Mar 19, 2026
2fd1c97
wasm: Fix texture extraction from BSP pakfiles
dowoge Mar 27, 2026
62ffb2d
wasm: Support LZMA compressed pakfile entries
dowoge Mar 27, 2026
3169261
wasm: Fix double-slash paths and external fetch for embedded VMTs
dowoge Mar 27, 2026
95dbcfc
wasm: support replay format v11 on all map types
dowoge Mar 31, 2026
67e94bc
wasm: fix replay format v10/v11 parsing per official bhoptimer spec
dowoge Mar 31, 2026
6411f6d
web: use relative API paths for offstyles.net domain migration
dowoge Apr 13, 2026
77ab621
Times list filters and pagination (#44)
dowoge Apr 18, 2026
2ade52b
Preserve server error reasons in offstylesApi (#46)
dowoge Apr 18, 2026
9b626ed
Model TimesFilter scope as discriminated union (#45)
dowoge Apr 18, 2026
848bbe5
New time lists (#37)
why-Mia Apr 18, 2026
317a521
Fix time column alignment in recent times when style filtered
dowoge Apr 19, 2026
99b2e8a
add view/download replay buttons to times list details dropdown (#47)
dowoge Apr 19, 2026
1f1caf1
fix server edit/delete buttons showing for all logged-in users
dowoge Apr 19, 2026
9276209
return to current page after steam sign-in (#49)
dowoge Apr 19, 2026
3f78516
clean up replay viewer HUD: remove timer and duplicate speed
dowoge Apr 19, 2026
4beb795
link player name to steam profile on player page
dowoge Apr 19, 2026
0cf0c6b
default server key owner to current user when steam id is empty
dowoge Apr 21, 2026
630b098
fix replay viewer crashes on chrome and node 25
dowoge Apr 24, 2026
97f463c
fix deploy: scope vite-devtools localStorage workaround to vite.config
dowoge Apr 24, 2026
a117ff2
fix replay viewer skybox missing on stock CS:S maps
dowoge Apr 25, 2026
5687a73
fix use location.replace for Steam auth so Back doesn't re-fire it (#53)
dowoge May 4, 2026
1fcf04e
Revert "fix use location.replace for Steam auth so Back doesn't re-fi…
dowoge May 4, 2026
98b57ea
fix open Steam auth in a popup so Back doesn't return to auth pages
dowoge May 5, 2026
02f95f2
swap replay viewer to noclip.website Source renderer (#54)
dowoge May 7, 2026
3bffcbe
fix prod 404: vite build was killed mid-render by stale type error
dowoge May 7, 2026
b30b343
fix replay viewer OOM on huge maps (e.g. bhop_gyat)
dowoge May 7, 2026
6a074e2
fix replay viewer obsolete textures on specific maps (#55)
dowoge May 9, 2026
28b6ad9
fix replay viewer FXAA had no visible effect, add MSAA 4× option (#56)
dowoge May 9, 2026
62cf502
brighten style text in times list to distinguish from date (#58)
dowoge May 9, 2026
72364e3
show map, player, and run time in replay viewer (#57)
dowoge May 9, 2026
77d94cd
round sync display on individual record page
dowoge May 9, 2026
6af77d2
remove replay viewer sky-brush depth occluder, use default noclip sky…
dowoge May 10, 2026
e6f77d7
navigate to top map match on enter in map search box (#59)
dowoge May 10, 2026
dc7a12c
Revert "remove replay viewer sky-brush depth occluder, use default no…
dowoge May 10, 2026
7585186
remove replay viewer sky-brush depth occluder, use default noclip sky…
dowoge May 10, 2026
5ddbb46
remove validity indicator from times list items (#61)
dowoge May 10, 2026
fa39a7a
preserve style of time row in player and map links (#60)
dowoge May 10, 2026
6ff5a5f
fix replay viewer selfillum surfaces see-through to skybox (#63)
dowoge May 10, 2026
f236b5d
fix replay viewer black world geometry on maps with digit-led path (#64)
dowoge May 10, 2026
2c59a5c
rebuild moderation as a /moderation route with activity, lookup, mode…
dowoge May 8, 2026
20c3ca1
show permissions as named badges on profile and moderation header
dowoge May 8, 2026
33de8bf
decode SERVER_OWNER_EDIT_SERVER and EDIT_SERVERS permission bits
dowoge May 8, 2026
bad54ce
npm audit fix
dowoge May 8, 2026
bad7103
wire bulk selection through times lists; retire old bulk modal
dowoge May 9, 2026
1923d2f
fix server-owner invalid-id counter and surface offending tokens
dowoge May 9, 2026
c366d6a
add username search and url query deep-link to lookup
dowoge May 9, 2026
b13f156
rework activity tab: honest stats, moderator and action filters, dens…
dowoge May 9, 2026
f1e1ec6
preview affected actions before confirming a reverse
dowoge May 9, 2026
1947310
a11y, simpler header, wider container
dowoge May 9, 2026
433ab7a
add server scope to /times and rebuild server-owner tab around it
dowoge May 9, 2026
73cc94b
revert server-owner browse ui until /servers exposes the key id
dowoge May 9, 2026
754e9af
restore server-owner browse view now that /servers exposes key_id
dowoge May 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,4 @@ coverage
*.sln
*.sw?

*.tsbuildinfo

env.d.ts
*.tsbuildinfo
47 changes: 21 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,34 @@
# offstyles-web

This template should help get you started developing with Vue 3 in Vite.
Web frontend for offstyles.net — bunnyhop times, records, and an in-browser
replay viewer for Counter-Strike: Source.

## Recommended IDE Setup

[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).

## Type Support for `.vue` Imports in TS

TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.

## Customize configuration

See [Vite Configuration Reference](https://vite.dev/config/).

## Project Setup
## Project setup

```sh
npm install
npm run dev # local dev server
npm run build # type-check + production build
npm run lint # eslint --fix
```

### Compile and Hot-Reload for Development
Recommended editor setup: VSCode + Volar.

```sh
npm run dev
```
## Replay viewer

### Type-Check, Compile and Minify for Production
The in-browser replay viewer renders Counter-Strike: Source maps using a vendored copy of [noclip.website](https://github.com/magcius/noclip.website)'s Source engine renderer. The viewer parses the BSP fully in-browser and streams CS:S assets (materials, models, props) on demand through the `/api/csspak` endpoint. WASM is still used to bz2-decompress the map download and parse replay files.

```sh
npm run build
```
The integration lives under `src/replay-viewer/noclip/` (vendored) plusthe adapter at `src/replay-viewer/noclipRenderer.ts`.

### Lint with [ESLint](https://eslint.org/)
## Credits

```sh
npm run lint
```
This project vendors and modifies portions of **[noclip.website](https://github.com/magcius/noclip.website)** and is licensed under the MIT License — the full notice ships with the vendored copy at `src/replay-viewer/noclip/LICENSE`. Patches against upstream are marked with a `Vendored:` comment in the source.

Other notable third-party libraries:

- [gl-matrix](https://github.com/toji/gl-matrix) — matrix/vector math.
- [pako](https://github.com/nodeca/pako) — deflate, used by the vendored
ZIP/BSP-pakfile parser.
- [crc-32](https://github.com/SheetJS/js-crc32) — CRC32 hashing for ZIP.
- [Vue 3](https://vuejs.org/) + [Vite](https://vite.dev/) +
[Tailwind CSS](https://tailwindcss.com/) — UI stack.
832 changes: 832 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
20 changes: 20 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const eslint_config_typescript_1 = require("@vue/eslint-config-typescript");
const eslint_plugin_vue_1 = __importDefault(require("eslint-plugin-vue"));
// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
// import { configureVueProject } from '@vue/eslint-config-typescript'
// configureVueProject({ scriptLangs: ['ts', 'tsx'] })
// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup
const vueEssentialConfig = eslint_plugin_vue_1.default.configs['flat/essential'];
const vueTsRecommendedConfig = eslint_config_typescript_1.vueTsConfigs.recommended;
exports.default = (0, eslint_config_typescript_1.defineConfigWithVueTs)({
name: 'app/files-to-lint',
files: ['**/*.{ts,mts,tsx,vue}'],
}, {
name: 'app/ignores',
ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'],
}, vueEssentialConfig, vueTsRecommendedConfig);
17 changes: 12 additions & 5 deletions eslint.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { globalIgnores } from 'eslint/config'
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
import pluginVue from 'eslint-plugin-vue'

Expand All @@ -7,14 +6,22 @@ import pluginVue from 'eslint-plugin-vue'
// configureVueProject({ scriptLangs: ['ts', 'tsx'] })
// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup

const vueEssentialConfig =
pluginVue.configs['flat/essential'] as unknown as Parameters<typeof defineConfigWithVueTs>[number]

const vueTsRecommendedConfig =
vueTsConfigs.recommended as unknown as Parameters<typeof defineConfigWithVueTs>[number]

export default defineConfigWithVueTs(
{
name: 'app/files-to-lint',
files: ['**/*.{ts,mts,tsx,vue}'],
},
{
name: 'app/ignores',
ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'],
},

globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),

pluginVue.configs['flat/essential'],
vueTsConfigs.recommended,
vueEssentialConfig,
vueTsRecommendedConfig,
)
Loading