feather is a free, open source publishing project written in Swift and released under MIT. It has 607 GitHub stars, 54 forks and 29 open issues, and was last pushed 4 hours ago. On this registry it ranks #41 of 46 tracked projects in Publishing, with 5 head-to-head comparisons available.

What is feather?

Feather is a Swift-based content management system for developers and publishing teams who want to run a blog or content site on their own infrastructure rather than through a hosted service.

What it is

Feather is a self-hosted CMS written in Swift and built on Swift 6 with async/await concurrency. It lives in the Swift server ecosystem and ships as a set of cooperating services rather than as one monolith: a Postgres database, a migrator, backend workers, a web and admin app, a static asset server, and OpenAPI services. Content rendering uses Mustache templates, and the repository also carries an API layer for programmatic access. The project is distributed under the MIT licence and complemented by a hosted presence at feathercms.com.

The concrete problem it solves is wiring the pieces of a publishing stack together. Instead of assembling a database, a migration runner, background workers, a front end, a static file server, and outbound email separately, Feather defines them as one Compose stack with named Make targets for each combination. It also separates browser-facing origins from internal service addressing: WEB_PUBLIC_BASE_URL, STATIC_PUBLIC_BASE_URL, and MEDIA_PUBLIC_BASE_URL control public URLs, while API_BASE_URL stays internal for the web app to reach the backend. Media assets live in their own storage volume and are served by the backend on port 8080 by default.

Key capabilities

  • make application builds the shared application artifact image once, derives minimal runtime images from it, then runs dependencies, migrations, backend workers, the web app, the static server, and OpenAPI services.
  • make local runs PostgreSQL in Docker while running the migrator, backend server, worker, web app, and static server as local Swift processes, storing local media in .docker/media.
  • make local-backend starts PostgreSQL in Docker plus the migrator, backend server, and worker locally, without the web app or static server.
  • make local-app builds and runs only the local WebApp executable.
  • Public origin variables WEB_PUBLIC_BASE_URL, STATIC_PUBLIC_BASE_URL, and MEDIA_PUBLIC_BASE_URL drive browser-facing URLs, set to ports 3456, 4567, and 8080 by default.
  • The worker sends email through Amazon SES using SES_ID, SES_SECRET, and SES_REGION from a local .env file kept beside docker-compose.yaml.
  • make test runs the backend package tests and make test-all runs the backend plus every package under modules; make docker-up and make docker-down start and remove the PostgreSQL and certificate services those tests need.

Who uses it and how

  • Self-hosters running the full Compose stack on a single machine or server, using the default ports or overriding the three public origin variables.
  • Developers working locally who want Swift processes they can attach a debugger to, using make local or make local-app instead of a full container build.
  • Teams splitting front end from backend, running make local-backend so the migrator, server, and worker come up without the bundled web app.
  • Module authors running make test-all across the backend and every package under modules after starting the required PostgreSQL and certificate services.
  • LAN-based setups, where make all and make all-up try to detect the local network address for the web, static, and media origins and fall back to localhost if detection fails.

Getting started

Keep SES credentials in a .env file next to docker-compose.yaml, then start the services with docker compose up --build from the repository root, or use make all to build and run the full local stack.

How it compares

No comparable or competing tools are named in the facts provided for this entry, and no list of paid products it replaces is given, so it stands alone in this registry.

When to use it — and when not to

A self-hoster must operate PostgreSQL, a media storage volume, and Amazon SES credentials for outbound email, and on some Docker installations make fails with Cache export is not supported for the docker driver until containerd image storage is enabled in Docker Desktop. The README marks the project with a repeated "WORK IN PROGRESS" warning, so anyone wanting a stable, finished publishing platform should look elsewhere for now. The repository has 29 open issues against 607 stars and 54 forks, and the documentation provided omits setup steps beyond the Make targets and Docker Compose workflow.

project readme (upstream, from github) — read inline

Feather CMS 🪶

⚠️ ⚠️ ⚠️ !WORK IN PROGRESS! ⚠️ ⚠️ ⚠️

🪶 Feather is a modern Swift-based Content Management System.

💬 Click to join the chat on Discord.

Make Commands

