No description
  • Go 61.4%
  • TypeScript 31.9%
  • CSS 5.7%
  • Astro 0.6%
  • Makefile 0.1%
Find a file
Sebastian Preisner 1db093bb9a
Some checks failed
Deploy Website / Build website (push) Failing after 4s
Deploy Website / Deploy to Forgejo Pages (push) Has been skipped
CI/CD Workflow / Detect changed paths (push) Successful in 11s
CI/CD Workflow / Security (Secrets: gitleaks) (push) Successful in 15s
CI/CD Workflow / Test Frontend (Node.js) (push) Successful in 1m29s
CI/CD Workflow / Test Postgres Store (push) Failing after 1m35s
CI/CD Workflow / Test Backend (Go) (push) Successful in 3m43s
CI/CD Workflow / Security (Go: govulncheck + gosec) (push) Successful in 6m17s
CI/CD Workflow / E2E (Playwright + Go) (push) Failing after 13m22s
CI/CD Workflow / Build and Publish Docker Image (push) Has been skipped
CI/CD Workflow / Trigger Dockhand Deployment (push) Has been skipped
feat(admin): inspect, retry and acknowledge failed publishes
The admin status panel showed "Attention needed" whenever a post failed to
publish, but with no way to see why or to clear it — so a single failed publish
left the banner red forever.

- store: add AdminListPublishFailures / AdminAcknowledgeFailedPost /
  AdminRetryFailedPost (sqlite + postgres); failed posts gain an acknowledged_at
  column and the posts_failed health metric now excludes acknowledged ones
