A hub for aggregating and searching through AT (Authenticated Transfer) Protocol lexicons.
- Node.js v20 or later
- Docker and Docker Compose (for running PostgreSQL and TAP)
- npm (comes with Node.js)
LexHub consists of three main components:
- LexHub (Next.js) - The web application that serves the UI and API
- PostgreSQL - Database for storing lexicon data
- TAP - AT Protocol firehose consumer that listens for lexicon records and delivers them to LexHub via webhook
This setup runs PostgreSQL and TAP in Docker while running the Next.js app locally for hot reloading.
-
Clone the repository
git clone https://github.com/internet-development/lexhub.git cd lexhub -
Install dependencies
npm install
-
Set up environment variables
cp .env.example .env
The default values in
.env.exampleare configured for local development and should work out of the box. -
Start the infrastructure services
docker compose up -d
This starts PostgreSQL and TAP. The
compose.override.yamlautomatically disables the lexhub container and configures services for development.Note for Linux users: The default
TAP_WEBHOOK_URLuseshost.docker.internalwhich works on macOS/Windows. On Linux, editcompose.override.yamland switch to thelocalhostURL instead (see comments in the file). -
Run database migrations
npm run db:migrate
-
Start the development server
npm run dev
-
Open your browser
Navigate to http://localhost:10000 to see the application.
Run everything in Docker containers:
# Start all services (lexhub, postgres, tap)
docker compose -f compose.yaml up -dNote: This skips compose.override.yaml, so all services run in containers. The lexhub container will automatically run migrations on startup.
-
Set up environment variables
Create a
.envfile with production values:DATABASE_URL=postgresql://lexhub:your_secure_password@postgres:5432/lexhub NODE_ENV=production PORT=10000 TAP_ADMIN_PASSWORD=your_tap_admin_password
-
Deploy with Docker Compose
docker compose -f compose.yaml up -d
This runs the production configuration without development overrides. The entrypoint script will:
- Wait for PostgreSQL to be ready
- Run database migrations
- Start the Next.js application
-
Verify the deployment
docker compose ps curl http://localhost:10000
docker build -t lexhub .| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | postgresql://lexhub:lexhub_password@localhost:5432/lexhub |
DATABASE_SSL |
SSL mode override: require or disable (optional) |
Auto-detected (disabled for localhost, required otherwise) |
NODE_ENV |
Environment: development or production |
development |
PORT |
Port for the Next.js server (production only) | 10000 |
TAP_ADMIN_PASSWORD |
Shared secret for TAP webhook authentication (optional) | - |
Note: The
PORTenvironment variable only affects production mode (npm run start). In development, the port is hardcoded to10000inpackage.json.
Note: If you set
TAP_ADMIN_PASSWORD, it must match theTAP_ADMIN_PASSWORDconfigured on the TAP service (see TAP Configuration below).
TAP must be configured to send webhooks to LexHub. The following environment variables configure TAP (set in compose.yaml):
| Variable | Description | Required Value |
|---|---|---|
TAP_WEBHOOK_URL |
URL where TAP sends lexicon events | http://lexhub:10000/api/ingest |
TAP_SIGNAL_COLLECTION |
Collection type to signal interest in | com.atproto.lexicon.schema |
TAP_COLLECTION_FILTERS |
Collection types to filter and deliver | com.atproto.lexicon.schema |
TAP_ADMIN_PASSWORD |
Shared secret for webhook authentication (must match LexHub) | - |
TAP_LOG_LEVEL |
Log verbosity (debug, info, warn, error) | info |
Important:
TAP_SIGNAL_COLLECTIONandTAP_COLLECTION_FILTERSmust be set tocom.atproto.lexicon.schemafor LexHub to receive lexicon records.
Note: To enable webhook authentication, set
TAP_ADMIN_PASSWORDto the same value on both the TAP and LexHub services. Seecompose.yamlfor commented examples.
For a complete list of TAP options, see the TAP documentation.
| Script | Description |
|---|---|
npm run dev |
Start the development server with hot reloading |
npm run build |
Build the application for production |
npm run start |
Start the production server |
npm run format |
Format code with Prettier |
npm run format:check |
Check code formatting |
npm run db:generate |
Generate Drizzle migrations from schema changes |
npm run db:migrate |
Run pending database migrations |
npm run db:push |
Push schema changes directly to database (dev only) |
npm run db:studio |
Open Drizzle Studio to browse database |
LexHub uses Drizzle ORM for database management.
After modifying the schema in src/db/schema.ts:
npm run db:generateThis creates a new migration file in the drizzle/ directory.
npm run db:migratenpm run db:studioThis opens a web UI at http://local.drizzle.studio to browse and edit your database.
# Stop all Docker services
docker compose down
# Stop and remove volumes (deletes all data)
docker compose down -vIf you have questions, ping me on Bluesky: