A fork of writefreely, in order to add features I'd like.
  • JavaScript 84.2%
  • Go 10.2%
  • Go Template 3.8%
  • Less 1%
  • Python 0.6%
  • Other 0.1%
Find a file
loweel 9c38fa4280
All checks were successful
continuous-integration/drone/push Build is passing
Center footer and show pinned posts
2026-06-13 18:34:07 +02:00
.github Initial Blogfrei import 2026-06-12 23:34:46 +02:00
appstats Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
author Initial Blogfrei import 2026-06-12 23:34:46 +02:00
cmd/writefreely Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
config Polish the default public theme 2026-06-13 18:14:45 +02:00
db Initial Blogfrei import 2026-06-12 23:34:46 +02:00
key Initial Blogfrei import 2026-06-12 23:34:46 +02:00
keys Initial Blogfrei import 2026-06-12 23:34:46 +02:00
less Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
LICENSES Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
mailer Initial Blogfrei import 2026-06-12 23:34:46 +02:00
migrations Migrate existing databases on startup 2026-06-13 09:40:17 +02:00
oauth Initial Blogfrei import 2026-06-12 23:34:46 +02:00
page Initial Blogfrei import 2026-06-12 23:34:46 +02:00
pages Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
parse Initial Blogfrei import 2026-06-12 23:34:46 +02:00
prose Fix WYSIWYG editor and test publishing 2026-06-13 10:28:35 +02:00
scripts Remove phone-home and maintain ActivityPub subscribers 2026-06-13 10:05:52 +02:00
smoketest Center footer and show pinned posts 2026-06-13 18:34:07 +02:00
spam Initial Blogfrei import 2026-06-12 23:34:46 +02:00
static Center footer and show pinned posts 2026-06-13 18:34:07 +02:00
templates Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
testdata Initial Blogfrei import 2026-06-12 23:34:46 +02:00
themes/default Center footer and show pinned posts 2026-06-13 18:34:07 +02:00
.dockerignore Initial Blogfrei import 2026-06-12 23:34:46 +02:00
.drone.yml Update .drone.yml 2026-06-13 10:48:35 +02:00
.editorconfig Initial Blogfrei import 2026-06-12 23:34:46 +02:00
.gitignore Add Blogfrei editor image storage and container pipeline 2026-06-13 00:14:12 +02:00
.golangci.yml Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
account.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
account_import.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
activitypub.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
activitypub_test.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
admin.go Remove phone-home and maintain ActivityPub subscribers 2026-06-13 10:05:52 +02:00
AGENTS.md Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
ap_subscriber_maintenance.go Remove phone-home and maintain ActivityPub subscribers 2026-06-13 10:05:52 +02:00
ap_subscriber_maintenance_test.go Remove phone-home and maintain ActivityPub subscribers 2026-06-13 10:05:52 +02:00
app.go Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
auth.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
AUTHORS.md Define Blogfrei licensing and first milestone 2026-06-12 23:43:47 +02:00
bootstrap_test.go Migrate existing databases on startup 2026-06-13 09:40:17 +02:00
cache.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
collections.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
CREDITS.md Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
database-lib.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
database-no-sqlite.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
database-sqlite.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
database.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
database_activitypub.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
database_test.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
docker-compose.prod.yml Bootstrap keys and database automatically 2026-06-13 09:26:37 +02:00
docker-compose.yml Bootstrap keys and database automatically 2026-06-13 09:26:37 +02:00
docker-setup.sh Initial Blogfrei import 2026-06-12 23:34:46 +02:00
Dockerfile Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
Dockerfile.prod Initial Blogfrei import 2026-06-12 23:34:46 +02:00
email.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
errors.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
export.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
feed.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
go.mod Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
go.sum Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
gopher.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
handle.go Serve CSS with the correct MIME type 2026-06-13 17:49:47 +02:00
hostmeta.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
images.go Fix WYSIWYG editor and test publishing 2026-06-13 10:28:35 +02:00
images_test.go Fix WYSIWYG editor and test publishing 2026-06-13 10:28:35 +02:00
instance.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
invites.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
jobs.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
keys.go Bootstrap keys and database automatically 2026-06-13 09:26:37 +02:00
LEGAL.md Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
LICENSE Define Blogfrei licensing and first milestone 2026-06-12 23:43:47 +02:00
main_test.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
Makefile Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
monetization.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
nodeinfo.go Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
oauth.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
oauth_generic.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
oauth_gitea.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
oauth_gitlab.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
oauth_signup.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
oauth_slack.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
oauth_test.go Add Blogfrei editor image storage and container pipeline 2026-06-13 00:14:12 +02:00
oauth_writeas.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
ossl_legacy.cnf Initial Blogfrei import 2026-06-12 23:34:46 +02:00
outbound.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
outbound_test.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
pad.go Remove phone-home and maintain ActivityPub subscribers 2026-06-13 10:05:52 +02:00
pad_test.go Remove phone-home and maintain ActivityPub subscribers 2026-06-13 10:05:52 +02:00
pages.go Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
postrender.go Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
postrender_test.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
posts.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
posts_test.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
read.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
README.md Polish the default public theme 2026-06-13 18:14:45 +02:00
request.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
routes.go Serve CSS with the correct MIME type 2026-06-13 17:49:47 +02:00
routes_test.go Serve CSS with the correct MIME type 2026-06-13 17:49:47 +02:00
schema.sql Initial Blogfrei import 2026-06-12 23:34:46 +02:00
SECURITY.md Initial Blogfrei import 2026-06-12 23:34:46 +02:00
semver.go Initial Blogfrei import 2026-06-12 23:34:46 +02:00
session.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
sitemap.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
smoketest.py Add Blogfrei editor image storage and container pipeline 2026-06-13 00:14:12 +02:00
sqlite.sql Initial Blogfrei import 2026-06-12 23:34:46 +02:00
templates.go Add Bilberry theme and complete Blogfrei rebrand 2026-06-13 17:28:46 +02:00
unregisteredusers.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00
users.go Add Blogfrei editor image storage and container pipeline 2026-06-13 00:14:12 +02:00
webfinger.go Eliminate inherited technical debt 2026-06-13 00:48:50 +02:00

