- JavaScript 84.2%
- Go 10.2%
- Go Template 3.8%
- Less 1%
- Python 0.6%
- Other 0.1%
|
|
||
|---|---|---|
| .github | ||
| appstats | ||
| author | ||
| cmd/writefreely | ||
| config | ||
| db | ||
| key | ||
| keys | ||
| less | ||
| LICENSES | ||
| mailer | ||
| migrations | ||
| oauth | ||
| page | ||
| pages | ||
| parse | ||
| prose | ||
| scripts | ||
| smoketest | ||
| spam | ||
| static | ||
| templates | ||
| testdata | ||
| themes/default | ||
| .dockerignore | ||
| .drone.yml | ||
| .editorconfig | ||
| .gitignore | ||
| .golangci.yml | ||
| account.go | ||
| account_import.go | ||
| activitypub.go | ||
| activitypub_test.go | ||
| admin.go | ||
| AGENTS.md | ||
| ap_subscriber_maintenance.go | ||
| ap_subscriber_maintenance_test.go | ||
| app.go | ||
| auth.go | ||
| AUTHORS.md | ||
| bootstrap_test.go | ||
| cache.go | ||
| collections.go | ||
| CREDITS.md | ||
| database-lib.go | ||
| database-no-sqlite.go | ||
| database-sqlite.go | ||
| database.go | ||
| database_activitypub.go | ||
| database_test.go | ||
| docker-compose.prod.yml | ||
| docker-compose.yml | ||
| docker-setup.sh | ||
| Dockerfile | ||
| Dockerfile.prod | ||
| email.go | ||
| errors.go | ||
| export.go | ||
| feed.go | ||
| go.mod | ||
| go.sum | ||
| gopher.go | ||
| handle.go | ||
| hostmeta.go | ||
| images.go | ||
| images_test.go | ||
| instance.go | ||
| invites.go | ||
| jobs.go | ||
| keys.go | ||
| LEGAL.md | ||
| LICENSE | ||
| main_test.go | ||
| Makefile | ||
| monetization.go | ||
| nodeinfo.go | ||
| oauth.go | ||
| oauth_generic.go | ||
| oauth_gitea.go | ||
| oauth_gitlab.go | ||
| oauth_signup.go | ||
| oauth_slack.go | ||
| oauth_test.go | ||
| oauth_writeas.go | ||
| ossl_legacy.cnf | ||
| outbound.go | ||
| outbound_test.go | ||
| pad.go | ||
| pad_test.go | ||
| pages.go | ||
| postrender.go | ||
| postrender_test.go | ||
| posts.go | ||
| posts_test.go | ||
| read.go | ||
| README.md | ||
| request.go | ||
| routes.go | ||
| routes_test.go | ||
| schema.sql | ||
| SECURITY.md | ||
| semver.go | ||
| session.go | ||
| sitemap.go | ||
| smoketest.py | ||
| sqlite.sql | ||
| templates.go | ||
| unregisteredusers.go | ||
| users.go | ||
| webfinger.go | ||
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-lintpasses.gosecpasses.- 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.