馃 distributed transcription service thistle.dunkirk.sh
1# Thistle - Project Guidelines 2 3This is a Bun-based transcription service using the [Bun fullstack pattern](https://bun.com/docs/bundler/fullstack) for routing and bundled HTML. 4 5## Project Info 6 7- Name: Thistle 8- Purpose: Transcription service 9- Runtime: Bun (NOT Node.js) 10- Language: TypeScript with strict mode 11- Frontend: Vanilla HTML/CSS/JS with lightweight helpers on top of web components 12 13## Design System 14 15ALWAYS use the project's CSS variables for colors: 16 17```css 18:root { 19 /* Color palette */ 20 --gunmetal: #2d3142ff; /* dark blue-gray */ 21 --paynes-gray: #4f5d75ff; /* medium blue-gray */ 22 --silver: #bfc0c0ff; /* light gray */ 23 --white: #ffffffff; /* white */ 24 --coral: #ef8354ff; /* warm orange */ 25 26 /* Semantic color assignments */ 27 --text: var(--gunmetal); 28 --background: var(--white); 29 --primary: var(--paynes-gray); 30 --secondary: var(--silver); 31 --accent: var(--coral); 32} 33``` 34 35**Color usage:** 36- NEVER hardcode colors like `#4f46e5`, `white`, `red`, etc. 37- Always use semantic variables (`var(--primary)`, `var(--background)`, `var(--accent)`, etc.) or named color variables (`var(--gunmetal)`, `var(--coral)`, etc.) 38 39**Dimensions:** 40- Use `rem` for all sizes, spacing, and widths (not `px`) 41- Base font size is 16px (1rem = 16px) 42- Common values: `0.5rem` (8px), `1rem` (16px), `2rem` (32px), `3rem` (48px) 43- Max widths: `48rem` (768px) for content, `56rem` (896px) for forms/data 44- Spacing scale: `0.25rem`, `0.5rem`, `0.75rem`, `1rem`, `1.5rem`, `2rem`, `3rem` 45 46## NO FRAMEWORKS 47 48NEVER use React, Vue, Svelte, or any heavy framework. 49 50This project prioritizes: 51- Speed: Minimal JavaScript, fast load times 52- Small bundle sizes: Keep bundles tiny 53- Native web platform: Use web standards (Web Components, native DOM APIs) 54- Simplicity: Vanilla HTML, CSS, and JavaScript 55 56Allowed lightweight helpers: 57- Lit (~8-10KB gzipped) for reactive web components 58- Native Web Components 59- Plain JavaScript/TypeScript 60 61Explicitly forbidden: 62- React, React DOM 63- Vue 64- Svelte 65- Angular 66- Any framework with a virtual DOM or large runtime 67 68## Commands 69 70```bash 71# Install dependencies 72bun install 73 74# Development server with hot reload 75bun dev 76 77# Run tests 78bun test 79 80# Build files 81bun build <file.html|file.ts|file.css> 82``` 83 84Development workflow: `bun dev` runs the server with hot module reloading. Changes to TypeScript, HTML, or CSS files automatically reload. 85 86**IMPORTANT**: NEVER run `bun dev` yourself - the user always has it running already. 87 88## Bun Usage 89 90Default to using Bun instead of Node.js. 91 92- Use `bun <file>` instead of `node <file>` or `ts-node <file>` 93- Use `bun test` instead of `jest` or `vitest` 94- Use `bun build <file>` instead of `webpack` or `esbuild` 95- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install` 96- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` 97- Bun automatically loads .env, so don't use dotenv 98 99## Bun APIs 100 101Use Bun's built-in APIs instead of npm packages: 102 103- `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`. 104- `bun:sqlite` for SQLite. Don't use `better-sqlite3`. 105- `Bun.redis` for Redis. Don't use `ioredis`. 106- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`. 107- `WebSocket` is built-in. Don't use `ws`. 108- Prefer `Bun.file` over `node:fs`'s readFile/writeFile 109- `Bun.$\`ls\`` instead of execa 110 111## Server Setup 112 113Use `Bun.serve()` with the routes pattern: 114 115```ts 116import index from "./index.html" 117 118Bun.serve({ 119 routes: { 120 "/": index, 121 "/api/users/:id": { 122 GET: (req) => { 123 return new Response(JSON.stringify({ id: req.params.id })); 124 }, 125 }, 126 }, 127 // optional websocket support 128 websocket: { 129 open: (ws) => { 130 ws.send("Hello, world!"); 131 }, 132 message: (ws, message) => { 133 ws.send(message); 134 }, 135 close: (ws) => { 136 // handle close 137 } 138 }, 139 development: { 140 hmr: true, 141 console: true, 142 } 143}) 144``` 145 146## Frontend Pattern 147 148Don't use Vite or any build tools. Use HTML imports with `Bun.serve()`. 149 150HTML files can directly import `.ts` or `.js` files: 151 152```html 153<!DOCTYPE html> 154<html lang="en"> 155 156<head> 157 <meta charset="UTF-8"> 158 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 159 <title>Page Title - Thistle</title> 160 <link rel="icon" 161 href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='0.9em' font-size='90'>馃</text></svg>"> 162 <link rel="stylesheet" href="../styles/main.css"> 163</head> 164 165<body> 166 <auth-component></auth-component> 167 168 <main> 169 <h1>Page Title</h1> 170 <my-component></my-component> 171 </main> 172 173 <script type="module" src="../components/auth.ts"></script> 174 <script type="module" src="../components/my-component.ts"></script> 175</body> 176 177</html> 178``` 179 180**Standard HTML template:** 181- Always include the `<auth-component>` element for consistent login/logout UI 182- Always include the thistle emoji favicon 183- Always include proper meta tags (charset, viewport) 184- Structure: auth component, then main content, then scripts 185- Import `auth.ts` on every page for authentication UI 186 187Bun's bundler will transpile and bundle automatically. `<link>` tags pointing to stylesheets work with Bun's CSS bundler. 188 189Frontend TypeScript (vanilla or with Lit web components): 190 191```ts 192import { LitElement, html, css } from 'lit'; 193import { customElement, property } from 'lit/decorators.js'; 194 195// Define a Lit web component 196@customElement('my-component') 197export class MyComponent extends LitElement { 198 @property({ type: String }) name = 'World'; 199 200 // Scoped styles using css tagged template 201 static styles = css` 202 :host { 203 display: block; 204 padding: 1rem; 205 } 206 .greeting { 207 color: blue; 208 } 209 `; 210 211 // Render using html tagged template 212 render() { 213 return html` 214 <div class="greeting"> 215 Hello, ${this.name}! 216 </div> 217 `; 218 } 219} 220 221// Or use plain DOM manipulation for simple interactions 222document.querySelector('h1')?.addEventListener('click', () => { 223 console.log('Clicked!'); 224}); 225``` 226 227**When to use Lit:** 228- Components with reactive properties (auto-updates when data changes) 229- Complex components needing scoped styles 230- Form controls with internal state 231- Components with lifecycle needs 232 233**When to skip Lit:** 234- Static content (use plain HTML) 235- Simple one-off interactions (use vanilla JS) 236- Anything without reactive state 237 238Lit provides: 239- `@customElement` decorator to register components 240- `@property` decorator for reactive properties 241- `html` tagged template for declarative rendering 242- `css` tagged template for scoped styles 243- Automatic re-rendering when properties change 244- Size: ~8-10KB minified+gzipped 245 246## Testing 247 248Use `bun test` to run tests. 249 250```ts 251import { test, expect } from "bun:test"; 252 253test("hello world", () => { 254 expect(1).toBe(1); 255}); 256``` 257 258## TypeScript Configuration 259 260Strict mode is enabled with these settings: 261 262```json 263{ 264 "strict": true, 265 "noFallthroughCasesInSwitch": true, 266 "noUncheckedIndexedAccess": true, 267 "noImplicitOverride": true 268} 269``` 270 271Deliberately disabled: 272- `noUnusedLocals`: false 273- `noUnusedParameters`: false 274- `noPropertyAccessFromIndexSignature`: false 275 276Module system: 277- `moduleResolution`: "bundler" 278- `module`: "Preserve" 279- JSX: `preserve` (NOT react-jsx - we don't use React) 280- Allows importing `.ts` extensions directly 281 282## Frontend Technologies 283 284Core (always use): 285- Vanilla HTML, CSS, JavaScript/TypeScript 286- Native Web Components API 287- Native DOM APIs (querySelector, addEventListener, etc.) 288 289Lightweight helpers: 290- Lit (~8-10KB gzipped): For reactive web components with state management 291 292Bundle size philosophy: 293- Start with vanilla JS 294- Add helpers only when they significantly reduce complexity 295- Measure bundle size impact before adding any library 296- Target: Keep total JS bundle under 50KB 297 298## Project Structure 299 300Based on Bun fullstack pattern: 301- `src/index.ts`: Server imports HTML files as modules 302- `src/pages/`: HTML files (route entry points) 303- `src/components/`: Lit web components 304- `src/styles/`: CSS files 305- `public/`: Static assets (images, fonts, etc.) 306 307**File flow:** 3081. Server imports HTML: `import indexHTML from "./pages/index.html"` 3092. HTML imports components: `<script type="module" src="../components/counter.ts"></script>` 3103. HTML links styles: `<link rel="stylesheet" href="../styles/main.css">` 3114. Components self-register as custom elements 3125. Bun bundles everything automatically 313 314## File Organization 315 316- `src/index.ts`: Main server entry point with `Bun.serve()` routes 317- `src/pages/*.html`: Route entry points (imported as modules) 318- `src/components/*.ts`: Lit web components 319- `src/styles/*.css`: Stylesheets (linked from HTML) 320- `public/`: Static assets directory 321- Tests: `*.test.ts` files 322 323**Current structure example:** 324``` 325src/ 326 index.ts # Imports HTML, defines routes 327 pages/ 328 index.html # Imports components via <script type="module"> 329 components/ 330 counter.ts # Lit component with @customElement 331 styles/ 332 main.css # Linked from HTML with <link> 333``` 334 335## Naming Conventions 336 337Follow TypeScript conventions: 338- PascalCase for components and classes 339- camelCase for functions and variables 340- kebab-case for file names 341 342## Development Workflow 343 3441. Make changes to `.ts`, `.html`, or `.css` files 3452. Bun's HMR automatically reloads changes 3463. Write tests in `*.test.ts` files 3474. Run `bun test` to verify 348 349## IDE Setup 350 351Biome LSP is configured in `crush.json` for linting and formatting support. 352 353## Common Tasks 354 355### Adding a new route 356Add to the `routes` object in `Bun.serve()` configuration 357 358### Adding a new page 359Create an HTML file, import it in the server, add to routes 360 361### Adding frontend functionality 362Import TS/JS files directly from HTML using `<script type="module" src="../components/my-component.ts"></script>`. Use Lit for reactive components or vanilla JS for simple interactions. Never React. 363 364### Adding WebSocket support 365Add `websocket` configuration to `Bun.serve()` 366 367## Important Notes 368 3691. No npm scripts needed: Bun is fast enough to run commands directly 3702. Private package: `package.json` has `"private": true` 3713. No build step for development: Hot reload handles everything 3724. Module type: Package uses `"type": "module"` (ESM) 3735. Bun types: Available via `@types/bun` (check `node_modules/bun-types/docs/**.md` for API docs) 374 375## Gotchas 376 3771. Don't use Node.js commands: Use `bun` instead of `node`, `npm`, `npx`, etc. 3782. Don't install Express/Vite/other tools: Bun has built-in equivalents 3793. NEVER EVER use React: This project is vanilla JS/TS with web components only. React is explicitly forbidden. 3804. Import .ts extensions: Bun allows importing `.ts` files directly 3815. No dotenv needed: Bun loads `.env` automatically 3826. HTML imports are special: They trigger Bun's bundler, don't treat them as static files 3837. Bundle size matters: Always consider the size impact before adding any library 384 385## Documentation Lookup 386 387Use Context7 MCP for looking up official documentation for libraries and frameworks. 388 389## Resources 390 391- [Bun Fullstack Documentation](https://bun.com/docs/bundler/fullstack) 392- [Lit Documentation](https://lit.dev/) 393- [Web Components MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components) 394- Bun API docs in `node_modules/bun-types/docs/**.md` 395 396## Future Additions 397 398As the codebase grows, document: 399- Database schema and migrations 400- API endpoint patterns 401- Authentication/authorization approach 402- Transcription service integration details 403- Deployment process 404- Environment variables needed