Blogfrei

Blogfrei is a self-hosted publishing platform focused on independent writing, simple operation, and a modern editing experience.

The project starts as a fork of WriteFreely, but follows its own direction from this point onward.

First Implementation Milestone

The first Blogfrei implementation milestone replaces the inherited default editor with TOAST UI Editor, an open-source Markdown WYSIWYG editor licensed under the MIT License.

The first milestone also includes image handling for posts:

  • Writers can upload and insert images directly from the editor.
  • Blogfrei saves uploaded image files as images/<md5>.<extension>.
  • The editor inserts the URL of the stored image into the canonical Markdown post instead of embedding base64 image data.
  • Blogfrei serves the stored images directly.

The container exposes /go/images as a volume. Uploaded images are available from the application at /images/<md5>.<extension>.

Select the editor under [app] in config.ini:

[app]
editor = wysywig

wysywig and wysiwyg select the Blogfrei TOAST UI editor and are the default when the option is absent. pad and bare keep the inherited plain Markdown editors available.

Public Theme

Blogfrei bundles an MIT-licensed default public theme derived from the Bilberry Hugo Theme. All static assets are vendored in the repository, so public pages do not need to contact an external CDN.

Themes follow Hugo's directory conventions under themes/<name>/layouts. Select the public theme under [app]:

[app]
blog_theme = default

default is used when the option is absent. Existing bilberry values are migrated transparently for compatibility. The inherited theme configuration option and per-blog Custom CSS editor are no longer used; public appearance belongs to the selected Hugo-style theme.

Network Policy

Blogfrei does not perform vendor update checks, telemetry, or load remote embedded content by default. In particular, it does not contact WriteFreely, write.as, or GitHub for updates or telemetry.

Outbound traffic is limited to features explicitly configured or requested: ActivityPub federation, OAuth providers, email delivery, Web Monetization, and links opened by a user. When federation is enabled, Blogfrei verifies remote ActivityPub subscribers in the background immediately after startup and every eight hours. Valid actors have their inboxes and public keys refreshed; unreachable or invalid actors and their local follow records are removed.

Container Compatibility

