A complete content website with code highlighting built using the Rustelo framework, demonstrating modern multi-crate architecture
  • Shell 24.7%
  • Rust 18.4%
  • Nushell 17.4%
  • JavaScript 12.3%
  • Fluent 7.1%
  • Other 20.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
claude-bot 09ee4a48b9
fix(agent-git): push the branch the target is on, and say which one moved
`--branch` defaulted to "main", so `agent-push <member>` read as "publish what I
just did" and meant "publish main" — on a checkout that might be standing
anywhere. On 2026-08-26 that published someone else's month-old unpushed commit
to origin: the agent had committed to a feature branch, asked to push, and moved
a ref it had never looked at.

The default is now the target's own HEAD. An explicit --branch still passes
through untouched, which is how a tag is pushed. A detached HEAD has no branch
to infer and is refused rather than guessed.

The other half is the one that made it unrecoverable rather than merely wrong:
the push now NAMES the ref it is moving. The transcript showed `push code` and
the output showed a hash range, and between them nothing said `main`. A default
that answers a question nobody asked is the same defect as a hook line read in
place of the file it points at — which is what the case file published the same
day is about.

Claude-Session: https://claude.ai/code/session_01UMeYdnjgunF56PSRHQ5gbw
2026-08-26 00:50:00 +01:00
.cargo init repo with source 2026-07-10 03:44:13 +01:00
crates feat(runtime): site.ncl declares the default language, and startup says which one won 2026-08-08 18:22:47 +01:00
justfiles fix(agent-git): push the branch the target is on, and say which one moved 2026-08-26 00:50:00 +01:00
lian-build fix(lian-build): the cook stage resolved the whole workspace, so it cooked Leptos 2026-08-09 05:02:49 +01:00
provisioning fix(distro): features.ncl es clase rebuild, no restart — el guard que sostuvo la noche 2026-08-09 05:02:33 +01:00
resources/nickel/htmx-site feat(nickel): server.ncl joins the cascade — 101 shared lines, 2 that are identity 2026-08-08 22:53:41 +01:00
scripts fix(agent-git): push the branch the target is on, and say which one moved 2026-08-26 00:50:00 +01:00
site feat(nickel): server.ncl joins the cascade — 101 shared lines, 2 that are identity 2026-08-08 22:53:41 +01:00
xtask init repo with source 2026-07-10 03:44:13 +01:00
.dockerignore init repo with source 2026-07-10 03:44:13 +01:00
.env.example init repo with source 2026-07-10 03:44:13 +01:00
.gitignore chore: content publish tooling, seo canonical, site config updates 2026-07-27 15:18:17 +01:00
.k init repo with source 2026-07-10 03:44:13 +01:00
.pre-commit-config.yaml init repo with source 2026-07-10 03:44:13 +01:00
bacon.toml init repo with source 2026-07-10 03:44:13 +01:00
Cargo.lock feat(assets): the rendered body decides what the <head> carries 2026-08-08 18:22:47 +01:00
Cargo.toml init repo with source 2026-07-10 03:44:13 +01:00
CHANGELOG.md init repo with source 2026-07-10 03:44:13 +01:00
justfile feat(nickel): server.ncl joins the cascade — 101 shared lines, 2 that are identity 2026-08-08 22:53:41 +01:00
package-lock.json init repo with source 2026-07-10 03:44:13 +01:00
package.json init repo with source 2026-07-10 03:44:13 +01:00
README.md init repo with source 2026-07-10 03:44:13 +01:00
run.sh init repo with source 2026-07-10 03:44:13 +01:00
rustelo.manifest.toml init repo with source 2026-07-10 03:44:13 +01:00
SETUP.md init repo with source 2026-07-10 03:44:13 +01:00
uno.config.ts init repo with source 2026-07-10 03:44:13 +01:00

Website Implementation - Rustelo Framework

A complete content website with code highlighting built using the Rustelo framework, demonstrating modern multi-crate architecture and PAP compliance.

🎯 Project Overview

This implementation validates Rustelo's project generation capabilities and serves as a reference for content websites that need code display features.

Key Features

  • Multi-crate architecture: Client, server, shared, pages with build.rs integration
  • Type-safe configuration: Nickel (NCL) for routes, themes, menus with compile-time validation
  • Bilingual single-source: Zero duplication - EN/ES in one file
  • Code highlighting: Complete syntax highlighting with copy functionality
  • Language-agnostic: Supports any language without code changes
  • Smart caching: Multi-layer cache system for incremental builds
  • PAP compliant: Follows Rustelo's Project Architecture Principles

