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

39 lines
2.8 KiB
Markdown

---
title: Admin SPA
description: 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.
section: backend
order: 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](../../modules/boardwalk/README.md). 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](users-and-permissions.md). 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:
```sh
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.