Skip to content

Twixes/rfc123

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

240 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

RFC123

The agent-native RFC platform for teams.

  1. Draft
  2. Discuss
  3. Decide

RFC123 turns GitHub pull requests into a real RFC workflow. Markdown in, RFC out. Every proposal is a PR in your existing repo, with the same auth, the same permissions, and the same git history. Walk away tomorrow and the record stays in git.

There's a canonical hosted instance at rfc123.com. The rest of this README is for running your own.

What you can do with this repo

The license (FSL-1.1-MIT) lets you run RFC123 for your team, your company, or yourself, on any infrastructure you like. The one thing it does not let you do is wrap it up and sell it back as a hosted RFC product. Two years after each release ships, that release converts to plain MIT.

Practically that means: if your goal is "RFC123, but for my team only," you're in the right place.

Run it with Docker Compose

The bundled docker-compose.yml stands up the whole stack: the Next.js app, a self-hosted Convex backend, the Convex dashboard, and a Redis cache. The only thing you have to register on the outside is a GitHub OAuth App.

It takes about five minutes.

What you need installed

  • Docker and Docker Compose (docker compose version should print v2.x or newer)
  • Node.js 20+, only because the optional Slack step uses it

1. Clone and configure

git clone https://github.com/Twixes/rfc123.git
cd rfc123
cp .env.example .env

Open .env and fill in the required values. There are five secrets to generate:

openssl rand -base64 32   # for AUTH_SECRET
openssl rand -base64 32   # for SECRET_KEY
openssl rand -base64 32   # for TOKEN_ENCRYPTION_KEY
openssl rand -hex 32      # for CONVEX_INSTANCE_SECRET
openssl rand -base64 32   # for UPSTASH_REDIS_REST_TOKEN (any random string works)

Plus two URLs. For a local play, use:

NEXTAUTH_URL=http://localhost:3000
NEXT_PUBLIC_CONVEX_URL=http://localhost:3210

For a real deploy behind a real domain, set NEXTAUTH_URL to your public app URL and NEXT_PUBLIC_CONVEX_URL to the public URL where you'll expose the Convex backend. Both are bundled into the client at build time, so changing them later means rebuilding the app image.

2. Create a GitHub OAuth App

Go to GitHub Settings β†’ Developer settings β†’ OAuth Apps β†’ New OAuth App. Fill in:

  • Application name: RFC123 (or whatever you want to call it)
  • Homepage URL: your NEXTAUTH_URL from step 1
  • Authorization callback URL: <your NEXTAUTH_URL>/api/auth/callback/github

Generate a client secret. Paste both values into .env:

GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...

The app asks for read:user user:email repo read:org. The read:org scope is what lets RFC123 resolve "review requested from team X" assignments.

3. Bring up the stack

This part is two phases, because the Convex admin key is generated by the running backend container and has to be pasted into the app's env before it can push schema.

Phase 1: backend up, admin key out.

docker compose up -d backend dashboard redis srh
docker compose exec backend ./generate_admin_key.sh

Copy the key it prints. Paste it into .env:

CONVEX_SELF_HOSTED_URL=http://backend:3210
CONVEX_SELF_HOSTED_ADMIN_KEY=<the key you just copied>

