README.md

August 6, 2026 · View on GitHub

spikard - polyglot web toolkit

One web toolkit, every language.

Codegen-first polyglot web toolkit. A Rust core plus 14 language bindings generated by alef — spec-driven codegen (OpenAPI, AsyncAPI, GraphQL, JSON-RPC, gRPC, and SQL→HTTP), type-safe routing, tower-http middleware, an MCP server for coding agents, and fixture-driven cross-language testing.

Rust core · Python · TypeScript · Ruby · PHP · Elixir · Go · Java · C# · Kotlin · Dart · Swift · Zig · WASM · C FFI

Install · Why spikard · Quick example · MCP server · Docs


Important

spikard is experimental and pre-1.0. APIs change between releases, and not every binding is at the same level of maturity. It is not yet recommended for production.

That is also the invitation: this is the point where feedback actually shapes the design. If you try it and something is wrong, awkward, or missing, please open an issue. If you want to help, good first issues are scoped to be finishable in an evening, and CONTRIBUTING.md explains the generated-bindings workflow.

Why spikard

CapabilityDetails
Type-safe across bindingsHTTP routing with path, query, body, and header validation. Errors convert losslessly between languages.
Polyglot bindingsPython, TypeScript/Node, Ruby, PHP, Elixir, Go, Java, C#, Kotlin, Dart, Swift, Zig, WASM, Rust, and C FFI.
Schema codegenParse OpenAPI 3.0, AsyncAPI 3.0, GraphQL SDL, and JSON-RPC 2.0 specs. Generate handlers and validators per binding.
SQL to HTTP codegenAnnotate SQL queries with @http GET /path, @http_auth bearer:jwt, and emit route metadata and OpenAPI specs.
Tower middlewareCompression, rate limiting, timeouts, request IDs, JWT/API-key auth, and static file serving.
Lifecycle hooksonRequest, preValidation, preHandler, onResponse, and onError.
WebSocket & SSEBidirectional streams and server-sent events.
Fixture-driven testingShared JSON fixtures drive tests across language bindings for behavioral consistency.
CLI & MCP serverInitialize projects, generate code, validate schemas, and integrate with MCP-compatible tools.

Installation

Each binding ships through its native package manager.

TargetPackageInstall
Rustspikard on crates.iocargo add spikard
CLIspikard-cli on crates.iocargo install spikard-cli or cargo binstall spikard-cli
Pythonspikard on PyPIpip install spikard
Node.js@spikard/node on npmnpm install @spikard/node
WASM@spikard/node-wasm on npmnpm install @spikard/node-wasm
Rubyspikard on RubyGemsgem install spikard
PHPgoldziher/spikard on Packagistcomposer require goldziher/spikard
Elixirspikard on HexAdd {:spikard, "~> 0.17"} to mix.exs
Gogithub.com/Goldziher/spikardgo get github.com/Goldziher/spikard
Javadev.spikard:spikard on Maven CentralMaven/Gradle — see Java README
C#Spikard on NuGetdotnet add package Spikard
Kotlindev.spikard:spikard on Maven CentralMaven/Gradle — see Kotlin README
Dartspikard on pub.devdart pub add spikard
SwiftSpikard via SwiftPMAdd to Package.swift
Zigspikard via build.zig.zonAdd to build manifest
C FFIspikard-ffi shared/static libraryGitHub Releases

Quick example

Python

from spikard import Spikard
from msgspec import Struct

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

app = Spikard()

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

if __name__ == "__main__":
    app.run(port=8000)

TypeScript

import { Spikard } from "@spikard/node";

const app = new Spikard();

app.get("/users/{id:int}", async (id: number) => {
  return { id, name: "Alice" };
});

app.run({ port: 8000 });
More examples (Ruby · PHP · Elixir · Go · Java · C# · Kotlin · Dart · Swift)

See the examples directory in the repository for working examples in every supported language.

MCP server

The CLI ships an MCP server so a coding agent can scaffold and generate spikard projects directly. It is enabled by default (spikard-cli feature mcp) and speaks stdio out of the box; streamable HTTP is available via the mcp-http feature.

{
  "mcpServers": {
    "spikard": {
      "command": "spikard",
      "args": ["mcp"]
    }
  }
}

Thirteen tools are exposed, covering project init, codegen from every supported spec format, the SQL→HTTP pipeline, AsyncAPI fixture and test-app generation, schema validation, and a feature summary. See the MCP documentation for the full tool list and worked flows.

SQL to HTTP

Annotate a SQL query and spikard emits the route, an OpenAPI 3.1 fragment, and a typed handler stub that calls into the generated query function:

-- @name GetUser
-- @returns :one
-- @http GET /users/{id}
-- @http_auth bearer:jwt
SELECT id, name, email FROM users WHERE id = \$1;

Query parsing and type inference come from scythe; spikard reads scythe's analyzed-query IR and overlays the HTTP vocabulary on top. scythe stays library-agnostic and owns no HTTP concepts. See the SQL codegen guide.

Architecture

All bindings call a shared Rust core through thin language-native layers:

How bindings work
Language bindings (Python, Node, Ruby, Go, Java, C#...)
        |
        v
FFI / NAPI / PyO3 / Magnus / runtime bridge
        |
        v
crates/spikard-http      Router, middleware, auth
crates/spikard-core      HTTP types, validation, errors
crates/spikard-codegen   OpenAPI, GraphQL, AsyncAPI, JSON-RPC

Bindings are generated from the Rust API surface via alef. Binding code stays thin: type conversion, error conversion, and runtime integration. Business logic, validation, middleware, and codegen all live in Rust.

Specification support
  • OpenAPI 3.0 — Route definitions to specs, parameter validators, Swagger/ReDoc UI
  • GraphQL — SDL schema parsing, query execution, introspection, Handler trait integration
  • AsyncAPI 3.0 — Channel/operation extraction, message validators, WebSocket integration
  • OpenRPC — JSON-RPC 2.0 method handlers, parameter validation, batch requests
Middleware stack

Compression (gzip/brotli), rate limiting, timeouts, request IDs, authentication (JWT/API key), static files. Configured via ServerConfig structs. All middleware is implemented in Rust via tower-http.

Development

task setup     # Install dependencies
task build     # Build Rust core (debug)
task test      # Run Rust tests
task test:all  # Run all tests (Rust + bindings)
task e2e:all   # Generate + build + run e2e tests
task format    # Format all code

Run task --list for the full task catalog.

Project status
  • Experimental and pre-1.0 — see the note at the top of this README. APIs change between releases.
  • Binding packages follow the Rust crate version.
  • E2E coverage is fixture-driven and shared across supported language targets.
  • See CONTRIBUTING.md for guidelines on modifying generated bindings.

License

MIT License — see LICENSE for details.