Appearance
Under Settings → Appearance, pick a built-in or custom theme, or build your own. A theme is a set of hex colors plus a card radius.
Share a theme
Section titled “Share a theme”Export downloads the selected theme as {name}.galene-theme.json and Copy JSON puts the same pack on the clipboard. Both use the colors you see, including a built-in such as Ocean. Importing a built-in creates a new custom theme; it does not change the built-in.
Import accepts pasted JSON or a .json / .galene-theme.json file. Galene shows a color preview and an editable name before anything is saved. Confirming saves a new custom theme and selects it. If that name is already used by one of your themes, Galene adds a suffix such as (2). Replace an existing custom theme only when you choose Replace this theme. Built-ins are never overwritten.
A pack that is not valid JSON, uses another version, omits a color, or has a bad hex or radius is declined with an error. Nothing is written.
Packs from other tools (shadcn, oklch, and similar) are not imported directly. Convert them to Galene hex JSON first.
Format (galeneTheme: 1)
Section titled “Format (galeneTheme: 1)”Unknown top-level fields are ignored. Every color key below is required.
{ "galeneTheme": 1, "name": "Tron", "colors": { "background": "#000102", "surface": "#0c1421", "surfaceHover": "#030e1c", "foreground": "#e1f2f8", "mutedForeground": "#8f8f8f", "primary": "#00c7c7", "primaryForeground": "#030303", "success": "#24b6a1", "destructive": "#d40f00", "border": "#003636", "warning": "#fbbf24", "input": "#001b1b", "radius": "0.5rem" }}Publish to the theme gallery
Section titled “Publish to the theme gallery”The public theme gallery lives at themes.galene.finance. Anyone can browse, search, preview, vote on, and download themes there. A download is the same galeneTheme: 1 JSON pack that Import accepts.
Publish sends the theme you have selected under Settings → Appearance to the gallery. It does not upload a file from your browser. The gallery has no upload form and no accounts. It only accepts a signed request from a Galene instance.
What gets sent
Section titled “What gets sent”The request body is the validated theme pack, the same JSON that Export produces: galeneTheme: 1, the theme name, and every color as a #rrggbb hex value, plus the card radius in rem. Apart from the signing headers below, nothing about your instance, account, or data is sent. The gallery checks the pack again and declines anything malformed. Packs over 32 KB are refused.
Signing
Section titled “Signing”Each Galene instance makes an Ed25519 key pair the first time it publishes and keeps it in its own database. Every publish is a POST with three headers:
| Header | Value |
|---|---|
Galene-Key |
The instance’s public key (raw, base64url). |
Galene-Timestamp |
Unix time in seconds. |
Galene-Signature |
Ed25519 signature (base64url) over the message below. |
The signed message is UTF-8 text with three lines:
galene-theme-publish<Galene-Timestamp><hex SHA-256 of the raw request body>The gallery rejects a request with a missing or invalid signature, or a timestamp more than five minutes from its own clock, so keep the host clock in sync (NTP). Back up the database as usual: restoring it keeps the same instance key, while a fresh database makes a new one.
Duplicate colors
Section titled “Duplicate colors”The gallery rejects a publish whose colors exactly match a theme that is already listed, no matter the name or which instance sends it. Colors are compared after normalizing hex to lowercase; light and dark blocks are included when the pack has them. A duplicate is refused (HTTP 409) and Appearance shows a message such as:
These colors are already published as “Ocean”. You can’t publish the same colors again.
A duplicate refusal does not use up the hourly publish slot.
One publish per hour
Section titled “One publish per hour”The gallery allows one successful publish per instance per hour, counted per instance key. A publish the gallery declines does not use up the hour. The gallery enforces this limit, not the app. A second publish inside the hour is refused (HTTP 429) and Appearance shows a message such as:
You can publish one theme per hour. Try again in about 12 minutes.
When the gallery does not say how long to wait, the message reads “You can publish one theme per hour. Try again later.”
Public demo
Section titled “Public demo”Publishing is turned off on the public demo. Appearance shows “Publishing is turned off on the public demo.” in place of the button, and the publish action returns 403.
Gallery address
Section titled “Gallery address”By default Galene publishes to https://themes.galene.finance/api/themes. Set GALENE_THEME_GALLERY_URL to send publishes somewhere else, such as a gallery you run yourself or a local test server. The address must use https. Plain http is allowed only for localhost or 127.0.0.1. Galene does not follow redirects on publish, so point the variable at the final URL. See Environment variables.