Getting Started
Create an HTTP service with mik-sdk’s ergonomic macros and mik’s embedded runtime.
Prerequisites
Section titled “Prerequisites”- Rust 1.85+ with
wasm32-wasip2target - cargo-component for building WASM
- wac-cli for composition
# Add WASM targetrustup target add wasm32-wasip2
# Install toolscargo install cargo-componentcargo install wac-cliInstall mik CLI
Section titled “Install mik CLI”Quick install (recommended):
curl -fsSL https://raw.githubusercontent.com/dufeutech/mik/main/install.sh | bashirm https://raw.githubusercontent.com/dufeutech/mik/main/install.ps1 | iexThis downloads the latest release and sets up shell completions automatically.
Or via cargo:
cargo install mik
# Optional: enable tab completionsmik completions bash > ~/.local/share/bash-completion/completions/mik # bashmik completions zsh > ~/.zfunc/_mik # zshmik completions fish > ~/.config/fish/completions/mik.fish # fishQuick Start
Section titled “Quick Start”# Create projectmik new my-apicd my-api
# Build and run (dev mode with watch + services)mik build -rcmik devTest your API:
curl http://localhost:3000/run/my-api/Project Structure
Section titled “Project Structure”After running mik new my-api:
my-api/├── Cargo.toml # Component package├── mik.toml # Project config├── wit/│ ├── world.wit # WIT world definition│ └── deps/core/ # Core handler interface├── src/│ └── lib.rs # Handler implementation├── modules/ # Dependencies directory└── .gitignoreHandler Implementation
Section titled “Handler Implementation”The generated src/lib.rs:
#[allow(warnings)]mod bindings;
use bindings::exports::mik::core::handler::{self, Guest, Response};use mik_sdk::prelude::*;
routes! { GET "/" | "" => home, GET "/health" => health,}
fn home(_req: &Request) -> Response { ok!({ "service": "my-api", "message": "Hello from mik!" })}
fn health(_req: &Request) -> Response { ok!({ "status": "healthy" })}Extending Your Handler
Section titled “Extending Your Handler”Add more routes with typed path parameters and request bodies:
#[allow(warnings)]mod bindings;
use bindings::exports::mik::core::handler::{self, Guest, Response};use mik_sdk::prelude::*;
// ---- Typed path parameters ----#[derive(Path)]struct UserPath { id: u32,}
// ---- Typed request body ----#[derive(Type)]struct CreateUserRequest { name: String, email: Option<String>,}
// ---- Typed response ----#[derive(Type)]struct User { id: u32, name: String,}
// ---- Typed query parameters ----#[derive(Query)]struct ListQuery { #[field(default = 1)] page: u32, #[field(default = 10)] limit: u32,}
routes! { GET "/" | "" => home, GET "/health" => health, GET "/users" => list_users(query: ListQuery), POST "/users" => create_user(body: CreateUserRequest), GET "/users/{id}" => get_user(path: UserPath) -> User, DELETE "/users/{id}" => delete_user(path: UserPath),}
fn home(_req: &Request) -> Response { ok!({ "service": "my-api", "version": "0.1.0" })}
fn health(_req: &Request) -> Response { ok!({ "status": "healthy" })}
fn list_users(query: ListQuery, _req: &Request) -> Response { ok!({ "users": [ { "id": 1, "name": "Alice" }, { "id": 2, "name": "Bob" } ], "page": query.page, "limit": query.limit })}
fn create_user(body: CreateUserRequest, _req: &Request) -> Response { guard!(!body.name.is_empty(), 400, "Name is required");
created!("/users/3", { "id": 3, "name": body.name })}
fn get_user(path: UserPath, _req: &Request) -> Response { ok!({ "id": path.id, "name": "Alice" })}
fn delete_user(_path: UserPath, _req: &Request) -> Response { no_content!()}Build and Run
Section titled “Build and Run”Build Options
Section titled “Build Options”# Development buildmik build
# Release buildmik build -r
# Release + compose with bridgemik build -rcOutput: dist/my-api-composed.wasm
Run the Server
Section titled “Run the Server”# Development mode (watch + services)mik dev
# Or foreground mode (no services)mik runOutput:
Starting development server...
Services available at http://127.0.0.1:9919 KV: /kv/:key SQL: /sql/query, /sql/execute Storage: /storage/*path Cron: /cron
Watching for changes...Server: http://127.0.0.1:3000Test Your API
Section titled “Test Your API”# Built-in health checkcurl http://localhost:3000/health
# Your handler routes (all under /run/<module>/*)curl http://localhost:3000/run/my-api/curl http://localhost:3000/run/my-api/userscurl http://localhost:3000/run/my-api/users/1
# Create a usercurl -X POST http://localhost:3000/run/my-api/users \ -H "Content-Type: application/json" \ -d '{"name": "Charlie"}'Routing
Section titled “Routing”All handler routes use the /run/<module>/* pattern:
- Single component:
/run/<name>/*- name derived from filename (strips-composedsuffix) - Multi-module:
/run/<module>/*- modules loaded frommodules/directory
The mik-sdk Macros
Section titled “The mik-sdk Macros”Derive Macros
Section titled “Derive Macros”| Macro | Purpose |
|---|---|
#[derive(Type)] | JSON body/response with automatic parsing |
#[derive(Path)] | Typed URL path parameters ({id}) |
#[derive(Query)] | Typed query string parameters with defaults |
Response Macros
Section titled “Response Macros”| Macro | Purpose |
|---|---|
routes! | Define routes with typed inputs |
ok! | Return JSON with 200 |
created! | Return JSON with 201 and Location header |
no_content! | Return 204 No Content |
error! | Return error response |
guard! | Early return if condition fails |
ensure! | Unwrap Option/Result or return error |
Configuration (mik.toml)
Section titled “Configuration (mik.toml)”[project]name = "my-api"version = "0.1.0"
[server]port = 3000
[composition]http_handler = true # Auto-downloads bridgeNext Steps
Section titled “Next Steps”- Configuration - Full mik.toml reference
- Reliability - Circuit breaker, rate limiting
- Scripts - JavaScript orchestration
- mik-sdk - Full SDK documentation