Files
gerbeur/mod.ts
khannurien f20ca83f0c v4: every email is rendered by its template in api/mail/ on one layout that takes the instance's style, and sent one way — the welcome email was built and sent inside the register route and the reset link in its service, each writing Markdown, running marked, and calling a nodemailer wrapper whose cc, bcc, replyTo and send result nothing used. Now api/mail/ holds one template per email (welcome.ts, password-reset.ts) on layout.ts's EmailKit, which draws each block with inline styles in a style from styles.ts: the six site styles' palettes, copied from src/themes/, and what makes each recognisable in a mail client (Brutalist's hard border and shadow, GeoCities' ridge and rainbow rules, Times' underlined ink links, Kanagawa's colored quotes, dates and wordmark, Melange's spice bar). On the "auto" scheme the light palette is inlined and the dark one swapped in by a prefers-color-scheme block; a chosen scheme sends only its own. User-written text is escaped where it lands. strings.ts holds every email's words in English and French. GERBEUR_EMAIL_LOCALE picks the language and GERBEUR_DEFAULT_STYLE the instance's style, which the welcome and reset emails are drawn in; GERBEUR_WELCOME_EMAIL_BODY still replaces the welcome's Markdown, whose blocks now take the style too. email-service sends a rendered email with its recipient and headers, refuses to load when GERBEUR_SMTPS_URL is set without GERBEUR_FROM_EMAIL (sends used to fail one by one), and takes a test transport, through which the tests now read what was sent. The welcome send moves to user-service's sendWelcomeEmail. The style and scheme names move to shared/theme.ts, which the server now needs. README, mod.ts and .env.example describe mail/ and the new variables, and drop the "notifications, invites" email that never existed. 221 backend tests pass (new: the layout's schemes, styles and escaping, both templates, the welcome on sign-up, a reset link from the email that works), and deno check, deno lint, doc:lint, deno fmt, tsc and eslint are clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 21:11:54 +00:00

65 lines
3.3 KiB
TypeScript

/**
* Documents gerbeur, a small invite-only social platform for sharing links and
* files. The repository holds three parts: the backend in `api/`, the
* frontend in `src/`, and in `shared/` whatever crosses the wire between them.
* [Every module](./all_symbols.html) is listed by path, so the list groups
* them by part and layer.
*
* ## Backend, in `api/`
*
* An Oak server over SQLite answers the API and the WebSocket, and serves the
* built frontend. `api/main.ts` builds the application and listens. A request
* goes to a route, which parses it, calls services and answers. The services
* hold the logic and every SQL query, read rows through the model, and reach
* other sites only through `remote/`. Each folder holds one kind of module,
* and each file is named after its domain.
*
* - `routes/` holds the HTTP API. Each router's page lists its endpoints, with
* their method and path, who may call them, and what they do.
* - `middleware/` holds what runs around the routes, which is auth, errors and
* the Open Graph tags.
* - `services/` holds the logic and every SQL query, one module per domain.
* - `model/` holds each table's row type, guard and mappers.
* - `validators/` holds the guards of the request bodies.
* - `remote/` is the only place that fetches from other sites, and its
* `providers/` build the previews of each kind of site.
* - `mail/` renders each email, one template per email on a shared layout
* that takes every site style, and `services/email-service.ts` sends them.
* - `lib/` holds the helpers that belong to no layer.
* - `db/` opens, creates and migrates the database, and cleans it up at
* startup. `db/migrations/` are applied in order, each once.
* - `config.ts` reads the settings from the environment, and `scripts/` holds
* the icon generator.
*
* ## Shared, in `shared/`
*
* The types and constants both halves use sit here, one module per domain.
* They are the API envelope, each domain's types and request bodies, the
* socket protocol, the validation limits and the role permissions. `shared/`
* imports nothing from either half. The server sends `Date`s, and the client
* reads the same types through `Wire<T>`, where every `Date` is an ISO string.
*
* ## Frontend, in `src/`
*
* The React app is built with Vite and translated with Lingui. `main.tsx`
* mounts it, `App.tsx` holds the providers and the route table, and `i18n.ts`
* sets the language. A page reads the API and the socket through contexts and
* hooks, and draws with components, while utils hold what isn't React at all.
*
* - `pages/` holds one component per route, each naming its route, and the two
* guards that keep routes to signed-in or signed-out visitors.
* - `config/` holds the settings read at startup.
* - `contexts/` holds, for each domain, a `FooContext` with its state and the
* `FooProvider` that fills it.
* - `hooks/` holds every hook, and `components/` only components.
* - `utils/` holds every module that isn't React.
*
* Every layer but `pages/` and `config/` is split into the same domains (auth,
* category, chat, comment, dump, editor, feed, form, layout, player, playlist,
* profile, social, theme, ws, and shared for what belongs to no one domain), so
* the chat lives in `components/chat/`, `contexts/chat/`, `hooks/chat/` and
* `utils/chat/`.
*
* @module
*/