diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index f0804dc23..5e12f1856 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -31,9 +31,13 @@
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// This can be used to network with other containers or with the host.
- "forwardPorts": [3000, 3001, 5432, 8000],
+ "forwardPorts": [1025, 3000, 3001, 5432, 8000, 8025],
"portsAttributes": {
+ "1025": {
+ "label": "Mailpit SMTP",
+ "onAutoForward": "silent"
+ },
"3000": {
"label": "Application Backend",
"onAutoForward": "silent"
@@ -49,6 +53,10 @@
"8000": {
"label": "PGAdmin",
"onAutoForward": "silent"
+ },
+ "8025": {
+ "label": "Mailpit",
+ "onAutoForward": "silent"
}
},
diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml
index 028a007ec..01f4227a9 100644
--- a/.devcontainer/docker-compose.yml
+++ b/.devcontainer/docker-compose.yml
@@ -37,6 +37,24 @@ services:
POSTGRES_USER: postgres
POSTGRES_DB: postgres
+ # A mail server that delivers nothing, which is what makes it useful: everything the wiki sends —
+ # a registration's confirmation link, a password reset, the admin area's test button — lands in a
+ # web inbox at http://localhost:8025 instead of somebody's mailbox.
+ #
+ # Configure it under Admin -> Mail: host `localhost`, port 1025, TLS off, no username or password.
+ # Sharing the database container's network namespace is what makes `localhost` reach it.
+ mailpit:
+ image: axllent/mailpit:latest
+ restart: unless-stopped
+ environment:
+ # -> Nothing here is reachable from outside the container, and a dev instance should not fail a
+ # send because of a credential nobody has set: any AUTH is accepted, over a plain connection.
+ - MP_SMTP_AUTH_ACCEPT_ANY=true
+ - MP_SMTP_AUTH_ALLOW_INSECURE=true
+ # -> Deliberately no volume: these are test messages, and a mailbox that survives a rebuild is a
+ # mailbox full of last month's password resets.
+ network_mode: service:db
+
pgadmin:
image: dpage/pgadmin4:latest
environment:
diff --git a/CLAUDE.md b/CLAUDE.md
index 486d2fc69..3d649f754 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -35,7 +35,11 @@ The backend is **TypeScript 7**; `frontend/` and `blocks/` are JavaScript. See
`assets/_assets/`. Served by the backend. Don't hand-edit.
- `dev/` — deployment/packaging artifacts: `dev/build/Dockerfile` (production image), `dev/helm/`,
`dev/packer/`, `dev/noto-emoji-build/`.
-- `.devcontainer/` — VS Code dev container (app + postgres + pgAdmin via docker-compose).
+- `.devcontainer/` — VS Code dev container (app + postgres + pgAdmin + mailpit via docker-compose).
+ Mailpit is the mail server for development: it accepts everything and delivers nothing, so a
+ confirmation link or a password reset lands in a web inbox at `http://localhost:8025` rather than a
+ real mailbox. Point the wiki at it under **Admin → Mail** — host `localhost`, port 1025, TLS off,
+ no credentials.
- `localazy.json` — translation sync config; locale strings live in `backend/locales/`.
### `backend/`
@@ -722,17 +726,15 @@ store; no SVG is ever written into content.
An earlier iteration of 3.x used GraphQL/Apollo. **All of it is deprecated** — there is no GraphQL
server left in `backend/`, and `APOLLO_CLIENT` is not defined as a global, so any call still going
-through it throws. `blocks/block-index/` also still imports a `tree.graphql`.
+through it throws.
-Three files under `frontend/src/` make live `APOLLO_CLIENT` calls, and each needs a REST endpoint
-that does not exist yet, so the feature behind it is currently broken:
+**One call is left.** `pages/AdminNavigation.vue`'s `save()` sends the navigation tree and its mode
+through `APOLLO_CLIENT.mutate`, so saving the navigation is broken until it is ported. Nothing else
+under `frontend/src/` references the global. That handler needs more than the endpoint, mind: it also
+calls `this.$store.commit(...)` nine times over, and the file is `