Upgrading an existing app? Review Getting Started for module re-vendoring and the Live UI guide for channel subscription and reconnect behavior. Apps using the built-in request limiter must select one worker; see the multi-worker migration note.
A batteries-included web framework for Objective-C.
Arlen is a free, open-source web framework for Objective-C. It runs natively on
GNUstep (Linux, and Windows for development) and the Apple runtime (macOS). It's in the spirit of
Mojolicious and Rails: one coherent toolchain that takes you from
arlen new to a supervised production deployment. You don't have to assemble
an HTTP layer from a dozen unrelated libraries.
You get server-rendered HTML with compiled templates, JSON APIs with generated OpenAPI docs, a PostgreSQL-first data layer, and realtime WebSocket/SSE. Auth with passkeys and OIDC, admin and job dashboards, and a production process manager are first-party modules, not plugins you have to vet.
For outbound vendor APIs, the HTTP client supports both buffered requests and incremental responses, with cancellation, deadlines, host allowlists and byte limits.
The bundled tech demo (./bin/tech-demo): compiled
templates, route params, implicit JSON, and live fragments updating without a
page reload.
A controller that serves an HTML page and a JSON endpoint:
@implementation HomeController
// GET / — render an EOC template inside the app layout
- (id)index:(ALNContext *)ctx {
[self renderTemplate:@"home/index"
context:@{ @"title" : @"Hello, Arlen",
@"items" : @[ @"routing", @"templates", @"JSON" ] }
error:NULL];
return nil;
}
// GET /api/greet/:name — return a dictionary and Arlen renders JSON
- (id)greet:(ALNContext *)ctx {
return @{ @"hello" : [self stringParamForName:@"name"] ?: @"world" };
}
@end<%@ layout "layouts/main" %>
<h1><%= $title %></h1>
<ul>
<%@ render "partials/_item" collection:$items as:"item" %>
</ul>EOC templates (.html.eoc) compile to Objective-C at build time. Output is
HTML-escaped by default, and template errors report the file and line.
On Linux or macOS, paste this command into your terminal:
bash -o pipefail -c 'curl -fsSL https://github.com/danjboyd/Arlen/releases/latest/download/install.sh | bash -s -- --yes' && export PATH="$HOME/.local/bin:$PATH"The installer checks release checksums, sets up supported prerequisites, and
adds arlen to future shells. The final export makes it available in this
terminal too. Linux setup builds Arlen's pinned patched GNUstep runtime in a
versioned, fixed prefix using the distribution's ICU and clang. Normal GNUstep
client builds default to -O2, with explicit debug flags retaining control. The Ubuntu 26.04 lock
includes a pinned clang 21 compatibility patch; see
manual/offline setup.
--yes allows prerequisite installation; Linux may ask for your
sudo password. On macOS, install Apple's Command Line Tools and Homebrew first
if they are missing; the installer explains the required steps.
On Windows x64, paste this into PowerShell:
irm https://github.com/danjboyd/Arlen/releases/latest/download/install.ps1 | iexThe Windows installer provisions the matching managed GNUstep toolchain when
needed and adds arlen to the current shell and your user PATH.
| Platform | Installation support |
|---|---|
| Linux | Automatic setup on Debian 13 (amd64/arm64), Ubuntu 24.04 LTS (arm64/aarch64), and Ubuntu 26.04 LTS (amd64). Other systems need a manually provisioned clang-built GNUstep toolchain. |
| macOS | Apple Silicon, macOS 14 or later; Xcode Command Line Tools and Homebrew at /opt/homebrew. Prebuilt tools; full Xcode is needed for arlen test. Intel Macs are not supported. |
| Windows | x64 with PowerShell 5.1; managed MSYS2 CLANG64 toolchain. Native development is supported; deploy production apps to Linux or macOS. |
Then run arlen doctor and continue below. For version pinning, offline
archives, custom locations, or manual prerequisite setup, see
Linux installation,
macOS installation, or
Windows installation.
Upgrading existing apps? Re-vendor their modules and review
Storage migration and backups and
Notifications migration and backups
before replacing workers. Storage and notifications need the operating system
SQLite runtime (libsqlite3-0 on Linux).
arlen new MyApp
cd MyApp
arlen boomhauer --port 3000Open http://127.0.0.1:3000/. Then try /healthz and the interactive API
explorer at /openapi.
Every app serves its generated OpenAPI spec with a built-in
explorer at /openapi (shown here: examples/api_reference).
Next, add a route:
arlen generate endpoint Hello --route /hello --method GET --templatePrefer a single file? arlen new MyApp --lite puts the controller, routes, and
main() in one app_lite.m (see the Lite Mode Guide).
- First App Guide: the shortest walkthrough to a real app.
- Getting Started (Linux) · Getting Started (macOS) · Getting Started (Windows)
- Getting Started Tracks: HTML-first, API-first, or data-layer-first.
- App Authoring Guide: the long-form guide to building apps.
- EOC Template Guide · Modules · Deployment · API Reference
- Coming from another framework? See the guides for Rails, Django, Laravel, Express/NestJS, FastAPI, and Mojolicious.
The Docs Index organizes everything by what you're trying to do.
| HTTP and MVC | Routing with path params, controllers, middleware, sessions, CSRF, rate limiting, security headers, static files with caching and ranges, multipart uploads |
| Templates | EOC (.html.eoc) compiled to Objective-C: layouts, partials, collection rendering, forms, auto-escaping, file/line diagnostics; safe Markdown rendering (CommonMark + GFM) |
| JSON APIs | Implicit JSON from controller return values, OpenAPI generation, interactive API explorer, JSON-first scaffolds, generated TypeScript clients and validators |
| Auth | Passwords, TOTP MFA, recovery codes, passkeys/WebAuthn, OIDC login (including Microsoft Entra), OAuth resource server; headless, stock-UI, or ejected-UI modes |
| Data | PostgreSQL-first migrations, schema codegen, typed SQL builder, optional ORM, MSSQL preview, Dataverse client and codegen |
| Realtime | WebSocket, SSE, live HTML fragments with a built-in live.js, durable event streams with replay |
| Background work | Durable PostgreSQL jobs with transactional enqueue, fenced leases, and crash recovery |
| First-party modules | auth, admin-ui, jobs, notifications, storage, ops, search (PostgreSQL, Meilisearch, OpenSearch), plus an MCP server module |
| Tooling | arlen CLI for scaffolding, generators, and module management; arlen doctor; in-process ALNTestClient for app tests |
| Runtime and deploy | boomhauer dev server with rebuild-on-change; propane production manager with worker supervision and graceful reloads; arlen deploy with named targets over SSH |
Adding a module takes one command:
arlen module add auth && arlen module migrate --env developmentFor production auth email, add jobs, configure a PostgreSQL jobs adapter and
worker, and set authModule.publicBaseURL; see the
auth module guide.
- Native Objective-C, end to end. Your app is a compiled binary. You keep Foundation, ARC, and the language you already know, with no interpreter or VM underneath.
- One framework, not a parts list. HTML, JSON, auth, jobs, admin, search, realtime, and deployment are designed together and tested together.
- Explicit and deterministic. Routes are registered in code, templates compile to readable Objective-C, and generated code uses stable names. When something breaks, the diagnostics point at a file and a line.
- Free software. LGPL-2.1-or-later, the same license family as GNUstep Base. You can build proprietary apps on Arlen.
Arlen is probably not for you if you need a large third-party plugin ecosystem today, sandboxed or untrusted templates (EOC templates are trusted code), or a GCC-built GNUstep stack.
- Basic App: the smallest app.
- API-First Reference: JSON endpoints and OpenAPI.
- Auth + Admin Demo: composing the auth and admin modules.
- Multi-Module Demo:
admin-ui,search, andopstogether. - React/TypeScript Reference: generated TypeScript contracts with a React frontend.
- Tech Demo: the full tour, including live UI. Run
./bin/tech-demoand open http://127.0.0.1:3110/tech-demo.
More examples, covering the ORM, Dataverse, search, and GSWeb migration, live in examples/.
Arlen is young but no longer a sketch. The core framework, runtime, and all first-party modules ship and are covered by required Linux CI with sanitizer and docs lanes.
| Platform | Status |
|---|---|
| Linux, clang-built GNUstep | Production baseline. This is the authoritative target. |
| macOS, Apple runtime | Verified for development and production (propane, launchd deploys). See Apple Platform for the Linux-only test lanes. |
Windows, gnustep-cli CLANG64 |
Supported for development (install, arlen new, build, boomhauer). Production (propane, jobs-worker, service deploys) is planned for 0.4.0. See Windows CLANG64. |
The current release is v0.2.1. Arlen follows semantic versioning; while it
is on 0.x, minor releases may still change public API, with migration notes.
See Releases and
docs/RELEASE_NOTES.md. The capability-level
maturity snapshot (shipped, preview, in flight) is in
docs/STATUS.md. Engineering history lives under
docs/internal/.
Questions, ideas, and things you've built go in GitHub Discussions. Bugs go in Issues.
Contributions are welcome: bug reports, small reproductions, doc fixes, and focused patches. CONTRIBUTING.md covers toolchain setup, the test and quality targets, and PR conventions. Report security issues privately through SECURITY.md. This project follows a Code of Conduct.
Arlen and its tools are named after characters from King of the Hill:
boomhaueris the development server.propaneis the production manager. All of its settings are called "propane accessories."
Copyright (C) 2026 Daniel Boyd.
Arlen is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version (LGPL-2.1-or-later), the same license family as GNUstep Base. See LICENSE for the full text.
Contributor performance check: after building boomhauer, run
python3 tests/performance/persistent_http.py to check persistent-connection
HTTP and static-file throughput. See CONTRIBUTING.md.

