Techadamia Backend
A secure REST API backend for the Techadamia platform, built with Go, PostgreSQL, and Redis (optional). It handles user accounts and roles, Markdown posts with categories, image uploads, and session-based auth with CSRF protection and rate limiting.
Note
New here? Jump to the API Reference. Two quick gotchas: requests are form-encoded, not JSON (responses are JSON), and everything past the public endpoints needs a session.
Documentation
| Doc | What's inside |
|---|---|
| API Reference | Every endpoint, auth, errors, and examples |
| Architecture | System design, data flow, database schema |
| Development | Local setup, testing, building |
| Codebase Structure | Directory and file layout |
| Code Documentation | Packages, types, and functions |
| Security | Auth model, hardening, and checklist |
| Deployment | Production deployment and operations |
| Contributing | Workflow, code standards, and PRs |
| Documentation Index | A guide to all docs, by role |
Tip
Prefer a browsable site? Run task docs to render these Markdown files into docs-site/ (searchable, themed, with a sidebar) and open docs-site/index.html.
What it does
- Accounts & roles — self-registration as an
author(admin-approved) orreader(self-service, email-verified), public profiles with display name/bio/avatar, profile editing, password change, and a one-time first-admin bootstrap. - Authentication — server-side sessions via cookie or bearer token, CSRF double-submit, bcrypt password hashing, one active session per user, email-based password reset with single-use hashed tokens.
- Content — Markdown posts with auto-generated slugs, categories,
draft/published/archivedstates, ownership, soft deletes, and DB-backed full-text search (Turkish stemming). - Social — threaded comments with admin moderation, post likes, follows, direct messages, and a notification inbox (comment/reply/like/follow/new-post/pending-user/activation events).
- Realtime — a Server-Sent Events stream (
GET /events) pushes notifications and messages to logged-in clients the moment they happen. - Media — image uploads (JPEG/PNG/WebP) with content-sniffing validation, long-lived immutable serving, and background cleanup of orphaned files (avatars are exempt).
- Rate limiting — fixed-window, per-IP, per-endpoint; optionally backed by Redis to share limits across instances.
- Operations —
/healthand/readyprobes, structured request logging, security headers (HSTS/CSP/…), CORS, a tunable DB pool, optional SMTP for transactional email, and automatic schema migrations on startup.
Quick start
Prerequisites: Go 1.26+, PostgreSQL 14+, and (optionally) Redis 6+. Docker is the fastest path.
Local
git clone https://github.com/S3-R4/Techadamia.git
cd techadamia-backend
go mod download
cp .env.example .env # then edit DATABASE_URL, BOOTSTRAP_TOKEN, etc.
go run ./cmd # migrations run automatically on startup
The API listens on http://localhost:8080 (set APP_PORT to change it).
Docker
# Builds the app image and starts app + postgres + redis with health checks.
BOOTSTRAP_TOKEN=$(openssl rand -hex 32) docker compose up --build
Create the first admin
Registration always creates a pending author. Bootstrap the first admin once, using the BOOTSTRAP_TOKEN from your .env:
curl -X POST http://localhost:8080/admin/bootstrap \
-H "X-Bootstrap-Token: $BOOTSTRAP_TOKEN" \
-d "username=admin" -d "email=admin@example.com" -d "password=change-me-please"
This endpoint refuses once any admin exists, so it is safe to leave enabled (or clear BOOTSTRAP_TOKEN to disable it). Admins then activate pending authors via GET /users/pending → PUT /users/:id/status with status=active.
Configuration
.env.example is the fully-commented catalog of every option. The server validates configuration at startup and refuses to boot if a required variable is missing or invalid. The essentials:
APP_PORT=8080
APP_ENV=development # development | staging | production
DATABASE_URL=postgresql://postgres:password@localhost:5432/techadamia_dev
BOOTSTRAP_TOKEN=change-me-to-a-long-random-secret
MEDIA_STORAGE_DIR=./uploads # must be writable by the process
CORS_ALLOWED_ORIGINS=http://localhost:3000
SESSION_COOKIE_SECURE=false # must be true when APP_ENV=production
Note
Sessions are server-side (database-stored UUIDs) and CSRF uses a double-submit cookie, so there is no SESSION_SECRET / CSRF_SECRET to configure. See .env.example for rate limits, the DB pool, trusted proxies, security headers, and media garbage-collection settings.
Architecture
A clean, layered architecture — HTTP handlers delegate to a service layer, which uses type-safe generated queries.
internal/
├── api/ # HTTP handlers, routes, request validation, response shapes
├── service/ # Business logic (auth, posts, media, users, categories)
├── middleware/ # Auth, CSRF, CORS, rate limiting, logging, security headers
├── sql/ # Queries and models (generated by sqlc)
├── migrate/ # Migration runner + migrations/
└── utils/ # Config, slugs, request IDs, helpers
See ARCHITECTURE.md for data flow, the database schema, and design decisions, and CODEBASE_STRUCTURE.md for a file-by-file tour.
Tech stack
| Layer | Choice |
|---|---|
| Language | Go 1.26 |
| HTTP | Gin |
| Database | PostgreSQL via pgx |
| Queries | sqlc (SQL-first, type-safe codegen) |
| Cache / limits | Redis (optional) |
| Auth | Server-side sessions, bcrypt, CSRF double-submit |
Contributing
See CONTRIBUTING.md for the workflow and code standards, and DEVELOPMENT.md for setup, testing, and debugging. Report issues on GitHub Issues.
License
Part of the Techadamia platform. See LICENSE for details.