Skip to content

Installing a theme

A theme deploys as a built artifact, never as source. You build it on your machine, package it as a zip file, and upload it in the admin.

Terminal window
astro build

The kit builds a self-contained artifact: everything the theme needs ends up inside dist/, with no node_modules on the server. Keep your theme’s dependencies to pure JavaScript, since compiled native code cannot load from the artifact.

The zip holds three things at its top level:

theme.json
server/ (from dist/server)
client/ (from dist/client)

theme.json is one line you write once:

{ "name": "mytheme", "version": "1.0.0", "kit": "0.3.0" }

Name the zip after the theme. Gophenberg installs mytheme.zip as mytheme, and the name inside theme.json has to match.

Open Themes in the admin, choose the zip, and select Install theme. Once it appears in the list, select Activate.

The old theme keeps serving until the new one is ready, so the site never goes quiet while you switch. Deactivate returns the site to the built-in renderer, and Roll back returns it to the choice before the current one.

An upload is refused whole, and the admin shows the reason:

  • theme.json present and valid, its name matching the zip name
  • server/entry.mjs present as a file, client/ as a directory
  • no symlinks anywhere, and nothing over 64 MiB packed or unpacked
  • at most 10000 files, which is far more than a theme needs

A refused upload leaves nothing behind. You cannot replace the theme that is active, so deactivate it first or upload it under another name.

You can also unpack a theme into a directory named after it inside the themes directory yourself, and name it in the environment:

environment:
GOPHENBERG_THEMES_DIR: /themes
GOPHENBERG_THEME: mytheme

A pinned theme wins over whatever the admin chose, and the admin refuses to change it while the pin is set. Pinning also changes what a broken theme costs you: a pinned theme that fails to load stops the server from starting, admin included. A theme chosen in the admin never does that. It shows as broken in the list and the built-in renderer keeps serving.

The container image already carries the Node runtime themes run on, so there is nothing else to install.