Files
axum-template/TEMPLATE_USAGE.md
2026-02-19 16:06:42 -05:00

6.2 KiB

Axum Template Usage Guide

This repository is a cargo-generate template for creating new Axum web services with a pre-configured, production-ready setup.

Quick Start

Prerequisites

Install cargo-generate:

cargo install cargo-generate

Generate a New Project

cargo generate --git https://gitea.fasharp.io/fa-sharp/axum-template

From Local Path (For Testing)

cargo generate --path /path/to/axum-template

Interactive Prompts

When you run cargo generate, you'll be prompted for:

  1. Project name: The name of your new project (e.g., my-api-server)
  2. Project description: Brief description (e.g., "REST API for user management")
  3. Environment variable prefix: Prefix for configuration env vars (e.g., APPAPP_HOST, APP_PORT)
  4. Default port: Server's default port (e.g., 8080)
  5. Default log level: Choose from trace, debug, info, warn, or error
  6. Include aide: Whether to include OpenAPI documentation support (true or false)

Non-Interactive Mode

You can skip prompts by providing values via CLI:

cargo generate --git <repo-url> \
  --name my-service \
  --define project-description="My awesome service" \
  --define env_prefix="API" \
  --define default_port="3000" \
  --define default_log_level="info" \
  --define include_aide=true

Generated Project Structure

my-project/
├── src/
│   ├── main.rs       # Application entry point with server setup
│   ├── lib.rs        # App initialization and plugin registration
│   ├── config.rs     # Configuration management (figment-based)
│   └── state.rs      # Application state management
├── Cargo.toml        # Dependencies (customized based on your choices)
├── .env.example      # Example environment variables
├── .gitignore        # Pre-configured for Rust projects
└── README.md         # Project-specific README

Configuration

The generated project uses environment variables for configuration. The prefix is customizable during generation.

Example with APP prefix:

# Required
APP_API_KEY=your-secret-api-key

# Optional (defaults are set during template generation)
APP_HOST=127.0.0.1
APP_PORT=8080
APP_LOG_LEVEL=info

In development, copy .env.example to .env:

cp .env.example .env
# Edit .env with your values

Features Included

Core Features (Always Included)

  • Axum 0.8 - Modern, ergonomic web framework
  • Environment-based Config - figment for flexible configuration
  • Structured Logging - tracing with JSON output in production
  • Graceful Shutdown - Handles SIGTERM, SIGINT, and Ctrl-C
  • Plugin Architecture - axum-app-wrapper for modular initialization
  • Rust 2024 Edition - Latest language features

Optional Features

  • OpenAPI Documentation - aide and schemars (optional during generation)

Next Steps After Generation

  1. Navigate to your project:

    cd my-project
    
  2. Configure environment:

    cp .env.example .env
    # Edit .env with your actual values
    
  3. Run in development:

    cargo run
    
  4. Add your routes:

    • Create a new module for your routes
    • Implement a plugin function
    • Register it in src/lib.rs
  5. Build for production:

    cargo build --release
    

Customization Tips

Adding Routes

Create a new module (e.g., src/routes.rs):

use axum::{routing::get, Router};
use axum_app_wrapper::AdHocPlugin;
use crate::state::AppState;

pub fn plugin() -> AdHocPlugin<AppState> {
    AdHocPlugin::new().on_router(|router| async move {
        let routes = Router::new()
            .route("/health", get(health_check));
        
        Ok(router.merge(routes))
    })
}

async fn health_check() -> &'static str {
    "OK"
}

Register it in src/lib.rs:

pub async fn create_app() -> anyhow::Result<(axum::Router, AppConfig, impl Future + Send)> {
    let (router, state, on_shutdown) = App::new()
        .register(config::plugin())
        .register(routes::plugin())  // Add this line
        .init()
        .await?;
    
    let app_config = state.config.to_owned();
    Ok((router.with_state(state), app_config, on_shutdown))
}

Adding Dependencies

Just edit Cargo.toml as normal:

cargo add sqlx --features postgres,runtime-tokio

Changing the Environment Prefix

The prefix is baked in during template generation. To change it later, search and replace in:

  • src/config.rs (the extract_config function)
  • .env.example

Publishing Your Template

GitHub

  1. Push this directory to GitHub
  2. Enable "Template repository" in Settings
  3. Others can use: cargo generate --git https://github.com/you/axum-template

GitLab/Gitea

  1. Push to your instance
  2. Share the URL: cargo generate --git https://gitea.example.com/you/axum-template

Private Repositories

cargo-generate supports authentication:

cargo generate --git https://github.com/you/private-template --branch main
# You'll be prompted for credentials if needed

Template Maintenance

Updating Dependencies

Update the versions in Cargo.toml.liquid and commit:

# Edit Cargo.toml.liquid
git add Cargo.toml.liquid
git commit -m "Update dependencies"
git push

Testing the Template

Generate a test project locally:

cargo generate --path . --name test-project --define include_aide=true
cd test-project
cargo check
cargo test

Troubleshooting

"Failed to parse Cargo.toml"

  • Make sure template syntax is on separate lines in .liquid files
  • Cargo-generate needs .liquid extension for files with Jinja2 syntax

Missing Imports in Generated Code

  • Check that Rust edition is set to 2024 in Cargo.toml.liquid
  • Edition 2024 includes Future in the prelude

Conditional Features Not Working

  • Use {% if variable %}...{% endif %} syntax
  • Keep conditionals on their own lines in TOML files
  • Test with both true and false values

License

Configure the license for your template as appropriate. The generated projects will inherit this license unless modified.