Skip to main content

Theme Forge Solar Sail

Deterministic theme compiler, library, and tfss CLI for Tailwind CSS v4 and shadcn/ui application theming. Sibling engine to Theme Forge Stellar Loom.

This source describes version 0.3.0.

Overview

Theme Forge Solar Sail translates declarative theme specifications (tfss.theme-v1) into:

  • Tailwind CSS v4 @theme inline configuration: Emits clean CSS theme variables directly compatible with Tailwind v4's stylesheet-first engine.
  • shadcn/ui semantic roles: Maps tokens to standard component roles (background, foreground, card, popover, primary, secondary, muted, accent, destructive, border, input, ring, and optional chart tokens).
  • Light and dark theme support: Emits scoped :root and .dark / @custom-variant dark (&:is(.dark *)) styles.
  • Radius progression: Defines full radius scales from --radius-sm through --radius-4xl.
  • Actionable diagnostics: Verifies color contrast ratios against background tokens and reports missing role warnings.
  • Standalone distribution packages: Generates self-contained packages in TypeScript or zero-build JavaScript that require zero runtime dependencies on Solar Sail or any external service.

Python installation

This Python distribution packages the frozen Theme Forge Node CLI. It requires Python 3.9 or later and an independently installed Node.js 22 or later on PATH; it does not install Node or install or invoke npm, npx, or corepack.

When this version is available from the Python package index:

python3 -m pip install "theme-forge-solar-sail==0.3.0"

For a locally built wheel or source distribution without an index lookup:

python3 -m pip install --no-index --no-deps --find-links ./dist "theme-forge-solar-sail==0.3.0"

Console entry points: tfss. For example:

tfss --help
tfss --version

The selected wheel target tuples are darwin-arm64, linux-arm64-gnu and linux-x64-gnu; use an artifact matching the host. Native compatibility depends on that artifact's platform requirements, not just the Node major version. The Python package exposes console launchers, not Python implementations of the upstream JavaScript theme/compiler APIs. Relative documentation links below describe upstream source layout rather than additional installed Python files.

CLI Usage

The tfss CLI provides three primary subcommands:

1. Validate a Theme Specification

Validates theme schema conformance, ensures required color roles are defined, and evaluates contrast diagnostics:

tfss validate path/to/theme.json
tfss validate path/to/theme.json --json

2. Compile to CSS

Compiles a theme specification into standalone CSS stylesheets:

tfss compile path/to/theme.json --out dist/styles
tfss compile path/to/theme.json --json

Emits:

  • theme.css: Complete Tailwind CSS v4 and shadcn/ui custom properties.
  • theme.descriptor.json: Deterministic SHA-256 digests of inputs and outputs.

3. Generate a Standalone Distribution Package

Generates a complete, installable npm package:

tfss generate path/to/theme.json --package path/to/package-metadata.json --out packages/my-app-theme --language typescript

Options:

  • --package <path>: Path to package metadata JSON (name, version, description, license).
  • --out <dir>: Target directory (must be empty or absent for safety).
  • --language <typescript|javascript>: Emission language mode (default: javascript).
  • --json: Structured machine-readable output.

Package Architecture & Modes

Generated theme packages are completely self-contained:

  • In TypeScript mode (--language typescript), emits src/index.ts, tsconfig.json, and builds compiled distribution files in dist/.
  • In JavaScript mode (--language javascript), emits zero-build index.js and index.d.ts entry points.
  • Neither mode requires Solar Sail, Nebular Fusion, or private repository packages at consumer runtime.

Upstream JavaScript programmatic API

The examples below describe the upstream Node library. This Python distribution exposes tfss rather than a Python theme-compilation API.

import {
  compileTheme,
  validateThemeSpecification,
  generateThemePackage,
  type ThemeSpecification,
} from "@knowledge-forge-ai/theme-forge-solar-sail";

