CMS

Add an inline-editing CMS to the project, served from the app’s own server or from a hosted one. It works in any SvelteKit project, including one Vela did not create.

Syntax

$ vela enable cms
$ vela enable cms --endpoint https://velastack.dev/v1/projects/<project>/cms

This installs @velastack/cms and marked, then wires the CMS into the app:

  • A loadCms call in the root +layout.server.ts, created if the project has none, so every page receives its content and a deleted page answers 404, 410 or a redirect
  • An <AdminBar /> in the root +layout.svelte, where editors sign in to edit copy in place, upload media and publish
  • The Vite plugin, which finds every editable field at build time

Where the CMS lives

The command decides where the CMS backend runs, in this order:

  1. --endpoint <url> always wins: the app reads from the hosted CMS at that URL.
  2. An app that runs as a Node server hosts the CMS itself. That is a project with a PocketBase backend, or one on @sveltejs/adapter-node with no PocketBase at all, which is where vela deploy leaves a project from npx sv create. @sveltejs/adapter-auto does not count: it decides per platform, and most of what it picks has no disk to keep a database on.
  3. Otherwise, a project linked to velastack.dev uses that project’s hosted CMS, so vela link followed by vela enable cms needs no URL. The command says which endpoint it picked.
  4. Otherwise it stops without changing anything and lists the ways forward: link the project, pass --endpoint, or give the app a server with vela enable backend or @sveltejs/adapter-node.

An app that hosts the CMS also gets better-sqlite3 and @velastack/kit installed, and the backend mounted at /api/cms, with its SQLite database and uploads in the data directory. The CMS keeps its own database; PocketBase is never involved.

With a hosted CMS, from --endpoint or from the link, the app reads from a CMS that runs elsewhere and the admin bar signs in there. That is the only shape a static site can use, since it has no server to host the backend; vela build then prerenders the published content and downloads its media into the site. A site velastack.dev hosts is rebuilt that way by vela cms deploy or by Deploy Site… in the admin bar.

Every project on velastack.dev has a hosted CMS at https://velastack.dev/v1/projects/<project>/cms, where <project> is the id vela link records. The CMS-ready templates from vela create arrive with this wiring in place and the endpoint of the linked project already in src/lib/site.ts, so they need no vela enable cms.

With i18n enabled, either shape uses the site’s locales instead of a single default.

Editors

An app that hosts the backend signs editors in against the CMS’s own table, which starts empty. Create the first login, then open any page with ?edit on the URL and sign in:

$ vela cms editor add you@example.com

The password is generated and shown once. vela cms editor password <email> <password> sets a new one, and vela cms editor list shows who can sign in; see vela cms editor. A hosted CMS manages its own editors.

Making content editable

Wrap copy in the components from @velastack/cms. Each takes a name for the field and a fallback for when nothing has been published yet:

<script lang="ts">
	import { CmsText, CmsImage } from '@velastack/cms';
</script>

<h1><CmsText name="hero.title" fallback="Welcome" /></h1>
<CmsImage name="hero.image" alt="Hero" />

Re-running

Running the command again only fills in what is missing. src/lib/cms.ts and, for a backend the app hosts, src/lib/server/cms.ts and the two routes are yours once written and are never overwritten, so edits such as adding locales survive.

Reverting

There is no vela disable cms yet. Delete src/lib/cms.ts and, if the app hosts the backend, src/lib/server/cms.ts, src/routes/api/cms and src/routes/uploads; remove cms() from vite.config.ts, the loadCms call from +layout.server.ts and <AdminBar /> from +layout.svelte; then uninstall @velastack/cms, marked and better-sqlite3. @velastack/kit stays if the project has a PocketBase backend, which uses it too.