Run these from the repository root:

  • make clean Clears only the Postgres database volume and media storage volume.
  • make reset Drops the full Compose stack, including all Compose-managed volumes.
  • make stop Stops all running services without removing them.
  • make deps Builds and runs the current dependency services: certificates, postgres, and migrator.
  • make application Builds the shared application artifact image once, builds the runtime images from it, and runs the application stack: dependencies, migrations, backend workers, web app, static server, and OpenAPI services.
  • make local Runs PostgreSQL in Docker and runs the migrator, backend server, worker, web app, and static server as local Swift processes. Local media is stored in .docker/media.
  • make local-app Builds and runs only the local WebApp executable.
  • make local-backend Runs PostgreSQL in Docker and runs the migrator, backend server, and worker locally, without starting the web app or static server.
  • make application-artifacts Compiles all application executables once and creates the local artifact image used by the runtime images.
  • make application-images Builds the artifact image and the separate minimal runtime images.
  • make all Builds and runs the full local stack. For the web app, this also sets browser-facing public origins for: WEB_PUBLIC_BASE_URL, STATIC_PUBLIC_BASE_URL, and MEDIA_PUBLIC_BASE_URL. By default, make all and make all-up try to detect the current LAN IP and use: http://:3456, http://:4567, and http://:8080. If LAN detection fails, Compose falls back to the localhost defaults. You can override any of them explicitly, for example: WEB_PUBLIC_BASE_URL=http://192.168.8.102:3456 STATIC_PUBLIC_BASE_URL=http://192.168.8.102:4567 MEDIA_PUBLIC_BASE_URL=http://192.168.8.102:8080 make all
  • make clean all Clears database and media storage, then builds and runs the full stack.
  • make clean application Clears database and media storage, then builds and runs the application stack.

Amazon SES Configuration

The worker sends email through Amazon SES. Keep credentials in a local .env file next to docker-compose.yaml; .env files are ignored by Git.

SES_ID=your-aws-access-key-id
SES_SECRET=your-aws-secret-access-key
SES_REGION=eu-central-1

Start the services with:

docker compose up --build

Module and Backend Tests

From the repository root, start all PostgreSQL and certificate services required by the module and backend tests:

make docker-up

Run tests from VS Code's Test Explorer, use make test for the backend package, or use make test-all for the backend and every package under modules. When finished, remove the test services, networks, and volumes with:

make docker-down

Docker BuildKit cache error

If make fails with Cache export is not supported for the docker driver, enable Use containerd for pulling and storing images in Docker Desktop Settings → General, then restart Docker Desktop and run make again.

Public Origin Variables

These variables control browser-facing URLs and are separate from the internal API_BASE_URL used by the web app to talk to the backend service.

  • WEB_PUBLIC_BASE_URL Public base URL for the web/admin app, for example http://localhost:3456.
  • STATIC_PUBLIC_BASE_URL Public base URL for static assets, for example http://localhost:4567.
  • MEDIA_PUBLIC_BASE_URL Public base URL for backend-served media assets, for example http://localhost:8080.

Compose defaults:

  • WEB_PUBLIC_BASE_URL=http://localhost:3456
  • STATIC_PUBLIC_BASE_URL=http://localhost:4567
  • MEDIA_PUBLIC_BASE_URL=http://localhost:8080

VS Code Workspace

When you open the FeatherCMS workspace folder in VS Code for the first time, it may open more slowly because "swift.searchSubfoldersForPackages": true searches for Swift packages in subfolders. This is expected.

VS Code Keybindings

You can add the FeatherCMS shortcuts to VS Code's keybindings.json file:

  1. Press Cmd+Shift+P to open the Command Palette.
  2. Search for and select Preferences: Open Keyboard Shortcuts (JSON).
  3. Add these entries inside the JSON array:
[
{
  "key": "cmd+ctrl+r",
  "command": "workbench.action.debug.selectandstart"
},
{
  "key": "cmd+ctrl+i",
  "command": "workbench.action.tasks.runTask",
  "args": "Ensure Local Dependencies"
},
{
  "key": "cmd+ctrl+.",
  "command": "workbench.action.debug.stop",
  "when": "inDebugMode"
},
{
  "key": "cmd+ctrl+s",
  "command": "workbench.action.tasks.runTask",
  "args": "FeatherCMS: Stop Local Runtime and Free Ports"
},
{
  "key": "cmd+ctrl+o",
  "command": "workbench.action.tasks.runTask",
  "args": "FeatherCMS: Open FeatherCMS"
}
]

Development Workflow

Before running the application, run Ensure Local Dependencies first. Run it only once per development session to avoid errors.

  • cmd+ctrl+i — Run Ensure Local Dependencies once per session.
  • cmd+ctrl+r — Select and start the debug session, such as Debug Server + Worker + WebApp + Static.
  • cmd+ctrl+o — Open FeatherCMS in the browser.
  • cmd+ctrl+. — Stop the debug session while in debug mode.
  • cmd+ctrl+s — Stop the FeatherCMS local runtime and free the ports for other applications. Run this when you finish the development session.

OpenAPI Generator

OpenAPI generators live in the owning module packages under modules/. Use make yaml to regenerate module contracts.

Frequently asked questions

Is feather free to use?

feather is open source under the MIT licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does feather do?

Feather is a modern Swift-based Content Management System.

What is feather written in?

feather is primarily written in Swift. Its source is publicly available at https://github.com/FeatherCMS/feather, and it has 607 GitHub stars.