// Validate
const validation = validateThemeSpecification(themeSpec);
if (!validation.valid) {
  console.error("Diagnostics:", validation.diagnostics);
}

// Compile CSS
const result = compileTheme(themeSpec);
console.log(result.css); // Compiled Tailwind v4 @theme inline block + custom properties

// Generate Package
const pkg = generateThemePackage({
  themeSpec,
  metadata: { name: "my-theme", version: "1.0.0" },
  language: "typescript",
});

Boundaries & Limitations

  • Theme Backend Only: Solar Sail is a deterministic theme backend and compiler. It generates CSS tokens, radius scales, and package envelopes. It does not generate arbitrary React/TSX application code or UI component implementations.
  • Tailwind v4 First: Output stylesheets are targeted for Tailwind CSS v4 @theme inline and standard CSS custom properties.
  • Filesystem Safety: Package generation requires the target directory to be absent or completely empty to prevent accidental overwrites.

License

This project is licensed under the GNU Affero General Public License v3.0 or later. See LICENSE and NOTICE. Commercial licensing terms are available; see COMMERCIAL-LICENSE.md.

v1 validation and compatibility contract

tfss.theme-v1 is a closed semantic schema. Unknown top-level, palette-mode, surface, typography and color-role fields fail validation. The supported optional roles are chart1–chart5 and the canonical sidebar* roles in ColorTokens; these must occur in both modes. Arbitrary custom roles, aliases such as sidebar-background, spacing, tracking and shadow fields require an explicit adapter and are not silently dropped. The former generated declaration index signature was broader than the source contract and has been corrected.

The supported color subset is hex (3/4/6/8 digits), numeric RGB/HSL/OKLCH functions and bounded CSS variable references with supported color fallbacks. Declaration escapes, comments, invalid components and nonfinite numbers fail. RGB channels, saturation/lightness and alpha are range-checked; finite hue angles and nonnegative OKLCH chroma have no additional magnitude cap. Gamut conversion and hue normalization are not performed. Other CSS color grammars are unsupported. Alpha and non-hex contrast remain UNEVALUATED_CONTRAST; that is not an accessibility pass. Font stacks support quoted names and ordinary multiword names. Nested color indirection such as hsl(var(--x)) / rgb(var(--x)) and font indirection such as var(--font-geist-sans), sans-serif are unsupported; resolve those references in an explicit adapter before validation. A standalone color var(--x) remains supported. Radius and border values use the validator's nonnegative CSS length subset; executable expressions are unsupported. No new spacing, tracking or typography-scale model is introduced.

parseThemeJson(bytesOrText) rejects duplicate decoded keys, malformed UTF-8, BOM and unsafe JSON within a 1 MiB/depth-20 bound. CLI input uses this boundary. Library object inputs cannot recover duplicates already lost by another parser. Library validation rejects accessors without evaluating getters, hidden/symbol properties, custom prototypes, cycles and nonfinite numbers, and returns owned, deeply frozen theme data. This is a plain-data contract, not a sandbox for hostile JavaScript proxies. Use the byte parser for untrusted external documents.

Validated token spelling, including ordinary surrounding spaces, remains identity-bearing; equal visual appearance does not imply equal digest. CSS token strings and description/author fields reject C0, DEL and C1 controls before trimming. Human CLI output escapes terminal controls; JSON preserves their data meaning using JSON escaping. Generated README descriptions encode Markdown punctuation and leading whitespace as text.

Security corrections may reject previously accepted malformed data. Compatible additions must preserve maintained valid fixtures and declared digest projections. New unsupported intent must produce an error or a mapping report. A schema version or migration is required for a new incompatible semantic contract; no v2 migration is implied here. The chart mapping correction emits --chart-1 / --color-chart-1 from chart1 (and likewise 2–5). Callers relying on the old accidental --chart1 spelling must update their CSS.

Mapping coverage and source provenance

Use the additive report or byte-bound API at orchestration boundaries:

