{"id":50720700,"url":"https://github.com/tschk/crepuscularity","last_synced_at":"2026-06-25T06:00:30.674Z","repository":{"id":345617095,"uuid":"1186311660","full_name":"tschk/crepuscularity","owner":"tschk","description":"write react for gpui tui and embedded, write rust for web extensions, write both for websites, swiftui, mobile apps and more.","archived":false,"fork":false,"pushed_at":"2026-06-23T14:59:01.000Z","size":57662,"stargazers_count":18,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-23T15:25:09.047Z","etag":null,"topics":["crepuscularity","gpui","jetpack-compose","mv3","mv3-extension","rust","swiftui","wasm"],"latest_commit_sha":null,"homepage":"http://crepuscularity.tsc.hk/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tschk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-19T13:49:24.000Z","updated_at":"2026-06-23T13:42:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tschk/crepuscularity","commit_stats":null,"previous_names":["semitechnological/crepuscularity","tschk/crepuscularity"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/tschk/crepuscularity","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tschk%2Fcrepuscularity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tschk%2Fcrepuscularity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tschk%2Fcrepuscularity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tschk%2Fcrepuscularity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tschk","download_url":"https://codeload.github.com/tschk/crepuscularity/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tschk%2Fcrepuscularity/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34761847,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-25T02:00:05.521Z","response_time":101,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crepuscularity","gpui","jetpack-compose","mv3","mv3-extension","rust","swiftui","wasm"],"created_at":"2026-06-10T00:00:24.932Z","updated_at":"2026-06-25T06:00:30.667Z","avatar_url":"https://github.com/tschk.png","language":"Rust","funding_links":[],"categories":["📦 Libraries","Tooling"],"sub_categories":["🏗️ Frameworks","Demos \u0026 Examples"],"readme":"# Crepuscularity\n\n\u003e **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.\n\nThink React Native turned into a systems UI toolkit: one compact `.crepus` language can drive GPUI desktop apps, Ratatui terminal UIs, Chromium/Firefox extensions, web output, native mobile shells, embedded panels, and LVGL Pro. Crepuscularity also ships hot reload, runtime rendering, and a GPUI desktop shell with an embedded V8 bridge for native capabilities.\n\nWrite 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), terminal UIs (Ratatui), browser extensions (MV3), HTML output, and React/JSX — and is the foundation for native mobile backends targeting SwiftUI and Jetpack Compose.\n\nUse [Aurorality](https://github.com/tschk/aurorality) for united SwiftUI macOS + iOS apps.\n\n## Why Crepuscularity\n\n- **GPUI component workflow with hot reload** — live template updates without recompiling app code\n- **Rust-owned MV3 extension target** — write popup, background, and content-script surfaces in `.crepus`, then emit Chromium or Firefox bundles without adopting a JavaScript framework or app bundler as the primary authoring model\n- **One syntax, multiple backends** — the same template works across GPUI (native desktop), HTML, React/JSX, and browser extensions today; **`crepuscularity-native`** lowers `.crepus` to JSON **View IR** for SwiftUI / Jetpack Compose shells (see [`examples/native-shells`](examples/native-shells/README.md))\n- **Polyglot plugin contract** — host languages consume View IR JSON through `crepus native ir` or the optional `crepuscularity-abi` C session API, then create UI from the typed node tree; drop-in reference packages and native workspace files live under [`plugins/`](plugins/README.md)\n- **Terminal UIs without a second UI language** — **`crepuscularity-tui`** maps `.crepus` elements, includes, slots, control flow, and Tailwind-style terminal classes onto Ratatui frames\n- **Embedded panels (in testing)** — **`crepuscularity-embedded`** renders `.crepus` into an RGB565 buffer you flush over SPI (**ILI9341**, **ST7789**) or into an **LTDC** framebuffer on STM32/ESP32; see [`docs/embedded.md`](docs/embedded.md) and [`examples/embedded-dashboard`](examples/embedded-dashboard/README.md)\n- **Desktop shell for embedded guest apps** — **`crepuscularity-lite`** embeds V8 in a GPUI host with a Rust native-capability bridge, optional file watching, workers, plugin capabilities, and TypeScript/TSX guest transpilation\n- **Compile-time and runtime paths** — `view!` macro for zero-overhead AOT compilation; `parse_template` / `render_nodes` for full runtime flexibility and hot reload\n\n## Quick Start\n\n```bash\n# Install the CLI\ncargo install --path crates/crepuscularity-cli\n\n# If `crepus` is not found, Cargo still installed the binary under ~/.cargo/bin — add it to PATH,\n# e.g. for zsh:  export PATH=\"$HOME/.cargo/bin:$PATH\"\n# (Rustup normally prepends this for login shells; some terminals omit it.)\n\n# Create a new GPUI app\ncrepus init gpui my-app\ncd my-app\nSDKROOT=$(xcrun --show-sdk-path) cargo run\n\n# Or create a browser extension\ncrepus init webext my-extension\ncd my-extension\ncrepus build\n# Load dist/unpacked/ in chrome://extensions\n```\n\n## Minimal target builds\n\nPut every output in one `crepus.toml`, then run one command:\n\n```toml\n[[targets]]\ntype = \"web\"\nid = \"site\"\nsite = \"docs-site\"\nout = \"docs-site/dist\"\nentry = \"index.crepus\"\n\n[[targets]]\ntype = \"lvgl\"\nid = \"panel\"\ntemplate = \"ui.crepus\"\nout = \"dist/panel.xml\"\nname = \"Panel\"\nroot = \"screen\"\n\n[targets.vars]\ndevice = \"STM32F411\"\n```\n\n```bash\ncrepus build\ncrepus build web\ncrepus build panel\ncrepus build --target panel\n```\n\nRust build scripts can use the same manifest for render-output targets:\n\n```rust\nlet artifacts = crepuscularity::target::write_manifest_file(\"crepus.toml\")?;\n```\n\n## Template Syntax (or you can write React JSX)\n\n```text\ndiv w-full h-full bg-zinc-950 text-white flex flex-col p-8\n  div text-2xl font-bold mb-4\n    \"Hello {name}\"\n  if {score \u003e 50}\n    div text-green-400\n      \"High score!\"\n  else\n    div text-red-400\n      \"Keep going\"\n```\n\n## Features\n\n- **`.crepus` syntax** — indentation-based, Tailwind-style classes\n- **Semantic native tags** — optional component tags for native shells (`navigationstack`, `sidebar`, `item`, `menu`, `label`, SF symbols, etc. in the SwiftUI `swiftgen` path)\n- **Control flow** — `if/else`, `match`, `for`\n- **String interpolation** — `\"Hello {name}\"`\n- **Expressions** — arithmetic, comparison, logical operators, property access\n- **Components** — single-file and multi-component files with slot support\n- **Hot reload** — live template updates via the runtime renderer\n- **Web SEO metadata** — `crepus.toml` web targets generate document head tags, social cards, `robots.txt`, and `sitemap.xml`\n- **Browser extensions** — `crepus webext` commands for MV3 extensions; typed Rust browser API wrappers; popup pre-rendered at build time; release WASM optimization when `wasm-opt` is installed; no JS bundler needed\n- **IDE integration** — structured JSON events with `--emit-events`\n\n## Output Targets\n\nThe `.crepus` DSL is the primary language. Each output target is a renderer that consumes the same parsed template — not a different framework.\n\n\n| Crate                   | Output                                                         |\n| ----------------------- | -------------------------------------------------------------- |\n| `crepuscularity-gpui`   | Native desktop (GPUI elements) — primary target                |\n| `crepuscularity-tui`    | Ratatui terminal frames with `.crepus` templates and typed handles |\n| `crepuscularity-lite`   | GPUI desktop shell with embedded V8, Rust plugins, and guest workers |\n| `crepuscularity-native` | View IR JSON for SwiftUI / Compose host apps (not an on-screen renderer) |\n| `crepuscularity-abi`    | Optional C ABI sessions for in-process IR rendering and event dispatch |\n| `crepuscularity-web`    | HTML strings — server rendering, WASM, browser extensions      |\n| `crepuscularity-webext` | MV3 browser extensions — manifest, assets, capability scanning |\n| `crepuscularity-embedded` | **UNSTABLE** — RGB565 framebuffer for SPI/LTDC panels (ILI9341, ST7789, ESP-LCD, …); see [`docs/embedded.md`](docs/embedded.md) |\n\n\nJSX/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 `\u003ctag\u003e` style, and both compile to the same AST.\n\n## CLI Commands\n\n```bash\ncrepus init \u003ckind\u003e \u003cname\u003e            # Scaffold web, webext, tui, mobile, native, ios, or gpui apps\ncrepus new \u003cname\u003e                    # Alias for crepus init gpui \u003cname\u003e\ncrepus dev [--emit-events]           # Hot-reload dev loop\ncrepus build [type-or-id] [--target ID]  # Build crepus.toml targets, selected type/id, or cargo fallback\ncrepus preview \u003cfile.crepus\u003e         # Live preview\n\ncrepus web new \u003cname\u003e                # Alias for crepus init web \u003cname\u003e\ncrepus webext new \u003cname\u003e             # Alias for crepus init webext \u003cname\u003e\ncrepus webext build [--app PATH] [--browser chromium|firefox]  # Build to dist/unpacked/ or dist/\u003cbrowser\u003e/\ncrepus webext manifest [--app PATH] [--browser chromium|firefox]  # Print manifest.json\n\ncrepus aurora dev [--watch DIR]      # SwiftUI hot-reload dev server (via Aurorality)\ncrepus aurora build [--watch DIR]    # Compile .crepus → View IR JSON\ncrepus aurora new \u003cname\u003e             # Scaffold SwiftUI + Rust project\n\ncrepus ios new \u003cname\u003e                # Alias for crepus init ios \u003cname\u003e\ncrepus ios generate [--dir]          # Run xcodegen (finds crepus.toml [ios] upward)\ncrepus ios build [--dir] [...]       # Simulator build via xcodebuild\n\ncrepus mobile new \u003cname\u003e             # Preferred iOS + Android scaffold\ncrepus mobile dev [--platform all]   # View IR hot-reload server on port 4001\ncrepus mobile build --platform android|ios|all\ncrepus mobile run --platform android|ios\n\ncrepus native ir \u003cfile.crepus\u003e       # Emit View IR JSON for plugins and native shells\ncrepus native sync \u003cfile.crepus\u003e --dir \u003capp\u003e [--out FILE]  # Write View IR fixtures into native containers\n\ncrepus embedded check \u003cfile.crepus\u003e  # UNSTABLE: validate template for firmware CI\ncrepus embedded snapshot … --out x.ppm  # UNSTABLE: debug PPM only (use Ui + rgb565() on device)\n```\n\n## Documentation\n\n- **Rendered site (GitHub Pages):** [here](https://crepuscularity.undivisible.dev) — WASM landing page plus HTML generated from the Markdown in [`docs/`](docs/). Built in CI with `crepus web build --manifest docs-site/crepus.toml`.\n- **Sources:** [docs/README.md](docs/README.md) indexes [DSL](docs/dsl.md) (including SwiftUI semantic tag mappings), [components](docs/components.md), [CLI](docs/cli.md), [runtime/reactivity](docs/runtime.md), [GPUI](docs/gpui.md), [TUI](docs/tui.md), [embedded / framebuffer](docs/embedded.md) (**UNSTABLE** — STM32, ESP32, SPI panels), [Lite](docs/lite.md), [native shells](docs/native.md), [polyglot plugins](docs/polyglot.md), and [extensions](docs/webext.md). Compiler-focused detail stays in-repo as [CREPUS_WEB_IMPLEMENTATION_SPEC.md](docs/CREPUS_WEB_IMPLEMENTATION_SPEC.md) but is not shipped on the public docs site.\n- **Native shells:** [examples/native-shells](examples/native-shells/README.md) — SwiftUI/XcodeGen (**`ios/`**), Gradle/Compose (**`android/`**), and shared **View IR** `fixture.json` next to **`crepuscularity-native`** (replaces the old separate **`crepuscularity-native-ui`** checkout).\n- **Contributors \u0026 coding agents:** root [**`AGENTS.md`**](AGENTS.md) is the canonical instructions (macOS `SDKROOT`, `cargo fmt` / `clippy` / `test` before push, workspace layout, DSL notes). **`CLAUDE.md`** is a symlink to **`AGENTS.md`** so duplicate context files cannot drift.\n\n## GPUI — Tailwind Class Support\n\nThe 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.\n\n### Supported\n\n\n| Category             | Classes                                                                                                                                            |\n| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Layout**           | `flex`, `grid`, `block`, `hidden`, `flex-col/row`, `flex-wrap`, `flex-1/auto/none`, `grow`, `shrink`                                               |\n| **Justify / Align**  | `justify-start/end/center/between/around`, `items-start/end/center/baseline`, `content-`*                                                          |\n| **Align self**       | `self-start`, `self-end`, `self-center`, `self-stretch`, `self-baseline`, `self-auto`                                                              |\n| **Sizing**           | `w-`*, `h-*`, `size-*`, `min-w/h-*`, `max-w/h-*` — numbers, fractions, `full`, `auto`, `[Npx]`                                                     |\n| **Aspect ratio**     | `aspect-square`, `aspect-video`, `aspect-auto`, `aspect-[N/M]`                                                                                     |\n| **Spacing**          | `p-`*, `px-*`, `py-*`, `pt/pb/pl/pr-*`, `m-*`, `mx/my-*`, `mt/mb/ml/mr-*`, `gap-*`, `gap-x/y-*`                                                    |\n| **Position**         | `absolute`, `relative`, `top/bottom/left/right/inset-`*                                                                                            |\n| **Overflow**         | `overflow-hidden`, `overflow-x/y-hidden`                                                                                                           |\n| **Colors**           | Full Tailwind palette (`bg/text/border-{family}-{shade}`), hex (`bg-[#rrggbb]`), hsla, rgba with `/alpha`                                          |\n| **Border**           | `border`, `border-0/2/4/8`, per-side `border-t/b/l/r-`*, `border-dashed`                                                                           |\n| **Border radius**    | `rounded-`* — all sizes, all sides, all corners                                                                                                    |\n| **Typography**       | Font weight (`font-thin` → `font-black`), style (`italic`), size (`text-xs` → `text-9xl`, `text-[Npx]`)                                            |\n| **Typography**       | Alignment (`text-left/center/right`), decoration (`underline`, `line-through`, `decoration-`*)                                                     |\n| **Typography**       | Line height (`leading-`*, `leading-[N]`), tracking (`tracking-*`, `tracking-[Npx]`), truncation (`truncate`, `text-ellipsis`, `whitespace-nowrap`) |\n| **Typography**       | Text transform (`uppercase`, `lowercase`, `capitalize`, `normal-case`)                                                                             |\n| **Font**             | `font-['Family']`, `line-clamp-N`, `font-features` via `FontFeatures` API                                                                          |\n| **Shadow**           | `shadow-2xs` → `shadow-2xl`, `shadow-none`                                                                                                         |\n| **Ring**             | `ring`, `ring-0/1/2/4/8`, `ring-[Npx]` — rendered as box-shadow spread                                                                             |\n| **Opacity**          | `opacity-N` (0–100), `opacity-{expr}`                                                                                                              |\n| **Cursor**           | `cursor-default/pointer/text/move/not-allowed` and all resize variants                                                                             |\n| **Grid**             | `grid-cols-N`, `grid-rows-N`, `col-span-N`, `col-start/end-N`, `row-span/start/end-N`                                                              |\n| **Arbitrary values** | `w-[Npx]`, `bg-[#hex]`, `text-[size]`, `rounded-[Npx]`, `border-[Npx]`, `aspect-[N/M]`, etc.                                                       |\n| **Dynamic context**  | `bg-{expr}`, `text-{expr}`, `border-{expr}`, `opacity-{expr}` — evaluated against template context                                                 |\n| **State prefixes**   | `hover:`, `focus:`, `active:` — accepted silently (state styling requires `.hover()`/`.on_click()` handlers in code)                               |\n\n\n### Not Supported (GPUI hard limits)\n\nThese cannot be added without forking GPUI itself:\n\n\n| Gap                                  | Reason                                                                                 |\n| ------------------------------------ | -------------------------------------------------------------------------------------- |\n| `ring-{color}`                       | Ring color customisation requires architectural change; default ring is blue-500/50    |\n| `md:` / `lg:` / `xl:` breakpoints    | No CSS cascade or viewport queries — GPUI uses Taffy layout                            |\n| `dark:` variant                      | No built-in dark mode detection — use `bg-{theme.surface}` context expressions instead |\n| `group-hover:` / `peer:`             | No selector/relationship system                                                        |\n| `before:` / `after:` pseudo-elements | No pseudo-elements — add child `div` nodes in the template instead                     |\n| `z-`* (z-index)                      | GPUI uses painter's algorithm / GPU layers, not z-index                                |\n| `float`                              | Not supported by Taffy layout engine                                                   |\n| `ring-inset`                         | GPUI has no inset box-shadow — accepted silently                                       |\n\n\n## Project Structure\n\n```text\ncrates/\n  crepuscularity/           Facade re-exporting prelude\n  crepuscularity-core/      AST, parser, evaluator\n  crepuscularity_macros/    Compile-time view! proc-macro\n  crepuscularity-runtime/   Hot-reload renderer (Tailwind → GPUI styler)\n  crepuscularity-web/       HTML backend\n  crepuscularity-webext/    Browser extension support\n  crepuscularity-gpui/      GPUI prelude + view! macro\n  crepuscularity-tui/       Ratatui backend + template_refs! handles\n  crepuscularity-lite/      GPUI + V8 shell and native plugin bridge\n  crepuscularity-native/    View IR JSON for SwiftUI / Compose shells\n  crepuscularity-reactive/  WASM signals, memos, effects, hydration lifecycle\n  crepuscularity-ssr/       Server-rendering helpers\n  crepuscularity-dev/       crepus-dev hot-reload server\n  crepuscularity-cli/       crepus CLI\nexamples/\n  examples.toml             Catalog by target (see examples/README.md)\n  extensions/               Git symlinks to undivisible/anywhere, rs_vimium\n  weather/                  Weather app example\n  quicknote/                Browser extension example (in-repo)\n  native-shells/            SwiftUI/XcodeGen and Gradle View IR hosts\n```\n\n## Building\n\nInstall the CLI:\n\n```bash\ncargo install --path crates/crepuscularity-cli\n```\n\nPre-built binaries for Linux and Windows are in the repo root (`crepus-linux-x86_64`, `crepus-windows-x86_64.exe`).\n\nOn macOS, GPUI requires the Xcode SDK path:\n\n```bash\nSDKROOT=$(xcrun --show-sdk-path) cargo build\n```\n\nWhen Xcode uses the downloadable Metal Toolchain component, let Cargo inherit the exact Xcode environment GPUI's build script needs:\n\n```bash\neval \"$(scripts/metal-env.sh)\"\ncargo build\nscripts/metal-env.sh -- cargo check -p crepuscularity-gpui\nscripts/metal-env.sh --check\n```\n\nThe 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 \u003e Components before debugging Cargo code.\n\n## License\n\nMozilla Public License 2.0 — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftschk%2Fcrepuscularity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftschk%2Fcrepuscularity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftschk%2Fcrepuscularity/lists"}