Rustelo/docs/howto/creating-a-site.md
Jesús Pérez 0d0297423e
Some checks failed
CI/CD Pipeline / Test Suite (push) Has been cancelled
CI/CD Pipeline / Security Audit (push) Has been cancelled
CI/CD Pipeline / Performance Benchmarks (push) Has been cancelled
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
CI/CD Pipeline / Build Docker Image (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Cleanup (push) Has been cancelled
chore: fix with CI and pre-commit
2026-02-08 20:37:49 +00:00

475 lines
13 KiB
Markdown

# Creating a Site with Rustelo Framework
This guide provides step-by-step instructions for creating a new website project using Rustelo as a framework dependency.
## 🎯 Overview
Rustelo follows a **framework-as-dependency** architecture, meaning you don't fork the framework - you use it as a library dependency in your own project. This ensures you can:
- ✅ Get framework updates automatically
- ✅ Keep your customizations separate from framework code
- ✅ Use the asset fallback system (Local → Framework → Generated)
- ✅ Avoid maintaining a fork
## 📋 Prerequisites
- Rust 1.70+ installed
- Node.js 18+ (for frontend assets)
- Just task runner: `cargo install just`
- Git (recommended for version control)
## 🚀 Step-by-Step Guide
### Step 1: Create Your Project Directory
```bash
# Create your site project
mkdir my-awesome-site
cd my-awesome-site
# Initialize git repository (optional but recommended)
git init
```
### Step 2: Create Cargo.toml
Create a `Cargo.toml` file with Rustelo dependencies:
```toml
[package]
name = "my-awesome-site"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <your.email@example.com>"]
description = "My awesome site built with Rustelo framework"
# Main binary
[[bin]]
name = "server"
path = "src/main.rs"
[dependencies]
# Core Rustelo framework dependencies
rustelo-core = { path = "../rustelo/crates/rustelo-core" }
rustelo-web = { path = "../rustelo/crates/rustelo-web" }
# Optional framework components (uncomment as needed)
# rustelo-auth = { path = "../rustelo/crates/rustelo-auth" }
# rustelo-content = { path = "../rustelo/crates/rustelo-content" }
# Web framework essentials
leptos = { version = "0.8.6", features = ["ssr"] }
leptos_axum = "0.8.5"
axum = "0.8.4"
tokio = { version = "1.47.1", features = ["rt-multi-thread", "signal"] }
tower = "0.5.2"
tower-http = { version = "0.6.6", features = ["fs"] }
# Basic utilities
tracing = "0.1"
tracing-subscriber = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
[features]
default = []
# Optional features (enable as needed)
# auth = ["rustelo-auth"]
# content = ["rustelo-content"]
# database = ["rustelo-core/database"]
[profile.release]
codegen-units = 1
lto = true
opt-level = 'z'
# Leptos configuration for development server
[[workspace.metadata.leptos]]
name = "my-awesome-site"
bin-package = "my-awesome-site"
bin-target-path = "src/main.rs"
lib-profile-release = "wasm-release"
```
### Step 3: Create Source Code Structure
```bash
# Create source directory
mkdir -p src
# Create basic directory structure
mkdir -p {content,assets,config,justfiles,public}
```
### Step 4: Create Main Application File
Create `src/main.rs`:
```rust
//! My Awesome Site - Built with Rustelo Framework
//!
//! This demonstrates using Rustelo as a framework dependency for a production site.
use axum::{
response::Html,
routing::get,
Router,
};
use rustelo_core::config::RusteloConfig;
use tower_http::services::ServeDir;
use tracing_subscriber;
/// Home page component
async fn home() -> Html<&'static str> {
Html(r#"
<!DOCTYPE html>
<html>
<head>
<title>My Awesome Site</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
line-height: 1.6;
}
.hero {
text-align: center;
padding: 4rem 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 1rem;
margin-bottom: 3rem;
}
.features { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; }
.feature {
background: #f8fafc;
padding: 2rem;
border-radius: 0.5rem;
border: 1px solid #e2e8f0;
}
.feature h3 { color: #2d3748; margin-top: 0; }
.footer {
text-align: center;
margin-top: 4rem;
padding-top: 2rem;
border-top: 1px solid #e2e8f0;
color: #718096;
}
</style>
</head>
<body>
<div class="hero">
<h1>🌟 My Awesome Site</h1>
<p>Built with Rustelo Framework-as-Dependency Architecture</p>
</div>
<div class="features">
<div class="feature">
<h3>🦀 Framework-as-Dependency</h3>
<p>Uses Rustelo as a library dependency, not a fork. Get framework updates automatically while keeping your customizations.</p>
</div>
<div class="feature">
<h3>📁 Asset Fallback System</h3>
<p>Local → Framework → Generated priority resolution. Override any framework asset with your local version.</p>
</div>
<div class="feature">
<h3>🔧 Modular Features</h3>
<p>Enable only the framework features you need: authentication, content management, database support, etc.</p>
</div>
<div class="feature">
<h3>🚀 Production Ready</h3>
<p>Built on Leptos + Axum with SSR, optimized builds, and cross-compilation support.</p>
</div>
</div>
<div class="footer">
<p><em>Powered by Rustelo Framework • <a href="/api/status">API Status</a></em></p>
</div>
</body>
</html>
"#)
}
/// About page
async fn about() -> Html<&'static str> {
Html(r#"
<!DOCTYPE html>
<html>
<head>
<title>About - My Awesome Site</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 2rem; }
.nav { margin-bottom: 2rem; }
.nav a { margin-right: 1rem; text-decoration: none; color: #2563eb; }
</style>
</head>
<body>
<div class="nav">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/api/status">API</a>
</div>
<h1>About My Awesome Site</h1>
<p>This site demonstrates the Rustelo framework-as-dependency architecture.</p>
<p>Key benefits:</p>
<ul>
<li>No source code forking required</li>
<li>Automatic framework updates</li>
<li>Local asset overrides</li>
<li>Modular feature system</li>
</ul>
</body>
</html>
"#)
}
/// API endpoint showing framework integration
async fn api_status() -> axum::Json<serde_json::Value> {
axum::Json(serde_json::json!({
"status": "ok",
"framework": "rustelo",
"architecture": "framework-as-dependency",
"features": {
"core": true,
"web": true,
"auth": false,
"content": false
},
"message": "🎉 Framework-as-dependency architecture working!"
}))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize logging
tracing_subscriber::fmt()
.with_target(false)
.init();
tracing::info!("🚀 Starting My Awesome Site...");
// Load framework configuration (with defaults if no config file exists)
let _config = RusteloConfig::load().unwrap_or_default();
tracing::info!("📋 Framework configuration loaded");
// Build application routes
let app = Router::new()
.route("/", get(home))
.route("/about", get(about))
.route("/api/status", get(api_status))
// Serve static files if they exist
.nest_service("/static", ServeDir::new("public"))
.nest_service("/assets", ServeDir::new("assets"))
.with_state(());
// Start server
let addr = "127.0.0.1:3030";
tracing::info!("🌐 Server starting at http://{}", addr);
tracing::info!("✨ Framework-as-dependency architecture active!");
let listener = tokio::net::TcpListener::bind(addr).await?;
axum::serve(listener, app).await?;
Ok(())
}
```
### Step 5: Create Framework Configuration (Optional)
Create `rustelo.toml` for framework configuration:
```toml
[framework]
name = "my-awesome-site"
version = "0.1.0"
description = "My awesome site built with Rustelo"
[assets]
# Asset resolution configuration
local_path = "assets"
framework_path = "../rustelo/assets"
organize_by_category = false
[server]
host = "127.0.0.1"
port = 3030
enable_tls = false
[features]
# Enable framework features as needed
auth = false
content = false
database = false
```
### Step 6: Create Justfile for Task Management
Create `justfile` with framework fallback pattern:
```just
# My Awesome Site - Task Runner with Framework Fallback
# Local tasks take priority, framework tasks as fallback
# Try to import local tasks, then framework tasks
mod? local-base 'justfiles/base.just' # Local base tasks
mod? base '../rustelo/justfiles/base.just' # Framework fallback
# Local development server
dev:
@echo "🚀 Starting development server..."
cargo run --bin server
# Local build
build mode="release":
@echo "🔨 Building for {{mode}} mode..."
@if [ "{{mode}}" = "release" ]; then \
cargo build --release; \
else \
cargo build; \
fi
# Local test
test:
@echo "🧪 Running tests..."
cargo test
# Local clean
clean:
@echo "🧹 Cleaning build artifacts..."
cargo clean
rm -rf target/
# Check code quality
check:
@echo "🔍 Checking code quality..."
cargo check
cargo clippy
cargo fmt --check
# Format code
fmt:
@echo "✨ Formatting code..."
cargo fmt
# Install dependencies
deps:
@echo "📦 Installing dependencies..."
cargo fetch
# Show available tasks
help:
@echo "Available tasks:"
@just --list
```
### Step 7: Create Local Justfile Tasks (Optional)
Create `justfiles/base.just` for site-specific tasks:
```just
# Local base tasks for My Awesome Site
# Custom deploy task
deploy:
@echo "🚀 Deploying My Awesome Site..."
just build release
# Add your deployment commands here
# Custom content tasks
content-update:
@echo "📝 Updating content..."
# Add content management commands here
# Custom asset processing
assets-build:
@echo "🎨 Processing assets..."
# Add asset processing commands here
```
### Step 8: Run Your Site
```bash
# Run development server
just dev
# Or run directly with cargo
cargo run --bin server
# Visit http://127.0.0.1:3030
```
## 🔧 Customization Options
### Enable Framework Features
Uncomment features in `Cargo.toml` as needed:
```toml
# Enable authentication
rustelo-auth = { path = "../rustelo/crates/rustelo-auth" }
# Enable content management
rustelo-content = { path = "../rustelo/crates/rustelo-content" }
[features]
auth = ["rustelo-auth"]
content = ["rustelo-content"]
database = ["rustelo-core/database"]
```
### Asset Fallback System
1. **Local Assets**: Place in `assets/` - highest priority
2. **Framework Assets**: Automatic fallback to framework assets
3. **Generated Assets**: Created by build system if needed
### Override Framework Justfile Tasks
Create `justfiles/base.just` with your custom tasks to override framework defaults.
## 📁 Final Project Structure
```
my-awesome-site/
├── Cargo.toml # Dependencies and configuration
├── rustelo.toml # Framework configuration (optional)
├── justfile # Task runner with framework fallback
├── src/
│ └── main.rs # Main application
├── justfiles/ # Local task overrides
│ └── base.just # Custom tasks
├── assets/ # Local assets (override framework)
├── content/ # Site content
├── config/ # Configuration files
├── public/ # Static public files
└── target/ # Build output
```
## 🚀 Next Steps
1. **Add Content**: Create pages in `src/` or use `rustelo-content` crate
2. **Style Your Site**: Add CSS in `assets/` or `public/`
3. **Enable Features**: Add authentication, database, etc.
4. **Deploy**: Use `just deploy` or your preferred deployment method
5. **Update Framework**: `cargo update` gets latest framework versions
## ✨ Benefits Achieved
-**No fork required** - Pure dependency usage
-**Framework updates** - Automatic via `cargo update`
-**Local customization** - Override any framework asset
-**Asset fallback** - Local → Framework → Generated
-**Modular features** - Enable only what you need
-**Production ready** - Optimized builds and deployment
This approach ensures you have a maintainable, updatable website that leverages the Rustelo framework without becoming dependent on a fork!