spikard/spikard

High-performance PHP web framework with a Rust core. Build REST APIs, WebSockets, and SSE services with ext-php-rs bindings, async handlers, dependency injection, and lifecycle hooks.

Maintainers

Package info

github.com/Goldziher/spikard

Documentation

Language:Rust

pkg:composer/spikard/spikard

Statistics

Installs: 19

Dependents: 0

Suggesters: 0

Stars: 100

Open Issues: 1


README

Rust Python Node.js WASM Ruby PHP Elixir Java Go C# License Documentation

Rust-centric polyglot HTTP framework with type-safe routing, OpenAPI/AsyncAPI/GraphQL/JSON-RPC codegen, tower-http middleware, and fixture-driven cross-language testing. Single Rust core compiled to 15 languages via alef-generated bindings.

Powered by Rust. Native performance for HTTP routing, validation, and middleware. Write once, bind everywhere.

Key Features

  • Type-safe across all bindings – HTTP routing with path, query, body, and header validation. Errors convert losslessly between languages.
  • Polyglot bindings – 15 languages: Python, TypeScript/Node, Ruby, PHP, Elixir, Go, Java, C#, Kotlin, Dart, Gleam, Swift, Zig, WASM, C FFI. All generated from Rust API surface via alef.
  • Fixture-driven testing – Shared JSON fixtures drive tests across all language bindings for behavioral consistency.
  • Schema codegen – Parse OpenAPI 3.0, AsyncAPI 3.0, GraphQL SDL, and JSON-RPC 2.0 specs. Generate type-safe handlers and validators per binding.
  • Tower middleware – Compression (gzip/brotli), rate limiting, timeouts, request IDs, authentication (JWT/API key), static file serving.
  • Lifecycle hooksonRequest, preValidation, preHandler, onResponse, onError. Execute in order with zero overhead when unregistered.
  • WebSocket, SSE, background tasks – Real-time bidirectional and server-sent event streams. Fire-and-forget background job support.
  • CLI and MCP server – Initialize projects, generate code, validate schemas. MCP-compatible for IDE integration.

Installation

Each language binding is available through its native package manager. Full installation guides with system requirements are provided per binding:

Scripting Languages:

  • Python – PyPI/spikard, async/await support, type stubs
  • Ruby – RubyGems/spikard, idiomatic Ruby API
  • PHP – Composer/spikard, PHP 8.2+ native extension
  • Elixir – Hex/spikard, OTP integration via NIFs

JavaScript/TypeScript:

  • Node.js – npm/@spikard/node, NAPI-RS native bindings
  • WASM – npm/@spikard/wasm, browser/Deno/Cloudflare Workers

Compiled Languages:

  • Go – go.mod github.com/Goldziher/spikard/packages/go, FFI bindings
  • Java – Maven Central/dev.spikard:spikard, Foreign Function & Memory API
  • C# – NuGet/Spikard, .NET 6.0+ with async/await

Native:

  • Rust – crates.io/spikard, core library, feature flags
  • C (FFI) – cbindgen headers + shared library, pkg-config/CMake support

Additional Targets:

  • Kotlin – Maven Central/dev.spikard:spikard
  • Dart – pub.dev/spikard
  • Gleam – Hex/spikard_gleam
  • Swift – SwiftPM or Cocoapods
  • Zig – build.zig.zon dependency

Quick Start

Python:

from spikard import Spikard
from spikard.config import ServerConfig
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")

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

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

TypeScript/Node.js:

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

interface User {
  id: number;
  name: string;
}

const app = new Spikard();

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

app.post("/users", async (user: User): Promise<User> => {
  return user;
});

const config = new ServerConfig({ port: 8000 });
app.run(config);

Architecture

All language bindings call through a thin FFI to the shared Rust core:

┌─────────────────────────────────────────────────────┐
│ Language Bindings (Python, Ruby, Node, Go, Java ...) │
│ Type conversion, async runtime integration         │
└────────────────┬────────────────────────────────────┘
                 │ FFI / NAPI / PyO3 / Magnus
                 ↓
    ┌────────────────────────────────┐
    │ crates/spikard-http            │
    │ Router, middleware, auth       │
    └────────────────┬───────────────┘
                     │
    ┌────────────────↓───────────────┐
    │ crates/spikard-core            │
    │ HTTP types, validation, errors │
    └────────────────┬───────────────┘
                     │
    ┌────────────────↓───────────────┐
    │ crates/spikard-codegen         │
    │ OpenAPI, GraphQL, AsyncAPI     │
    └────────────────────────────────┘

Bindings are auto-generated from the Rust API surface via alef. No hand-written FFI glue — just type and error conversion at language boundaries.

Development

Install Rust 1.x and Node 18+ (for running alef). Use the task command runner:

# Setup: install dependencies + alef + pre-commit hooks
task setup

# Build: compile Rust core + all bindings
task build

# Test: run all test suites (Rust core + language-specific)
task test

# E2E: generate + run cross-language tests from fixtures
task test:e2e

# Lint: run clippy, ruff, biome, rubocop, phpstan, etc. via pre-commit
task lint

# Format: run cargo fmt + alef format
task format

Full task list: task --list

Project Status

Phase 1-2 Complete:

  • Rust core (HTTP router, middleware, validation, auth)
  • Polyglot bindings for 15 languages via alef code generation
  • OpenAPI 3.0, AsyncAPI 3.0, GraphQL SDL, JSON-RPC 2.0 codegen

E2E Testing In Progress:

  • Rust and Node.js: 410 fixtures, all green
  • Python, Ruby, PHP, Elixir, Go, Java, C#: generators ready, tests being filled in
  • All tests powered by shared JSON fixtures for consistent behavior across languages

Stability: Rust core is stable (0.14.0). Language bindings follow Rust versioning; pre-release versions are in active development pending full e2e coverage.

Contributing

Contributions welcome. See CONTRIBUTING.md for guidelines — start with issues marked good-first-issue or help-wanted.

Code must pass task lint + task test before submission. No modifications to generated code under e2e/; instead, update fixtures or generator source and regenerate.

License

MIT License — see LICENSE for details.