Files
summercms/docs/backend/admin-spa.md
Jakub Zych 44bd1446f5 feat(11.1-04): add the Backend section, the remaining Services pages and the concept map links
- docs/backend: admin controllers, forms, lists and filters, relation
  manager, users and permissions, settings, partials and widgets, admin SPA
- docs/services: storage, outbound HTTP, realtime, Web Push, search, parity
  testing and the Frontend and AJAX (not provided) page
- Examples for cabana (with testdata/docs YAML), fetchguard, lighthouse and
  its centrifugo driver, flare, beachcomber and typesense, tide; lighthouse
  and beachcomber TestDocs* regions run on their Postgres harnesses
- concept map rows link their guide pages and the not-provided rows the
  Frontend and AJAX page; index lists Backend, Database and Services
- TestDocsRequiredPages asserts the D-08 section order
2026-09-30 23:18:35 +02:00

2.8 KiB

title, description, section, order
title description section order
Admin SPA How boardwalk serves the embedded Vue admin SPA under backend.uri, how the SPA talks to the admin API, and how its TypeScript types come from OpenAPI. backend 80

Admin SPA

WinterCMS renders its backend on the server with layouts, partials and the AJAX framework. SummerCMS replaces that with one Vue 3 single-page app, built once and embedded in the binary by boardwalk. Plugins do not ship admin pages: they ship YAML and, when they need them, partials and scripts, and the SPA renders every controller from the schemas the admin API serves.

Serving

cabana mounts the SPA under the admin prefix, backend.uri (/backend by default; one or more lowercase path segments). boardwalk.Handler serves the build:

  • Any path under the prefix that is not a file and not under api/ returns index.html, so the SPA's own routes work on reload.
  • Paths under api/ that no API route matches return the admin API's JSON not_found error, never the SPA.
  • Hashed files under assets/ are cached for a long time; index.html is never cached.
  • Every response carries a restrictive Content-Security-Policy, frame denial, nosniff, a same-origin referrer policy and noindex, nofollow.

The build is path-agnostic: index.html holds a placeholder (boardwalk.BaseToken) that boardwalk.RewriteIndex replaces with the prefix once, when the handler is built. A build without the placeholder fails the start-up.

A plugin route under the admin prefix also fails the start-up: the SPA and the admin API own that whole path.

How the SPA talks to the server

The SPA signs in through the admin API and keeps the token in the HttpOnly cookie described on Users and permissions. For each screen it loads the controller's localized schema (schema/list, schema/form), then the records, and renders the fields and columns the schema names. Strings come from GET <prefix>/api/v1/lang, the backend::lang bundle in the request locale, with CLDR plural forms.

Types from OpenAPI

The admin API is described by swag annotations in cabana. scripts/check-admin-openapi.sh generates the OpenAPI document (admin/openapi/admin.json) from them and the SPA's TypeScript types (admin/src/api/schema.d.ts) from the document, so the SPA's API client is checked against the server's shapes at compile time. --check fails when either committed file is out of date:

scripts/check-admin-openapi.sh --check

Building the SPA

The SPA's source is the admin/ Vite project. npm --prefix admin run build type-checks it and writes the build to modules/boardwalk/dist, which the next go build embeds. An application that only uses the framework never builds the SPA: the build is committed with the framework.