Skip to main content

Almasix

Laravel's application shape, in async Python.

A full-stack web framework on FastAPI and Starlette — routing, validation, an ORM, a view engine, auth, queues, mail, cache, events, a scheduler, and a first-class CLI — arranged the way Laravel arranges them, and asynchronous all the way down.

PyPI downloads CI coverage tests python docs license

Why Almasix

Python has excellent HTTP libraries and very few opinions about what an application looks like. Almasix supplies the opinions. It takes the conventions that make a Laravel codebase legible on first read — the directory layout, service providers, facades, fluent builders, Route groups, Eloquent-style models, Blade-style templates, Artisan-style commands — and implements them in modern Python. Requests, the ORM, queue workers, and the scheduler all run on asyncio, and the FastAPI application underneath is never taken away from you.

It is a parity project, not an homage. Each area of the framework is built against the corresponding page of Laravel's documentation, method by method, and every deliberate divergence is named in Almasix's own page for that feature — so Str, Collection, the query builder, and the scheduler behave the way your muscle memory expects, while async/await, type hints, context managers, and dataclasses are used where Python has the better answer.

Piece What it is
Almasix (almasix) the framework
almasix new the application installer
Smith (smith …) the in-app CLI — smith serve, smith make:model, smith queue:work, smith loupe
Prism (almasix.prism) the view engine — .prism.html templates, directives, components, stacks
Articulate (almasix.orm) the ORM — models, relationships, migrations, pagination, on SQLAlchemy Core

A tour in five files

Routes are declarative and grouped, controllers are plain classes, and route names and middleware sit where you'd look for them:

# routes/web.py
from app.http.controllers.post_controller import PostController
from almasix.routing import Route

with Route.group(middleware=["web"]):
    Route.get("/posts", [PostController, "index"], name="posts.index")
    Route.get("/posts/{post}", [PostController, "show"], name="posts.show")

Models carry their own casts, scopes, and relationships:

# app/models/post.py
from app.models.user import User
from almasix.orm import Model, SoftDeletes, relation


class Post(SoftDeletes, Model):
    fillable = ("title", "body", "published")
    casts = {"published": "bool", "published_at": "datetime"}

    def scope_published(query):
        return query.where("published", True)

    @relation
    def author(self):
        return self.belongs_to(User)

Controllers read like their Laravel counterparts, with await at the edges:

# app/http/controllers/post_controller.py
from app.models.post import Post
from almasix.prism import view
from almasix.http import Controller


class PostController(Controller):
    async def index(self):
        posts = await Post.query().published().with_("author").latest().get()
        return view("posts.index", {"posts": posts})

Templates are Prism — Blade's directives, compiled to Python:

{{-- resources/views/posts/index.prism.html --}}
@extends('layouts.app')

@section('content')
  @foreach(posts as post)
    <article>
      <h2>{{ post.title }}</h2>
      <p>by {{ post.author.name }} — {{ post.created_at }}</p>
    </article>
  @endforeach
@endsection

Console commands and scheduled work are declared together, and run under smith:

# routes/console.py
from almasix.console import Artisan, schedule


def send_digest(command) -> int:
    command.info("digest sent")
    return 0


Artisan.command("digest:send", send_digest).purpose("Mail yesterday's digest")

schedule.command("digest:send").daily_at("07:00").timezone("Africa/Nairobi").without_overlapping()
schedule.command("model:prune").daily().on_one_server()

Getting started

Create an application

python -m venv .venv && source .venv/bin/activate
pip install almasix

almasix new blog
cd blog
pip install -e .        # the framework requirement is already satisfied
smith serve             # or: python smith serve

almasix new writes a complete application: app/, bootstrap/, config/, routes/, resources/views with error pages, database/migrations, storage/, a Vite config, and a root smith script. Installing the application (pip install -e .) puts smith on your PATH inside that project's environment; python smith … runs the root script without any install step. Installing the framework itself only gives you the global almasix command.

Work on the framework

git clone https://github.com/almasix-dev/almasix.git && cd almasix
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

make test          # full unit + smoke suite
make test-cov      # the same, with the coverage gate
make lint          # ruff
make docs          # the documentation site, locally

What ships today

The framework is built in milestones, each closed against a Laravel documentation page. Closed today:

  • The basics — routing and route groups, controllers, middleware and aliases, requests and responses, session, CSRF, validation with form requests, URL generation, error handling and the debug page, logging, asset bundling.
  • Prism views — layouts and sections, includes, control directives, components and slots, stacks, and a dd() dump page.
  • Articulate ORM — models with casts and serialization, the whole relationship surface, eager loading, soft deletes, pruning, migrations, seeding, pagination, and streaming reads through lazy collections.
  • Digging deeper — the Smith console with prompts and closure commands, the task scheduler (frequencies, constraints, hooks, sub-minute tasks), cache, Redis, queues and workers, mail, notifications, events, the filesystem, collections, helpers and Str, the HTTP client, localization, and encryption.
  • Security — authentication guards and providers, hashing, gates and policies, email verification, password confirmation and resets.

