Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.letmepost.dev/llms.txt

Use this file to discover all available pages before exploring further.

The same code that runs api.letmepost.dev runs locally. There is no feature gate between the OSS image and the hosted SaaS.

What you need

  • Docker + Docker Compose
  • Postgres 15+ (or use the bundled service)
  • Redis 7+ (BullMQ workers run here)
  • An S3-compatible bucket for media (R2, MinIO, AWS S3 — anything signed-url-able)
  • Your own OAuth app credentials per platform (Bluesky doesn’t need one)

Compose

The repo ships a docker-compose.dev.yml that wires up Postgres, Redis, the API, the worker, and the dashboard:
bring-it-up.sh
git clone https://github.com/rosekamallove/letmepost.dev.git
cd letmepost.dev
cp .env.example .env
# Fill in your platform OAuth client ids + secrets in .env
docker compose -f docker-compose.dev.yml up
The API binds to :3000, the dashboard to :3001. Health probe: GET http://localhost:3000/healthz.

Required env

varwhat
DATABASE_URLPostgres URL
REDIS_URLRedis URL (BullMQ + idempotency cache)
MEDIA_S3_BUCKETbucket name
MEDIA_S3_REGIONregion
MEDIA_S3_ENDPOINTfor R2 / MinIO; omit for AWS S3
MEDIA_S3_ACCESS_KEY_IDbucket credentials
MEDIA_S3_SECRET_ACCESS_KEY
MEDIA_PUBLIC_BASE_URLpublic URL prefix; concatenated with the s3 key
ENCRYPTION_KEY32-byte base64 key for token encryption at rest
WEBHOOK_SIGNING_SECRETHMAC secret for outbound webhook signatures
PUBLIC_API_BASE_URLthe URL your API is reachable on (used in OAuth callbacks)
Per-platform OAuth client ids (when you connect that platform):
platformenv vars
Blueskynone
LinkedInLINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET
Twitter / XTWITTER_CLIENT_ID, TWITTER_CLIENT_SECRET
Facebook (and Instagram)META_APP_ID, META_APP_SECRET
ThreadsTHREADS_APP_ID, THREADS_APP_SECRET
PinterestPINTEREST_CLIENT_ID, PINTEREST_CLIENT_SECRET
Reload after editing .env. The auth flows themselves are identical to hosted — see accounts.

Migrations

pnpm --filter @letmepost/api db:migrate
Schema is managed via Drizzle; migrations live in apps/api/drizzle/. For zero-downtime deploys, follow the standard “additive then destructive in a follow-up release” pattern.

Updating

git pull
docker compose pull
docker compose up -d
Schema migrations run on container start. Breaking schema or env changes are called out in the changelog and DEPLOY.md.

Production notes

  • Run the API and worker as separate processes in production. Compose runs both for convenience; deployments should split them so one queue backlog doesn’t starve HTTP.
  • Postgres + Redis must persist. The dev compose ships ephemeral volumes — don’t ship that to prod.
  • Rotate ENCRYPTION_KEY carefully — there is no automatic re-encryption today; rotation requires a script that decrypts with the old key and re-encrypts with the new.

Differences vs. hosted

There are none in the API surface. The hosted tier wins on managed OAuth apps (you don’t have to register your own with each platform) and managed infrastructure. Same code, same contracts.