diff --git a/TEMPLATE_USAGE.md b/TEMPLATE_USAGE.md new file mode 100644 index 0000000..b283ae8 --- /dev/null +++ b/TEMPLATE_USAGE.md @@ -0,0 +1,255 @@ +# 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`: + +```bash +cargo install cargo-generate +``` + +### Generate a New Project + +#### From a Git Repository (Recommended for Production Use) + +```bash +cargo generate --git https://gitea.fasharp.io/fa-sharp/axum-template +``` + +#### From Local Path (For Testing) + +```bash +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., `APP` → `APP_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: + +```bash +cargo generate --git \ + --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: + +```bash +# 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`: + +```bash +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**: + ```bash + cd my-project + ``` + +2. **Configure environment**: + ```bash + cp .env.example .env + # Edit .env with your actual values + ``` + +3. **Run in development**: + ```bash + 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**: + ```bash + cargo build --release + ``` + +## Customization Tips + +### Adding Routes + +Create a new module (e.g., `src/routes.rs`): + +```rust +use axum::{routing::get, Router}; +use axum_app_wrapper::AdHocPlugin; +use crate::state::AppState; + +pub fn plugin() -> AdHocPlugin { + 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`: + +```rust +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: + +```bash +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: + +```bash +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: + +```bash +# Edit Cargo.toml.liquid +git add Cargo.toml.liquid +git commit -m "Update dependencies" +git push +``` + +### Testing the Template + +Generate a test project locally: + +```bash +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.