The Blogfrei container is initially a drop-in replacement for the WriteFreely container. An existing deployment should be able to replace its image with r.keinpfusch.net/blogfrei:latest while keeping the same configuration file, database, keys, mounted paths, port, and startup command.

Until an explicit migration is provided, changes must preserve compatibility with existing WriteFreely installations and data.

The container is built with Go 1.26.4 and uses Debian 13 as its runtime base.

Goals

Develop new Blogfrei work under the EUPL

New original Blogfrei work is licensed under the European Union Public Licence v1.2 (EUPL-1.2). Code inherited from WriteFreely, and modifications derived from that code, remain covered by the GNU Affero General Public License v3.0 (AGPL-3.0).

Add a true WYSIWYG editor

Replace the current editing experience with TOAST UI Editor, providing a real JavaScript WYSIWYG editor whose canonical output remains Markdown.

The editor should provide direct visual formatting while preserving clean, portable content and a focused writing experience. Blogfrei will preserve the TOAST UI Editor attribution and MIT licence notice.

Manage uploaded images

Allow writers to insert and upload images directly from the WYSIWYG editor.

Blogfrei should save uploaded images in a dedicated, configurable folder and serve them directly as part of the published blog. Image files should remain easy to inspect, back up, restore, and migrate together with Markdown content.

Store posts as Markdown files

Store blog posts primarily as Markdown files on the filesystem instead of in the database.

Each post should have a stable path based on its author and identifier, for example:

data/<author>/<post-id>.md

The Markdown files are the source of truth and should be easy to inspect, version, copy, restore, and migrate. The database may still hold accounts, configuration, and rebuildable indexes, but not the canonical post content.

Export portable archives

Export a blog by creating a ZIP archive containing only its canonical Markdown files and uploaded images.

An export should not require a database dump. Its contents should remain readable and usable without Blogfrei, making backup and migration simple.

Support Hugo themes

Allow blogs to load and use themes in the Hugo theme format.

This should make it possible to reuse the existing Hugo theme ecosystem while keeping theme installation and selection straightforward for Blogfrei administrators and writers.

Current Status

Blogfrei is at the beginning of its independent development. The current codebase provides the technical foundation inherited from WriteFreely; project identity, documentation, user experience, and deployment practices are being reworked for Blogfrei.

Development

Blogfrei is written primarily in Go, with JavaScript and LESS used for the web interface.

make
make test

Docker and Compose files are also available for local development and testing.

At normal startup Blogfrei automatically creates any missing encryption keys under /go/keys and initializes an empty configured database. Existing keys and initialized databases are left unchanged. Persist /go/keys, /go/images, and the database storage as shown in the included Compose files; do not use docker compose down -v unless those volumes should be deleted.

For NFS-backed volumes, /go/keys and /go/images must be writable by the container runtime user daemon (numeric UID/GID 1:1). Database storage requires an NFS server and mount options that provide reliable POSIX locking; do not share one live database volume between multiple database containers.

Definition of Done

Every Blogfrei change is complete only when:

  • The requested implementation is finished.
  • Relevant automated tests have been added or updated.
  • The complete test suite passes.
  • The race detector passes.
  • Go source files pass gofmt.
  • golangci-lint passes.
  • gosec passes.
  • The completed change is committed and pushed to the canonical repository.

Run the local quality checks with:

make dod

The full gate includes the smoke-test suite in smoketest/. It verifies the editor, valid and invalid image storage cases, zero gosec findings, and the built container contract. Run it separately with ./smoketest.py; use ./smoketest.py --build to include an additional clean Docker build.

The security gate requires zero gosec findings, zero reachable Go vulnerabilities reported by govulncheck, and zero known npm vulnerabilities. golangci-lint enforces govet, errcheck, staticcheck, and ineffassign.

Repository

The canonical repository is:

https://git.keinpfusch.net/loweel/blogfrei

License

Blogfrei uses a mixed-licence model:

  • New original Blogfrei work: EUPL-1.2.
  • Code inherited from WriteFreely and derivative modifications: AGPL-3.0.
  • Independent third-party components: their respective licences.

See LICENSE, LEGAL.md, CREDITS.md, and LICENSES/AGPL-3.0.txt. Copyright for inherited code remains with its original copyright holders.