Build#
This project uses the stable Rust toolchain (1.86 as of 5/31/25) and features a modern i18n system built on fluent-templates with unified template rendering.
Architecture Overview#
I18n System (fluent-templates)#
smokesignal uses fluent-templates for high-performance internationalization:
- Static Loading: Translations compiled into binary at build time
- Zero Runtime Overhead: No file I/O for translation loading
- Automatic Fallbacks: English fallback for missing translations
- Gender Support: Full French Canadian gender variant support
Template Rendering System#
Unified template rendering with automatic context enrichment:
- Centralized API: Single
TemplateRendererfor all template operations - Auto-Context: Automatic i18n, HTMX, and gender context injection
- Error Handling: Consistent error templates with context preservation
- Type Safety: Compile-time template context validation
Bare Metal#
If you're not using devcontainers, you'll need to install Rust and the necessary dependencies on your system.
Prerequisites#
- Rust toolchain (1.86 or newer)
- PostgreSQL
- Redis or Valkey
- SQLx CLI:
cargo install sqlx-cli@0.8.3 --no-default-features --features postgres
Common Commands#
- Build:
cargo build - Check:
cargo check - Lint:
cargo clippy - Run tests:
cargo test - Run server:
cargo run --bin smokesignal - Run with debug:
RUST_BACKTRACE=1 RUST_LOG=debug cargo run - Run database migrations:
sqlx migrate run
I18n-Specific Testing#
- All i18n tests:
cargo test i18n - Template tests:
cargo test template - Template helpers:
cargo test template_helpers - Middleware tests:
cargo test middleware_i18n - Template renderer:
cargo test template_renderer
Build Options#
- Build with embedded templates:
cargo build --bin smokesignal --no-default-features -F embed - Build with template reloading:
cargo build --bin smokesignal --no-default-features -F reload
Feature Flags#
embed: Compile templates into binary (production, smaller runtime footprint)reload: Enable template reloading (development, faster iteration)
Translation Validation#
The build process validates all translations at compile time:
# Validate all translations are accessible
cargo test fluent_loader
# Check translation completeness
cargo test i18n -- --nocapture
# Validate gender variants (French Canadian)
cargo test gender
Devcontainers (Recommended)#
The easiest way to get started is by using the provided devcontainer configuration with Visual Studio Code.
Setup#
- Install Visual Studio Code
- Install the Dev Containers extension
- Clone this repository
- Open the repository in VS Code
- When prompted, click "Reopen in Container" or run the "Dev Containers: Reopen in Container" command
The devcontainer will set up the following services:
- Rust development environment with all dependencies
- PostgreSQL database
- Valkey (Redis-compatible) key-value store
- Tailscale networking (optional)
Disabling Tailscale#
If you don't need the Tailscale service, you can disable it by:
- Open
.devcontainer/docker-compose.yml - Comment out or remove the
tailscaleservice section - Rebuild the devcontainer (Command Palette > "Dev Containers: Rebuild Container")
VS Code Configuration#
The devcontainer comes with recommended VS Code extensions for Rust development:
- Rust Analyzer
- Jinja HTML
- Even Better TOML
A launch configuration example is provided in .vscode/launch.example.json. Copy this to .vscode/launch.json to enable debugging in VS Code.
Development Configuration#
The application requires several environment variables for cryptographic operations. You can generate appropriate values using the included crypto binary.
Generating Cryptographic Keys#
Generate a random 64-byte key encoded in base64:
cargo run --bin crypto -- key
Generate a JWK (JSON Web Key):
cargo run --bin crypto -- jwk
The generated JWK should be added to a JWKS (JSON Web Key Set) in the file keys.json:
{
"keys": [
{ "kid": "01J7PM272ZF0DYZAPR3499VBTM" ...},
{ "kid": "01J8G3J3CDVJ15C63PMCDS3K97" ...},
{ "kid": "01JF2QS2S86SG2R23HTZ0JKB76" ...}
]
}
Environment Variables#
Set the following environment variables with values generated from the commands above:
SIGNING_KEYS: The path to thekeys.jsonfileOAUTH_ACTIVE_KEYS: A comma seperated list of JWK IDs used to actively sign OAuth sessionsDESTINATION_KEY: A JWK ID used to sign destination (used in redirects) valuesHTTP_COOKIE_KEY: A key used to encrypt HTTP sessions
You can add these to your .env file or set them directly in your environment.
Additional Configuration for Airgapped Development#
For airgapped development, you can configure:
PLC_HOSTNAME: Custom PLC hostname for developmentDNS_NAMESERVERS: Custom DNS nameserversADMIN_DIDS: Comma-separated list of admin DIDs
Example:
PLC_HOSTNAME=localhost:3000
DNS_NAMESERVERS=1.1.1.1,1.0.0.1
ADMIN_DIDS=did:plc:yourdevdid1,did:plc:yourdevdid2