Self-hosting
Architecture, configuration and commands for running your own gitpad deployment, and your obligations under AGPL-3.0.
Before you start
gitpad is open source under the GNU Affero General Public License, version 3 only (AGPL-3.0-only). The source is at github.com/sachouliax/gitpad.
Running gitpad in production means holding signing keys that control other people's fees. Read Security and review the code paths you deploy. Never run integration tests against a production database: several suites truncate tables.
Architecture
| Component | Responsibility |
|---|---|
| Web (Next.js) | Pages, API routes, quotes, wallet transaction preparation, GitHub sessions, payout authorization and protected payout signing |
| Worker (Node.js) | Finalized launch and trade indexing, fee evidence, signed-intent recovery, reconciliation, optional trend intake |
| PostgreSQL | Workflow state, canonical repository-to-market mappings, indexed evidence, payout intents; schema managed with Drizzle migrations |
| Solana RPC | Reading pools and transactions, simulating and submitting transactions |
| GitHub App | Repository identity and the current user's admin permission |
| Meteora DBC config | The on-chain configuration every new market is created from |
Browser + user wallet -> Web (Next.js) -> GitHub App API
-> PostgreSQL
-> Solana RPC -> Meteora DBC / DAMM v2
Worker -------------------------------> PostgreSQL, Solana RPC
Sources of truth: GitHub for repository identity and permission; Solana and Meteora for pools, swaps, fees, migration and settlement; PostgreSQL for workflow records and balances derived from verified evidence.
No custom Solana program is required. Fees are routed by Meteora's creator and partner fee authorities, held by the web service's protected signers.
The web service runs as a single persistent instance, because launch signing sessions keep in-memory state. The worker is a separate persistent process.
Requirements
- Node.js 22 and npm, using the committed
package-lock.json. - PostgreSQL (the recorded tests use PostgreSQL 17).
- A Solana RPC endpoint for the intended network. A second, independent RPC is recommended for graduation and chart verification.
- A GitHub App with repository Metadata: read permission and a callback at
<APP_ORIGIN>/api/github/callback. - A Meteora DBC config account that you create and control (see below).
- For chain integration tests: a local
solana-test-validatorwith the Meteora DBC and Metaplex program fixtures.
Meteora DBC config
Each deployment must create its own DBC config on chain and set its address in DBC_CONFIG. A mainnet config address from another deployment does not exist on a local validator, and a config you do not control routes fees to someone else.
The launch guard checks the main on-chain settings and rejects configs that do not match:
| Setting | Value |
|---|---|
| Quote asset | SOL, fees collected in the quote token |
| Trading fee | 175 bps fixed, dynamic fee disabled |
| Creator trading fee percentage | 71 |
| Pool creation fee | 0 |
| Token | SPL token, 6 decimals |
| Migration | Meteora DAMM v2 |
| Migrated liquidity | 50% partner and 50% creator, both permanently locked |
The supply (1,000,000,000), token authority and curve shape come from the profile you use to build the config. src/launch-curve.mjs builds the reviewed curve profiles, including the 85 SOL graduation profile with the 1% builder allocation. Compare profiles offline with:
node scripts/compare-launch-curves.mjs
New pools are created with the public key of PLATFORM_CREATOR_SECRET_KEY as pool creator, and the config's fee claimer must be the public key of PLATFORM_PARTNER_SECRET_KEY. When you change DBC_CONFIG, keep every previously used config in DBC_LEGACY_CONFIGS so existing markets keep resolving.
Environment variables
Copy the names from .env.example into an ignored .env.local for development, or into your provider's secret store for production. Secrets are server-only: never put them in a NEXT_PUBLIC_ variable.
Core
| Variable | Service | Purpose |
|---|---|---|
APP_ORIGIN |
Web | Canonical HTTPS origin; used for OAuth callbacks, wallet messages and metadata URLs |
DATABASE_URL |
Web, worker, migrations | PostgreSQL connection |
SOLANA_RPC_URL |
Web, worker | RPC endpoint for the intended network |
DBC_CONFIG |
Web, worker | Approved DBC config for new launches |
DBC_LEGACY_CONFIGS |
Web, worker | Comma-separated configs still used by existing markets |
GITHUB_APP_CLIENT_ID |
Web | GitHub App client ID |
GITHUB_APP_CLIENT_SECRET |
Web | OAuth exchange, session encryption and signed reviews |
GITHUB_APP_INSTALLATION_ID |
Web | Installation used for repository metadata requests |
GITHUB_APP_PRIVATE_KEY_BASE64 |
Web | Base64-encoded GitHub App private key |
NEXT_PUBLIC_PRIVY_APP_ID |
Web | Privy app used to connect wallets (Solana wallets, or email, Google, GitHub and X with an embedded Solana wallet). Unset: the built-in Wallet Standard chooser is used |
NEXT_PUBLIC_SOLANA_RPC_URL |
Web (browser) | Public RPC for the Privy modal's balances and simulations. Never put a keyed private RPC here |
NEXT_PUBLIC_GITHUB_APP_SLUG |
Web | Public slug of the GitHub App (github.com/apps/<slug>), used for install links. Defaults to gitpad-app |
PLATFORM_CREATOR_SECRET_KEY |
Web only | Creator fee authority; must match the config's pool creator |
$GITPAD identity
Everything tied to the platform token stays hidden until GITPAD_TOKEN_MINT is set. These are public addresses, not secrets.
| Variable | Service | Purpose |
|---|---|---|
GITPAD_TOKEN_MINT |
Web, worker | Official $GITPAD mint |
GITPAD_TOKEN_REPO_ID |
Web | GitHub numeric ID of the gitpad repository the token is launched for |
GITPAD_TEAM_WALLET |
Web, worker | Team wallet whose buys are published as team buybacks |
GITPAD_BUYBACK_CUSTODY_WALLET |
Web, worker | Platform revenue custody wallet |
GITPAD_PLATFORM_FEE_WALLET |
Web, worker | Partner fee wallet; direct buys from it count as platform-revenue buybacks |
GITPAD_POOL |
Web | Canonical $GITPAD DAMM v2 pool, for protocol liquidity receipts |
GITPAD_SOL_VAULTS |
Worker | Comma-separated SOL vaults of the $GITPAD curve and pool, for buyback detection |
GITPAD_BUYBACK_SINCE |
Worker | ISO timestamp; earlier buys (launch buy, early team buys) are not buybacks |
Hand-verified receipts (buybacks, protocol liquidity deposits, team locks) are published in data/platform-receipts.json, so every addition is a reviewable commit. The worker adds later buybacks it detects on chain.
Rewards and allocation
| Variable | Service | Purpose |
|---|---|---|
PLATFORM_PARTNER_SECRET_KEY |
Web only | Partner authority for discovery payouts and platform fee claims |
DISCOVERY_REWARDS_ENABLED |
Web | Enrolls new launches in discovery rewards; disabling it stops new enrollment but not existing obligations |
BUILDER_ALLOCATION_CONFIGS |
Web | Configs whose launches reserve the 1% builder allocation; unset keeps it inactive |
Operations and treasury
| Variable | Service | Purpose |
|---|---|---|
PLATFORM_OPERATOR_GITHUB_IDS |
Web | Numeric GitHub user IDs allowed to use operator tools; empty denies access |
PLATFORM_FEE_TREASURY_WALLET |
Web | Public SOL wallet receiving collected platform fees |
PLATFORM_DBC_COLLECTION_ENABLED |
Web | Enables reviewed DBC partner fee collection (after reserving unpaid discovery rewards) |
GRADUATION_VERIFICATION_RPC_URL |
Web, worker | Independent read-only RPC for graduation and chart verification |
RESERVE_ALERTS_ENABLED, RESERVE_ALERT_WEBHOOK_URL |
Worker | Optional private webhook for reserve movement alerts |
TRADE_CANARY_ENABLED |
Worker | Set to false to disable the simulated trade canary |
Optional features
| Variable | Service | Purpose |
|---|---|---|
TREND_INTAKE_ENABLED |
Worker | Collects public evidence for Find repos |
REPO_SMART_SEARCH_ENABLED, TYPESAFE_API_KEY |
Web | Optional natural-language repository search |
AGENT_LAUNCH_ENABLED, AGENT_LAUNCH_SECRET |
Web | Public MCP launch review tools; the secret must be random and at least 32 bytes |
BUILDER_REMINDERS_ENABLED, RESEND_API_KEY, BUILDER_REMINDER_FROM, BUILDER_REMINDER_SECRET |
Web, worker | Double opt-in builder earnings emails |
X_CLIENT_ID, X_CLIENT_SECRET, X_CALLBACK_URL |
Web | Optional read-only X account connection |
MAINTAINER_INVITE_MIN_SOL |
Web | Minimum unclaimed builder fees before a repository appears in operator invites |
Financial execution gates
Keep these disabled unless you have reviewed their separate activation requirements:
REPO_BUYBACK_EXECUTION_ENABLED=false
REPO_LIQUIDITY_EXECUTION_ENABLED=false
BUILDER_REINVEST_ENABLED=false
The related REPO_BUYBACK_*, REPO_TOKEN_MINT, REPO_TREASURY_TOKEN_ACCOUNT, REPO_LIQUIDITY_* and BUILDER_REINVEST_* variables have no default spending values. An incomplete configuration stops execution.
The worker needs database, RPC and config access, but neither signer secret. It recovers transactions that the web service already authorized and signed.
Commands
Install and run the web app in development (it serves on port 3001):
npm ci
npm run dev
Apply database migrations:
npm run db:migrate
With a .env.local file, standalone scripts need the variables loaded explicitly:
node --env-file=.env.local ./node_modules/drizzle-kit/bin.cjs migrate --config drizzle.config.mjs
Run the worker:
# persistent worker
npm run worker
# a single cycle, for local checks
node --env-file=.env.local scripts/run-worker.mjs --once
Build and start the production web service:
npm run build
npm run start
Tests
Checks that need no database or chain:
node scripts/compare-launch-curves.mjs
node --test tests/market-config.test.mjs tests/discovery-rules.test.mjs
git diff --check
Integration suites need a disposable PostgreSQL database and, for chain tests, a local validator with the Meteora fixtures. Examples:
npm run test:launch
npm run test:launch:chain
npm run test:trade
npm run test:fees
npm run test:claim
npm run test:discovery
npm run test:reconcile
These suites truncate tables and create local transactions with disposable in-memory keys. Some enforce a specific database name or port; keep those guards in place.
The full suite runs through one entry point that provisions every database it needs on a disposable PostgreSQL server (127.0.0.1:55432) and expects solana-test-validator on 127.0.0.1:8909 for chain suites:
node scripts/ci/run-tests.mjs
Receipt and buyback-detection tests run against real finalized transactions from the upstream deployment, preloaded from tests/fixtures/reference-platform.json by the runner.
Release order
- Build and test the exact revision you will deploy.
- Check that you have a recent, restorable database backup.
- Apply additive migrations.
- Deploy the worker, then the web service.
- Confirm pages respond, operator endpoints reject anonymous requests, and indexing and reconciliation succeed across existing markets.
Back up the database off-host. Payout history is part of the ledger: restoring fee evidence without settled payouts could allow duplicate payments, so restore and reconcile the complete claim ledger before enabling payouts.
AGPL-3.0 obligations
gitpad is licensed under AGPL-3.0-only. If you run a modified version of gitpad and let users interact with it over a network, you must offer those users the complete corresponding source code of your modified version, under the same license. A link to a public repository containing your exact deployed source is a common way to do this.
- Keep the license and copyright notices.
- License your modifications under AGPL-3.0-only.
- Third-party dependencies and assets keep their own licenses.
This is a summary, not legal advice. Read the license text.
Found something wrong? Edit this page on GitHub.
