357 lines
No EOL
12 KiB
Markdown
357 lines
No EOL
12 KiB
Markdown
# 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. |