- LoadPostTargets skips already-posted targets so a re-queued post never
  double-posts (also fixes the scheduler's own retry path)
- api: GET /v1/admin/publish-failures + POST .../{postID}/acknowledge|retry
- admin UI: the failed-posts signal expands into a panel listing each failure
  (team, time, attempts, error and per-account errors) with Retry and
  "Mark reviewed" actions; acknowledging/retrying clears the banner
- i18n (en/de) and sqlite store tests (list/acknowledge/retry/no-double-post)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 02:55:45 +02:00
.forgejo/workflows chore(deps): update postgres docker tag to v18 (#12) 2026-06-27 01:09:39 +02:00
.github/workflows chore(deps): bump workflow actions (node 24, docker actions) 2026-06-27 01:11:36 +02:00
api feat(admin): inspect, retry and acknowledge failed publishes 2026-06-27 02:55:45 +02:00
cmd/server Bootstrap backend scheduler service 2026-04-30 15:35:28 +02:00
db feat(admin): inspect, retry and acknowledge failed publishes 2026-06-27 02:55:45 +02:00
deploy/helm/goloom feat(helm): add Kubernetes Helm chart + docs 2026-06-27 02:21:04 +02:00
develop feat(analytics): hashtag intelligence, activity heatmap and Bluesky rich text 2026-06-13 00:04:01 +02:00
docs docs: document the post validation pipeline and title/team requirements 2026-06-23 12:28:09 +02:00
frontend feat(admin): inspect, retry and acknowledge failed publishes 2026-06-27 02:55:45 +02:00
internal feat(admin): inspect, retry and acknowledge failed publishes 2026-06-27 02:55:45 +02:00
locales feat(admin): inspect, retry and acknowledge failed publishes 2026-06-27 02:55:45 +02:00
website feat(helm): add Kubernetes Helm chart + docs 2026-06-27 02:21:04 +02:00
.dockerignore add platform provider tests for mastodon and bluesky 2026-04-30 22:35:23 +02:00
.env.example fix: dual API rate limits for SPA; dashboard schedule cards 2026-05-05 08:24:31 +02:00
.gitignore chore: remove unused tooling dirs and stale ignore rules 2026-06-14 23:02:39 +02:00
.release-please-manifest.json chore(main): release 0.1.2 (#16) 2026-06-27 02:05:14 +02:00
AGENTS.md docs: expand caveman section in DOX rail 2026-06-15 22:17:32 +02:00
CHANGELOG.md chore(main): release 0.1.2 (#16) 2026-06-27 02:05:14 +02:00
docker-compose-traefik.yml chore(deps): update postgres docker tag to v18 (#12) 2026-06-27 01:09:39 +02:00
docker-compose.yml chore(deps): update postgres docker tag to v18 (#12) 2026-06-27 01:09:39 +02:00
Dockerfile feat(release): version embedding + automated SemVer releases 2026-06-27 00:15:14 +02:00
flake.lock fix: resolve syntax error in http.go after refactoring 2026-05-12 06:59:12 +00:00
flake.nix Add provider instance management and connect the dashboard. 2026-04-30 18:37:22 +02:00
go.mod fix(deps): update module modernc.org/sqlite to v1.53.0 (#2) 2026-06-27 00:46:43 +02:00
go.sum fix(deps): update module modernc.org/sqlite to v1.53.0 (#2) 2026-06-27 00:46:43 +02:00
goloom.code-workspace feat(recurring): add monthly_ordinal_weekday + template var expansion 2026-05-27 20:10:53 +02:00
LICENSE chore: add MIT LICENSE 2026-06-27 00:21:00 +02:00
Makefile feat(release): version embedding + automated SemVer releases 2026-06-27 00:15:14 +02:00
README.md feat(helm): add Kubernetes Helm chart + docs 2026-06-27 02:21:04 +02:00
redocly.yaml feat(docs): add professional OpenAPI and Redocly workflow 2026-05-07 13:04:02 +02:00
release-please-config.json feat(release): version embedding + automated SemVer releases 2026-06-27 00:15:14 +02:00
renovate.json chore(renovate): group the Astro/Starlight ecosystem into one PR (#74) 2026-06-13 13:29:53 +02:00
ROADMAP.md docs: remove deprecated Unsplash/Giphy integrations 2026-05-05 08:42:58 +02:00

goloom logo

goloom

Lightweight, self-hosted social media planning for teams and AI agents.

Plan posts across Mastodon, Bluesky and Friendica from a single Go binary — no enterprise stack, no per-seat pricing.

Deploy website Go TypeScript Single binary Self-hosted API-first E2E: Playwright License: MIT

Last commit Open issues Open PRs Stars


goloom content calendar

goloom is a self-hosted social media planning application built as one Go binary (API + web UI). It helps teams plan posts across multiple social accounts without the heavy infrastructure and pricing model of typical enterprise-first tools.

Why goloom exists

Most tools in this space are powerful but heavy: complex stacks, many paid tiers, and product scope optimized for large organizations.

goloom was created for one focused outcome:

  • plan posts across different social media accounts
  • collaborate across teams
  • keep operations simple
  • integrate cleanly with AI agents such as OpenClaw

Screenshots

Post composer with live previews Team performance analytics
Composer — write once, preview per platform Analytics — engagement & follower trends

Highlights

  • Single binary deployment: UI and API in one process.
  • SQLite by default: no external database needed.
  • PostgreSQL optional for larger deployments.
  • Team workspaces with member roles (owner, editor, viewer).
  • Scheduling, validation, per-account post versions, media library.
  • Built-in analytics for post and account metrics.
  • API-first architecture with bearer-token auth.
  • OIDC support for browser sign-in.
  • Mastodon onboarding can auto-register app credentials from instance URL.

Getting Started

Three ways to run goloom — pick one (full guide: Installation):

  • Dockerdocker run ... ghcr.io/goloom-app/goloom:latest (see Docker).
  • Prebuilt binary — download a static Linux binary from the latest release (goloom_<version>_linux_amd64 / arm64), chmod +x, set ENCRYPTION_KEY + BOOTSTRAP_ADMIN_TOKEN and run it. The web UI is embedded; data goes to ./data/goloom.db (SQLite) by default.
  • From source — build it yourself (below).

1) Configure environment

cp .env.example .env

Set required values:

ENCRYPTION_KEY=replace-with-a-long-random-secret
BOOTSTRAP_ADMIN_TOKEN=replace-with-a-strong-bootstrap-token

2) Build and run

make build
./bin/goloom

Open http://localhost:8080.

3) Bootstrap first admin access

Use the bootstrap token in the UI Settings screen. After first login, create normal API tokens and rotate bootstrap secrets.

API Documentation

goloom API is designed for both developers and AI agents. Professional documentation stack uses OpenAPI + Redocly.

Base paths

  • Primary: /v1/...
  • Alias: /api/v1/... (same handlers, for tools expecting /api/v1)

Authentication

Use bearer tokens:

Authorization: Bearer <oidc-id-token-or-api-token>

API quickstart (curl)

Health and auth status:

curl -s http://localhost:8080/healthz
curl -s http://localhost:8080/v1/auth/status

List providers:

curl -s http://localhost:8080/v1/providers

Get current identity:

curl -s \
  -H "Authorization: Bearer $TOKEN" \
  http://localhost:8080/v1/me

Endpoint groups

  • Discovery: /healthz, /v1/providers, /v1/auth/status
  • Identity: /v1/me, /v1/me/api-tokens
  • Teams: /v1/teams, /v1/teams/{teamID}/members
  • Accounts: /v1/teams/{teamID}/accounts, OAuth start endpoints
  • Posts: /v1/teams/{teamID}/posts, validation, versions, cancel
  • Analytics: /v1/teams/{teamID}/analytics*, post analytics
  • Admin: /v1/admin/*, provider instance management

For complete route list, see api/http.go.

API docs

The interactive API reference is rendered with Scalar and served by the website at /api/. It reads the OpenAPI spec directly, so there is no separate static build step.

Lint the OpenAPI spec:

make docs-api-lint
  • source spec: docs/api/openapi.yaml (single source of truth)
  • the spec is copied to website/public/openapi.yaml by make website-build

AI agent integration notes (OpenClaw and similar)

  • Built-in MCP server (Streamable HTTP transport) at /mcp (enabled by default, MCP_ENABLED), authenticated with API tokens carrying read / write:draft / write:schedule / write / delete scopes (unscoped tokens have full access).
  • Stable JSON responses across core endpoints.
  • Predictable resource paths with team-scoped objects.
  • Validation endpoint before scheduling: POST /v1/teams/{teamID}/posts/validate.
  • API token lifecycle endpoints for secure agent onboarding.

Website & Documentation

The project website (Astro + Starlight) lives in website/: a marketing landing page, the documentation (3-column Starlight layout) and the Scalar API reference at /api/.

Local dev server:

make website-dev

Build static site (includes API docs):

make website-build

Generated output: website/dist/

Deployed via GitHub Pages on push to main when website/ or docs/api/ changes: the pages.yml workflow builds the site with make website-build and force-pushes website/dist to the org Pages repo goloom-app.github.io, which GitHub serves at the root URL https://goloom-app.github.io/.

Provider Support

Mastodon

  • OAuth account connection
  • optional automatic app registration via instance URL
  • publishing and metrics (likes, reposts, replies)

Friendica

  • manual provider app credentials
  • publishing and Mastodon-compatible metrics

Bluesky

  • account connection with app password
  • publishing and metrics support

Deployment Options

Default (single binary + SQLite)

Best for low-ops environments and small-to-medium teams.

DATABASE_URL=file:./data/goloom.db

PostgreSQL

Use when you need external DB operations and scale patterns:

DATABASE_URL=postgres://postgres:postgres@localhost:5432/goloom?sslmode=disable

Upgrading PostgreSQL to a new major version (e.g. 16 → 18) is a dump & restore, not an in-place swap — see the PostgreSQL major upgrade guide.

Kubernetes (Helm)

A Helm chart is provided at deploy/helm/goloom (SQLite on a PersistentVolume, or external PostgreSQL; optional Ingress):

helm install goloom ./deploy/helm/goloom \
  --namespace goloom --create-namespace \
  --set secret.encryptionKey="$(openssl rand -hex 32)" \
  --set secret.bootstrapAdminToken="change-me-please" \
  --set config.publicBaseUrl="https://goloom.example.com"

See the Kubernetes (Helm) guide.

Production migration (Docker → Kubernetes)

If you run Goloom with Docker PostgreSQL and want to move to the homelab CNPG deployment, see docs/migrations/docker-to-kubernetes-homelab.md.

Docker

Use the published multi-arch image (linux/amd64 + arm64) from GHCR:

docker run --rm \
  -p 8080:8080 \
  -e ENCRYPTION_KEY=replace-with-a-long-random-secret \
  -e BOOTSTRAP_ADMIN_TOKEN=replace-with-a-strong-bootstrap-token \
  -v "$(pwd)/data:/app/data" \
  ghcr.io/goloom-app/goloom:latest

For production, pin a version tag (e.g. ghcr.io/goloom-app/goloom:v0.1.0) instead of :latest. To build the image yourself: docker build -t goloom ..

Development

nix develop
make run

Frontend-only dev server:

make frontend-dev

Recommended API-doc workflow in CI:

  • run make docs-api-lint on pull requests to validate the OpenAPI spec
  • the reference is published as part of the website (make website-build)

Configuration

Start from .env.example. Common keys:

  • APP_ENV, HTTP_ADDR, PUBLIC_BASE_URL
  • DATABASE_URL
  • ENCRYPTION_KEY
  • BOOTSTRAP_ADMIN_*
  • SCHEDULER_*
  • OIDC_*
  • MASTODON_*

Positioning vs heavy platforms

goloom is intentionally optimized for:

  • lower runtime overhead
  • easier self-hosting
  • practical team collaboration
  • API-first automation for agent workflows

If you need broad enterprise suites, many commercial upsell modules, or advanced campaign ecosystems, other products may fit better. If you need a focused scheduler with strong API ergonomics and simple ops, goloom is the target shape.

Security notes

  • Provider access tokens are encrypted at rest.
  • API tokens are stored as hashes.
  • Set strong ENCRYPTION_KEY and rotate bootstrap/admin secrets after setup.

Versioning & releases

goloom follows Semantic Versioning and is intentionally pre-1.0 (0.x) — usable and self-hostable today, but breaking changes can still land between minor versions, so pin a version and read the notes before upgrading.

  • Releases are automated from Conventional Commits via release-please: a release PR maintains CHANGELOG.md and the version; merging it tags vX.Y.Z, publishes a GitHub Release with prebuilt Linux binaries (amd64/arm64), and pushes the ghcr.io/goloom-app/goloom image.
  • The running version is reported by GET /healthz and the agent discovery doc.
  • The REST API has its own contract version under /v1, independent of the app version; it changes only on breaking API changes.

About this project

goloom grew out of my own needs as a self-hosted tool. It is built with heavy use of AI, and I use it as a testbed for exploring methods for efficient, AI-assisted development.

License

Licensed under the MIT License.