🚀 Quick Start

Prerequisites

  • Rust 1.75+ - Core language and toolchain
  • Node.js 18+ - Frontend tooling
  • Nickel (Configuration language) - REQUIRED for type-safe configuration
  • Site content in ../site/ directory

Note

: This project uses Nickel (NCL) for all configuration files (routes, themes, menus, content types). See NCL Configuration section below.

Setup & Development

# Install dependencies
just setup

# Start development server with hot reload
just dev

# Build for production
just build-prod

Development Commands

# Development
just dev              # Hot reload with CSS watching
just dev-server       # Rust only (no CSS watching)
just dev-css          # CSS watching only

# Building
just build            # Development build
just build-prod       # Production build
just build-rust       # Rust components only
just build-css        # CSS only

# Quality & Testing
just quality          # All quality checks
just test             # Run tests
just format           # Format code
just lint             # Lint code

# Content & Deployment
just validate-content # Validate site content
just deploy-staging   # Deploy to staging
just status           # Project status

🏗️ Architecture

Multi-Crate Structure

website-impl/
├── crates/
│   ├── shared/         # Route generation & shared types
│   ├── pages/          # Custom page component generation
│   ├── client/         # WASM frontend with asset processing
│   ├── server/         # Axum backend with configuration
│   └── plugin-example-theme/   # Example plugin (theme + i18n)
├── config.toml         # Application configuration
├── uno.config.ts       # UnoCSS configuration (synced with @website)
├── package.json        # Code highlighting & build tools
├── justfile           # Development automation
└── scripts/           # Build scripts for themes & highlighting

🔌 Plugin System

This implementation demonstrates Rustelo's Level 5 Plugin Architecture - a trait-based plugin system for unlimited extensibility without framework coupling.

Included Plugins

  • WebsiteResourceContributor (core): Provides themes, menus, and i18n
  • plugin-example-theme (example): Complete working theme plugin with tests

Plugin Features

  • ResourceContributor Trait: Contribute themes, menus, translations
  • Type-Safe Registration: Compile-time validation
  • Zero Conditional Compilation: Framework code is pure Rust
  • Configuration-Driven: Resources from TOML/FTL files
  • Self-Contained: Plugins are independent crates

Creating Custom Plugins

Step 1: Create plugin crate

cd crates/
cargo new --lib my-custom-plugin

Step 2: Implement ResourceContributor

use rustelo_core_lib::registration::ResourceContributor;

pub struct MyPlugin;

impl ResourceContributor for MyPlugin {
    fn contribute_themes(&self) -> HashMap<String, String> {
        let mut themes = HashMap::new();
        themes.insert("my-theme".to_string(),
            include_str!("../config/themes/my-theme.toml").to_string());
        themes
    }

    fn name(&self) -> &str {
        "my-plugin"
    }
}

Step 3: Add to workspace

  • Add to main Cargo.toml workspace members
  • Create configuration files in config/themes/ and config/i18n/

Step 4: Register at startup

// In crates/server/src/resources.rs
rustelo_core_lib::register_contributor(&MyPlugin)?;

Plugin Types

Type Purpose Example
Resource-Only Themes, menus, translations Custom theme plugin
Page Provider Custom page components Analytics dashboard
Composite Resources + pages Feature module

Example Plugin Walkthrough

See crates/plugin-example-theme/ for a complete, production-ready example:

  • Analytics dashboard theme configuration
  • English and Spanish translations
  • 10/10 passing unit tests
  • Comprehensive documentation

Plugin Documentation

🎨 Code Highlighting Features

Syntax Highlighting

  • highlight.js: Multi-language syntax highlighting
  • highlightjs-copy: One-click code copying
  • Theme system: Light/dark mode with custom themes
  • UnoCSS integration: Built-in code styling with design system

Design System Integration

Uses complete design system from @website:

  • ds-* prefixed utility classes
  • Theme variables for consistent styling
  • Built-in dark mode support
  • Code block styling with proper contrast

📝 NCL Configuration

This project uses Nickel (NCL) for type-safe, DRY configuration. All configuration files use .ncl format with TOML fallback support.

Why NCL?

Type Safety: Compile-time validation catches errors before runtime Zero Duplication: Bilingual configs in single file (no separate en.toml/es.toml) DRY Principles: Shared defaults and helper functions Better Tooling: Syntax highlighting, LSP support, validation

Configuration Files

