A production-ready template for building fullstack web applications with Dioxus (Rust fullstack framework) and SurrealDB (multi-model database). Perfect for quickly spinning up MVPs and proof-of-concepts.
- 🦀 Full Rust Stack - Type-safe from database to UI
- ⚡ Server Functions - RPC-style API endpoints with zero boilerplate
- 🎨 Component-Based UI - Reactive components with built-in state management
- 🗄️ SurrealDB Integration - Modern database with embedded (dev) and remote (prod) support
- 🛣️ File-Based Routing - Declarative routing with layouts
- 📦 Asset Pipeline - CSS/JS minification and bundling
- 🔄 Hot Reload - Fast development cycle
| Layer | Technology |
|---|---|
| Frontend | Dioxus (compiles to WebAssembly) |
| Backend | Dioxus Server Functions |
| Database | SurrealDB (RocksDB in dev) |
| Language | Rust (100%) |
- Rust (latest stable)
- Dioxus CLI:
cargo install dioxus-cli
- Click "Use this template" on GitHub
- Clone your new repository
- Follow setup steps below
git clone https://github.com/verystochastic/dioxus-surrealdb-template my-new-project
cd my-new-project
rm -rf .git
git init-
Rename your project in
Cargo.toml:[package] name = "my-new-project" # Change this version = "0.1.0" authors = ["Your Name <your.email@example.com>"]
-
Update app title in
Dioxus.toml:[web.app] title = "My New Project" # Change this
-
Install dependencies:
cargo build
-
Run development server:
dx serve --platform web
-
Open browser: http://localhost:8080
.
├── src/
│ ├── main.rs # App entry point + routing
│ ├── db.rs # Data models + database client
│ ├── server_functions.rs # API endpoints (server functions)
│ ├── components/ # Reusable UI components
│ │ ├── mod.rs
│ │ ├── idea_form.rs # Example: Form component
│ │ └── idea_list.rs # Example: Data-fetching component
│ └── views/ # Page-level components
│ ├── mod.rs
│ ├── home.rs # Home page
│ ├── navbar.rs # Layout wrapper
│ └── blog.rs # Example dynamic route
├── assets/
│ ├── favicon.ico
│ └── styling/
│ ├── main.css # Global styles
│ └── idea_form.css # Component-specific styles
├── Cargo.toml # Rust dependencies
├── Dioxus.toml # Dioxus configuration
└── ideas.db/ # Local database (gitignored)
Edit src/db.rs:
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct YourModel {
pub id: Option<String>,
pub field1: String,
pub field2: i32,
}Edit src/server_functions.rs:
#[post("/api/your-endpoint")]
pub async fn your_function(param: String) -> Result<YourModel> {
#[cfg(feature = "server")]
{
let db = get_db().await;
// Your database logic here
}
}Create in src/components/:
#[component]
pub fn YourComponent() -> Element {
rsx! {
div { "Your UI here" }
}
}Edit src/main.rs:
#[derive(Debug, Clone, Routable, PartialEq)]
enum Route {
#[layout(Navbar)]
#[route("/")]
Home {},
#[route("/your-route")]
YourPage {},
}dx serve --platform webHot reload enabled by default.
dx build --platform web --releaseOutputs to dist/ directory.
cargo testcargo fmtcargo clippyUses embedded RocksDB (file-based). Data stored in ideas.db/ directory.
To deploy with a networked database, update src/db.rs:
// Replace RocksDB connection with remote SurrealDB
use surrealdb::engine::remote::ws::{Client, Ws};
pub async fn get_db() -> &'static Surreal<Client> {
DB.get_or_init(|| async {
let db = Surreal::new::<Ws>(env::var("DATABASE_URL")?)
.await?;
db.signin(Root {
username: &env::var("DB_USER")?,
password: &env::var("DB_PASS")?,
}).await?;
db.use_ns("your_ns").use_db("your_db").await?;
db
}).await
}Update Cargo.toml:
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
surrealdb = { version = "2.1", features = ["protocol-ws"] }| Platform | Best For | Rust Support |
|---|---|---|
| Shuttle.rs | Rust-native apps | Native |
| Fly.io | Global edge | Docker |
| Railway | Simple deploys | Docker |
-
Install Shuttle CLI:
cargo install cargo-shuttle
-
Initialize:
cargo shuttle init
-
Deploy:
cargo shuttle deploy
-
Create
Dockerfile:FROM rust:1.75 as builder WORKDIR /app COPY . . RUN cargo build --release --features server,web FROM debian:bookworm-slim COPY --from=builder /app/target/release/your-app /usr/local/bin/ CMD ["your-app"]
-
Deploy:
fly launch fly deploy
This template includes a simple idea tracker as a reference implementation:
- Model:
Ideawith title, description, tags - Server Functions:
submit_idea_server(),get_all_ideas_server() - Components:
IdeaForm,IdeaList - Features:
- Form submission with validation
- Real-time list updates
- Tag parsing from comma-separated input
Feel free to delete and replace with your own implementation.
// Define once, call from client like a local async function
#[post("/api/endpoint")]
pub async fn my_function(param: String) -> Result<Data> {
// Server-only code
}
// Client usage
let data = my_function("test".to_string()).await?;// Local reactive state
let mut count = use_signal(|| 0);
// Update state
count.set(count() + 1);
// Read in JSX
rsx! { div { "{count}" } }// Parent
#[component]
fn Parent() -> Element {
let mut trigger = use_signal(|| 0);
rsx! {
Child { on_event: move |_| trigger += 1 }
}
}
// Child
#[component]
fn Child(on_event: EventHandler<()>) -> Element {
rsx! {
button { onclick: move |_| on_event.call(()), "Click" }
}
}- Create component in
src/views/my_page.rs - Add to
src/views/mod.rs:pub use my_page::MyPage; - Add route to
src/main.rs:#[route("/my-page")] MyPage {}
- Create in
src/components/my_component.rs - Export in
src/components/mod.rs:pub use my_component::MyComponent; - Use in any view:
MyComponent {}
- Create CSS file in
assets/styling/ - Import in component/view:
const MY_CSS: Asset = asset!("/assets/styling/my_styles.css"); rsx! { document::Link { rel: "stylesheet", href: MY_CSS } }
Stop all running instances: pkill -f december
Restart dev server: dx serve --platform web
Clear cache: cargo clean && dx serve
Kill process on 8080: lsof -ti:8080 | xargs kill -9
- Dioxus Documentation
- SurrealDB Documentation
- Rust Book
- This template's architecture guide (coming soon)
Found an issue or want to improve this template? PRs welcome!
MIT License - use freely for personal or commercial projects.
Happy Building! 🚀
For questions or feedback, open an issue on GitHub.