Bragi
Bragi is a self-hosted CMS for blogs, personal sites, and resumes. Write in a visual editor, keep your content as Markdown, and manage multiple sites from one installation.
The editing interface and public website run as separate apps, sharing a SQLite database and attachment storage. Bragi is built with Python and Flask.
Try it locally · Deploy it · Documentation · Release notes
What you can do
- Publish posts, pages, and resumes. Schedule posts, preview draft changes, and restore earlier revisions. Organize pages into a navigation tree.
- Run several sites. Give each site its own hostname, theme, owner, and collaborators.
- Bring your content with you. Import from Hugo, Ghost, and WordPress, or use a LinkedIn data export to build a resume. Export your content as Markdown with attachments and redirects.
- Choose a look. Four built-in themes support light and dark mode. Install or build additional themes as Python packages.
- Make content discoverable. Sitemaps, Atom feeds, social previews, structured metadata, search, and redirects are included.
- Connect and extend. Use webmentions and ActivityPub, embed data tables and charts, or add features through plugins.
Bragi is intended for a single operator managing one or more sites. Each site has one language. It does not provide simultaneous collaborative editing or per-post translations.
Try it locally
You need Python 3.14+, uv, Git, and make. Run these commands in a fresh checkout:
git clone https://github.com/sgaduuw/bragi.git
cd bragi
uv sync
uv run bragi db upgrade
uv run bragi user create --email you@example.com --display-name "Your name" --superuser
uv run bragi site create --slug blog --hostname localhost --title "My blog" \
--canonical-url http://localhost:8002 --owner you@example.com
make dev
The user command prints a generated password. Use it to sign in, then change it when prompted.
- Open the admin at http://localhost:8001/ and sign in with the email above.
- Open your public site at http://localhost:8002/. Use
localhost, matching the hostname you created. - In the admin, open your site to create pages and posts. A new site starts with a welcome page; configure a post-index page to give posts public URLs.
make dev runs the admin, delivery app, and background tasks. This local
setup uses development defaults. Use the deployment guide for a public site.
Deploy it
The repository includes a Docker Compose example using published images from GitHub Container Registry. It runs the admin app, public delivery app, and a background task service against a shared data volume.
For production, pin an image release, keep a persistent secret key, configure a TLS reverse proxy, and back up the shared data. Follow the deployment and operations guide for configuration.
Bragi is also available on PyPI as bragi-cms. The Python import name
is bragi. See GitHub Releases
for published versions and the changelog for changes.
Documentation
| I want to… | Read |
|---|---|
| Learn about publishing, imports, exports, or datasets | Features and content tools |
| Configure deployment, integrations, limits, or backups | Deployment and operations |
| Recover a site or accidentally deleted media | Backup and recovery |
| Build or install a theme | Building a theme |
| Work on Bragi or run its checks | Development |
| Look up a configuration field or default | Settings reference |
| Report a bug or suggest a change | GitHub issues |
License
MIT.
Metadata
Release files for bragi-cms 1.54.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bragi_cms-1.54.1.tar.gz | 1.6 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bragi_cms-1.54.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.8 MB
Release files / bragi_cms-1.54.1.tar.gz
| Download URL | bragi_cms-1.54.1.tar.gz |
|---|---|
| Size | 1.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3116bdb9d9449f2268fd1c4e3d60600a02be543cb5bd65b9c66d931e86121e2d
|
|
BLAKE2b-256 checksum How to use checksums |
41e4d58f343299212106db25e395198ad905468d2696a73292032ec2afe0f9c0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logRelease files / bragi_cms-1.54.1-py3-none-any.whl
| Download URL | bragi_cms-1.54.1-py3-none-any.whl |
|---|---|
| Size | 1.1 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
653c78eaf7f77b905e6e484cca815d990dee652f16783e7015e5add1f6088489
|
|
BLAKE2b-256 checksum How to use checksums |
c51a7171f6de92b8f965989cc5a6259e790b031ab6213f6e8d7db2e8123f1ce9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency log