141 lines
7.2 KiB
Markdown
141 lines
7.2 KiB
Markdown
---
|
|
title: "How this portal works: static pages, a visual editor, git as the database"
|
|
description: "The architecture behind this demo: a visual editor in the browser, content as Markdown in git, and a public site that is nothing but static files."
|
|
date: 2026-09-11
|
|
category: demo
|
|
author: Cyfronet
|
|
cover: /uploads/diagrams/cover-git-cms.svg
|
|
draft: false
|
|
---
|
|
|
|
This portal is a set of **static HTML files** generated from Markdown kept in a
|
|
git repository. Editors work in a **visual editor in their browser**, and still
|
|
**nothing on the public side runs an application or a database**: between the
|
|
reader and the content there is only a file server. This article was written
|
|
and published through exactly the path it describes.
|
|
|
|
## The stack in three parts
|
|
|
|

|
|
|
|
**Sveltia CMS is the editor.** A single JavaScript file, served as an ordinary
|
|
page under `/admin/`. It signs the editor in to the git server and writes
|
|
Markdown files and images straight into the repository, with no CMS server and
|
|
no database behind it. Every save is a commit.
|
|
|
|
**Git, served by Gitea, is the database.** An article is a Markdown file with a
|
|
fixed set of fields, such as title, date and cover image, and uploaded images
|
|
sit next to it. Full history, and restoring any earlier version in one step,
|
|
come from git itself rather than from a paid tier of a product.
|
|
|
|
**Astro is a generator, not a server.** Its build turns those Markdown files
|
|
into a directory of plain HTML, CSS and images, so deploying means copying that
|
|
directory onto a file server, and nothing from Astro runs in production. If an
|
|
article has a broken field the build stops, so a faulty article never reaches
|
|
readers. Interactive parts, a dashboard for example, can be added later without
|
|
changing the technology.
|
|
|
|
## From a save to a published page
|
|
|
|

|
|
|
|
Publishing is automatic. A save in the editor shows up on the site moments
|
|
later, with no manual deployment step in between. If a build fails, the
|
|
previous version simply keeps serving.
|
|
|
|
## How it runs on the machine
|
|
|
|

|
|
|
|
Two repositories, by design: the portal **code**, maintained by the developers,
|
|
and the editorial **content**, written by the CMS. Each build takes the newest
|
|
version of both, so a change in either one republishes the site. Editors never
|
|
touch the code, and development never mixes with editorial history.
|
|
|
|
Everything runs in three containers on one machine: the git server, the web
|
|
server, and a build container that starts only after a change and exits when it
|
|
is done.
|
|
|
|
For comparison, the same machine running a classic CMS. The diagram keeps the
|
|
same shape on purpose: the application is up around the clock, editors and
|
|
readers use that same application, and its login page faces the internet.
|
|
|
|

|
|
|
|
## Why a static site
|
|
|
|

|
|
|
|
- **Security.** What faces the internet is a file server and a set of files: no
|
|
admin panel to attack, no database to steal, no application code needing
|
|
urgent security fixes.
|
|
- **Maintenance.** Nothing on the reader's side has to be watched and upgraded.
|
|
What is left is the git server, which the team runs anyway, and a short build
|
|
script.
|
|
- **Speed.** A ready-made HTML file is the fastest thing a server can hand over,
|
|
which search engines reward as well.
|
|
- **History.** Every version of every article is kept, and going back is a
|
|
single step.
|
|
|
|
## How it compares with a database-backed CMS
|
|
|
|
The dividing line is not whether content sits in a database or in files. It is
|
|
**whether a running application stands between the reader and the content**. The
|
|
portal should last at least six years, so the last row matters as much as the
|
|
first ones.
|
|
|
|
| | Static + git CMS *(this demo)* | CMS that serves the site itself |
|
|
|---|---|---|
|
|
| Examples | Sveltia, Decap (+ Astro / Hugo / Eleventy) | Strapi, WordPress, Drupal, Grav, TinaCMS |
|
|
| Content lives in | Markdown files in git | usually a database |
|
|
| In production you run | a file server | an application, usually with a database |
|
|
| Maintenance | a build script plus a git service | patches, upgrades, database backups |
|
|
| Change history | git, built in | product-dependent, sometimes paid |
|
|
| Day one | few moving parts, a visual editor ready to use; simple permissions, no editorial roles | a richer panel at once: roles, workflow, structured content; more parts to set up and secure |
|
|
| Over six years | nothing to patch on the reader's side; content in an open format outlives the tools | major upgrades, database backups, a permanent attack surface |
|
|
|
|
Two products blur the line: **Grav** keeps content in files but still serves
|
|
every page with a PHP application, and **TinaCMS** keeps content in git but
|
|
needs a backend with a database to edit it.
|
|
|
|
In the free self-hosted editions we checked, Strapi keeps content version
|
|
history for paid plans only, while WordPress and Grav carry long records of
|
|
vulnerabilities. Features can move into paid plans over time; content and
|
|
history in git leave nothing a vendor can put behind a paywall.
|
|
|
|
## Isn't Gitea just another CMS?
|
|
|
|
A fair question, because Gitea also has a login, a database and security
|
|
updates, so maintenance here is not zero either. Three things differ:
|
|
|
|
- **It is off the reader's path.** Gitea can be down, mid-upgrade or even broken
|
|
into while the portal keeps serving its files. The worst case is vandalised
|
|
content: visible, recorded, undone with one command. In a CMS that serves the
|
|
site, the same incident means a compromised public site.
|
|
- **The team already runs it.** The content repository can live on the instance
|
|
the team maintains anyway, so the extra cost is close to zero.
|
|
- **It is smaller software.** Gitea is one program with a small database, and an
|
|
upgrade is a restart. CMS platforms are frameworks with plugins and regular
|
|
major migrations.
|
|
|
|
## No lock-in
|
|
|
|
The content is plain Markdown, so each part can be swapped on its own: Sveltia
|
|
for Decap (one line of configuration), Astro for another generator, Gitea for
|
|
any other git hosting. Leaving the approach entirely is a plain export.
|
|
|
|
That is the conclusion from this demo: start with the simplest solution that
|
|
meets the requirements, a visual editor for the editors and a public site that
|
|
needs no care, and add complexity only when a need appears that this approach
|
|
cannot serve.
|
|
|
|
## Where things are
|
|
|
|
| What | Where |
|
|
|---|---|
|
|
| Portal | this site |
|
|
| Content editor | `/admin/`, the "Content editor" link in the footer |
|
|
| Content repository | `ctao/content` on the demo machine's Gitea, written by the CMS |
|
|
| Code repository | `ctao/portal`, maintained by the team |
|
|
| Deployment documentation | `deploy/README.md` in the code repository |
|