project-bifrost-platform/CLAUDE.md
2026-04-18 16:09:49 +02:00

9.1 KiB
Raw Blame History

Project Bifrost — Claude Code Memory

This file is persistent context for every Claude Code session on this repo. Keep it under 200 lines. If something is only relevant to one feature, it does not belong here — put it in SPEC.md or a scoped file.

Project

Project Bifrost is Fenja AI's invite-only pilot hub — a private website for pilot participants and Customer Advisory Board members during a ~34 month pilot of Fenja's sovereign AI platform. Full product specification lives in SPEC.md. Read it before doing anything substantial; it is the source of truth.

Stack

  • Framework: Astro 4+ (server output mode where needed, static elsewhere)
  • Language: TypeScript, strict mode
  • Styling: Vanilla CSS with design tokens derived from design/colors_and_type.cssno Tailwind, no CSS-in-JS, no component libraries with baked-in styling
  • Database: SQLite via better-sqlite3
  • Auth: Custom. Session cookies + bcrypt + signed invite tokens. No third-party auth providers.
  • Runtime: Node 22 LTS
  • Package manager: pnpm (never npm, never yarn)
  • Hosting: Single Hetzner Cloud VPS (CAX11, Helsinki) behind Caddy

Commands

pnpm install          # install dependencies
pnpm dev              # start dev server on :4321
pnpm build            # production build
pnpm preview          # preview production build locally
pnpm test             # run vitest
pnpm typecheck        # tsc --noEmit
pnpm lint             # eslint + prettier check
pnpm db:migrate       # apply migrations to dev SQLite
pnpm db:seed          # seed dev database with test users

Always run pnpm typecheck and pnpm test before claiming a task is done.

File structure

/
├── SPEC.md                      # product spec (source of truth)
├── CLAUDE.md                    # this file
├── design/                      # design system — authoritative for all visual language
│   ├── SKILL.md                 # instructions for how to use this design system (read first)
│   ├── README.md                # human overview
│   ├── ICONOGRAPHY.md           # icon style & usage
│   ├── colors_and_type.css      # authoritative colour & type tokens
│   ├── assets/                  # logo and brand assets
│   ├── fonts/                   # font files
│   ├── preview/, screenshots/, ui_kits/, uploads/  # reference material
├── content/                     # markdown content
│   ├── updates/                 # YYYY-MM-DD-slug.md progress posts
│   ├── meetings/                # YYYY-MM-DD-slug.md meeting pages
│   └── roadmap.md               # single roadmap file
├── src/
│   ├── pages/                   # Astro routes
│   ├── components/              # Astro components
│   ├── layouts/                 # page layouts
│   ├── styles/
│   │   ├── tokens.css           # CSS custom properties — derived from design/colors_and_type.css
│   │   └── global.css           # base styles, resets, @font-face declarations
│   ├── lib/
│   │   ├── db.ts                # SQLite connection & typed queries
│   │   ├── auth.ts              # session + password + invite token helpers
│   │   └── content.ts           # markdown collection helpers
│   └── env.d.ts
├── migrations/                  # numbered .sql files
├── scripts/                     # ops scripts (backup, deploy, seed)
└── public/                      # static assets served as-is
    ├── logo.svg                 # copied from design/assets/ on first session
    └── fonts/                   # copied from design/fonts/ on first session

Code standards

  • TypeScript strict. No any without a comment explaining why. Prefer unknown and narrow.
  • No runtime dependencies unless asked. Before adding a package, justify it. The current stack is chosen for minimalism — resist padding it.
  • SQL is written by hand. No ORM. Queries live in src/lib/db.ts as typed functions (getUserByEmail(email): User | null, etc.).
  • Zod schemas for all content collection frontmatter, all form inputs, and all env vars. Parse at boundaries; trust internally.
  • Server-only secrets go through astro:env or a server-only env.ts module. Never import secrets into client code — verify this.
  • Errors in route handlers return proper status codes with minimal JSON. Never leak stack traces to clients.
  • Dates are always UTC in the database, rendered in Europe/Copenhagen on the page.
  • Accessibility is not optional. Every interactive element keyboard-reachable; every image has alt; colour contrast meets WCAG AA against tokens from design/colors_and_type.css.

