v0.1 — Now available on Composer

A microservices-first PHP framework for fast JSON APIs and internal systems.

Valhalla is a lightweight, opinionated PHP framework built for service-to-service communication, CLI scaffolding, JWT and API token auth, and local agent-style workers. No monolith. No boilerplate. Just the parts you need.

Install globally
$composer global require asyassin10/valhalla-framework
PHP
8.2+
Footprint
~300 KB
License
MIT
Valhalla
asyassin10/valhalla-framework
Lightweight PHP framework for service-oriented APIs
$valhalla new project orders-service# scaffold a new service
$cd orders-service
$composer install# install dependencies
$php -S 127.0.0.1:8080 -t public# start the dev server
GET /health
200 · 4ms
{
  "ok": true,
  "service": "orders",
  "uptime_ms": 1284
}
Why Valhalla

Built for the way modern teams actually ship services.

Valhalla focuses on the parts of a framework that matter for APIs, internal systems and small operational tools — and removes everything else.

Microservices-first architecture

Designed for small, focused services that do one thing well — not bloated monoliths.

API-first JSON responses

Every route returns structured JSON by default. No view layer, no template engine to fight.

Lightweight core

A minimal kernel with no hidden dependencies. Boots in milliseconds and stays out of your way.

CLI scaffolding

Generate projects, controllers, middleware and services from a single binary you already trust.

JWT and API token auth

First-class auth primitives with middleware-driven enforcement and zero-config defaults.

Service-to-service HTTP client

Talk to other Valhalla services with a typed client, retries, timeouts and tracing-ready headers.

Local agent workflow

Spin up long-running, MCP-style local agents for background tasks, scoring and summarization.

Readable project structure

An opinionated layout that maps cleanly to how engineers actually think about services.

Installation

From zero to a running service in four commands.

Valhalla ships as a single Composer package. Install it once globally, drop the binary on your PATH, and you're done.

  1. 01
    Install globally

    Pull Valhalla into your global Composer bin so the CLI is available system-wide.

  2. 02
    Expose Composer's bin on your PATH

    On macOS zsh, append the Composer bin directories so the valhalla command resolves.

  3. 03
    Verify the install

    Run the CLI without arguments to confirm Valhalla is wired up correctly.

  4. 04
    Create your first service

    Scaffold a fresh microservice and start building.

Already installed? Skip ahead to the CLI workflow or code examples.

$composer global require asyassin10/valhalla-framework# install Valhalla globally

Composer will pull the framework into your global vendor directory and link the valhalla binary.

CLI Workflow

A single binary for the entire service lifecycle.

The valhalla CLI scaffolds projects, generates components, runs migrations, builds containers, signs tokens and orchestrates local agents.

28 first-party commands

Project setup

Bootstrap a service and pull in dependencies. Fresh projects ship without an ORM — install one when you need it.

  • Create a new microservice with the standard src/ layout.
  • Install Composer dependencies for the current project.
$valhalla new project orders-service
$valhalla install

Routing & scaffolding

Generate the boring parts so you can focus on business logic.

  • Generate a controller in src/Controllers.
  • Add a middleware class wired into the pipeline.
  • Create a service-to-service HTTP client class.
$valhalla make:controller OrdersController
$valhalla make:middleware InternalAuth
$valhalla make:service BillingService

Auth & inspection

Issue tokens and audit your route table without leaving the terminal.

  • Print every registered route with its middleware stack.
  • Issue a signed JWT for user 1 using the configured secret.
$valhalla routes:list
$valhalla auth:generate 1 "Jane Doe"

ORM

Install one driver — Eloquent or Doctrine — then run migrations and generate models.

  • Wire up Eloquent and create src/Models.
  • Uninstall the current ORM driver cleanly.
  • Generate a model (Eloquent) or entity (Doctrine).
  • Create a new migration in database/migrations.
  • Run pending migrations against the configured database.
  • Roll back the most recent migration batch.
  • Doctrine: generate a diff migration from entity metadata.
$valhalla orm:install eloquent
$valhalla orm:remove
$valhalla make:model Order
$valhalla make:migration create_orders_table
$valhalla migrate
$valhalla migrate:rollback
$valhalla migrate:diff

Containers

Generate a Docker or Podman setup for your service in one command.

  • Scaffold docker/Dockerfile and docker-compose.yml.
  • Generate a podman-compose-based container stack.
  • Build container images for the current project.
  • Start the container stack in the background.
  • Tail logs from the running services.
  • Open an interactive shell inside the app container.
  • Stop and remove the container stack.
$valhalla install:docker
$valhalla install:podman
$valhalla build
$valhalla up
$valhalla logs
$valhalla shell
$valhalla down

Agents

Install, run and call long-running local TCP workers, MCP-style.

  • Register a new local agent on port 9501.
  • Boot the agent process and start listening for tasks.
  • Invoke an action on the running agent.
  • Shut down a running agent gracefully.
  • List installed agents, ports and process status.
  • Run all agents in the foreground (great for dev).
$valhalla agent:install summarizer 9501
$valhalla agent:start summarizer
$valhalla agent:call summarizer summarize
$valhalla agent:stop summarizer
$valhalla agent:list
$valhalla agent:serve

Runtime operations

Day-2 commands for queues and operational work.

  • Process queued jobs using the configured driver.
$valhalla queue:work
Code, not magic

The Route:: facade is the recommended style.

Valhalla supports closure routes, controller routes, route groups, route parameters, and PHP 8 attribute routes — all in plain, readable PHP.

<?php

use Valhalla\Framework\Facades\Route;
use Valhalla\Framework\Core\Request;
use Valhalla\Framework\Core\Response;
use App\Controllers\OrdersController;

