---
name: sliprail-theme
description: "Building or changing a Sliprail theme that restyles the Sliprail desktop launcher, a package whose sliprail.json has a theme section."
---

# Sliprail theme conventions

Themes restyle the launcher window of the Sliprail desktop app with CSS. A theme has no code and cannot contain an app, an extension or data lists.

## Package

A package is one directory with sliprail.json at its root:

```json
{
  "displayName": { "en": "Ocean", "zh-hans": "海洋" },
  "description": { "en": "Calm blue launcher", "zh-hans": "宁静的蓝色启动器" },
  "theme": {
    "main": "main.css",
    "preview": "preview.png",
    "appearance": "Dark",
    "extend": { "top": 0, "right": 0, "bottom": 0, "left": 0 }
  }
}
```

- displayName and description are a string or a map of the languages en, zh-hans with en required.
- id identifies the theme. The first publish assigns it when sliprail.json has none; keep it unchanged afterwards.
- theme.main is the only CSS file loaded; do not use @import. Relative url(...) references are resolved from the package directory, so include every image they use.
- theme.appearance is Light, Dark or FollowSystem and decides the colors of everything the CSS does not restyle.
- theme.extend adds 0 to 500 pixels of room around the launcher on each side for decorations.
- theme.preview is an image of the themed launcher shown when people pick a theme.

## Styling

Style these stable classes:

- .window is the outer canvas, for backgrounds and decorations around the launcher, and .window-foreground is a layer above it that does not take the pointer.
- .main holds the launcher content and takes its background and frame.
- .search-input-box is the search box and .results the result list.
- .result-item is a result row, .result-item-selected the active one, with .result-item-title, .result-item-subtitle, .result-item-icon and .app-icon inside.

Keep the row height and the layout, keep text readable against the background in both the selected and normal rows, and avoid heavy transitions because the list changes while people type.

## Trying it

When Sliprail runs on this computer, make sure sliprail.json has an id, setting it to a new UUID if it has none, then open com.fengcen.sliprail://develop?path=<URL-encoded absolute path of the package directory> with open on macOS or Start-Process in PowerShell on Windows, and confirm in Sliprail. Pick the theme in the theme settings. Open the link again after changes to reload it.

## Publishing

Publish with the tools of the Sliprail MCP server at https://sliprail.com/_api/sliprail/mcp. If they are not available, ask the user to connect it as described in https://sliprail.com/docs/developer/connect-your-agent; it needs an access token with Sliprail publishing access, created at https://account.fengcen.com/create-access-token.

1. Pack the package directory, the one with sliprail.json at its root, into a gzipped tarball outside of it, leaving out node_modules and hidden files:
   - macOS and Linux: `tar -czf "${TMPDIR:-/tmp}/sliprail-package.tgz" -C <package directory> --exclude=node_modules --exclude='*/.*' .`
   - Windows PowerShell: `tar.exe -czf "$env:TEMP\sliprail-package.tgz" -C <package directory> --exclude=node_modules --exclude="*/.*" .`
2. Read the size of the tarball in bytes with `wc -c < "${TMPDIR:-/tmp}/sliprail-package.tgz"`, or `(Get-Item "$env:TEMP\sliprail-package.tgz").Length` in PowerShell.
3. Call create_package_upload with the size, run the upload command it returns as it is, then call publish_package with the returned uploadKey.
4. When publish_package returns an id that is not the id in sliprail.json, or sliprail.json has no id, write the returned id into sliprail.json and keep it, so that later publishes update the same package and its data.

The theme stays private to the user and installs automatically in their Sliprail desktop app after they sign in. To change a package published earlier, get its files with get_package_files, edit them and publish them again. Never include secrets or private data in the files.
