The engineering behind this site: a Java content backend, pure frontend views, reviewed publishing, CI/CD and Kubernetes.
ACTIVE
This website is a useful place to make the engineering visible. The writing, projects and photography all need to change over time. The system underneath them should make that work understandable, reviewable and repeatable.
The site is also its own first case study: a content backend, an administration interface, a public view and a publishing tool that agents can use without turning a draft into a production change accidentally.
I want a contributor to work on the content, a reviewer to inspect the exact proposed result, and the publishing action to make an authorized change. Those are separate decisions, even when the same person is responsible for all three.
That separation makes the site easier to grow. Adding a project or a weekly restoration update is a content operation. It should not require an engineer to edit a frontend catalog, copy a timeline into a page component or rebuild the site for each new entry.
The architecture gives the database responsibility for content and publication state. The frontend presents what the public API permits it to read. A private Git repository gives agents a workspace for writing and reviewing material before the explicit publication step.
The same idea applies to operations. A release needs a known artifact, a deployment target and evidence that the result is working. Kubernetes keeps the services running; the delivery process decides which version they should run.
The backend uses Java21 and QQQ, a Java application framework built around metadata. Entities define content fields, relationships, validation and the Admin interface. The same native query, get, insert, update and process actions serve the administration and publishing paths.
PostgreSQL holds the CMS records. Liquibase versions the schema. Blogs and posts are separate entities; the post has its canonical body and publication state. Related LinkedIn, Medium and Facebook versions remain private records beside the post. Recording an external publication URL or date in Admin is distinct from posting to that external platform.
Projects extend that model. A category identifies the software or personal collection. A project owns its overview. Each update has its own title, stable slug, body, date and publication decision. Existing photo albums can belong to a project or one of its updates, while standalone photography albums remain usable.
Database constraints preserve those relationships. An update belongs to one project. An album attached to an update must belong to the same project and site. Native public reads require the record and its publication ancestors to be visible, so an unpublished project cannot expose a gallery through a guessed photo ID.
The public frontend uses Next.js, React and Tailwind. It reads the backend's public API, renders authored Markdown and displays the catalog, project history and galleries from database records. Category names, descriptions, order and content belong to the CMS.
An overview is fetched by its resolved record ID so the complete body is available. Updates are ordered by their recorded date and a stable ID, with pagination. A two-year restoration journal can grow one entry at a time without changing the page template.
The view does not infer architecture facts from a heading or a keyword. A case study should say what the system actually uses, with evidence behind the description. That is why this page is authored content rather than an automatically invented infrastructure diagram.
The publishing CLI is Java as well. It reads Markdown and frontmatter from the private content repository, validates them against the content contract and resolves existing CMS identities through authenticated native queries.
private Git content
→ Java validation and exact-state plan
→ owner review of content, target and plan digest
→ explicit native QQQ publishing process
→ PostgreSQL content and durable receipt
→ public read API
→ website view
The plan binds the source commit and exact file bytes to the target and current database state. The backend compares that state again during the mutation. If an Admin edit or another publication changes it, the old plan is rejected. Canonical Admin edits must be reconciled into source; exports preserve the versions stored in the database.
Content changes, ownership metadata and receipts commit in one transaction. A request has an identity and payload digest. An exact retry returns the existing receipt; using the same identity for different data fails. That gives an agent a recovery path after a timeout without asking it to guess whether another publish is safe.
Authentik supplies interactive Admin authentication and short-lived machine tokens. The machine identity reaches a small allowlist of identity queries and publishing processes. It does not receive general Admin CRUD. Generation credentials and website publishing credentials serve different purposes and stay outside source files and command arguments.
CircleCI runs the repositories' required checks. Backend verification includes native API behavior, database constraints, publication privacy, retries and conflict handling. Frontend verification includes the production build and component/API tests. The content repository runs the same Java validation classes used by the publishing tool.
The shared Munitor delivery tooling builds versioned container images and updates the deployment configuration. Argo CD reconciles that GitOps configuration into Kubernetes. The backend and frontend run as separate deployments, with readiness checks and multiple replicas.
Application releases and content publication remain separate operations. A content merge is an authoring checkpoint. A code release changes the software that performs or presents publication. Neither should silently stand in for an exact decision to make a particular article live.
Database migrations need their own release reasoning. Adding a table can be compatible with the previous application, while undoing a data change may not be. An image rollback and a database restoration answer different recovery questions. Keep their evidence and recovery paths explicit.
The public standards repository records the expectations behind this work. The SDLC connects planning, review, verification, release and maintenance. The WISP describes the information, identities, safeguards and recovery responsibilities along that path.
A published policy is an expectation to implement and test. This project journal is where I can explain the decisions, show the changes and record the limitations as the site develops.
The next useful additions are real updates and galleries attached to the work they document. The model gives each project a durable home; the content will show what happens there.
$ ls
No published updates on this page.