Skip to content

Quick Start

Build the same minimal service in each binding. Choose a tab, copy the snippet, and run.

Define routes

from spikard import App, ServerConfig
from msgspec import Struct

class User(Struct):
    id: int
    name: str

app = App()

@app.get_decorator("/users/{id:int}")
async def get_user(id: int) -> User:
    return User(id=id, name="Alice")

@app.post_decorator("/users")
async def create_user(user: User) -> User:
    return user

if __name__ == "__main__":
    app.config(ServerConfig(port=8000))
    app.run()
import { App, ServerConfig } from "@spikard/node";
import { z } from "zod";

const UserSchema = z.object({ id: z.number(), name: z.string() });
type User = z.infer<typeof UserSchema>;

const app = new App();

app.get("/users/:id", async (req) => {
  const id = Number(req.params["id"] ?? 0);
  return { id, name: "Alice" };
});

app.post("/users", async (req) => {
  const body = await req.json();
  return UserSchema.parse(body);
});

if (require.main === module) {
  app.config(new ServerConfig({ port: 8000 }));
  app.run();
}
require "spikard"

app = Spikard::App.new

app.get("/users/:id") do |params, _query, _body|
  { id: params[:id].to_i, name: "Alice" }
end

app.post("/users") do |_params, _query, body|
  user = body
  { id: user["id"], name: user["name"] }
end

app.run(config: { port: 8000 })
<?php

declare(strict_types=1);

use Spikard\App;
use Spikard\Attributes\Get;
use Spikard\Attributes\Post;
use Spikard\Config\ServerConfig;
use Spikard\Http\Request;
use Spikard\Http\Response;

final class UsersController
{
    #[Get('/users')]
    public function list(): Response
    {
        return Response::json([
            'users' => [
                ['id' => 1, 'name' => 'Alice'],
                ['id' => 2, 'name' => 'Bob'],
            ]
        ]);
    }

    #[Get('/users/{id}')]
    public function show(Request $request): Response
    {
        $userId = (int) $request->pathParams['id'];
        return Response::json(['id' => $userId, 'name' => 'Alice']);
    }

    #[Post('/users')]
    public function create(Request $request): Response
    {
        $user = $request->body;
        return Response::json($user, 201);
    }
}

$app = (new App(new ServerConfig(port: 8000)))
    ->registerController(new UsersController());

$app->run();
use axum::response::Json;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use spikard::{get, post, App, RequestContext};

#[derive(Serialize, Deserialize, JsonSchema)]
struct User {
    id: i64,
    name: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut app = App::new();

    app.route(get("/users/:id"), |ctx: RequestContext| async move {
        let id = ctx.path_param("id").unwrap_or("0").parse::<i64>().unwrap_or_default();
        Ok(Json(User { id, name: "Alice".into() }).into())
    })?;

    app.route(
        post("/users").request_body::<User>().response_body::<User>(),
        |ctx: RequestContext| async move {
            let user: User = ctx.json()?;
            Ok(Json(user).into())
        },
    )?;

    app.run().await?;
    Ok(())
}

Run it

python app.py

Then hit http://localhost:8000/users/1

pnpm ts-node app.ts

Then hit http://localhost:8000/users/1

ruby app.rb

Then hit http://localhost:8000/users/1

<?php

declare(strict_types=1);

use Spikard\App;
use Spikard\Attributes\Get;
use Spikard\Config\ServerConfig;
use Spikard\Http\Response;

final class HealthController
{
    #[Get('/health')]
    public function health(): Response
    {
        return Response::json(['status' => 'ok']);
    }
}

$config = ServerConfig::builder()
    ->withHost('0.0.0.0')
    ->withPort(8000)
    ->withWorkers(4)
    ->build();

$app = (new App($config))
    ->registerController(new HealthController());

$app->run();
cargo run

inside your crate/binary, then hit http://localhost:8000/users/1

Next steps

  • Add middleware (logging, auth, tracing) with the same signature in every binding.
  • Wire JSON Schema validation so request/response contracts stay enforced.
  • Deploy using the Rust binary, the CLI, or container images (see Deployment).

Edit this page on GitHub