Setup Guide
Prerequisites
- Node.js 18+ (recommended: 20 LTS)
- npm 9+
Quick Start
- Clone the repository
git clone https://github.com/your-org/openbook.git cd openbook - Install dependencies
npm install - Start the development server
npm run devThe database is created and migrations are applied automatically. No
.envfile is required for local development.
First-Time Setup
- Visit
/admin/registerto create an admin account. The first person to register becomes the admin. - Configure your town at
/admin/setup(name, slug, branding). - Upload budget data at
/admin/upload. - Map columns and confirm. Your portal is now live.
Environment Variables
| Variable | Required | Description |
|---|---|---|
DATABASE_URL | No | SQLite database file path (defaults to file:./dev.db) |
Deployment Guide
OpenBook runs locally with SQLite out of the box, but for a public-facing portal you'll want to deploy it to a hosting provider with a production database. This section walks through the recommended path.
Deploying to Vercel (Recommended)
Vercel is the easiest way to get OpenBook online. It auto-builds on every push to your main branch, handles SSL, and has a free tier that works fine for municipal portals.
- Fork the repository
Go to
https://github.com/your-org/openbookand click Fork. This gives your town its own copy of the codebase. - Connect to Vercel
Sign up at
vercel.com, click Add New Project, and import your forked repo. Vercel will detect the Next.js framework automatically. - Add environment variables
In the Vercel project settings, go to Environment Variables and add:
Variable Value DATABASE_URLYour Postgres connection string (see Database Migration below) For the database, grab a free Postgres instance from
neon.techorsupabase.com. Both offer free tiers that are more than enough for a single town's budget data. - Deploy
Click Deploy. Vercel builds the app and gives you a public URL like
openbook-yourtown.vercel.app. Every push to your main branch triggers a new deployment automatically.
Database Migration (SQLite to Postgres)
Locally, OpenBook uses SQLite. For production you need to switch to Postgres. Here's how:
- Get a Postgres connection string
It looks something like:
postgresql://user:password@host:5432/dbname - Update the Prisma schema
In
prisma/schema.prisma, change the datasource provider:datasource db { provider = "postgresql" // was "sqlite" url = env("DATABASE_URL") } - Set the environment variable
DATABASE_URL="postgresql://user:password@host:5432/dbname" - Run migrations
npx prisma migrate dev
Note:Your local SQLite data does not carry over when you switch to Postgres. After migrating, re-upload your budget data through the admin panel. The schema and tables are created by the migration — it's just the row data that doesn't transfer.
Custom Domain Setup
Once your portal is deployed, you can point a real domain at it.
- Add the domain in Vercel
Go to your project's Settings → Domains and add your domain (e.g.,
budget.townname.gov). - Add a CNAME record in your DNS provider
Create a CNAME record pointing to:
cname.vercel-dns.comFor
.govsubdomains, your IT department sets this in the town's DNS management. For domains on GoDaddy, Namecheap, Cloudflare, etc., do the same thing in their DNS panel. - SSL is automatic
Vercel provisions and renews SSL certificates automatically once the DNS record propagates. No extra configuration needed.
IT Department Handoff
In most towns, the person setting up OpenBook (town manager, finance director) is not the same person who manages DNS and hosting. Here's how the work splits:
What the town manager does:
- Fork the OpenBook repo to the town's GitHub account
- Run the app locally and create the admin account
- Configure the town name, slug, and branding
- Upload budget data and verify everything looks right
What IT does:
- Connect the forked repo to Vercel
- Set up a Postgres database (Neon or Supabase free tier)
- Add the
DATABASE_URLenvironment variable in Vercel - Point the subdomain (e.g.,
budget.townname.gov) via CNAME - Verify the deployment is live and SSL is working
IT Handoff Checklist
- Fork the repo at
https://github.com/your-org/openbook - Create a Vercel account and import the forked repo
- Provision a Postgres database (Neon:
neon.tech, Supabase:supabase.com) - Copy the connection string and add it as
DATABASE_URLin Vercel environment variables - Update
prisma/schema.prismaprovider to"postgresql"and commit the change - Deploy — Vercel builds automatically on push
- Add custom domain in Vercel and set the CNAME record to
cname.vercel-dns.com - Wait for DNS propagation and confirm SSL is active
- Have the town manager log in, re-upload budget data, and verify the public portal
Alternative Hosting
Vercel is the path of least resistance, but OpenBook is a standard Next.js app. You can host it anywhere that runs Node.js.
- Railway (
railway.app) — connect your repo, addDATABASE_URL, and Railway handles the rest. - Render (
render.com) — similar flow. Create a Web Service, point it at your repo, set environment variables. - Self-hosted — build and run it yourself:
npm run build npm startThe app listens on port 3000 by default. Put it behind nginx or Caddy for SSL termination.
Regardless of hosting provider, the same database migration steps apply: switch the Prisma provider to "postgresql", set DATABASE_URL, and run migrations.
Budget Data Format
OpenBook accepts budget data in CSV (.csv) or Excel (.xlsx) format. Upload one file per data category (expenses, revenues, capital).
General Rules
- Files must have a header row with column names
- Maximum file size: 10MB
- Each column must have a unique name
- Empty rows are automatically skipped
- Dollar signs, commas, and parentheses in amounts are handled automatically
Amount Columns
OpenBook recognizes fiscal year amounts in column headers:
FY2026 BudgetFY25 Actual2026 AppropriationAdopted 2026
Sample: Expenses CSV
Dept,Function,Description,Object Code,FY2024 Actual,FY2025 Budget,FY2026 Budget
Selectmen,General Government,Town Admin Salary,5110,165000,170000,175000
Police,Public Safety,Chief Salary,5110,145000,150000,155000
Police,Public Safety,Patrol Salaries,5110,680000,710000,740000Sample: Revenues CSV
Category,Source,Description,FY2025 Actual,FY2026 Budget
Tax Levy,Property Tax,Real Estate Tax,28500000,29200000
State Aid,Chapter 70,School Aid,5200000,5350000
Local Receipts,Motor Vehicle,MV Excise,1800000,1850000Sample: Capital CSV
Department,Purpose,FY2026 Budget,Funding Source
DPW,Road Resurfacing Program,500000,Free Cash
Fire,Engine Replacement,350000,Borrowing
Schools,HVAC Replacement,200000,Capital StabilizationUMAS (Uniform Municipal Accounting System)
Massachusetts towns report financials using the UMAS format. OpenBook is designed to work with UMAS exports. To upload your UMAS data:
- Export your Schedule A data from your accounting system as a CSV or Excel file.
- Make sure the export includes column headers (Department, Function Area, Object Code, amounts by fiscal year).
- On the upload page, select the matching category (Expenses, Revenues, or Capital).
- OpenBook will auto-detect common UMAS header patterns like "FY2026 Budget" and "Object Code".
- Review the auto-detected mappings and correct any that look wrong.
UMAS expenditure categories map to OpenBook fields as follows:
| UMAS Column | OpenBook Mapping |
|---|---|
| Department / Dept | Department |
| Function / Functional Area | Function Area |
| Object Code / Account Code | Account / Object Code |
| Description / Line Item | Line Item / Description |
| FY20XX Budget / Appropriation | Fiscal Year Amount (type: Budget) |
| FY20XX Actual / Expenditure | Fiscal Year Amount (type: Actual) |
The DOR Schedule A format from the Massachusetts Division of Local Services also works. Export your town's data from the DOR gateway and upload directly.
Common Issues
- "File has only 1 column" — Your CSV may use semicolons instead of commas. Convert to comma-separated format.
- "Duplicate column names" — Each column must have a unique header.
- No fiscal year detected— Include the year in amount column headers (e.g., "FY2026 Budget") or add a separate "Fiscal Year" column.