website-htmx-rustelo-code/README.md

357 lines
12 KiB
Markdown
Raw Permalink Normal View History

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
- macOS: `brew install nickel`
- Linux/Windows: `cargo install nickel-lang-cli`
- See [Nickel Installation Guide](../../docs/guides/nickel-installation.md)
- Site content in `../site/` directory
> **Note**: This project uses Nickel (NCL) for all configuration files (routes, themes, menus, content types). See [NCL Configuration](#-ncl-configuration) section below.
### Setup & Development
```bash
# Install dependencies
just setup
# Start development server with hot reload
just dev
# Build for production
just build-prod
```
### Development Commands
```bash
# 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**
```bash
cd crates/
cargo new --lib my-custom-plugin
```
**Step 2: Implement ResourceContributor**
```rust
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**
```rust
// 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
- **Quick Start**: See this README's "Creating Custom Plugins" section above
- **Complete Guide**: [Plugin Development Guide](../../.coder/info/PHASE3-PLUGIN-DEVELOPMENT-GUIDE.md)
- **Architecture**: [Rustelo Plugin Architecture](../../docs/architecture/rustelo-plugin-architecture.md)
- **Example Plugin**: `./crates/plugin-example-theme/README.md`
## 🎨 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):**
```toml
# en.toml
[[items]]
route = "/services"
label = "Services"
# es.toml
[[items]]
route = "/servicios"
label = "Servicios"
```
**After (NCL - 115 lines, single file):**
```nickel
{
items = [
make_menu_item {
routes = { en = "/services", es = "/servicios" },
labels = { en = "Services", es = "Servicios" },
},
]
}
```
### Working with NCL Configs
**Export to JSON:**
```bash
nickel export --format json site/ui/menus/menu.ncl | jq '.'
```
**Validate:**
```bash
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
- **Configuration Guide**: [../../docs/guides/nickel-configuration-guide.md](../../docs/guides/nickel-configuration-guide.md)
- **Installation**: [../../docs/guides/nickel-installation.md](../../docs/guides/nickel-installation.md)
- **ADR**: [../../docs/adr/0002-nickel-configuration-language.md](../../docs/adr/0002-nickel-configuration-language.md)
- **Implementation Summary**: [./.coder/info/summaries/2026-02-09-nickel-config-implementation-complete.md](./.coder/info/summaries/2026-02-09-nickel-config-implementation-complete.md)
### 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
```toml
# 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](https://github.com/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
```bash
# 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.