spikard - polyglot web toolkit

Spikard — Part of the spikard polyglot web toolkit.

Rust-centric polyglot HTTP framework with OpenAPI/AsyncAPI/GraphQL/JSON-RPC codegen, tower-http middleware, and fixture-driven cross-language testing. Ruby bindings via Magnus with idiomatic Ruby API.

Built with alef Rust Python Node.js WASM Ruby PHP Elixir Java Go C# Kotlin Dart Swift Zig C FFI Homebrew License GitHub Stars

Install · Quick example · Features · Docs


What this package provides

  • Magnus-backed native extension — Ruby 3.2+ with native performance for routing and validation

  • Type-safe routing — HTTP definitions with path, query, body, and header validation across all bindings

  • Spec-driven codegen — OpenAPI 3.0, AsyncAPI 3.0, GraphQL SDL, and JSON-RPC 2.0 support

  • Cross-language parity — same DTOs, fixtures, and error model prevent runtime drift

  • Tower middleware — compression, rate limiting, timeouts, auth (JWT/API key), static files

  • Lifecycle hooksonRequest, preValidation, preHandler, onResponse, onError

Installation

gem:

gem install spikard

Bundler:

gem 'spikard'

System Requirements

  • Ruby 3.2+ required

Quick example

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 })

Features

Feature Support
Type-safe routing Path, query, body, and header parameter validation
Request extraction Typed structs for JSON, form data, multipart, and raw bodies
Spec support OpenAPI 3.0 · AsyncAPI 3.0 · GraphQL SDL · JSON-RPC 2.0
Middleware Compression, rate limiting, timeouts, authentication, static files
Lifecycle hooks Request, pre-validation, pre-handler, response, and error hooks
WebSocket & SSE Bidirectional streams and server-sent events
Error handling Consistent error responses across all bindings via ProblemDetails
Fixture testing Shared JSON fixtures for behavioral consistency across languages
Routing
require "spikard"

app = Spikard::App.new

app.get("/health") { |_params, _query, _body| { status: "ok" } }
app.post("/users") { |_params, _query, body| body }
Validation
require "spikard"

PaymentSchema = Dry::Schema.Params do
  required(:id).filled(:string)
  required(:amount).filled(:float)
end

app = Spikard::App.new

app.post("/payments") do |_params, _query, body|
  PaymentSchema.call(body)
end
Middleware & configuration
require "spikard"

app = Spikard::App.new

app.on_request do |request|
  puts "#{request[:method]} #{request[:path]}"
  request
end

Resources

License

MIT License — see LICENSE for details.