Architecture of a Runique Project

Architecture of a Runique Project

A Runique project is a standard Rust binary crate. runique new generates the base structure, which you evolve as needed.

Project structure

my-project/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ entities/          # Model declarations
β”‚   β”‚   β”œβ”€β”€ users.rs       # Uses Runique AST for the makemigrations CLI
β”‚   β”‚   └── blog.rs        # CLI is not compatible with plain structs
β”‚   β”‚
β”‚   β”œβ”€β”€ formulaire/        # Form declarations
β”‚   β”‚   β”œβ”€β”€ inscription.rs # Using the form engine
β”‚   β”‚   └── blog.rs        # or proc-attribute macros
β”‚   β”‚
β”‚   β”œβ”€β”€ main.rs            # Entry point β€” RuniqueApp builder
β”‚   β”œβ”€β”€ admin.rs           # admin!{} declaration (if admin enabled, required for runique start)
β”‚   β”œβ”€β”€ urls.rs            # urlpatterns! β€” routing table
β”‚   β”œβ”€β”€ views.rs           # Handlers (async functions)
β”‚   └── forms.rs           # RuniqueForm structs (or forms/ folder)
β”‚
β”œβ”€β”€ templates/             # Tera templates (.html)
β”œβ”€β”€ static/                # Static files (CSS, JS, images)
β”‚   └── media/             # Uploads (FileField)
β”‚                          # media/ can be placed in another folder
β”‚
β”œβ”€β”€ migration/             # SeaORM migrations
β”‚   └── src/
β”‚       └── lib.rs
β”œβ”€β”€ .env                   # Environment variables
└── Cargo.toml

Role of each file

main.rs β€” Configures and starts the application via the builder:

#[macro_use]
extern crate runique;
use runique::prelude::*;

mod entities;
mod formulaire;
mod urls;
mod views;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = RuniqueConfig::from_env();
    let db_config = DatabaseConfig::from_env()?.min_connections(1).build();
    let db: DatabaseConnection = db_config.connect().await?;

    password_init(PasswordConfig::auto());

    RuniqueApp::builder(config)
        .routes(urls::routes())
        .with_database(db)
        .statics()
        .build()
        .await?
        .run()
        .await?;

    Ok(())
}

urls.rs β€” Declares routes via urlpatterns!:

use runique::prelude::*;
use crate::views;

pub fn routes() -> Router {
    urlpatterns! {
        "/" => view!{ views::index }, name = "index",
        "/register" => view!{ views::register }, name = "register",
    }
}

views.rs β€” Request handlers:

pub async fn index(mut request: Request) -> AppResult<Response> {
    context_update!(request => { "title" => "Home" });
    request.render("index.html")
}

formulaire/ β€” Typed forms:

pub struct RegisterForm { pub form: Forms }

impl RuniqueForm for RegisterForm {
    fn register_fields(form: &mut Forms) {
        form.field(&TextField::text("username").label("Username").required());
        form.field(&TextField::email("email").label("Email").required());
    }
    impl_form_access!();
}

admin.rs β€” Admin view declaration (files generated into src/admins/):

admin! {
    users: users::Model => RegisterForm {
        title: "Users",
        permissions: ["admin"],
    }
}

Starting a new project

runique new my-project
cd my-project
runique start

runique new generates the minimal structure above. What to edit and what to leave alone:

File / folderEdit?Role
src/main.rsYesConfigures the builder and declares modules
src/urls.rsYesRouting table
src/views.rsYesRequest handlers
src/entities/YesModel declarations (Runique AST, compatible with makemigrations)
src/formulaire/YesForms and validation
src/admin.rsYes (if admin)admin!{} declaration, required for runique start
src/admins/NoGenerated by the daemon β€” do not edit manually
templates/YesTera templates
static/YesCSS, JS, images
migration/No (unless adding tables)SeaORM migrations
.envYesEnvironment variables

runique start watches src/admin.rs and regenerates src/admins/ on every change. For apps without an admin view, cargo run is sufficient.


Framework internal structure

runique/src/
β”œβ”€β”€ app/                    # App Builder, Templates & Intelligent Builder
β”‚   β”œβ”€β”€ builder.rs          # RuniqueAppBuilder with slots
β”‚   β”œβ”€β”€ error_build.rs      # Build errors
β”‚   β”œβ”€β”€ templates.rs        # TemplateLoader (Tera)
β”‚   └── staging/            # Staging structs
β”‚       β”œβ”€β”€ core_staging.rs
β”‚       β”œβ”€β”€ middleware_staging.rs
β”‚       └── static_staging.rs
β”œβ”€β”€ config/                 # Configuration & Settings
β”œβ”€β”€ context/                # Request Context & Tera tools
β”‚   β”œβ”€β”€ request.rs          # Request struct (extractor)
β”‚   └── tera/               # Tera filters and functions
β”œβ”€β”€ db/                     # ORM & Database
β”œβ”€β”€ engine/                 # RuniqueEngine
β”œβ”€β”€ errors/                 # Error handling
β”œβ”€β”€ flash/                  # Flash messages
β”œβ”€β”€ forms/                  # Form system
β”œβ”€β”€ macros/                 # Utility macros
β”‚   β”œβ”€β”€ context_macro/      # context!, context_update!
β”‚   β”œβ”€β”€ flash_message/      # success!, error!, info!, warning!, flash_now!
β”‚   └── router/             # urlpatterns!, view!, impl_objects!
β”œβ”€β”€ middleware/             # Middleware (Security)
β”‚   └── security/           # CSRF, CSP, Host, Cache, Error Handler
β”œβ”€β”€ utils/                  # Utilities
β”œβ”€β”€ lib.rs
└── prelude.rs