import { bindSourceProfile, generateThemePackage } from
  "@knowledge-forge-ai/theme-forge-solar-sail";

const bound = bindSourceProfile(profileBytes, { expectedSha256 });
const { specification, report } = bound.mapToSolarSail();
// Present/disposition report.entries before adoption; unsupported != consumed.
const generated = generateThemePackage({
  themeSpec: specification,
  metadata: { name: "@example/application-theme", version: "1.0.0" },
});

Reports retain source paths, target paths where mapped, values, and reasons for consumed, unsupported, target-specific, overridden, normalized and degraded dispositions. No color conversion is claimed. Solar surface overrides win over shared values explicitly. Reading width and Loom/syntax intent remain visible as unsupported or another target's intent. Unknown Solar-specific override leaves require the report API; the bare mapper rejects them.

summary.totalLeaves currently counts report entries, including synthetic defaults; it is not a unique source-leaf count. An empty description can have both consumed and normalized entries, and empty override containers can be reported unsupported. Disposition entries individually. mapToSyntaxPalette() remains a legacy value projection with no coverage report; do not use it to certify cross-target coverage. These report-shape refinements are deferred to B2.

Library error constructors other than FilesystemSafetyError are not exported from the package root in this candidate. StaleProvenanceError identifies itself by Error.name and carries expected/actual hashes, but public instanceof discrimination and a unified library error taxonomy remain deferred. The CLI JSON taxonomy is separately stable. writeCssFile is CLI-internal, not a root library export.

bindSourceProfile verifies SHA-256 against the actual bytes and freezes the profile deeply. normalizedSha256 hashes canonical paired JSON; it is a separate identity from exact source bytes, and is representation-normalized, not a claim that all CSS-equivalent colors or font strings are semantically equal. transform validates a new profile, binds its canonical serialized bytes, and retains the prior raw hash as parentSourceSha256. A changed profile cannot inherit the old current source hash. Serializing canonicalizeJson(transformed.profile) reproduces those transformed source bytes.

Bare v1 mappers keep their return shape. Embedded sha256 or sourceProfileSha256 fields are rejected as unknown authority. An explicit legacy Solar sourceProfileSha256 option and a direct theme field remain caller assertions, never evidence that bytes were verified. For Loom, pass the companion sourceProfileSha256 from bound.mapToStellarLoom(baseCatalog) explicitly to compileThemeCatalog(catalog, { sourceProfileSha256 }). Catalog objects carry no hidden hash; the old bare Loom provenance option is rejected with guidance to use the explicit compiler option. Bare mappers are not loss-reporting adoption interfaces; consumers must use the additive report APIs to certify coverage.

Identity and determinism domains

Identity Exact v1 meaning
Profile source hash SHA-256 of exact verified source bytes; whitespace matters.
Normalized profile hash SHA-256 of recursively localeCompare("en") key-sorted, two-space JSON with one LF. Arrays retain order.
Compiler input digest SHA-256 of that canonical JSON encoding of the validated Solar theme, including any caller-supplied source hash.
Compiler output digest SHA-256 of exact generated CSS bytes.
Descriptor inventory digest SHA-256 of canonical { inputDigest, outputDigest, name, version }.
Package inventory digest SHA-256 of tfss.package-inventory-v1\n followed by compact JSON.stringify of path/size/hash records sorted with localeCompare("en").
Provenance hash SHA-256 of the emitted provenance.json bytes. That file excludes itself from its file inventory to avoid a cycle.
Generation invocation digest Domain-prefixed canonical tfss.generation-invocation-v1: validated theme, effective metadata/defaults, language and compiler name/version.

describeGenerationInvocation(options) returns that complete direct-generator invocation plus every generated file's size/hash, including provenance. It names the two different inventory domains separately. Destination and overwrite policy are execution inputs, not generated-content inputs. Package metadata and language are content inputs. Compiler name/version identifies release code; qualification must also bind the actual source/build used while a candidate retains the same version. The maintained qualification receipt records the compiler source inventory and Node/ICU version. Existing locale ordering is preserved, not replaced with the Design Director's byte ordering.

