About rust-fullstack
Rust Full-Stack Web Development Patterns is a skill for developers building web applications with Rust. It covers a Leptos frontend, Axum and SQLx backend, PostgreSQL, and patterns for authentication, state, API requests, and tenant routing.
Key features
- 01Leptos frontend with Tailwind CSS and DaisyUI
- 02Axum and SQLx backend patterns
- 03JWT access and refresh token flow
- 04Frontend state and TTL-based cache
- 05API retry handling and tenant routing
- 06PostgreSQL queries and enums
Use cases
- 01Structure a Rust full-stack web application
- 02Implement cookie-based JWT authentication
- 03Handle API rate limits and 401 retries
- 04Route requests by tenant subdomain
Install
Copy the command and run it in a terminal.
$
npx skills add https:/ / github.com/ daiki48/ dotfiles --skill rust-fullstackAfter installing, type/rust-fullstackin Claude Code to confirm it loaded.
Details
From the project READMERust Full-Stack Web Development Patterns
Tech Stack
| Layer | Tech |
|---|---|
| Frontend | Leptos (Rust→WASM CSR), Tailwind CSS + DaisyUI |
| Backend | Axum, SQLx (compile-time checked queries) |
| Database | PostgreSQL |
| Build | Trunk (WASM), Docker, Makefile |
JWT Dual-Token Auth
Access Token (short-lived) → API request auth
Refresh Token (long-lived) → Access token renewal
- Store in HTTP-only Cookie (XSS protection)
- Backend: Token validation
- Frontend: Auto-retry on 401
// Backend: Cookie setup
let cookie = format!(
"access_token={}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age={}",
token, 900 // 15 min
);
// Frontend: 401 retry
if response.status() == 401 {
refresh_token().await?;
// Retry original request
}
Frontend State Management
provide_context(AuthContext::new());
provide_context(AppCache::new()); // TTL-based cache
provide_context(ToastContext::new());
// localStorage for preferences
let stored = window().local_storage()?.get_item("preferences")?;
API Client Pattern
// Rate limiting (429) handling
async fn fetch_with_retry<T>(request: impl Fn() -> Future<T>) -> Result<T> {
loop {
match request().await {
Err(e) if e.status() == 429 => {
let delay = e.retry_after().unwrap_or(1000);
sleep(delay).await;
}
result => return result,
}
}
}
// Token refresh queue (prevent multiple refreshes)
static REFRESH_LOCK: OnceCell<RwLock<()>> = OnceCell::new();
Multi-tenant Routing
{tenant}.example.com → Tenant identification
fn extract_subdomain(host: &str) -> Option<String> {
let parts: Vec<&str> = host.split('.').collect();
(parts.len() >= 3).then(|| parts[0].to_string())
}
async fn check_tenant_access(claims: &Claims, subdomain: &str) -> Result<(), AppError> {
// Verify user has access to this tenant
}
Database
// SQLx compile-time query checking
let user = sqlx::query_as!(
User,
r#"SELECT id, name, role as "role: UserRole" FROM users WHERE id = $1"#,
id
).fetch_one(&pool).await?;
// PostgreSQL ENUMs
#[derive(sqlx::Type)]
#[sqlx(type_name = "user_role", rename_all = "PascalCase")]
pub enum UserRole { Admin, AreaManager, ServiceStation }
Common Commands
make dev # Start local environment
make fmt # Format (cargo fmt + leptosfmt)
make lint # Clippy checks
make test # Run tests
make migrate-run # Apply migrations
Dev Notes
| Item | Value |
|---|---|
| Backend port | 3000 |
| Local subdomain | lvh.me (resolves to 127.0.0.1) |
| Env files | .env.development, .env.staging, .env.production |
| Required env | DATABASE_URL, JWT_SECRET, APP_ENV |
Related Skills
leptos-guide- Leptos frontendaxum-guide- Axum backendsqlx-postgres- SQLx + PostgreSQL
Comments
Markdown supported