Creating & Publishing Themes

How to scaffold a new theme, build and pack it, publish to pureadmin.io, and understand the integrity system that protects the ecosystem.

Quick Start

The fastest way to create a new theme is to download the template and tools from pureadmin.io:

# Scaffold a new theme project (downloads template + tools)
npx @keenmate/pureadmin init my-theme "My Theme"
cd my-theme

# Install dependencies, build, and pack
npm install
npm run build
npm run pack

Or manually via the API:

curl -o template.zip "https://pureadmin.io/api/tools/template?id=my-theme&name=My%20Theme"
unzip template.zip -d my-theme && cd my-theme

This gives you a ready-to-go theme project with:

  • theme.json — theme manifest with schema reference and starter colors
  • src/scss/my-theme.scss — SCSS source importing Pure Admin core with variable overrides
  • package.json — npm scripts for build, pack, and publish

Project Structure

my-theme/\n├── theme.json              # Theme manifest (required)\n├── src/scss/my-theme.scss  # SCSS source (required)\n├── dist/my-theme.css       # Compiled CSS (generated)\n├── pure-admin.json         # CLI config (server URL, API key)\n├── assets/                 # Optional: fonts, images, icons\n│   ├── fonts/\n│   └── logo.svg\n├── preview/                # Optional: thumbnail screenshots\n│   └── thumbnail.png\n└── package.json

theme.json

The theme manifest describes your theme's metadata, color variants, modes, and exports. It follows the Pure Admin theme schema.

{
  "$schema": "https://pureadmin.io/schemas/pure-admin-theme.schema.json",
  "manifestVersion": "1.0",
  "name": "My Theme",
  "id": "my-theme",
  "version": "1.0.0",
  "description": "A custom Pure Admin theme.",
  "author": "Your Name",
  "license": "MIT",
  "coreVersion": ">=2.0.0",
  "colorVariants": [
    {
      "id": "",
      "name": "Default",
      "file": "dist/my-theme.css",
      "modes": [
        {
          "id": "light",
          "name": "Light",
          "default": true,
          "colors": {
            "accent": "#3b82f6",
            "background": "#f9fafb",
            "surface": "#ffffff",
            "text": "#1a1a1a"
          }
        }
      ]
    }
  ],
  "exports": {
    "css": "./dist/my-theme.css",
    "scss": "./src/scss/my-theme.scss"
  },
  "external_domains": [],
  "scripts": []
}

Key fields:

  • manifestVersion — schema version, currently "1.0"
  • id — lowercase slug with hyphens, used in filenames and URLs
  • colorVariants — array of color variants, each with modes (light/dark) and per-mode color palettes
  • external_domains — any domains your CSS references via url() (font CDNs, image hosts)
  • scripts — any JavaScript files in the package (must be declared or upload is rejected)

Building

Compile your SCSS to CSS:

# Build current theme\nnpx @keenmate/pureadmin build\n\n# In a multi-theme workspace, build specific themes\nnpx @keenmate/pureadmin build audi corporate

This runs sass with the correct load paths to resolve @keenmate/pure-admin-core imports. The output lands in dist/my-theme.css.

Packing

Package your theme into a distributable ZIP:

# Build + pack\nnpx @keenmate/pureadmin pack\n\n# Pack without rebuilding\nnpx @keenmate/pureadmin pack --no-build\n\n# Pack specific themes in a workspace\nnpx @keenmate/pureadmin pack audi corporate

The pack tool:

  1. Reads and validates theme.json
  2. Compiles SCSS if no CSS exists yet
  3. Rewrites url() paths in CSS/SCSS to be ZIP-relative
  4. Collects font files, images, and other assets
  5. Computes SHA-256 checksums for every file
  6. Computes a metadata hash and content_sha
  7. Scans CSS for external domain references
  8. Generates a README
  9. Creates pure-admin-theme-my-theme-1.0.0.zip

Publishing

Upload your theme to pureadmin.io:

# Build + pack + upload (all in one)\nnpx @keenmate/pureadmin publish\n\n# Publish specific theme with explicit API key\nnpx @keenmate/pureadmin publish audi --api-key your-key-here\n\n# Publish to a different server\nnpx @keenmate/pureadmin publish --server https://staging.pureadmin.io

Store your API key and server URL in pure-admin.json (project-level) or ~/.pure-admin.json (user-level) so you don't have to pass them every time:

// pure-admin.json
{
  "url": "https://pureadmin.io",
  "apiKey": "your-key-here"
}

On upload, the server validates your package:

  • Schema validation against the theme JSON schema
  • File checksums — every file must match what's declared
  • External domains — CSS url() references must be declared in external_domains
  • No undeclared JavaScript — all .js files must be listed in scripts

If the theme already exists with identical checksums, the server responds with "unchanged" and skips the update.

Integrity System

Every theme package includes cryptographic integrity data. This enables change detection, HTTP caching, and trust verification.

What gets hashed

// Inside the ZIP's theme.json after packing:
"checksums": {
  "files": {
    "css/my-theme.css": "sha256:abcd...",
    "scss/my-theme.scss": "sha256:ef01...",
    "assets/fonts/MyFont.woff2": "sha256:2345...",
    "README.md": "sha256:6789..."
  },
  "metadata": "sha256:abab...",
  "content_sha": "sha256:cdcd..."
}
  • checksums.files — SHA-256 of every file in the ZIP (excluding theme.json itself)
  • checksums.metadata — SHA-256 of canonical JSON of descriptive fields (name, description, version, etc.). Detects content-only updates without CSS changes.
  • checksums.content_sha — combined hash of all file checksums + metadata hash. This is the single value that represents the entire package state.

ETag caching

The content_sha is used as the HTTP ETag header when you fetch a theme from the API. Clients can verify downloads by comparing:

# 1. Get the ETag from the API
ETAG=$(curl -sI https://pureadmin.io/api/themes/my-theme | grep -i etag | awk '{print $2}' | tr -d '"\r')

# 2. Download the ZIP and extract content_sha
curl -o my-theme.zip https://pureadmin.io/api/themes/my-theme/download
SHA=$(unzip -p my-theme.zip theme.json | python3 -c "import sys,json; print(json.load(sys.stdin)['checksums']['content_sha'])")

# 3. Compare — they should match
[ "$ETAG" = "$SHA" ] && echo 'Integrity verified' || echo 'MISMATCH'

The pureadmin CLI

All theme operations — building, packing, publishing, downloading — are handled by the @keenmate/pureadmin CLI. No separate scripts needed.

# Install globally\nnpm install -g @keenmate/pureadmin\n\n# Or use via npx (no install)\nnpx @keenmate/pureadmin --help

Key commands for theme authors:

Command Description
pureadmin build Compile SCSS to CSS
pureadmin pack Build + package into ZIP with integrity checksums
pureadmin publish Build + pack + upload to pureadmin.io
pureadmin init <id> Scaffold a new theme project

See the npm package for full documentation.