Equal complete direct invocations under the qualified compiler/runtime produce equal emitted source-package bytes. This does not certify subsequent build/npm archive reproducibility, cross-runtime locale equivalence, or source-to-package reproducibility from equal paired-profile/delta claims. Profile application, ordered transformations, defaults and mapping policy must also be bound for that larger claim. Incidental formatting is not a universal compatibility promise; changes to an identity-bearing encoding require explicit compatibility disposition.

Structured CLI failures and filesystem contract

In --json mode, each invocation emits one JSON result on stdout. Success fields remain available; failures have status: "error", command, code, message, and validation details where relevant, and exit 1. Codes are ARGUMENT_ERROR, PARSE_ERROR, VALIDATION_ERROR, UNSUPPORTED_INTENT, DIAGNOSTIC_FAILURE, FILESYSTEM_SAFETY_ERROR, IO_ERROR, and INTERNAL_ERROR. Error prose is not a stable parser interface. Warnings/info remain nonfatal by default; --fail-on-diagnostics explicitly fails on contrast warnings or unevaluated contrast before writing. Human mode retains diagnostic text.

Package generation accepts absent or empty destinations. It rejects traversal, absolute/member separator ambiguity, case/Unicode collisions, file/directory prefix conflicts, symlink destinations/ancestors and nonempty destinations even with the legacy library overwrite option. Use physical paths: system alias symlinks are also rejected. Package names never determine filesystem destinations. Cooperating writers reserve an empty directory exclusively; every file uses exclusive creation. On I/O failure, rollback checks identity and removes only unchanged entries created by that invocation, preserving prior empty directories. Cleanup failure is reported, never relabeled success or hidden by recursive removal.

Package files become visible incrementally; this is not crash-atomic publication. A crash may retain partial files and the reservation marker. Inspect and remove only the abandoned invocation's owned state before retrying. Portable Node path APIs cannot prevent a hostile concurrent actor replacing parent directories between checks; parent directories must remain trusted and stable for the operation. There is no hostile-same-user confinement claim. CSS compile --overwrite stages and checks a regular-file replacement; without it, existing bytes are preserved. JSON/TypeScript serialization, CSS grammar checks, constrained package names, README escaping and independent file-map validation each own their output sink.

Paired Profile v2 checkpoint

The upstream paired protocol defines neutral semantic groups and separately named target adapters. Existing paired v1 functions and historical identities remain maintained. V2 requires explicit version migration, source-byte binding and capability reports; it is not a silent replacement for v1. Unsupported intent remains visible.

Loom pixel geometry does not imply rem/em conversion, and font families require explicit font-ID bindings. Code/syntax mapping is part of the report. Solar component/sidebar/chart vocabulary stays in target-only overrides. Complete invocations additionally bind base inputs, final configuration, generation options and compiler identity. Report or profile equality alone is insufficient.

See the B2 evaluation for qualification and limitations. Current Studio ingestion/adoption is not qualified for v2. No release or adoption authorization is implied.

The additive v2 root API includes validatePairedProfileV2, bindSourceProfileV2, canonicalizeProfileV2, migrateV1ToV2, migrateV2ToV1, applyRecipe, classifyProfileError, ERROR_CODES and the schema/adapter constants and associated types listed in the protocol reference. Migrations and recipes take source bytes, not parsed-object assertions. Bound profiles expose mapToSolarSail() and mapToStellarLoom(explicitInputs); the latter returns catalog, syntax and one source-leaf capability report. Native generation still uses the independent target library. V2 does not extend the CLI or Studio file-open contract. Protocol Markdown remains repository documentation, not a new upstream Node package directory.

