pgx
PGX — Lightweight Postgres for AI agents. Written in Rust. Thousands of isolated databases in one runtime. 🐘
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Interactive calibration and validation dashboard for the Wasatch Front Regional Council
(WFRC) Activity-Based Travel Demand Model (ActivitySim).檢視完整 README ↗Interactive calibration and validation dashboard for the Wasatch Front Regional Council (WFRC) Activity-Based Travel Demand Model (ActivitySim).
Hosted app: wfrc.utah.gov/wftdm-dashboard · wfrcanalytics.github.io/APP-wftdm-dashboard
Analysts load a scenario folder of pre-computed Parquet summary files directly in the browser — no upload, no server, data never leaves the machine. The dashboard assembles charts, maps, and tables from those files using DuckDB-WASM as the in-browser query engine. Multiple scenarios can be loaded simultaneously for side-by-side or overlaid comparison. Observed validation data (AADT counts, household travel survey) is always registered and available to every panel.
The dashboard covers:
ActivitySim model run (TDM repo)
│
▼ Python post-processor (uv run summarize.py)
│ Reads CSVs + OMX skims → writes Parquet summary files
▼
Scenarios/{run-name}/
manifest.yaml
summary/
summary_kpis.parquet
trip_mode_share.parquet
...
│
├──► Local use: wftdm-dashboard serve/here
│ Analyst loads folder via folder picker or local server
│
└──► Publish to web app: copy to public/scenarios/{name}/
Add name to public/scenarios/index.json → push → deploy
│
▼ Browser (DuckDB-WASM)
│ observed/ always pre-loaded · public/scenarios/* auto-discovered
│ ?s=observed&s=2027-rtp-baseyear for shareable deep links
▼
Dashboard panels (Observable Plot / D3 / MapLibre / flowmap.gl / Graphic Walker)
All computation happens locally. The hosted web app is static HTML/JS/CSS.
Status: the hosted web app,
wftdm-dashboard summarize(the Python post-processor) and, since 072,here,serveandinitexist. Not built yet:init --scenario-dir(the model-repository scaffold) and a configuration check in the library (usenpm run check -- <folder>in this repository).
Visit the hosted URL in Chrome or Edge. Published scenarios from public/scenarios/ load
automatically — no folder picker needed. Share any scenario combination as a URL:
?s=observed&s=2027-rtp-baseyear. Analysts can also load local folders via
Load Local Scenario using the browser's File System Access API (showDirectoryPicker) —
local files never leave the machine.
# Install once
uv tool install git+https://github.com/WFRCAnalytics/APP-wftdm-dashboard
# Start a dashboard from a folder
wftdm-dashboard init some-folder # writes a starter dashboard-config.yaml and one page (never overwrites)
wftdm-dashboard here some-folder # serves the app and the folder on localhost and opens the browser
wftdm-dashboard serve some-folder # serves only the folder, with cross-origin access, for a hosted copy of the app
The folder holds a dashboard-config.yaml (the site file), the page files it lists and the runs:
some-folder/
├── dashboard-config.yaml # the site file
├── dashboard-1-overview.yaml # the pages it lists
├── scenarios/<run>/ # one folder per run: manifest.yaml and summary/*.parquet
├── observed/ # optional
└── geometry/ # optional zone and rail GeoParquet files
A folder that already has a dashboard-config/ subfolder (the app's own public/ layout) is served as it is, so
wftdm-dashboard here public works. here needs no internet for the app itself (DuckDB still downloads its own
extensions unless network.duckdb_extensions points at a mirror, see project-docs/CONFIG-REFERENCE.md); it never writes to the
folder, binds to 127.0.0.1 by default (--host changes that, with a warning), refuses any path outside the folder,
supports range requests, and makes the browser re-check files on every load so an edit shows on reload. --port picks a
port (otherwise 8050, or the next free one) and --no-browser skips opening the browser. A folder with no site file shows
the app's first-run screen. serve has limits: some browsers refuse to let a secure (https) page read a local http
address (mixed content, private network access); here always works.
# pyproject.toml
[tool.uv.sources]
wftdm-dashboard = { git = "https://github.com/WFRCAnalytics/APP-wftdm-dashboard" }
The post-processor converts raw ActivitySim output to Parquet summary files. It is
configured by summarize.yaml alongside the model scripts in the TDM repo — not in
this repository. Output is written to Scenarios/{run-name}/summary/.
Setting up a new scenario directory for the first time? Scaffold default configs before hand-writing anything:
wftdm-dashboard init --scenario-dir Scenarios/2027-RTP-BaseYear
# creates summarize.yaml + the default dashboard-*.yaml set,
# only for files that don't already exist — never overwrites your edits
init copies from the package's bundled templates/: a default summarize.yaml
pre-filled with the standard WFRC segmentations (income group, auto sufficiency, the
four geography levels, person type, etc. — see project-docs/CALIBRATION-SUMMARIES.md) and
the default dashboard-*.yaml files matching the Navigation model in
project-docs/SPEC.md. It's a one-time scaffold, not a synced resource — once these files
exist, editing them is a plain YAML edit with zero package involvement (see
project-docs/ARCHITECTURE.md).
uv run summarize.py --config summarize.yaml --scenario-dir Scenarios/2027-RTP-BaseYear
# writes to Scenarios/2027-RTP-BaseYear/summary/
To publish a scenario to the web app:
Scenarios/2027-RTP-BaseYear/summary/ → APP-wftdm-dashboard/public/scenarios/2027-rtp-baseyear/summary/Scenarios/2027-RTP-BaseYear/manifest.yaml → APP-wftdm-dashboard/public/scenarios/2027-rtp-baseyear/manifest.yaml"2027-rtp-baseyear" to public/scenarios/index.json in the dashboard reponpm run build:pages and commit docs/ to deploy (see the GitHub Pages deploy section below)To publish dashboard layout changes to the web app: dashboard-*.yaml files are
authored alongside the model scripts in the TDM repo, not per-scenario — publish them
once, not per scenario run:
dashboard-*.yaml files from wherever they're authored in the TDM repo →
APP-wftdm-dashboard/public/dashboard-config/ in the dashboard repo (overwriting
the existing copies)public/dashboard-config/index.json in the dashboard repo to list exactly
the filenames now present, in display order — same step as
public/scenarios/index.json, just for tabs instead of scenariosnpm run build:pages and commit docs/ to deploy (see the GitHub Pages deploy section below)The tab set is discovered from index.json at runtime, not hardcoded in the app —
adding, removing, or reordering a tab is purely an index.json + file edit.
OMX skim matrices are converted using the DuckDB h5db community extension
(fallback: Python openmatrix library). Zone geometry is converted to GeoParquet
via DuckDB spatial or GeoPandas.
Dashboard layout and panels are authored in YAML files kept alongside the model scripts in the TDM repo — not authored in this repository. Three file types:
| File | Purpose | Published to this repo at |
|---|---|---|
dashboard-*.yaml | Tab layout, panels, filters. First file = landing page. | public/dashboard-config/ |
manifest.yaml | Scenario name, engine, run date, display color | public/scenarios/{name}/ (per scenario) |
summarize.yaml | Post-processor config | never published — post-processor-only, not read by the browser |
See project-docs/GRAMMAR.md for the full YAML grammar reference.
| Layer | Technology | Why |
|---|---|---|
| Build | Vite + TypeScript | TypeScript throughout src/; React arrives with whichever feature first needs it, not before (constitution v2.1.1 — no phase gate, no dedicated branch for either) |
| In-browser query | DuckDB-WASM | Columnar SQL, same dialect as Python pipeline |
| Offline pipeline | Python DuckDB | Same SQL, reads CSV/OMX/shapefiles |
| Charts | Observable Plot + D3 | Observable Plot draws bars, lines, areas, dots and cells; D3 draws Sankey, treemap, sunburst, pie, radar and chord. One tooltip, one palette, light and dark |
| Explore tab | Graphic Walker | Tableau-style drag-and-drop sandbox |
| Base maps | MapLibre GL | Open-source, no Mapbox token required |
| O-D flow maps | flowmap.gl + deck.gl | Zoom-adaptive desire line clustering |
| File format | Parquet / GeoParquet | Columnar, DuckDB-native, compact |
npm install
npm run dev
Requires Chrome or Edge for local development (cross-origin isolation headers).
npm run build # production build → dist/ (feeds the Python package embed; no demo content, so an unconfigured copy shows a first-run screen)
npm run build:demo # the same build with the demo content in it → dist/ (to try the app)
npm run build:pages # the demo build → docs/ (the GitHub Pages demo output)
npm run preview # preview the dist/ build locally
The demo dashboard at wfrcanalytics.github.io/APP-wftdm-dashboard/ is
deployed by building locally and committing the output — there is no
GitHub Actions workflow:
npm run build:pages — builds the app into docs/ with base path
/APP-wftdm-dashboard/ (docs/.nojekyll is emitted so Jekyll leaves
it alone).docs/ and push to main.main → /docs, so
the push publishes it.docs/ therefore currently contains the built demo app, not
documentation — the reference docs live in project-docs/. Once the
real dashboard deploys from WFRC's own server, docs/ reverts to a
documentation source tree.
APP-wftdm-dashboard/
├── CLAUDE.md ← Claude Code specification (AI coding agent)
├── README.md
├── project-docs/ ← internal reference docs
│ ├── ARCHITECTURE.md ← Design decisions and rationale
│ ├── SPEC.md ← Implementation specification
│ ├── GRAMMAR.md ← Full YAML grammar reference
│ ├── PIPELINE.md
│ ├── CALIBRATION-SUMMARIES.md ← Metric inventory by submodel
│ ├── UX-REDESIGN-PROPOSAL.md
│ └── BASEMAP-PICKER-PROPOSAL.md
├── docs/ ← ⚠ committed GitHub Pages BUILD OUTPUT of the
│ demo app (`npm run build:pages`), not docs.
│ Reverts to a docs tree post-WFRC-server deploy.
├── public/
│ ├── asset-cache-serviceworker.js ← Caches the DuckDB and Parquet assets
│ ├── demo-scenarios/ · demo-dashboard-config/ · demo-geometry/ ← the git-tracked demo content
│ ├── observed/ ← Observed validation data (always pre-loaded, deselectable)
│ │ ├── manifest.yaml
│ │ └── summary/
│ │ ├── observed_mode_share.parquet
│ │ └── observed_counts.parquet
│ ├── scenarios/ ← Published model runs (auto-discovered on load)
│ │ ├── index.json ← ["2027-rtp-baseyear", ...]
│ │ └── 2027-rtp-baseyear/
│ │ ├── manifest.yaml
│ │ └── summary/
│ └── dashboard-config/ ← Published tab layout (discovered + fetched at startup)
│ ├── index.json ← ["dashboard-1-summary.yaml", "dashboard-2-person.yaml", ...]
│ ├── dashboard-1-summary.yaml
│ └── ... ← whatever else index.json lists (six, by default)
├── src/ ← Dashboard application source
├── python/
│ └── wftdm_dashboard/ ← Python package (CLI + embedded app)
├── package.json
├── vite.config.ts
└── pyproject.toml
| Repo | Role |
|---|---|
WFRCAnalytics/APP-Commute-Explorer | Production reference: MapLibre + flowmap.gl + DuckDB-WASM |
ar-puuk/omx-viewer | Production reference: DuckDB-WASM + h5wasm + Vite + GH Pages |
ar-puuk/spatial-sql-explorer | Production reference: DuckDB spatial + MapLibre choropleth |
ar-puuk/parquet-viewer | Production reference: GeoParquet reading + spatial extension |
MIT — Wasatch Front Regional Council, 2025