No description
Find a file
2026-09-20 15:41:01 +02:00
.github/workflows change layout of login 2026-09-20 15:41:01 +02:00
cmd/server change layout of login 2026-09-19 18:43:40 +02:00
deploy change layout of login 2026-09-20 15:41:01 +02:00
internal build and ready for demo 2026-09-19 17:33:44 +02:00
ui change layout of login 2026-09-20 15:41:01 +02:00
.dockerignore build and ready for demo 2026-09-19 17:33:44 +02:00
.env.example build and ready for demo 2026-09-19 17:33:44 +02:00
.gitignore change layout of login 2026-09-20 15:41:01 +02:00
Dockerfile build and ready for demo 2026-09-19 17:33:44 +02:00
go.mod build and ready for demo 2026-09-19 17:33:44 +02:00
go.sum build and ready for demo 2026-09-19 17:33:44 +02:00
Makefile change layout of login 2026-09-20 15:41:01 +02:00
README.md changing layout 2026-09-19 16:51:24 +02:00
server git actions 2026-09-19 17:48:04 +02:00

CMS project

This repository contains a Go backend and React frontend for the CMS.

Backend

The backend targets Go 1.27.1 and uses a layered design (internal/web, service, repository, persistence, security, and domain). A single PostgreSQL database stores content; Goose migrations run automatically at startup.

go run ./cmd/server

Configuration is read from environment variables (see .env). The API includes GET /health, GET /api/auth/session, GET /api/protected, GET /api/content, GET /api/content/categories, GET /api/content/badges, and GET|PUT /api/content/:slug.

Single sign-on

The CMS never signs anyone in and stores no users, admins, or sessions. An identity-aware proxy (oauth2-proxy, Authelia, Cloudflare Access, ...) authenticates the owner and forwards a header on every accepted request:

  • Header present → the request is the owner and can edit content (canEdit: true).
  • Header absent → the request is anonymous and content is read-only (canEdit: false).

Configure the header with CMS_SSO_HEADER (default X-SSO-Token). Set CMS_SSO_TOKEN to a shared secret to require an exact value; leave it empty to trust any non-empty forwarded value. CMS_SSO_COOKIE optionally names a cookie fallback.

Because the backend trusts the forwarded header, it must only be reachable through the proxy. Bind it to the loopback interface or a private network, and make sure the proxy strips any client-supplied copy of that header.

Anonymous visitors get a Sign in with Google button in the header. It redirects the browser to VITE_SSO_LOGIN_URL (frontend setting), where the provider authenticates the owner and returns to the page; the CMS itself never performs an OAuth exchange and holds no client secret. Leave the setting empty to hide the button when the proxy gates the whole app automatically.

Content

Content supports one reusable category per document plus any number of badges. The anonymous GET /api/content endpoint accepts category=engineering and repeated badge=go&badge=docker filters; selected badges are combined with AND semantics. GET /api/content/categories returns the category dropdown values. The frontend applies these filters immediately when the category changes or when a badge is entered.

Editing requires the SSO identity: PUT /api/content/:slug returns 401 without it. GET /api/content/:slug and the taxonomy endpoints are public.

make up        # start PostgreSQL
make migrate   # apply the PostgreSQL migrations
make seed      # load repeatable sample content
make backend   # run the Go server
make frontend  # run the React app
make dev       # up + migrate + backend + frontend