- /sitemap.xml, from the API's /slugs plus the landing and listings:
every address in every language, with hreflang and x-default. A 503
when the API is down, rather than a sitemap missing half the site.
- /robots.txt, naming the sitemap on whatever domain this is served on.
- Slugs renamed in the panel now redirect. The API has always kept the
old address the moment one changed; middleware/redirects.ts answers
it with a 301, from a list kept for a minute and through outages.
- og:url, og:image (the record's own picture, the logo otherwise) and
schema.org JSON-LD: Organization on the landing; WebPage,
CreativeWork, Person or Service elsewhere. Shared through core/head.
- The proxy-derived origin moves to core/origin.ts, used by the page
shell, the landing and both server routes.
In development only /api/* reaches Nitro, so the two files 404 under
`npm start`; they were checked against a production build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A call now has its address — description, what the volunteer gets, the
commitment added up, level, closing date, project, technologies — and
the application form right there. The landing's call card leads to it
instead of scrolling to the general form, and shows the level in the
visitor's language rather than the API's `mid` or `any`.
The form is the landing's, with a `callSlug` that hides the kind
selector and posts to the new /api/calls/{slug}/apply handler: the API
refuses a `kind` on an application, which is always an offer of time.
Both handlers share one check, core/submission.ts, now tested on its
own.
A call that is filled or closed keeps its page — a link to it may
still be out there — but shows why there is no form, and where to
write instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>