尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Public sales demo: queryless, cited security-advisory search over NVD CVE data with a simulated RBAC role toggle
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Ask a question about an organisation's open data in plain English and get a short data story with charts. Every number comes from a SQL query run on the real data, and every chart shows its query.
One engine, one config folder per client. Live: search.portaljs.com (DataHub, the default) · search.portaljs.com/demo/toronto
How it works in depth (pipeline, costs, hosting, decisions): ARCHITECTURE.md.
Datopian has two ways to build a client demo. They are different products, in different repos.
| PortalJS Ask (this repo) | Portal demo | |
|---|---|---|
| What the client sees | One page with a question box. A question gets a short data story with charts | Their own portal, modernised: catalogue, search, dataset pages, plus an optional data story and "Ask AI" |
| What it sells | The AI question-answering layer on its own | A portal revamp or migration (with AI as a bonus) |
| Best for | Organisations with open data but no portal they care about, or an AI add-on for an existing client | Anyone who already runs a portal: CKAN, ArcGIS Hub, EntryScape, Opendatasoft, Socrata |
| Effort | Hours: pick 5–20 datasets, write data notes and example questions | Days: connect the backend, brand it, write one story |
| Repo | datopian/portaljs-ask, one folder per client in portals/ | datopian/data-portal-examples (internal), see its CLIENT-DEMO-GUIDE.md |
| URL | search.portaljs.com/demo/<slug> or the client's own domain | <slug>.arc.portaljs.com or <slug>.portaljs.com |
They combine well: a portal demo's story page can link to the client's PortalJS Ask page for follow-up questions.
It is:
portals/<slug>/. Never a fork.It is not:
/security, /governance) were removed on 2026-10-12.portal-refresh).| What | Where |
|---|---|
| Code | This repo. main is production |
| Hosting | Vercel, Datopian team, project portaljs-ask. Every pull request gets a preview URL |
| Client configs | portals/<slug>/: portal.json, sources.json, notes.md, profile.md, instant.json |
| Which portal is the homepage, client domains | portals/index.json |
| Data files | Vercel Blob store portaljs-ask-data, one folder per portal and snapshot. Not in git |
| Team skills for Claude Code | .claude/skills/: portal-new, portal-verify, portal-refresh, ask-cost-report |
Existing portals: datahub (17 DataHub core datasets, the homepage) and toronto (20 City of
Toronto datasets).
You need Node 20+ and an Anthropic API key (ask for the team key; never commit it).
gh repo clone datopian/portaljs-ask
cd portaljs-ask
npm install
cp .env.example .env.local # set ANTHROPIC_API_KEY at minimum
npm run dev # builds the portal configs, then starts Next.js
instant.json and cost nothing. Typed questions call the API and cost money.portals/, re-run npm run portals (dev and build do it for you).Easiest: in Claude Code, from this repo, run the portal-new skill and give it the
organisation, its catalogue URL and (optionally) the datasets. It follows the steps below and
stops at a preview link.
By hand (full detail in ARCHITECTURE.md §6 and .claude/skills/portal-new/SKILL.md):
git checkout -b portal/<slug>portals/<slug>/portal.json by copying portals/toronto/portal.json
and changing every field (name, owner, headline, theme colours, logo, source, catalogue,
data.base = /data/<slug>/, data.snapshot = today). Add sources.json with 5–20 tables.
Pick tabular datasets with dates and categories people ask about; skip map-only, PDF-only
or very large datasets.node scripts/portal-data.mjs <slug> downloads, cleans and converts the data and
writes profile.md. Resolve every Check item it lists.portals/<slug>/notes.md: for every table, what one row is, every column
with unit and range, how to count correctly, and traps. This is where answer quality comes
from. Check every number you write with DuckDB.datasets and 15–20 examples to portal.json. The first 3 are the
headline ones.BLOB_READ_WRITE_TOKEN=... node scripts/upload-data.mjs <slug>, then put the
printed URL in data.remote in portal.json. Deploys fail without it.npm run portals && npx tsc --noEmit -p ., commit, push, open a draft PR and
wait for the Vercel preview.ASK_ADMIN_TOKEN=... node scripts/precompute.mjs <slug> --api <preview URL>, then run the
portal-verify skill. Read every saved story against its rows (counts, ratios,
"highest", periods), not only the headline numbers.search.portaljs.com/demo/<slug>.Zero-risk mode: set "live": false in portal.json. The question box disappears, only
the pre-computed examples show, and the AI cost is zero. Use it for demos sent by email.
Client's own domain (e.g. ask.example.org): add "<host>": "<slug>" to domains in
portals/index.json, add the domain to the Vercel project, and have the client point a CNAME
at cname.vercel-dns.com. See ARCHITECTURE.md §6.
| Limit | Default | Env var |
|---|---|---|
| Monthly AI spend for live questions | $40 (Anthropic account hard cap: $50) | ASK_MONTHLY_BUDGET_USD |
| Live questions per day, all portals | 30 | ASK_DAILY_TOTAL |
| Live questions per visitor per day | 5 | ASK_DAILY_PER_VISITOR |
When a limit is hit, live questions pause and the examples keep working. Check spend with the
ask-cost-report skill, or:
curl -H "x-ask-admin: $ASK_ADMIN_TOKEN" https://search.portaljs.com/api/data/status
?q=...) and check the link preview."live": true or false for this audience.data.snapshot (this starts a fresh cache), re-check the
notes, re-run pre-compute.| Problem | Fix |
|---|---|
| "Live questions are paused" | A daily or monthly limit was hit. Examples still work. See §6 |
| Deployment fails | A portal is missing data.remote in portal.json (step 6), or npx tsc --noEmit -p . fails |
| Wrong or odd numbers in answers | Fix notes.md (units, how to count, traps), then re-run precompute.mjs (--restory rewrites stories from existing rows) |
| Question outside the data | Expected: the page offers a free catalogue search linking to matching datasets |