Every closed milestone ships four things: the implementation, tests, a documentation page, and a runnable demonstration in the living example app.

Documentation

website/ holds 54 pages of application-developer documentation (Astro Starlight), written to follow Laravel's structure page for page — including a section per method for collections, strings, and helpers. Read it at almasix-dev.github.io/almasix, or run make docs for a local copy at http://localhost:4321.

examples/progress is the living example — a real Almasix application that demonstrates each closed milestone through routes you can visit and smith progress:* commands you can run. Its /progress page is the project's milestone board.

How the project is built

docs/PLAN.md is the binding architecture and milestone document: 51 milestones, each mapped to the Laravel documentation it must match, with the parity audit and the named deviations recorded in place. docs/SMOKE.md records the exit criteria that close a milestone.

The gates are enforced in CI on Python 3.11, 3.12, and 3.13:

Gate Command
Milestone smoke tests make smoke
Contract regressions make regression
Full suite, coverage ≥ 98% (aim 100%) make test-cov

make lint runs ruff locally but is not a CI gate yet, and does not pass — choosing a rule set and clearing the backlog is M51.

Currently 1,886 tests at 99.38% coverage.

Status

25 of 51 milestones closed. M5 (Articulate ORM) and M30 (Smith console exhaust) are deliberately partial, with the remainder scheduled. Next up: M42 — query builder and database exhaust.

Repository layout

src/almasix/
  framework/     # Application, container, providers, bootstrap
  config/        # env + config repository
  http/          # kernel, request, response, middleware
  routing/       # Route DSL → FastAPI bridge
  validation/    # form requests, rules, messages
  orm/           # Articulate — models, relations, builder, migrations
  prism/      # Prism views — compiler, directives, components
  auth/          # guards, providers, gates and policies
  console/       # Smith commands, prompts, scheduler, loupe
  queue/         # jobs, dispatcher, workers, failed jobs
  cache/         # cache repository and stores
  mail/          # mailables and transports
  notifications/ # channels and notifiables
  events/        # dispatcher, listeners, subscribers
  filesystem/    # Storage disks
  client/        # HTTP client
  support/       # collections, helpers, Str, Number
  translation/   # __(), trans_choice(), locales
  installer/     # almasix new
  smith/         # the smith CLI
docs/            # PLAN.md, SMOKE.md — the binding project documents
website/         # the documentation site (Astro Starlight)
examples/        # the living example application
tests/           # unit, smoke, and regression suites
smith            # root script → the same CLI as `smith`

Contributing

Read docs/PLAN.md first — it is the source of truth for what belongs where and what parity means for the area you are touching. Work in milestone order, keep the coverage gate green, add the documentation page alongside the code, and extend examples/progress so the new surface can be demonstrated, not just claimed.

License

MIT © Almasix Contributors

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

almasix-0.2.0.tar.gz (731.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

almasix-0.2.0-py3-none-any.whl (483.5 kB view details)

Uploaded Python 3

File details

Details for the file almasix-0.2.0.tar.gz.

File metadata

  • Download URL: almasix-0.2.0.tar.gz
  • Upload date:
  • Size: 731.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for almasix-0.2.0.tar.gz
Algorithm Hash digest
SHA256 e3da2a822a8ef3d71a745250ef11dc1249e20e26c7d13460bdf5125da6c1f079
MD5 0cfd8f79c26c182b722f686f56c2143d
BLAKE2b-256 ab88f00164db14f91c2e7996b0551c4f48f15a64143fc2c42b8c705bcc7d8766

See more details on using hashes here.

Provenance

The following attestation bundles were made for almasix-0.2.0.tar.gz:

Publisher: publish.yml on almasix-dev/almasix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file almasix-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: almasix-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 483.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for almasix-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fd356c0c2c68ad2d52c43e3af68b462ade1fb406901844778612966c0a96becb
MD5 4b28775560dad20d73b833f1f0b619e3
BLAKE2b-256 8d5e498fe30bc390f2b01daa174476bf4899a54713caeba1bfcfc547d8f49558

See more details on using hashes here.

Provenance

The following attestation bundles were made for almasix-0.2.0-py3-none-any.whl:

Publisher: publish.yml on almasix-dev/almasix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page