Design principles (from SPEC §6)

The aesthetic is authoritative quietude — academic, editorial, Danish-minimal. The design/ folder is the authoritative source; design/SKILL.md is the entry point for how to use it. Concrete rules that hold unless the design system overrides them:

  • No visible borders on cards or sections. Separation = tonal background shift + whitespace.
  • No drop shadows. If elevation is needed, use a tonal shift.
  • Editorial type scale — headlines are large, body copy has room to breathe, line-height ≥ 1.6 for body.
  • Asymmetric layouts preferred over centred ones. Use the 12-column grid deliberately.
  • Motion is minimal. Transitions < 200ms, ease-out. No parallax, no auto-play.
  • Light mode only for v1.
  • All colour, font, and spacing values come from design/colors_and_type.css via src/styles/tokens.css. Never hardcode hex values, font names, or magic spacing numbers in components — reference tokens. If a token is missing, stop and add it to tokens.css (faithful to the design system) before continuing.

First-session tasks (in order)

When Claude Code first opens this project:

  1. Read SPEC.md end to end.
  2. Read design/SKILL.md — follow its instructions. It is the primary guide for how to use the design system.
  3. Read design/README.md, design/ICONOGRAPHY.md, and design/colors_and_type.css. Skim design/preview/, design/screenshots/, and design/ui_kits/ for reference.
  4. Scaffold the Astro project per the file structure above. Install only what the spec requires.
  5. Copy logo assets from design/assets/ into public/ (prefer SVG; keep filenames stable, e.g. public/logo.svg).
  6. Copy fonts from design/fonts/ into public/fonts/ and set up @font-face declarations in src/styles/global.css.
  7. Create src/styles/tokens.css derived from design/colors_and_type.css. Either @import it directly, or re-express its values as CSS custom properties — whichever design/SKILL.md recommends.
  8. Build a /style-guide internal route that renders: every colour token, every type scale step, spacing scale, buttons, form inputs, cards, iconography, and the logo in context. This is for human review before any real pages are built.
  9. Stop and wait for review.

Do not skip step 9. The visual language needs human approval before pages get built on top of it.

Behavioural preferences

  • Plan before coding. For any task larger than a trivial fix, propose a plan first and wait for approval.
  • Small, reviewable commits. One logical change per commit. Conventional commit messages (feat:, fix:, chore:, docs:, refactor:, style:).
  • Ask before: adding a dependency, changing the database schema, changing anything in design/, changing this file or SPEC.md, deploying.
  • Never: commit secrets, commit .env* files, run git push --force, modify files inside design/ (that folder is read-only from the code's perspective — if the design needs to change, update design/ directly via a separate deliberate commit).
  • When uncertain about product intent, check SPEC.md. If the spec is ambiguous, ask — do not guess.
  • When uncertain about visual language, re-read design/SKILL.md and design/colors_and_type.css. If it is still ambiguous, ask.
  • When blocked by a missing decision, write the options as a short note in DECISIONS.md and ask for a ruling. Do not silently pick.
  • Write state to files for long tasks. If a task spans many steps, keep notes in progress.md so a fresh session can pick up.

Out of scope

Read SPEC.md §8. Do not build: email sending, file uploads, rich-text editors, dark mode, mobile app, search, analytics, i18n, 2FA, public pages. If the user asks for one of these, confirm it is a scope change and suggest updating SPEC.md first.

Known gotchas

  • better-sqlite3 is native. On Hetzner ARM it must be built for ARM. The deploy script rebuilds it on the server.
  • Astro server output mode requires an adapter — use @astrojs/node in standalone mode.
  • Signed invite tokens are HMAC-signed, not JWTs. Keep them short and opaque.
  • Sessions are HttpOnly, Secure, SameSite=Lax cookies. Never expose session IDs to client JS.
  • Font licensing. The fonts in design/fonts/ may be licensed — check design/README.md and design/SKILL.md for any usage restrictions before serving them publicly.