V2 report provenance distinguishes source-bytes, transformed (canonical bytes created by a bound transformation), and serialized-profile. Group applicability states adapter capability independently of supplied leaves. Generated-default counts include only defaults surviving source projection and explicit overrides; source-derived syntax/chrome colors are not defaults. Validation preserves authored color spelling and returns a detached frozen object without freezing caller data.

Current Python distribution and upstream packaging

The current Python distribution uses the versioned pip commands and three target tuples listed above. Its native consumer qualification remains a separate gate.

The maintained public source composition separately includes DISTRIBUTION.md, release-layout.json, a locked first-party flake and an installed-package probe. Use that public source for sibling-free builds. See the public distribution guide in composed releases; in the upstream development source tree the source is docs/operations/loom-solar-distribution.md. The three required systems are Apple Silicon macOS, Linux ARM64 and Linux AMD64. Declared packaging coverage and qualified native execution remain separate gates.

Metadata

Release files for theme-forge-solar-sail 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for theme-forge-solar-sail 0.3.0
File Size Uploaded Provenance Actions
theme_forge_solar_sail-0.3.0.tar.gz 378.9 kB With provenance Details for theme_forge_solar_sail-0.3.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for theme-forge-solar-sail 0.3.0
File Interpreter ABI Platform Actions
theme_forge_solar_sail-0.3.0-py3-none-manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64 Details for theme_forge_solar_sail-0.3.0-py3-none-manylinux_2_28_x86_64.whl
theme_forge_solar_sail-0.3.0-py3-none-manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.28+ ARM64 Details for theme_forge_solar_sail-0.3.0-py3-none-manylinux_2_28_aarch64.whl
theme_forge_solar_sail-0.3.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details for theme_forge_solar_sail-0.3.0-py3-none-macosx_11_0_arm64.whl

Total release size: 2.0 MB

Release files / theme_forge_solar_sail-0.3.0.tar.gz

Download URL theme_forge_solar_sail-0.3.0.tar.gz
Size 378.9 kB
Tags Source
SHA-256 checksum
How to use checksums
b7656f537057b5cb263ee5a2349da9e6c88b691f81d9a82d5234334a9b3bf5c0
BLAKE2b-256 checksum
How to use checksums
175964d8678bb18563c5ecddaf032f0a1fe7d296bc1fb0f918522a35aa515151
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / theme_forge_solar_sail-0.3.0-py3-none-manylinux_2_28_x86_64.whl

Download URL theme_forge_solar_sail-0.3.0-py3-none-manylinux_2_28_x86_64.whl
Size 543.8 kB
Tags Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
4123dd5bd3af716c505be4a7ed87ba639733dbdf350df215e7659b4902b2c1ff
BLAKE2b-256 checksum
How to use checksums
10329623b666e27a20cc8821888a2655dad43215db24830d7062c88c30340c11
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / theme_forge_solar_sail-0.3.0-py3-none-manylinux_2_28_aarch64.whl

Download URL theme_forge_solar_sail-0.3.0-py3-none-manylinux_2_28_aarch64.whl
Size 543.8 kB
Tags Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
0295e7c2ea283d0142d44298da66fe14df28cf0c542a9616811b2bb4f4c078fc
BLAKE2b-256 checksum
How to use checksums
46ca8856cd1be4ce29c5a30a3d5b5d665a132d1049c2cdde01efcfdb6c76cb5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / theme_forge_solar_sail-0.3.0-py3-none-macosx_11_0_arm64.whl

Download URL theme_forge_solar_sail-0.3.0-py3-none-macosx_11_0_arm64.whl
Size 543.8 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d37dce044f61edb026cbded2a317ddbbf840df09aa2d7d06a663b9e872f30039
BLAKE2b-256 checksum
How to use checksums
89c4381723788388b24628258ec679cbfa5981192fc6fcfa9a3a9a301cc3a7f2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Security for theme-forge-solar-sail 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 4 files in this release have been uploaded with provenance metadata.

Select from 4 files

Attestation for theme_forge_solar_sail-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page