(http://backend:3210 is the in-network hostname between containers. The browser uses NEXT_PUBLIC_CONVEX_URL instead.)

Phase 2: app up.

docker compose up -d app

The app container waits for Convex to be reachable, pushes the schema and functions, then starts serving on port 3000.

Open http://localhost:3000. Sign in with GitHub. Pick a repo. Write an RFC.

The Convex dashboard is at http://localhost:6791 if you ever need to look inside the database. The admin key from above is what you log in with.

Updating later

git pull
docker compose build app
docker compose up -d app

The app re-pushes Convex on every start, so schema migrations come along for free. The Convex backend and dashboard images update with docker compose pull && docker compose up -d.

Backups

State lives in two named Docker volumes:

  • convex_data: Convex SQLite plus uploaded files. Back this up.
  • redis_data: just a cache. Don't bother.

You can snapshot the volume directly, or use Convex's own export:

docker compose exec backend convex export --path /convex/data/backup.zip
docker compose cp backend:/convex/data/backup.zip ./backup-$(date +%F).zip

Optional: Slack briefing

RFC123 can DM every user a daily summary of RFCs awaiting their review. To turn it on, create a Slack app.

  1. Render the manifest with your URL filled in:

    node --env-file=.env scripts/render-slack-manifest.mjs
  2. Go to https://api.slack.com/apps, "Create New App", "From a manifest". Paste the output.

  3. From the app's "Basic Information" page, copy the Client ID and Client Secret into .env:

    SLACK_CLIENT_ID=...
    SLACK_CLIENT_SECRET=...
    
  4. Restart the app:

    docker compose up -d app

Users connect their own Slack workspace from /settings. The hourly Convex cron fires the briefing and respects each user's timezone and weekday preferences. No briefing on a day with no open RFCs.

Optional: AI body summaries

Set OPENAI_API_KEY in .env to get one-sentence summaries on new PR bodies and AI-generated first-commit messages. Without it, both features fall back to plain non-AI defaults.

Optional: PostHog

Set NEXT_PUBLIC_POSTHOG_KEY and NEXT_PUBLIC_POSTHOG_HOST to point at your PostHog project for product analytics and error tracking. Source map upload at build time is opt-in via POSTHOG_PERSONAL_API_KEY and POSTHOG_PROJECT_ID.

Develop locally without Docker

If you're hacking on the code itself, running outside Docker is much faster. This path uses Convex Cloud (free tier) instead of self-hosted Convex.

pnpm install
cp .env.example .env.local
npx convex dev     # provisions a Convex project and prints NEXT_PUBLIC_CONVEX_URL
# paste that URL into .env.local
pnpm dev

Generate the three secrets (AUTH_SECRET, SECRET_KEY, TOKEN_ENCRYPTION_KEY) the same way as the Docker setup. Then mirror two of them to Convex so the cron worker can authenticate back:

npx convex env set SECRET_KEY "<value>"
npx convex env set NEXTAUTH_URL "http://localhost:3000"

You'll also need an Upstash Redis (their free tier covers it) for the GitHub response cache, or run a local Redis next to Hiett's serverless-redis-http shim like the bundled compose does.

Running it for real

A few things worth knowing before you point this at a production team:

  • The Convex backend is single-instance. Crons would double-fire under multiple replicas. The Next.js app container is stateless and scales horizontally to as many replicas as you want.
  • HTTPS in front. NextAuth and Slack OAuth both refuse non-HTTPS callbacks unless the host is localhost. Put Caddy or your platform's managed TLS in front.
  • Persistent disk for convex_data. Attach at least 5 GB and grow it as your RFC archive does.
  • NEXTAUTH_URL and NEXT_PUBLIC_CONVEX_URL are baked into the client at build time. Change them and you need docker compose build app again.
  • Keep the secrets stable. AUTH_SECRET rotation invalidates every session; TOKEN_ENCRYPTION_KEY rotation requires re-encrypting every stored GitHub token; CONVEX_INSTANCE_SECRET rotation invalidates the admin key.

Commands cheat sheet

pnpm dev           # next dev with React Compiler
pnpm build         # production build
pnpm start         # next start, after pnpm build
pnpm lint          # biome check
pnpm format        # biome format --write
pnpm typecheck     # tsc --noEmit
pnpm test          # vitest, single run
pnpm test:watch    # vitest, watch mode

Contributing

Bug reports and PRs welcome. Before pushing, run pnpm lint && pnpm typecheck && pnpm test. And review every single line of code from a coding agent - yes, you, as a human. Slop not accepted here.

License

FSL-1.1-MIT. Run it for any purpose, including commercially within your own org. Just don't offer it to third parties as a hosted RFC service.

About

πŸ”’ The RFC platform for teams: 1. draft, 2. discuss, 3. distribute

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages