Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| sidebar_position: 3 | |
| displayed_sidebar: developersSidebar | |
| # Quick Start Guide | |
| ## Three Services | |
| This project runs three separate services. Launch all three at once with `./start-all.sh`: | |
| | Service | Port (Local) | Live URL | Description | | |
| |---------|--------------|----------|-------------| | |
| | **βοΈ Open Navigator** (`web_app`) | 5173 | [www.communityone.com](https://www.communityone.com) | **Main application** β search, filters, heatmap, data exploration | | |
| | **π Documentation** (`web_docs`) | 3000 | [www.communityone.com/docs](https://www.communityone.com/docs) | Docusaurus site with complete guides and tutorials | | |
| | **π₯ API Backend** (`api`) | 8001 | [www.communityone.com/api/docs](https://www.communityone.com/api/docs) | FastAPI server with AI agents | | |
| > **π‘ LIVE DEMO:** Visit **[www.communityone.com](https://www.communityone.com)** to use the hosted application. | |
| > | |
| > **π» LOCAL DEV:** After running `./start-all.sh`, visit **http://localhost:5173**. | |
| ## Prerequisites | |
| - Python 3.11+ | |
| - Node.js 18+ | |
| - A local Postgres warehouse on `localhost:5433` (databases `open_navigator` and `openstates`) β see [Configuration](#configuration) below | |
| - **PostgreSQL client tools 17** (`psql`, `pg_dump`, `pg_restore`) β **recommended version**. | |
| The local warehouse server runs PG 16, but a **17** client dumps it *and* the (PG 16/17) | |
| Neon serving DB, and reads both dump formats. Keep `pg_dump` and `pg_restore` on the | |
| **same major version** (β₯ any server you back up) to avoid `unsupported version` errors. | |
| - Docker (optional β only for the containerized deployment) | |
| ## Installation | |
| ### Option 1: Start Everything at Once (Recommended) | |
| ```bash | |
| # Clone repository | |
| git clone https://github.com/getcommunityone/open-navigator.git | |
| cd open-navigator | |
| # Install dependencies | |
| ./install.sh # Python backend (creates .venv + .env from template) | |
| cd web_app && npm install && cd .. # React app | |
| cd web_docs && npm install && cd .. # Documentation | |
| # Start all three services in tmux | |
| ./start-all.sh | |
| ``` | |
| `start-all.sh` auto-installs the `web_app`/`web_docs` `node_modules` if they're missing, | |
| so the two `npm install` steps above are optional on first run. | |
| ### Option 2: Using Makefile | |
| ```bash | |
| # Install | |
| make install # Python backend | |
| make install-web_app # React app | |
| make install-docs # Documentation | |
| # Start all services | |
| make start-all | |
| # β¦or individually: | |
| make dev # API only | |
| make dev-web_app # React app only | |
| make dev-docs # Docs only | |
| ``` | |
| ### Option 3: Manual Setup | |
| ```bash | |
| # Python backend | |
| python3 -m venv .venv | |
| source .venv/bin/activate # On Windows: .venv\Scripts\activate | |
| pip install -r requirements.txt | |
| # Optional: Spark + Delta Lake (only if you'll run Databricks/Spark scripts). | |
| # Requires a Java runtime (e.g. `sudo apt install openjdk-17-jre-headless`). | |
| # pip install -r requirements-spark.txt | |
| # React app + documentation | |
| cd web_app && npm install && cd .. | |
| cd web_docs && npm install && cd .. | |
| # Configure environment (see Configuration below) | |
| cp .env.example .env | |
| # Start services in separate terminals: | |
| source .venv/bin/activate && python main.py serve # Terminal 1 β API (8001) | |
| cd web_app && npm run dev # Terminal 2 β App (5173) | |
| cd web_docs && npm start # Terminal 3 β Docs (3000) | |
| ``` | |
| ### Option 4: Windows (PowerShell) | |
| The `.sh` scripts and the `make` targets are Unix-oriented (`start-all.sh` uses | |
| `tmux`, which Windows lacks). Use the PowerShell equivalents instead β they create | |
| the same `.venv`, install from the same `requirements.txt`, and launch the same three | |
| services, each in its own window: | |
| ```powershell | |
| # From the repo root, in PowerShell: | |
| .\install.ps1 # Python backend: creates .venv, installs deps, seeds .env | |
| cd web_app; npm install; cd .. | |
| cd web_docs; npm install; cd .. | |
| .\start-all.ps1 # API (8001) + App (5173) + Docs (3000), one window each | |
| ``` | |
| If you see *"running scripts is disabled on this system"*, PowerShell's execution | |
| policy is blocking the script. Either allow local scripts once for your user: | |
| ```powershell | |
| Set-ExecutionPolicy -Scope CurrentUser RemoteSigned | |
| ``` | |
| β¦or run each script without changing the policy: | |
| ```powershell | |
| powershell -ExecutionPolicy Bypass -File .\install.ps1 | |
| powershell -ExecutionPolicy Bypass -File .\start-all.ps1 | |
| ``` | |
| > **β οΈ Don't use `uv sync` to set up the backend on any OS.** The root | |
| > `pyproject.toml` is a **uv workspace** whose members are only `packages/*`, so | |
| > `uv sync` installs those workspace libraries but **not** the top-level | |
| > `requirements.txt` β leaving out the dev tooling (`pytest`, `black`, `ruff`) and | |
| > runtime deps like `yt-dlp`. Install the backend from `requirements.txt` | |
| > (`.\install.ps1`, `./install.sh`, or `pip install -r requirements.txt`), which is | |
| > the complete set. `uv sync` is only for working *inside* the `packages/*` | |
| > libraries. | |
| > **Tesseract / OCR on Windows:** `install.ps1` installs Tesseract via `winget` | |
| > (or Chocolatey) when available; otherwise grab the | |
| > [UB-Mannheim build](https://github.com/UB-Mannheim/tesseract/wiki). OCR is | |
| > optional β the app runs without it. | |
| ## Configuration | |
| `.env.example` is organized in tiers so you only set what you actually use. | |
| Copy it to `.env` and fill in values as needed: | |
| ```bash | |
| cp .env.example .env | |
| ``` | |
| ### Required (minimum to run locally) | |
| The site needs exactly **one** variable to boot. It points the API at the | |
| already-running local Postgres warehouse on port `5433`, and the API reads it for | |
| both the civic-data warehouse and the auth/user tables: | |
| ```bash | |
| NEON_DATABASE_URL_DEV=postgresql://postgres:password@localhost:5433/open_navigator | |
| ``` | |
| The web app (`5173`) and docs (`3000`) need no env vars to boot. With just the line | |
| above, `./start-all.sh` brings up all three services. | |
| ### Optional for local development | |
| Set these only for the features that need them β the site runs without all of them: | |
| ```bash | |
| # OAuth login (omit a provider to disable just that login button) | |
| FRONTEND_URL=http://localhost:5173 | |
| API_BASE_URL=http://localhost:8001 | |
| # GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET, HUGGINGFACE_CLIENT_ID / _SECRET, etc. | |
| # Stable JWT signing across restarts (auto-generated if unset) | |
| # JWT_SECRET_KEY=$(openssl rand -hex 32) | |
| # Bill / legislator / vote features (restore the Open States dump first) | |
| # OPENSTATES_DATABASE_URL=postgresql://postgres:postgres@localhost:5433/openstates | |
| ``` | |
| ### Data-source API keys (ingestion only) | |
| Keys such as `OPENAI_API_KEY`, the `GEMINI_API_KEY_*` pool, `CENSUS_API_KEY`, and the | |
| other source keys are needed **only** to run the ingestion/enrichment pipelines that | |
| populate the warehouse β not to view the site. | |
| ### Deployment | |
| `HF_TOKEN` / `HF_ORGANIZATION` (HuggingFace Spaces), `NEON_DATABASE_URL` (production | |
| Neon), and the `DATABRICKS_*` variables are for deployment only and are not needed for | |
| local development. | |
| > See [`.env.example`](https://github.com/getcommunityone/open-navigator/blob/main/.env.example) | |
| > for the full, commented list of every variable across all five tiers. | |
| ## Restore the Database | |
| The three services give you the UI, but the app shows no civic data until you load a | |
| warehouse snapshot into the local Postgres on `localhost:5433`. Restoring a shared dump | |
| is far faster than rebuilding every dbt model from scratch. | |
| **If you have the [Google Drive backup folder](#google-drive-folder-one-time-setup) synced**, it's one command: | |
| ```bash | |
| make restore VERSION=snapshot-20260609 # dev only | |
| ``` | |
| **Otherwise, restore a dump someone shared with you** directly: | |
| ```bash | |
| # Create the DB if needed, then restore (rebuilds the `public` serving schema the API reads): | |
| PGPASSWORD=password createdb -h localhost -p 5433 -U postgres open_navigator 2>/dev/null || true | |
| PGPASSWORD=password pg_restore -h localhost -p 5433 -U postgres -d open_navigator \ | |
| --clean --if-exists open_navigator.dump | |
| ``` | |
| The API serves the **`public`** schema in `open_navigator` by default (`API_DB_SCHEMA=public`). | |
| After the restore, refresh http://localhost:5173 β search, maps, and the heatmap will be populated. | |
| > **Restore only into a local/dev warehouse β never into a production database.** | |
| ## Access Points | |
| **π» Local development:** | |
| - **π Main App:** http://localhost:5173 | |
| - **π Documentation:** http://localhost:3000 | |
| - **π₯ API Docs:** http://localhost:8001/docs | |
| **π Live application:** | |
| - **π Open Navigator:** https://www.communityone.com | |
| - **π Documentation:** https://www.communityone.com/docs | |
| - **π₯ API Docs:** https://www.communityone.com/api/docs | |
| ## Stop Services | |
| ```bash | |
| ./stop-all.sh | |
| # or | |
| make stop-all | |
| ``` | |
| ## Running the System | |
| ### Start the API Server | |
| ```bash | |
| # Using the virtual environment | |
| source .venv/bin/activate | |
| python main.py serve | |
| # Or using make | |
| make run | |
| ``` | |
| Visit http://localhost:8001 for the API and http://localhost:8001/docs for interactive documentation. | |
| ## Common Commands | |
| ```bash | |
| # Activate virtual environment (required for all commands) | |
| source .venv/bin/activate | |
| # Start API server | |
| python main.py serve | |
| # Run with auto-reload (development) | |
| python main.py serve --reload | |
| # Check system status | |
| python main.py status | |
| # Run tests | |
| pytest | |
| # Or using make | |
| make test | |
| ``` | |
| ## Troubleshooting | |
| ### "ModuleNotFoundError: No module named 'click'" | |
| You need to activate the virtual environment first: | |
| ```bash | |
| source .venv/bin/activate | |
| ``` | |
| ### "Tesseract binary not found" or OCR errors | |
| The `install.sh` script automatically installs tesseract-ocr on Linux (via apt) and macOS (via brew). If it failed or you're on a different system, install manually: | |
| **Linux (Debian/Ubuntu):** | |
| ```bash | |
| sudo apt-get update && sudo apt-get install -y tesseract-ocr | |
| ``` | |
| **macOS:** | |
| ```bash | |
| brew install tesseract | |
| ``` | |
| **Verify installation:** | |
| ```bash | |
| tesseract --version | |
| ``` | |
| OCR is optional but enables text extraction from scanned PDFs and images. | |
| ### "error: externally-managed-environment" | |
| Don't use `pip install` directly. Use the virtual environment: | |
| ```bash | |
| # Create venv if not exists | |
| python3 -m venv .venv | |
| # Activate it | |
| source .venv/bin/activate | |
| # Now install | |
| pip install -r requirements.txt | |
| ``` | |
| ### Permission denied when running install.sh | |
| ```bash | |
| chmod +x install.sh | |
| ./install.sh | |
| ``` | |
| ## Releases & Data Versioning | |
| Open Navigator follows [Semantic Versioning](https://semver.org/) (`MAJOR.MINOR.PATCH`). | |
| **Every release is tied to a Postgres backup** so that a given version of the code can | |
| always be paired with the warehouse state it was built and tested against. | |
| Given a version `MAJOR.MINOR.PATCH` (e.g. `1.4.2`): | |
| | Bump | When | Example | | |
| | --------- | ------------------------------------------------------------------------------- | --------------- | | |
| | **MAJOR** | Breaking API/schema change, dropped table or endpoint, incompatible dbt model | `1.4.2 β 2.0.0` | | |
| | **MINOR** | New data source, new endpoint, new dbt mart, backward-compatible feature | `1.4.2 β 1.5.0` | | |
| | **PATCH** | Bug fix, data backfill, doc change, no schema or contract change | `1.4.2 β 1.4.3` | | |
| A release bundles three things at the same version number: | |
| 1. **Code** β a git tag (`vMAJOR.MINOR.PATCH`). | |
| 2. **Schema/marts** β the dbt models as built at that tag. | |
| 3. **Data** β a Postgres backup snapshot stored off-machine (see [Database Backups](#database-backups) below). | |
| ## Database Backups | |
| Backup and restore are Makefile targets β no manual `pg_dump`/`pg_restore` needed. Each | |
| stamps the dump files with version/date/git SHA and syncs them off-machine through Google | |
| Drive. Pick the scope that fits β and note that **two of the three are free of personal | |
| user data**: | |
| | Command | Scope | Personal user data? | | |
| | --- | --- | --- | | |
| | `make backup VERSION=v1.5.0` | **Full** β entire `open_navigator` warehouse (bronze/gold/staging/intermediate/public) **+** `openstates`. Self-contained; ~170 GB. | β οΈ **Yes** β includes the `user`/auth/social tables. Keep private. | | |
| | `make backup-neon VERSION=v1.5.0` | **Neon serving** (recommended) β dumps the production Neon serving DB; civic data as standalone materialized tables. Small (~0.5 GB). | β **No** | | |
| | `make backup-public VERSION=v1.5.0` | **Local public** β dumps only the local `public` serving schema; civic views + `event_documents`. | β **No** (personal tables excluded) | | |
| | `make restore VERSION=v1.5.0` | Restore the full backup into the local warehouse. **Dev only.** | β | | |
| | `make restore-neon VERSION=v1.5.0` | Restore a Neon snapshot into a separate local db (`open_navigator_serving`). **Dev only.** | β | | |
| | `make restore-public VERSION=v1.5.0` | Restore the local `public` schema (needs `gold` present). **Dev only.** | β | | |
| The `VERSION` label decides **where the dump is filed** inside the backup folder: | |
| - A **semver tag** (`v1.5.0`) β `open-navigator-backups/releases/v1.5.0/` β for tagged releases. | |
| - **Any other label** (e.g. `2026-06-09`, `snapshot-20260609`) β `open-navigator-backups/snapshots/<label>/` β for ad-hoc point-in-time backups. | |
| `restore*` searches **both** folders, so you restore with the same label you backed up with | |
| regardless of which one it landed in. Exact commands live in the | |
| [`backup` targets in the Makefile](https://github.com/getcommunityone/open-navigator/blob/main/Makefile). | |
| ### Backing up the serving data without user PII | |
| To share or version the public civic data **without** shipping personal user information | |
| (accounts, OAuth state, social graph, feed prefs, saved locations), use one of the | |
| PII-free targets. Both exclude the same app/runtime tables that the Neon serving DB never | |
| mirrors (`user`, `contact_oauth_state`, `social_follows`, `user_lens_prefs`, | |
| `user_locations`, `user_signal_prefs`, `meeting_document_gap_cache`). | |
| **`make backup-neon` (recommended).** Dumps the production Neon serving DB | |
| (`NEON_DATABASE_URL` from `.env`). That DB is **civic-only by construction** β the | |
| `sync_public_to_neon.py` loader never copies the user/auth tables β and its serving objects | |
| are real **materialized tables**, so the dump is standalone (no dependency on `gold`): | |
| ```bash | |
| make backup-neon VERSION=snapshot-20260609 # writes one small neon_serving_*.dump, no PII | |
| ``` | |
| `pg_dump` is read-only, so this is safe to run against prod. Restore into a **separate | |
| local** database (never prod) and optionally point the API at it for a PII-free local | |
| serving instance: | |
| ```bash | |
| make restore-neon VERSION=snapshot-20260609 # β local db open_navigator_serving (dev only) | |
| ``` | |
| The Neon dump is taken with `--no-owner --no-privileges`, and `restore-neon` restores with | |
| `--role=$(PG_USER)`, so all objects end up owned by your **local** `postgres` user β not the | |
| Neon role. (Same for `make backup-public`.) | |
| **`make backup-public`.** Dumps the local `public` schema with the personal tables | |
| excluded β civic views + `event_documents` only. It does **not** include the Postgres | |
| extensions (`pg_trgm`, `btree_gin`, β¦) that live in `public`, so restoring it never drops | |
| them and `gold`'s indexes stay safe. Because the views reference `gold`, restore it onto a | |
| warehouse that already has `gold`: | |
| ```bash | |
| make backup-public VERSION=snapshot-20260609 # local public, personal tables excluded | |
| ``` | |
| > **Restore only into a local/dev warehouse β never into a production database.** The full | |
| > `make backup` is the only one that contains user accounts; treat its dumps as private and | |
| > do not share them via a public Drive link. | |
| > **Client version.** The backup targets auto-select the newest PostgreSQL client under | |
| > `/usr/lib/postgresql/*/bin` (so a PG 17 `pg_dump` is used for the PG 17 Neon server even | |
| > when your `PATH` still points at PG 16). Install PG 17 client tools (see | |
| > [Prerequisites](#prerequisites)). Override the choice if needed with | |
| > `make backup-neon VERSION=β¦ PG_BIN=/usr/lib/postgresql/17/bin/` (or `PG_BIN=` to force `PATH`). | |
| ### Google Drive folder (one-time setup) | |
| `make backup` writes into a folder synced by **Google Drive for Desktop**, reached in WSL | |
| through a symlink named `open-navigator-backups` in the repo root. Set it up once per machine: | |
| ```bash | |
| # 1. Google Drive for Desktop must be running on Windows (so H:\My Drive is accessible). | |
| # 2. Mount H: into WSL and make it persist across restarts: | |
| sudo mkdir -p /mnt/h && sudo mount -t drvfs 'H:' /mnt/h | |
| echo 'H: /mnt/h drvfs defaults 0 0' | sudo tee -a /etc/fstab | |
| # 3. Create the Drive folder and link it into the repo (the symlink is gitignored): | |
| mkdir -p "/mnt/h/My Drive/open-navigator-backups" | |
| ln -sfn "/mnt/h/My Drive/open-navigator-backups" open-navigator-backups | |
| # 4. Verify: | |
| test -d open-navigator-backups/ && echo "β Drive backup folder ready" | |
| ``` | |
| > Different Drive letter? Swap `H:` / `/mnt/h`. No Drive for Desktop? Point `BACKUP_DIR` | |
| > at any folder and sync it with [`rclone`](https://rclone.org/drive/) instead. | |
| ### Create a backup | |
| With the [Google Drive folder](#google-drive-folder-one-time-setup) in place, dump both | |
| databases with one command. Pick any label β a semver tag for a release, or a date for an | |
| ad-hoc snapshot: | |
| ```bash | |
| make backup VERSION=snapshot-20260609 | |
| ``` | |
| This stages the dumps on local disk, copies them into | |
| `open-navigator-backups/snapshots/snapshot-20260609/` (a non-`v` label files under | |
| `snapshots/`; each filename stamped with the version, date, and git SHA), and Google Drive | |
| for Desktop syncs them off-machine automatically. Confirm they landed: | |
| ```bash | |
| ls open-navigator-backups/snapshots/snapshot-20260609/ | |
| # open_navigator_snapshot-20260609_20260609_a1b2c3d.dump | |
| # openstates_snapshot-20260609_20260609_a1b2c3d.dump | |
| ``` | |
| ### Share a snapshot with a collaborator | |
| 1. Run `make backup VERSION=<label>`. | |
| 2. At [drive.google.com](https://drive.google.com), open the `open-navigator-backups` | |
| folder β right-click the `<label>` folder β **Share** β set "Anyone with the link β | |
| Viewer" and copy the link. | |
| 3. The recipient either shares the **same** Drive folder and runs | |
| `make restore VERSION=<label>`, or downloads the `.dump` and restores it manually | |
| (see [Restore the Database](#restore-the-database)). | |
| For a tagged release, also push the matching git tag and record the backup link + SHA in | |
| the [Release History](development/release-history.md): | |
| ```bash | |
| git tag -a v1.5.0 -m "feat: add grants.gov opportunities to search" && git push origin v1.5.0 | |
| ``` | |
| ## Next Steps | |
| 1. Configure your `.env` file (see [Configuration](#configuration) β only `NEON_DATABASE_URL_DEV` is required) | |
| 2. Start all three services: `./start-all.sh` | |
| 3. Open the app at http://localhost:5173 | |
| 4. Check out the interactive API docs: http://localhost:8001/docs | |
| For more details, see the main [README.md](https://github.com/getcommunityone/open-navigator/blob/main/README.md). | |