Crepuscularity
Stability: This project is unstable and in active development. APIs, CLI flags, and template semantics may change without a semver-major release until 1.0. Pin exact dependency versions and expect occasional breakage.
The first GPUI component and runtime system with hot reloading, and the first non-web-language, plug-and-play browser extension framework.
Write UI in a concise, indentation-based template DSL (.crepus files). Templates compile at build time via the view! macro or render at runtime with full hot-reload support. The same .crepus syntax drives native desktop (GPUI), browser extensions (MV3), HTML output, and React/JSX — and is the foundation for native mobile backends targeting SwiftUI and Jetpack Compose.
Why Crepuscularity
- First GPUI component system with hot reload — live template updates without recompiling; no other GPUI framework offers this
- First plug-and-play browser extension framework in Rust — write your popup/background/content scripts in
.crepus, get a MV3-compliant extension bundle out; no JavaScript framework or bundler required - One syntax, multiple backends — the same template works across GPUI (native desktop), HTML, React/JSX, and browser extensions today;
crepuscularity-nativelowers.crepusto JSON View IR for SwiftUI / Jetpack Compose shells (seeexamples/native-shells) - Compile-time and runtime paths —
view!macro for zero-overhead AOT compilation;parse_template/render_nodesfor full runtime flexibility and hot reload
Quick Start
# Install the CLI
# If `crepus` is not found, Cargo still installed the binary under ~/.cargo/bin — add it to PATH,
# e.g. for zsh: export PATH="$HOME/.cargo/bin:$PATH"
# (Rustup normally prepends this for login shells; some terminals omit it.)
# Create a new GPUI app
SDKROOT=
# Or create a browser extension
# Load dist/unpacked/ in chrome://extensions
Template Syntax
div w-full h-full bg-zinc-950 text-white flex flex-col p-8
div text-2xl font-bold mb-4
"Hello {name}"
if {score > 50}
div text-green-400
"High score!"
else
div text-red-400
"Keep going"
Features
.crepussyntax — indentation-based, Tailwind-style classes- Control flow —
if/else,match,for - String interpolation —
"Hello {name}" - Expressions — arithmetic, comparison, logical operators, property access
- Components — single-file and multi-component files with slot support
- Hot reload — live template updates via the runtime renderer
- Browser extensions —
crepus webextcommands for MV3 extensions; popup pre-rendered at build time; no JS bundler needed - IDE integration — structured JSON events with
--emit-events
Output Targets
The .crepus DSL is the primary language. Each output target is a renderer that consumes the same parsed template — not a different framework.
| Crate | Output |
|---|---|
crepuscularity-gpui |
Native desktop (GPUI elements) — primary target |
crepuscularity-native |
View IR JSON for SwiftUI / Compose host apps (not an on-screen renderer) |
crepuscularity-web |
HTML strings — server rendering, WASM, browser extensions |
crepuscularity-webext |
MV3 browser extensions — manifest, assets, capability scanning |
JSX/HTML tag syntax is supported as an input format in the core parser — the same .crepus templates can be written in either indentation style or <tag> style, and both compile to the same AST.
CLI Commands
Documentation
- Rendered site (GitHub Pages): here — WASM landing page plus HTML generated from the Markdown in
docs/. Built in CI withcrepus web build --site docs-site. - Sources: docs/README.md indexes DSL, components, CLI, and extensions. Compiler-focused detail stays in-repo as CREPUS_WEB_IMPLEMENTATION_SPEC.md but is not shipped on the public docs site.
- Native shells: examples/native-shells — SwiftPM (
ios/), Gradle (android/), and shared View IRfixture.jsonnext tocrepuscularity-native(replaces the old separatecrepuscularity-native-uicheckout). - Contributors & coding agents: root
AGENTS.mdis the canonical instructions (macOSSDKROOT,cargo fmt/clippy/testbefore push, workspace layout, DSL notes).CLAUDE.mdis a symlink toAGENTS.mdso duplicate context files cannot drift.
GPUI — Tailwind Class Support
The GPUI renderer maps Tailwind-style class strings to native GPUI style calls. This is a native desktop renderer, not a browser, so the mapping is intentionally selective.
Supported
| Category | Classes |
|---|---|
| Layout | flex, grid, block, hidden, flex-col/row, flex-wrap, flex-1/auto/none, grow, shrink |
| Justify / Align | justify-start/end/center/between/around, items-start/end/center/baseline, content-* |
| Align self | self-start, self-end, self-center, self-stretch, self-baseline, self-auto |
| Sizing | w-*, h-*, size-*, min-w/h-*, max-w/h-* — numbers, fractions, full, auto, [Npx] |
| Aspect ratio | aspect-square, aspect-video, aspect-auto, aspect-[N/M] |
| Spacing | p-*, px-*, py-*, pt/pb/pl/pr-*, m-*, mx/my-*, mt/mb/ml/mr-*, gap-*, gap-x/y-* |
| Position | absolute, relative, top/bottom/left/right/inset-* |
| Overflow | overflow-hidden, overflow-x/y-hidden |
| Colors | Full Tailwind palette (bg/text/border-{family}-{shade}), hex (bg-[#rrggbb]), hsla, rgba with /alpha |
| Border | border, border-0/2/4/8, per-side border-t/b/l/r-*, border-dashed |
| Border radius | rounded-* — all sizes, all sides, all corners |
| Typography | Font weight (font-thin → font-black), style (italic), size (text-xs → text-9xl, text-[Npx]) |
| Typography | Alignment (text-left/center/right), decoration (underline, line-through, decoration-*) |
| Typography | Line height (leading-*, leading-[N]), tracking (tracking-*, tracking-[Npx]), truncation (truncate, text-ellipsis, whitespace-nowrap) |
| Typography | Text transform (uppercase, lowercase, capitalize, normal-case) |
| Font | font-['Family'], line-clamp-N, font-features via FontFeatures API |
| Shadow | shadow-2xs → shadow-2xl, shadow-none |
| Ring | ring, ring-0/1/2/4/8, ring-[Npx] — rendered as box-shadow spread |
| Opacity | opacity-N (0–100), opacity-{expr} |
| Cursor | cursor-default/pointer/text/move/not-allowed and all resize variants |
| Grid | grid-cols-N, grid-rows-N, col-span-N, col-start/end-N, row-span/start/end-N |
| Arbitrary values | w-[Npx], bg-[#hex], text-[size], rounded-[Npx], border-[Npx], aspect-[N/M], etc. |
| Dynamic context | bg-{expr}, text-{expr}, border-{expr}, opacity-{expr} — evaluated against template context |
| State prefixes | hover:, focus:, active: — accepted silently (state styling requires .hover()/.on_click() handlers in code) |
Not Supported (GPUI hard limits)
These cannot be added without forking GPUI itself:
| Gap | Reason |
|---|---|
ring-{color} |
Ring color customisation requires architectural change; default ring is blue-500/50 |
md: / lg: / xl: breakpoints |
No CSS cascade or viewport queries — GPUI uses Taffy layout |
dark: variant |
No built-in dark mode detection — use bg-{theme.surface} context expressions instead |
group-hover: / peer: |
No selector/relationship system |
before: / after: pseudo-elements |
No pseudo-elements — add child div nodes in the template instead |
z-* (z-index) |
GPUI uses painter's algorithm / GPU layers, not z-index |
float |
Not supported by Taffy layout engine |
ring-inset |
GPUI has no inset box-shadow — accepted silently |
Project Structure
crates/
crepuscularity/ Facade re-exporting prelude
crepuscularity-core/ AST, parser, evaluator
crepuscularity-web/ HTML backend
crepuscularity-gpui/ GPUI prelude + view! macro
crepuscularity_macros/ Compile-time view! proc-macro
crepuscularity-runtime/ Hot-reload renderer (Tailwind → GPUI styler)
crepuscularity-cli/ crepus CLI
crepuscularity-webext/ Browser extension support
examples/
weather/ Weather app example
quicknote/ Browser extension example
Building
Install the CLI:
Pre-built binaries for Linux and Windows are in the repo root (crepus-linux-x86_64, crepus-windows-x86_64.exe).
On macOS, GPUI requires the Xcode SDK path:
SDKROOT=
When Xcode uses the downloadable Metal Toolchain component, let Cargo inherit the exact Xcode environment GPUI's build script needs:
The required variables are SDKROOT for SDK headers, DEVELOPER_DIR for the active Xcode, and TOOLCHAINS=Metal for xcrun toolchain selection. scripts/metal-env.sh reads the downloaded Metal toolchain search path from xcodebuild -showComponent MetalToolchain -json, exports the short selector that xcrun -sdk macosx metal accepts, and prepends Metal.xctoolchain/usr/bin to PATH for direct metal / metallib probes. If --check reports xcrun_metal=failed, run xcodebuild -downloadComponent MetalToolchain or install the component from Xcode Settings > Components before debugging Cargo code.
License
Mozilla Public License 2.0 — see LICENSE.