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