site structure
This commit is contained in:
parent
af35862749
commit
8790b6629b
1 changed files with 327 additions and 0 deletions
327
SITE_STRUCTURE_REFERENCE.md
Normal file
327
SITE_STRUCTURE_REFERENCE.md
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
# Project Bifrost — Site Structure Reference
|
||||
|
||||
This document labels every editable piece of the site with a short name you can quote when asking for changes, and notes where each piece lives in the code. Use the labels (e.g. **S1 lede**, **P3 footer**) to point at changes precisely.
|
||||
|
||||
---
|
||||
|
||||
## Top-level structure
|
||||
|
||||
The site has **three pages**, each occupying the full viewport. A dot-nav at the bottom switches between them.
|
||||
|
||||
```
|
||||
/timeline → ┌─────────────────────────────────────────────┐
|
||||
│ [P1] TIMELINE │
|
||||
│ [P2] OVERVIEW (Project Bifrost scenes) │
|
||||
│ [P3] ARCHIVE │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Only one page is visible at a time. They are mutually exclusive — switching between them is a class toggle on the page wrapper, not a navigation.
|
||||
|
||||
Before reaching any of the three, users see the **entrance** at `/` (email form → welcome step). The entrance is a separate HTML file in `public/`.
|
||||
|
||||
---
|
||||
|
||||
## [P1] TIMELINE — horizontal scroll catalog
|
||||
|
||||
**Files:** `protected/index.html` (`#page-timeline`, lines ~739–758) + `protected/timeline.js`
|
||||
|
||||
A horizontal mousewheel-driven scroll through 23 editorial cards, set over a slowly rotating orthographic globe. Cards alternate above and below a central spine; each is accented by one of four colours (copper/ochre/terracotta/crimson) denoting register.
|
||||
|
||||
| Label | What it is | Where to change |
|
||||
|---|---|---|
|
||||
| **P1 page title** | *"From the promise of AI to the loss of **sovereignty.**"* | `index.html` line 740 |
|
||||
| **P1 subtitle** | *"Twenty-three headlines, quietly laid across a tinted map. Scroll the wheel — the map turns with you."* | `index.html` line 741 |
|
||||
| **P1 globe** | Rotating orthographic globe that tracks scroll position from N. America → Europe | `timeline.js` — `buildGlobe()` + `setRotation` in `applyScroll()` |
|
||||
| **P1 events** | The 23 headline cards. Each has `date`, `kind`, `accent`, `hed`, `body`, `source` | `timeline.js` — `EVENTS` array, lines 4–102 |
|
||||
| **P1 card styles** | Card layout, above/below-spine positioning, colour accents per `accent` value | `index.html` CSS `.evt`, `.accent-*` |
|
||||
| **P1 year ticks** | "2022", "2023", … on the spine between groups of cards | `timeline.js` — `buildTimeline()`, year-tick loop |
|
||||
| **P1 "Read the editor's note" button** | Bottom-right, appears near the end of the catalog; fires dot-nav switch to Overview | `index.html` line 747 (text) + `.continue-btn` CSS + `timeline.js` click handler |
|
||||
|
||||
---
|
||||
|
||||
## [P2] OVERVIEW — The Project Bifrost scroll
|
||||
|
||||
**Files:** `protected/index.html` (`#page-overview`, lines ~2232–2619) + `protected/bifrost.js`
|
||||
|
||||
A vertically scrolling container that holds six scroll-bound scenes. The Europe map sits as a fixed background behind them all and fades in/out with scroll position.
|
||||
|
||||
```
|
||||
┌─ S1 HERO ──────────────┐
|
||||
│ "Secure & Sovereign │ ← Europe map fades behind
|
||||
│ AI, hosted where it │
|
||||
│ belongs." │
|
||||
└────────────────────────┘
|
||||
┌─ S2 ARCHITECTURE ──────┐
|
||||
│ 4 layer cards fall + │ ← pinned, scrubbed
|
||||
│ morph into 2x2 grid │
|
||||
└────────────────────────┘
|
||||
┌─ S3 WORDS ─────────────┐
|
||||
│ "...built with them, │ ← words fly in
|
||||
│ not just for them." │
|
||||
└────────────────────────┘
|
||||
┌─ S4 BIFROST ARC ───────┐
|
||||
│ 🌈 aurora arc draws │ ← "Introducing Project Bifrost"
|
||||
│ "Project Bifrost" │
|
||||
└────────────────────────┘
|
||||
┌─ S5 TREASURE MAP ──────┐
|
||||
│ Community, Advisory │ ← 3 stops on a winding path
|
||||
│ Council, Pilot Proj. │
|
||||
└────────────────────────┘
|
||||
┌─ S6 JOIN CTA + FOOTER ─┐
|
||||
│ "Join us in shaping…" │ ← button → confirmation panel
|
||||
│ [Proj] [Fenja] [Innov]│ ← 3-column footer
|
||||
└────────────────────────┘
|
||||
```
|
||||
|
||||
### S0 — Europe map background
|
||||
|
||||
The map stays static behind all six scenes. It does not rotate with scroll; it only fades.
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **P2 Europe map** | Static orthographic globe centered on Europe, sitting behind the hero | `index.html` line 2234 (`.overview-globe`) + CSS line 441 |
|
||||
| **P2 map opacity ceiling** | Maximum map opacity (currently `0.42`) | `bifrost.js` — `MAP_MAX_OPACITY` constant |
|
||||
| **P2 map fade curve** | Fully visible 0–20% scroll, fades to 0 by 80% scroll, fades back in when scrolling up | `bifrost.js` — `updateMapOpacity()` function |
|
||||
|
||||
### S1 — Hero
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **S1 eyebrow** | *"For regulated environments"* | `index.html` line 2246 |
|
||||
| **S1 headline** | *"Secure & **Sovereign** AI, hosted where it **belongs.**"* | `index.html` lines 2247–2250 |
|
||||
| **S1 lede** | *"Enabling highly advanced AI capabilities hosted within the client's own secure infrastructure."* | `index.html` lines 2251–2253 |
|
||||
| **S1 supported-by** | Innovationsfonden placeholder logo + *"Supported by"* strip | `index.html` lines 2258–2267 |
|
||||
| **S1 scroll hint** | "Scroll →" indicator bottom-right | `index.html` lines 2268–2271 |
|
||||
| **S1 hero styles** | Type scale, colours, grid positioning, left-column anchoring | `index.html` CSS `#hero`, `.hero-title`, `.hero-lede`, `.hero-foot` |
|
||||
| **S1 hero animation** | Word-by-word reveal of the headline on scene entry | `bifrost.js` — search `HERO — staggered intro` |
|
||||
|
||||
### S2 — Architecture stack
|
||||
|
||||
Four cards fall into a stack one at a time, then rearrange into a 2x2 grid. As they do, three copy panels crossfade on the left.
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **S2 copy panel A** | *"All the capabilities to solve business use cases with AI. Four layers. One architecture. Every piece yours to own."* | `index.html` lines 2284–2288 (`data-copy="0"`) |
|
||||
| **S2 copy panel B** | *"Full client **control.** Complete **sovereignty.**"* + *"Nothing proprietary above the hardware…"* | `index.html` lines 2289–2292 (`data-copy="1"`) |
|
||||
| **S2 copy panel C** | *"Built in **Denmark.** For **Europe.**"* + *"Engineered against the standards that matter here…"* | `index.html` lines 2293–2297 (`data-copy="2"`) |
|
||||
| **S2 card 1 — Foundation** | *"AI — An **open-source** model, running on your **own hardware.**"* | `index.html` lines 2302–2310 (`data-layer="0"`) |
|
||||
| **S2 card 2 — Knowledge** | *"The **vocabulary** of your business — **learned, retained.**"* | `index.html` lines 2312–2320 (`data-layer="1"`) |
|
||||
| **S2 card 3 — Tools** | *"How the AIs **act** — not just what they **know.**"* | `index.html` lines 2322–2330 (`data-layer="2"`) |
|
||||
| **S2 card 4 — Agents** | *"**Specialists**, **collaborating** to solve distinct tasks."* | `index.html` lines 2332–2340 (`data-layer="3"`) |
|
||||
| **S2 stack animation** | The fall, stack, morph-to-grid scrub sequence | `bifrost.js` — search `ARCHITECTURE — two-phase scrubbed sequence` |
|
||||
| **S2 card styles** | Shape, padding, "brain" illustration, eyebrow, grid-mode styles | `index.html` CSS `.layer-card`, `.card-box`, `.card-brain`, `.in-grid` |
|
||||
|
||||
### S3 — Words fly in
|
||||
|
||||
Sixteen individual words fly in from random directions as the user scrolls, assembling into one full sentence. Two words (`with` and `them,`) are given extra visual weight.
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **S3 full sentence** | *"But a platform for regulated organisations has to be built with them, not just for them."* | `index.html` lines 2361–2376 |
|
||||
| **S3 highlight words** | `with`, `them,` — the two words with emphasis class `hi` | `index.html` lines 2371–2372 |
|
||||
| **S3 word styles + animation** | Individual word reveal with scatter/scale/blur | `bifrost.js` — search `WORDS fly in`; CSS `.words`, `.w`, `.w.hi` |
|
||||
|
||||
### S4 — Bifrost aurora arc
|
||||
|
||||
A rainbow arc draws across the scene, then the "Project Bifrost" title fades in below it. This is the only place on the site where a gradient is used.
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **S4 eyebrow** | *"Introducing"* | `index.html` line 2441 |
|
||||
| **S4 name** | *"**Project Bifrost**"* (split into two tokens — "Project" + "Bifrost") | `index.html` lines 2442–2445 |
|
||||
| **S4 subtitle** | *"The bridge **between** an industrial-grade AI platform and the realities of regulated organisations — built **with** them, not just for them."* | `index.html` lines 2446–2448 |
|
||||
| **S4 arc** | The rainbow arc that draws across the scene | `index.html` lines 2391–2436 — `<svg>` with `#arcHalo`, `#arcMain`, `#arcThin` |
|
||||
| **S4 arc colors** | The aurora gradient stops (ochre → terracotta → indigo → heather) | `index.html` lines 2393–2408 — `<linearGradient>` stops |
|
||||
| **S4 arc animation** | Stroke-dashoffset draw-in on scroll | `bifrost.js` — search `PROJECT BIFROST REVEAL` |
|
||||
|
||||
### S5 — Treasure map (3 stops)
|
||||
|
||||
A winding path draws down the scene, passing through three "stops" — each an illustrated card about one way to participate in Project Bifrost. Stops alternate left / right of the path.
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **S5 intro title** | *"What being part of **Project Bifrost** means"* | `index.html` lines 2469–2471 |
|
||||
| **S5 intro lede** | *"Three ways to **shape**, to **influence**, and to **build with** the platform from the inside — a journey through what participation actually looks like."* | `index.html` lines 2472–2474 |
|
||||
| **S5 winding path** | The bezier curve drawn between stops; rebuilt at runtime to pass through dot positions | `index.html` lines 2482–2494 (SVG shell); `bifrost.js` — `buildMapPath()` |
|
||||
| **S5 intro stop** | *"Being part of **Project Bifrost** means **three** things — a community to shape the future with, a council to influence the platform through, and pilot projects that put it in your hands first."* (centered introductory copy) | `index.html` lines 2497–2504 |
|
||||
| **S5 stop 1 — Community** | Eyebrow *"Be part of a"* + title ***"Community"*** + sub *"Shape the future together"* + body copy + illustration of six people in discussion | `index.html` lines 2507–2518; illustration `fenja/illustrations/community.svg` |
|
||||
| **S5 stop 2 — Advisory Council** | Eyebrow *"Be part of an"* + title ***"Advisory Council"*** + sub *"Turn insight into influence"* + body copy + illustration of a man and a woman in conversation | `index.html` lines 2521–2532; illustration `fenja/illustrations/council.svg` |
|
||||
| **S5 stop 3 — Pilot Projects** | Eyebrow *"Be part of"* + title ***"Pilot Projects"*** + sub *"Access the platform before others"* + body copy + illustration of two people at a computer | `index.html` lines 2535–2546; illustration `fenja/illustrations/pilot.svg` |
|
||||
| **S5 path animation + per-stop reveals** | Draw-in of path; dot pops in + text/image fade on reach | `bifrost.js` — search `Treasure-map path draw` |
|
||||
| **S5 styles** | Layout, alternating left/right stops, dots, path styling | `index.html` CSS `.map-intro`, `.map-canvas`, `.map-stop`, `.dot-anchor`, `.stop-*` |
|
||||
|
||||
### S6 — Join CTA + footer
|
||||
|
||||
The final scene is a large call-to-action headline with a single button. Clicking the button crossfades to a confirmation panel listing what happens next. Below, a three-column footer with brand marks.
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **S6 CTA eyebrow** | *"Ready?"* | `index.html` line 2565 |
|
||||
| **S6 CTA headline** | *"Join us in shaping the future of **trusted sovereign AI.**"* | `index.html` lines 2566–2568 |
|
||||
| **S6 CTA button text** | *"Join Project Bifrost"* | `index.html` lines 2569–2572 |
|
||||
| **S6 CTA subtext** | *"Built in Denmark. Supported by the Innovation Fund."* | `index.html` line 2573 |
|
||||
| **S6 confirmation eyebrow** | *"You're in"* | `index.html` line 2578 |
|
||||
| **S6 confirmation headline** | *"Thank you for joining **Project Bifrost**."* | `index.html` lines 2579–2581 |
|
||||
| **S6 confirmation list item 1** | *"The **Fenja AI team** will reach out to you shortly."* | `index.html` line 2583 |
|
||||
| **S6 confirmation list item 2** | *"You'll receive an invitation to the **project portal** soon…"* | `index.html` line 2584 |
|
||||
| **S6 confirmation list item 3** | *"We're currently setting the date for the **first advisory council meeting**…"* | `index.html` line 2585 |
|
||||
| **S6 confirmation list item 4** | *"We'll be in touch shortly about your participation in the **pilot project**."* | `index.html` line 2586 |
|
||||
| **S6 footer left — "Project Bifrost"** | Wordmark rendered in Newsreader with italic emphasis on "Bifrost" | `index.html` line 2593 |
|
||||
| **S6 footer center — Fenja logo** | `<img>` pointing to `/fenja/fenja-wordmark-black.svg` | `index.html` lines 2595–2599 |
|
||||
| **S6 footer right — Innovationsfonden** | Placeholder slanted-I mark + "nnovationsfonden" text (to be swapped for real asset) | `index.html` lines 2601–2612 |
|
||||
| **S6 click handler** | CTA → confirmation crossfade + staggered checkmarks on list items | `bifrost.js` — search `SCENE 6 — Join section` |
|
||||
|
||||
---
|
||||
|
||||
## [P3] ARCHIVE — 23-row table
|
||||
|
||||
**Files:** `protected/index.html` (`#page-archive`, lines ~2622–2651) + `protected/timeline.js` archive-builder IIFE
|
||||
|
||||
A tabular view of the same 23 events from the timeline, sorted chronologically. Each row fades its background on hover.
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **P3 headline** | *"All twenty-three entries, in order of **publication.**"* | `index.html` line 2625 |
|
||||
| **P3 sub** | *"Dates, sources and plate numbers for every card in the catalog. Hover a row to lift it from the paper."* | `index.html` lines 2626–2629 |
|
||||
| **P3 table** | 5 columns: №, Date, Register, Headline, Source | `index.html` table markup + `timeline.js` archive-builder IIFE (lines 406–420) |
|
||||
| **P3 data** | Same `EVENTS` array as the timeline | `timeline.js` — `EVENTS` |
|
||||
| **P3 footer** | *"Fenja AI · Field Notes, No. IV / Catalog closed 14 April 2026 / Page III of III"* | `index.html` lines 2644–2648 |
|
||||
|
||||
---
|
||||
|
||||
## Shared chrome — visible on all three pages
|
||||
|
||||
**Files:** `protected/index.html` (lines 2207 + 2653–2668) + `protected/timeline.js`
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **Site wordmark** | Top-left Fenja logo, 118px wide | `index.html` line 2207 |
|
||||
| **Dot-nav tray** | Subtle gradient fade at the bottom edge of the viewport | `index.html` `.dot-nav-tray` |
|
||||
| **Dot-nav** | Bottom-center "Timeline / Overview / Archive" page switcher | `index.html` lines 2653–2668 |
|
||||
| **Dot-nav logic** | Page activation + bifrost lazy-init on first Overview visit | `timeline.js` — `activatePage()` function, lines 439–457 |
|
||||
|
||||
---
|
||||
|
||||
## Entrance — before login
|
||||
|
||||
**Files:** `public/entrance.html` + `public/entrance.js`
|
||||
|
||||
The only public-facing page. A single email field; on submit, if the email is on the invite list, advances to a welcome step. Otherwise shows an inline "not invited" message.
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **Entrance tagline** | *"Thank you for your commitment and willingness to contribute."* | `entrance.html` step-email `.tagline` |
|
||||
| **Entrance email input** | The single input field with "your email" placeholder | `entrance.html` step-email `<form>` |
|
||||
| **Entrance topographic currents** | Concentric-circle SVG background in the top-right | `entrance.js` — `drawCurrents()` IIFE |
|
||||
| **Entrance error messages** | *"Please enter a valid email address."* / *"This email is not on the invite list."* / *"Too many attempts…"* | `entrance.js` — inside the submit handler |
|
||||
| **Welcome title** | *"Thanks for your interest, **[Name].**"* (or *"Thank you for your **interest.**"* when no first name) — set by JS after a successful login | `entrance.js` — `setWelcomeTitle()` |
|
||||
| **Welcome body, paragraph 1** | *"Thank you for joining and for your interest in enabling sovereign AI in Denmark and Europe. Project Bifrost is a deliberate effort to advance it — the conviction that how we build these systems, and where, will shape the next decades."* | `entrance.html` step-welcome `.welcome-body` (first one) |
|
||||
| **Welcome body, paragraph 2** | *"What follows is a timeline: twenty-three moments that explain why this matters now, and what the path looks like."* | `entrance.html` step-welcome `.welcome-body` (second one) |
|
||||
| **"Learn more" button** | The button that routes to `/timeline` | `entrance.html` step-welcome `#welcome-continue` |
|
||||
| **Welcome logo ghost** | Faint Fenja wordmark occupying the right half of the viewport | `entrance.html` `.welcome-logo` |
|
||||
|
||||
---
|
||||
|
||||
## Auth — server-side
|
||||
|
||||
**Files:** `src/auth.js` + `src/sessions.js` + `src/db.js` + `bin/invite.js`
|
||||
|
||||
For completeness — not UI, but labelled here so you can point at it when relevant.
|
||||
|
||||
| Label | What it is | Where |
|
||||
|---|---|---|
|
||||
| **Login endpoint** | `POST /auth/login` — accepts `{email}`, returns `{ok, firstName}` on success or `{error: "not_invited"}` with 403 | `src/auth.js` |
|
||||
| **Login rate limit** | 30 attempts per IP per hour | `src/auth.js` — `rateLimit({…})` on `/login` route |
|
||||
| **Logout endpoint** | `POST /auth/logout` — clears session cookie | `src/auth.js` |
|
||||
| **Me endpoint** | `GET /auth/me` — returns `{email, firstName}` for current session or 401 | `src/auth.js` |
|
||||
| **Invite CLI** | `node bin/invite.js add <email> [FirstName]` / `remove` / `list` | `bin/invite.js` |
|
||||
| **Invite schema** | `invites(email, first_name, invited_at, invited_by)` | `src/db.js` |
|
||||
| **Session duration** | 30 days | `src/sessions.js` — `SESSION_TTL_MS` |
|
||||
|
||||
---
|
||||
|
||||
## Design tokens — safe to change, affect everything cohesively
|
||||
|
||||
**File:** `protected/fenja/colors_and_type.css`
|
||||
|
||||
| Token | Value | Meaning |
|
||||
|---|---|---|
|
||||
| `--paper` / `--background` | `#faf6ee` | Primary paper background |
|
||||
| `--ink` / `--on-surface` | `#383831` | Primary text colour |
|
||||
| `--ink-soft` / `--on-surface-variant` | `#5f5e5e` | Muted text |
|
||||
| `--ink-dim` / `--on-surface-muted` | `#8a887f` | Very muted text |
|
||||
| `--walnut` / `--secondary` | `#785f53` | Primary accent (links, focus rings) |
|
||||
| `--crimson` | `#8a3a2f` | Destructive / error |
|
||||
| `--pigment-terracotta` | `#b96b58` | Warnings, S4 Bifrost accent |
|
||||
| `--pigment-copper` | `#6d8c7c` | Success, organic / growth |
|
||||
| `--pigment-ochre` | `#c29d59` | Cautions, tertiary |
|
||||
| `--pigment-indigo` | `#5a6d83` | Info (only "blue" allowed) |
|
||||
| `--pigment-heather` | `#8d7a85` | Categorical, supportive |
|
||||
| Aurora gradient stops | ochre → terracotta → indigo → heather | S4 arc only |
|
||||
|
||||
Fonts: **Newsreader** (serif, for intent) and **Manrope** (sans, for execution). Both self-hosted as variable fonts in `protected/fenja/fonts/`.
|
||||
|
||||
The "no line" rule applies throughout: depth comes from tonal surface shifts, not 1px borders. Emphasis is applied via the Fenja rule — last keyword in Newsreader Bold Italic, followed by the absolute period.
|
||||
|
||||
---
|
||||
|
||||
## How to ask for changes
|
||||
|
||||
Pick a label from the tables above and tell me what you want changed. Examples:
|
||||
|
||||
- *"Change **S1 lede** to say …"*
|
||||
- *"Swap the colour of the **S4 arc** from terracotta to copper"*
|
||||
- *"Remove **S5 stop 2** entirely; renumber the path"*
|
||||
- *"Add a 5th item to the **S6 confirmation list**"*
|
||||
- *"Reorder: move **S3 Words** to come after **S4 Bifrost Arc**"*
|
||||
- *"Make the **P2 Europe map** fully fade out by 40% scroll instead of 80%"*
|
||||
- *"Change the **Welcome title** to read differently when the user has no first name"*
|
||||
- *"Update **P1 events** entry #14 (the November 2024 rupture) to say …"*
|
||||
|
||||
If a change crosses multiple sections (for example, "add a fourth treasure map stop" or "reorganise the six scenes into five"), I'll lay out the pieces that need to move in a plan before writing code, so you can sign off.
|
||||
|
||||
If something you want to change isn't on this map, quote a phrase from the site and I'll find it.
|
||||
|
||||
---
|
||||
|
||||
## File index — where each label's code lives
|
||||
|
||||
```
|
||||
protected/
|
||||
├── index.html [P1], [P2 except animations], [P3], shared chrome
|
||||
├── timeline.js [P1 events + globe + card builder], [P3 table builder],
|
||||
│ dot-nav logic + bifrost lazy-init
|
||||
├── bifrost.js All [P2] scene animations + Europe map fade
|
||||
├── vendor/
|
||||
│ ├── lenis.min.js Smooth scroll (for [P2])
|
||||
│ ├── gsap.min.js Animation engine
|
||||
│ ├── scrolltrigger.min.js Scroll-bound timelines
|
||||
│ ├── d3-array.min.js Globe math (used by timeline.js)
|
||||
│ ├── d3-geo.min.js Globe projection
|
||||
│ ├── topojson-client.min.js World topology parser
|
||||
│ └── countries-110m.json World country shapes
|
||||
└── fenja/
|
||||
├── colors_and_type.css Design tokens
|
||||
├── fonts/ Manrope + Newsreader (variable fonts)
|
||||
├── fenja-wordmark-black.svg Logo — used by site-mark + S6 footer
|
||||
└── illustrations/
|
||||
├── community.svg S5 stop 1
|
||||
├── council.svg S5 stop 2
|
||||
└── pilot.svg S5 stop 3
|
||||
|
||||
public/
|
||||
├── entrance.html Entrance + welcome steps (before login)
|
||||
└── entrance.js Entrance form behaviour, welcome title logic
|
||||
|
||||
src/
|
||||
├── auth.js /auth/login, /auth/logout, /auth/me
|
||||
├── db.js SQLite schema + prepared queries
|
||||
├── sessions.js Session cookie lifecycle
|
||||
└── middleware.js rateLimit() + requireAuth()
|
||||
|
||||
bin/
|
||||
└── invite.js CLI: add / remove / list invites
|
||||
|
||||
server.js Entry point, CSP, routing
|
||||
```
|
||||
Loading…
Add table
Reference in a new issue