Skip to main content

Project Anatomy

A Forge project builds into a Rust binary with an optional embedded frontend.

Directory Structure

my-app/
├── forge.toml # Configuration
├── Cargo.toml # Rust dependencies
├── .env # Environment variables
├── sqlx.toml # sqlx offline-mode config

├── src/
│ ├── main.rs # Application entry point
│ ├── functions/ # Queries, mutations, jobs, workflows
│ │ ├── mod.rs
│ │ └── todos.rs
│ └── schema/ # Data models
│ ├── mod.rs
│ └── todo.rs

├── migrations/ # SQL migrations (numbered, run automatically)
│ └── 0001_todos.sql
├── .sqlx/ # Offline query cache generated by `forge migrate prepare`

└── frontend/ # Optional frontend target
├── src/
│ ├── routes/ # SvelteKit pages
│ ├── lib/
│ │ └── forge/ # SvelteKit bindings (`forge generate`)
│ └── forge/ # Dioxus bindings (`forge generate --target dioxus`)
├── package.json # Present for SvelteKit frontends
├── Cargo.toml # Present for Dioxus frontends
└── Dioxus.toml # Present for Dioxus frontends

forge new uses explicit template ids. Choose with-svelte/* for SvelteKit frontends and with-dioxus/* for Dioxus frontends.

Key Files

forge.toml

Runtime configuration. Environment variables expand at startup.

[project]
name = "my-app"

[database]
url = "${DATABASE_URL}"

[gateway]
port = 8080

src/functions/

Your backend logic. Each file can contain any combination of:

// Query - read data
#[forge::query(tables = ["todos"])]
pub async fn list_todos(ctx: &QueryContext) -> Result<Vec<Todo>> { ... }

// Mutation - write data
#[forge::mutation]
pub async fn create_todo(ctx: &MutationContext, input: CreateTodoInput) -> Result<Todo> { ... }

// Job - background work
#[forge::job]
pub async fn send_email(ctx: &JobContext, email: String) -> Result<()> { ... }

// Cron - scheduled tasks
#[forge::cron("0 9 * * *")]
pub async fn daily_report(ctx: &CronContext) -> Result<()> { ... }

// Workflow - durable multi-step processes
#[forge::workflow]
pub async fn onboarding(ctx: &WorkflowContext, user_id: Uuid) -> Result<()> { ... }

// Daemon - persistent services
#[forge::daemon]
pub async fn event_processor(ctx: &DaemonContext) -> Result<()> { ... }

// Webhook - incoming HTTP callbacks
#[forge::webhook(path = "/hooks/stripe")]
pub async fn stripe_webhook(ctx: &WebhookContext) -> Result<WebhookResult> { ... }

src/schema/

Data models with #[forge::model] generate frontend types automatically: TypeScript for SvelteKit targets and Rust types for Dioxus targets. The macro handles derive attributes internally, so place #[forge::model] before any #[derive(...)]:

#[forge::model]
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
pub struct Todo {
pub id: Uuid,
pub title: String,
pub completed: bool,
pub created_at: DateTime<Utc>,
}

migrations/

SQL files prefixed with numbers. Run automatically on startup with distributed locking.

-- @up
CREATE TABLE todos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title TEXT NOT NULL,
completed BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

SELECT forge_enable_reactivity('todos');

-- @down
SELECT forge_disable_reactivity('todos');
DROP TABLE IF EXISTS todos;

The forge_enable_reactivity() function sets up LISTEN/NOTIFY triggers for real-time subscriptions.

sqlx.toml and .sqlx/

Forge templates scaffold sqlx.toml with offline mode enabled so sqlx::query! and sqlx::query_as! can be checked without a live database in CI once the cache is prepared.

Refresh the cache after changing SQL or migrations:

forge migrate prepare

Generated frontend bindings

Run forge generate after adding or modifying functions.

// SvelteKit target: frontend/src/lib/forge
import { listTodos$, createTodo, updateTodo, deleteTodo } from "$lib/forge";
import type { Todo, CreateTodoInput } from "$lib/forge";
// Dioxus target: frontend/src/forge
use crate::forge::use_list_todos;
  • SvelteKit bindings are backed by the @forge-rs/svelte package.
  • Dioxus bindings are backed by the forge-dioxus crate.

Build Output

cargo build --release

Produces a single binary in target/release/my-app. Enable embedded-frontend feature to bundle the frontend build into the binary for single-artifact deployment.