site/
├── schemas/              # Reusable NCL type definitions
│   ├── content/
│   │   ├── contracts.ncl    # Type contracts for content
│   │   └── defaults.ncl     # Shared defaults + helpers
│   ├── menus/
│   │   ├── contracts.ncl
│   │   └── defaults.ncl
│   ├── footer/
│   │   ├── contracts.ncl
│   │   └── defaults.ncl
│   └── themes/
│       ├── contracts.ncl
│       └── defaults.ncl
├── config/
│   └── themes/
│       ├── default.ncl      # Default theme
│       └── dark.ncl         # Dark theme variant
├── content/
│   └── content-kinds.ncl    # Content type definitions
└── ui/
    ├── menus/
    │   └── menu.ncl         # Navigation menu (bilingual)
    └── footer/
        └── footer.ncl       # Footer config (bilingual)

Example: Bilingual Menu (Before vs After)

Before (TOML - 130 lines across 2 files):

# en.toml
[[items]]
route = "/services"
label = "Services"

# es.toml
[[items]]
route = "/servicios"
label = "Servicios"

After (NCL - 115 lines, single file):

{
  items = [
    make_menu_item {
      routes = { en = "/services", es = "/servicios" },
      labels = { en = "Services", es = "Servicios" },
    },
  ]
}

Working with NCL Configs

Export to JSON:

nickel export --format json site/ui/menus/menu.ncl | jq '.'

Validate:

nickel typecheck site/ui/menus/menu.ncl

Auto-Detection: Build system automatically prefers .ncl files over .toml:

site/config/themes/dark.ncl  ✅ Used
site/config/themes/dark.toml ⏭️  Ignored (fallback)

Documentation

Metrics

Config Type Lines Duplication Reduced
Content-Kinds 29 ~60% less
Menus 115 100% (bilingual)
Footers 63 29% smaller
Themes 4 × 14 Variants from base

Total: ~140 lines of config + ~920 lines of reusable schemas


🔧 Configuration

Site Integration

# Links to site content structure
[content]
root_path = "../site"                    # Site content directory
public_path = "../site/public"           # Static assets
content_url = "/content"                  # Content API URL
types = ["blog", "recipes"]              # Available content types
languages = ["en", "es"]                 # Supported languages
default_language = "en"                  # Default language

🧪 PAP Compliance

Configuration-driven: All routes, themes, menus from NCL files with type-safety Language-agnostic: No hardcoded languages, bilingual single-source configs Custom routing: Uses Rustelo routing, NOT Leptos router Error handling: Proper Result<T, E> patterns, no unwrap() Modular design: Feature-based architecture with plugin system Type-safe configuration: Nickel contracts validate at compile-time No hardcoding: All paths and routes configurable Self-describing: Architecture tracked via on+re protocol — .ontology/ + adrs/

🔍 Architecture Self-Description (on+re)

This project implements the Ontoref on+re protocol. The .ontology/ and adrs/ directories provide a machine- and agent-readable description of the project's architecture, current state, and invariants as a Rustelo consumer (Service kind).

.ontology/ files

File Contents
core.ncl Knowledge graph: axioms (rustelo-consumer, bilingual-content), tensions (hydration complexity, build-time vs runtime), project nodes
state.ncl State dimensions: deployment-readiness (pre-production), hydration-stability (zero-mismatch), auth-system (operational), css-pipeline (correct)
gate.ncl Membranes: hydration-parity (Low permeability), content-integrity (Medium), rbac-correctness (Low)
manifest.ncl Service manifest: EndUser, Developer, Agent consumption modes; implementation, content, self-description layers

ADR System (adrs/)

ADR Decision
adr-001 NCL (Nickel) over TOML for site configuration
adr-002 SsrTranslator in both SSR and WASM targets for hydration parity — 4 hard constraints
adr-003 WebSocket broadcast for RBAC hot-reload without server restart

Browsing the architecture

# What this project is and how it can be consumed
nickel export .ontology/manifest.ncl

# Current state across all tracked dimensions
nickel export .ontology/state.ncl

# Active architecture constraints and gates
nickel export .ontology/gate.ncl

# Cross-project: browse Rustelo framework capabilities
# (rustelo-browse operational mode in manifest.ncl)
nickel export ../../rustelo/.ontology/core.ncl

📖 Documentation

  • Setup Guide: info/setup_from_rustelo_plan.md - Complete implementation journey
  • Enhancements: info/enhancements/ - Proposed improvements for Rustelo

📄 License

MIT License - Part of the Rustelo framework ecosystem.