A mini app built with Antler IRL Browser that displays a list of everyone that scanned a QR code.
Note: This repository is built to deploy to Cloudflare. For self-hosting, see meetup-cloudflare. We recommend using Cloudflare because it works on Cloudflare's free tier.
This is a pnpm workspace monorepo with three packages:
- client/ - React frontend
- server/ - Hono backend (REST API + SSE for real-time updates + SQLite database)
- shared/ - Shared utilities (JWT verification, Social links, etc.)
- User scans QR code with Antler
- Client requests profile from
window.irlBrowser.getProfileDetails()API - IRL Browser generates and signs JWT with profile details
- JWT is sent to server, verified, stored in the database, and broadcasted to all connected clients via SSE
- All connected clients see real-time list of everyone that scanned the QR code
Useful commands to run:
pnpm install # Install all workspace dependencies
pnpm run dev # Start both client (localhost:5173) and server (localhost:3000)
pnpm run dev:client # Start only client
pnpm run dev:server # Start only server
pnpm run build # Build all packages (shared → server → client)
pnpm db:generate # Check schema from server/src/db/schema.ts and generate migration files
pnpm db:push # Manually run migrations
pnpm db:studio # Open Drizzle Studio visual database manager- Run
pnpm ito install dependencies - Copy the
server/.env.examplefile toserver/.env. The defaults should work for local development. - Update
data.jsonwith meetup details - Run
pnpm run devto start both client and server - Open
http://localhost:5173in your browser. IRL Browser Simulator is enabled in development mode, so you will instantly login with a test profile (Paul Morphy). - If you need to test multiple users using your app, click the IRL Browser Simulator debug panel "Open as X" button to open a new tab and simulate multiple users.
The app is designed to be easily self-hosted using Docker.
- Run
docker compose upto start the app - The app will be available at
http://localhost:3000 - SQLite database is persisted in a Docker volume, so you can stop and restart your app without losing any data.
- Railway uses the Dockerfile in the root of the repository to build the app.
- Create a new Railway project.
- Add the following environment variables:
DATABASE_URL- The URL of the SQLite database (e.g.file:/app/server/data/meetup.db)
Note: Because the database is stored inside the container, it will reset every time you redeploy the app. You can use a persistent volume to persist the database, or self-host using Docker Compose. The Docker Compose file uses volumes to persist the database.
The IRL Browser Simulator injects the window.irlBrowser API into a regular browser, allowing you to test your mini app locally without needing the Antler mobile app.
Note: This is a development-only tool and should never be used in production.
if (import.meta.env.DEV) {
const simulator = await import('irl-browser-simulator')
simulator.enableIrlBrowserSimulator()
}That's it! The simulator will:
- Inject
window.irlBrowserinto your page - Load a default test profile (Paul Morphy)
- Show a floating debug panel
- Click "Open as X" to open a new tab and simulate multiple users
- Load a profile from the URL parameter
?irlProfile=<id>
- React - UI library
- Tailwind CSS - Styling
- Vite - Build tool
- qrcode.react - Display QR code
- irl-browser-simulator - IRL Browser debugging (dev only)
- Hono - REST API framework
- @hono/node-server - Node.js adapter
- Drizzle ORM - TypeScript ORM for database operations
- @libsql/client - LibSQL/SQLite client for database operations
- Server-Sent Events (SSE) - Real-time updates
- @noble/curves - Ed25519 signature verification
- base58-universal - Base58 encoding/decoding
- jwt-decode - JWT parsing
All shared dependencies are hoisted to the workspace root via pnpm.