Agents.md
This commit is contained in:
38
AGENTS.md
38
AGENTS.md
@@ -2,6 +2,7 @@
|
||||
|
||||
A collaborative wiki of math concepts. Articles are written in Markdown with LaTeX
|
||||
(KaTeX) and stored in MongoDB behind an Express API; a Nuxt 4 app renders and edits them.
|
||||
The interface itself speaks five languages (en, es, ca, fr, de), chosen per account.
|
||||
|
||||
```
|
||||
mathew/
|
||||
@@ -46,7 +47,9 @@ Plain JavaScript, ESM (`"type": "module"`, `.js` files with relative `.js` impor
|
||||
`User` (username + `passwordHash`, `select: false`; `setPassword`/`checkPassword`
|
||||
via bcrypt, `toPublic()` for responses, and `credentialProblem()` as the single
|
||||
place account rules are checked). The profile picture lives on `User.avatar` as a
|
||||
small data URL — no file storage. `User.role` is `'admin'` or `'member'`
|
||||
small data URL — no file storage. `User.locale` is the interface language the
|
||||
person picked (`SUPPORTED_LOCALES`: `en es ca fr de`, default `'en'`).
|
||||
`User.role` is `'admin'` or `'member'`
|
||||
(`ROLES`); `User.hasNone()` and `User.ensureAnAdmin()` cover who gets the
|
||||
former — see the roles gotcha below.
|
||||
- `src/routes/` — one Express `Router` per resource, mounted in `index.js`.
|
||||
@@ -55,7 +58,8 @@ Plain JavaScript, ESM (`"type": "module"`, `.js` files with relative `.js` impor
|
||||
`POST /api/auth/login`, `GET /api/auth/me` (who a token belongs to).
|
||||
Login answers the same way to a wrong name and a wrong password. Account updates,
|
||||
all behind `requireAuth`: `PUT /api/auth/me` (rename), `PUT /api/auth/password`
|
||||
(needs the current one), `PUT /api/auth/avatar` (data URL, `""` clears).
|
||||
(needs the current one), `PUT /api/auth/avatar` (data URL, `""` clears),
|
||||
`PUT /api/auth/locale` (interface language, one of `SUPPORTED_LOCALES`).
|
||||
- `src/routes/admin.js` — mounted at `/api/admin`, everything behind
|
||||
`requireAuth, requireAdmin`: `GET /api/admin/users` (every account, newest
|
||||
first, with `createdAt`), `PUT /api/admin/users/:id/role` (`role` is `'admin'`
|
||||
@@ -91,6 +95,16 @@ the accent themes generate from a map in `_tokens.scss`. Colours stay CSS custom
|
||||
properties so themes swap at runtime via `data-theme`/`data-accent` attributes
|
||||
(set pre-paint by an inline script in `nuxt.config.ts`).
|
||||
|
||||
UI wording is localized with `@nuxtjs/i18n` (`frontend/i18n/`): `i18n.config.ts` plus
|
||||
one JSON catalog per language in `i18n/locales/` (all 309 keys, kept in parity with
|
||||
`en.json`). `strategy: 'no_prefix'` — the interface language never appears in a URL
|
||||
(`/wiki/<lang>/<slug>` is the *article's* language) — with cookie detection
|
||||
(`mathew-locale`, `fallbackLocale: 'en'`) so the server renders in the right language
|
||||
from the first draw. Every UI string goes through `t()` in the catalogs; messages that
|
||||
carry `<code>`/`<span>` markup are drawn with `v-html` through `th()`
|
||||
(`useAppLocale`), which escapes interpolated values. Adding a language = add a catalog
|
||||
copy + an `APP_LANGUAGES` entry + the code in the backend's `SUPPORTED_LOCALES`.
|
||||
|
||||
- `app/pages/` — `/` (search), `/wiki/[slug]` (article + TOC), `/wiki/[slug]/edit`, `/new`,
|
||||
`/admin` (the dashboard: every account and its role, plus the buttons that hand the
|
||||
role on or take it back — an admin alone sees anything but a refusal here).
|
||||
@@ -117,9 +131,13 @@ properties so themes swap at runtime via `data-theme`/`data-accent` attributes
|
||||
profile popup), `useArticleActionsMenu` (same, for an article's ⋮ menu), and
|
||||
`useAccountActionsMenu` (same, for a dashboard row's ⋮ — it holds the **id** of
|
||||
the row that is open, so one row's menu is open at a time rather than a
|
||||
boolean per row).
|
||||
boolean per row), and `useAppLocale` (the interface language: `APP_LANGUAGES` —
|
||||
the five supported UI languages with their own names —, `choose(code)` to turn
|
||||
the UI (`setLocale` also keeps the `mathew-locale` cookie in step), `applyAccount(code)`
|
||||
to let an account overrule the device, and `th()` for messages drawn as HTML).
|
||||
- `app/plugins/auth.ts` — runs `restoreSession()` once at startup on server and client,
|
||||
so the sidebar's account row and the editor's gate are right in the first render.
|
||||
so the sidebar's account row and the editor's gate are right in the first render,
|
||||
and applies the account's `locale` when it restores one.
|
||||
- `app/utils/markdown.ts` — the single render pipeline: `markdown-it` (**html: false**,
|
||||
raw HTML is escaped) + `markdown-it-texmath` + KaTeX (`$...$` inline, `$$...$$` display,
|
||||
macros `\R \N \Z \Q \C`) + highlight.js, sanitized with DOMPurify. It also builds the
|
||||
@@ -128,6 +146,18 @@ properties so themes swap at runtime via `data-theme`/`data-accent` attributes
|
||||
|
||||
## Gotchas
|
||||
|
||||
- The **interface language** is not the article language: `/wiki/fr/…` addresses the
|
||||
French *article*, never the UI. UI precedence: the signed-in account's `locale` (applied
|
||||
at startup and on signing in) > the `mathew-locale` cookie (written by `setLocale`, read
|
||||
on the server pre-render) > browser > `en`. The settings popup always turns this device;
|
||||
with a session it also saves to the account — an account that refuses (dead session)
|
||||
doesn't undo the switch. Error messages that come back from the API stay English; only
|
||||
the frontend's own fallbacks are translated.
|
||||
- Never call `t()` in `withDefaults` static prop defaults — they don't react to locale
|
||||
changes. Use `props.x ?? t(...)` in the template/computed instead (see `AuthGate`,
|
||||
`ConfirmModal`).
|
||||
- Message catalogs are compiled: literal `{`/`@` break the compiler, so the editor's LaTeX
|
||||
seed lives as a JS constant in `ArticleForm.vue` and only its words are catalog keys.
|
||||
- Reading is open; **writing takes an account**. `POST /api/articles` and `PUT`/`DELETE`
|
||||
by slug need `Authorization: Bearer <token>` from `/api/auth/login` or
|
||||
`/api/auth/register`. The frontend keeps that token in the `mathew-session` cookie
|
||||
|
||||
Reference in New Issue
Block a user