// Closure routes
Route::get('/health', fn () => Response::json([
    'ok'      => true,
    'service' => 'orders',
]));

Route::get('/users/{id}', fn (Request $request) => Response::json([
    'id' => $request->route('id'),
]));

// Controller routes
Route::post('/orders', [OrdersController::class, 'store']);
Route::get('/orders/{id}', [OrdersController::class, 'show']);
Core features

Everything you need. Nothing you don't.

A small surface area, intentionally chosen. The pieces that matter for service-oriented PHP — and clean APIs for everything else.

Routing

A typed router that gets out of your way.

Closure-style or controller-bound routes, route groups with shared middleware, parameter constraints, and route-level naming for inspection.

  • Group middleware
  • Route parameters
  • Named routes
  • routes:list command
Authentication

JWT and API tokens, ready out of the box.

Sign tokens from the CLI, validate them through middleware, and protect entire route groups with a single line. Works for both end-user and service auth.

  • auth:generate CLI
  • JWT verification middleware
  • Per-service API tokens
  • Configurable secrets
Service mesh

Talk to other services without ceremony.

A small HTTP client purpose-built for internal calls — base URLs, bearer tokens, retries, timeouts and structured JSON responses with one fluent API.

  • Base URL config
  • Retry & timeout
  • Auth headers
  • JSON helpers
Local agents

Long-running PHP workers, MCP-style.

Install a local agent, expose actions, then call them from any service. Great for scoring, summarization, image analysis and other on-box tasks.

  • agent:install
  • agent:start
  • agent:call
  • Per-agent ports
Pluggable ORM

Pick the data layer that fits your service.

Valhalla ships with a pluggable ORM system. Install exactly one driver — Eloquent or Doctrine — and only that driver's directories appear in your project.

One driver per project

Eloquent

Active Record · illuminate/database

Install Eloquent for fluent, model-first development with classic up/down migrations.

Creates src/Modelsvalhalla orm:install eloquent
  • Built on illuminate/database
  • Generate models with valhalla make:model Order
  • Hand-written migrations via make:migration
  • Run with migrate · migrate:rollback
$valhalla orm:install eloquent# wire up Eloquent
$valhalla make:model Order
$valhalla make:migration create_orders_table
$valhalla migrate
$valhalla migrate:rollback# undo the last batch

Doctrine

Data Mapper · doctrine/orm

Install Doctrine for entity-driven design with diff-based migrations generated from your metadata.

Creates src/Entitiesvalhalla orm:install doctrine
  • Built on doctrine/orm and doctrine/migrations
  • Generate entities with valhalla make:model Invoice
  • Diff-based migrations from entity metadata
  • Run with migrate:diff · migrate · migrate:rollback
$valhalla orm:install doctrine# wire up Doctrine
$valhalla make:model Invoice
$valhalla migrate:diff# generate from entity metadata
$valhalla migrate
$valhalla migrate:rollback
i
Fresh projects ship without src/Models or src/Entities. The matching directory is created only when you install a driver.
i
config/orm.php controls the installed driver. config/database.php holds the connection settings.
Containers

Ship-ready Docker and Podman scaffolding.

Generate a production-shaped container setup for your service in one command. Pick PHP version, database, Redis, queue workers and exposed port — Valhalla writes the rest.

Docker · Podman

Container lifecycle

$valhalla install:docker# scaffold a Docker stack
$valhalla install:podman# or scaffold a Podman stack
$valhalla build# build images
$valhalla up# start the stack
$valhalla logs# tail service logs
$valhalla shell# open a shell in the app container
$valhalla down# stop and clean up

Generated files

  • docker/DockerfileMulti-stage PHP image
  • docker/docker-compose.ymlOr podman-compose.yml for Podman
  • docker/nginx/nginx.confProduction-ready vhost
  • docker/mysql/init.sqlGenerated when MySQL is selected
  • docker/.dockerignoreSensible defaults
  • config/container.phpContainer settings exposed to the app

Configurable at install

Runtime

  • PHP 8.2 or 8.3

Database

  • MySQL
  • PostgreSQL
  • No database

Cache & queues

  • Redis or no Redis
  • Queue worker yes/no

Networking

  • Configurable HTTP port

The generator targets either docker compose or podman compose, so the same project boots on either runtime without changes to your code.

Project structure

An opinionated src/layout you'll actually want to keep.

Controllers, middleware and services live under src/. Routes, config and migrations get their own top-level homes. New engineers can read a Valhalla service in minutes — not hours.

  • src/Controllers, Middleware, Services — your domain code.
  • routes/HTTP entrypoints, grouped by middleware concern.
  • config/Plain PHP arrays — auth, services, logging, agents, database.
  • database/Schema and migrations once an ORM driver is installed.

src/Models appears only for Eloquent installs. src/Entities appears only for Doctrine installs. Fresh projects ship with neither.

orders-service · tree
fresh project
orders-service/
├─ src/ # domain & framework code
│ ├─ Controllers/
│ │ ├─ OrdersController.php
│ │ └─ HealthController.php
│ ├─ Middleware/
│ │ ├─ InternalAuth.php
│ │ └─ RequestId.php
│ └─ Services/
│ └─ BillingService.php
├─ routes/
│ └─ api.php
├─ config/
│ ├─ auth.php
│ ├─ services.php
│ ├─ logging.php
│ ├─ agents.php
│ └─ database.php
├─ database/ # schema & migrations
│ └─ migrations/
├─ public/ # web entrypoint
│ └─ index.php
├─ composer.json
└─ .env.example