portaljs
NewScaffold and extend PortalJS data portals: /new-portal, /add-dataset, /add-chart, /add-map, /deploy.
Overview
<p align="center"> <img src="assets/portaljs-logo.svg" alt="PortalJS" width="96" height="96" /> <h1 align="center">PortalJS</h1> <p align="center"> <b>The AI-native framework for building data portals.</b> <br /> Describe the portal you want — your agent helps you choose an architecture, scaffolds it, and loads your data. <br /> <br /> <a href="https://www.portaljs.com/opensource">Docs</a> · <a href="https://github.com/datopian/portaljs/discussions">Discussions</a> · <a href="https://github.com/datopian/portaljs/issues/new">Report a bug</a> <br /> <br /> <a href="https://discord.gg/krmj5HM6He"><img src="https://dcbadge.limes.pink/api/server/krmj5HM6He" alt="Join our Discord server"/></a> <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"/> </p> </p>
Why PortalJS
Building a data portal has always meant more than a website. You have to decide where the data lives, how it's versioned, how people search it, how it's served, and how it's governed — and then wire a frontend on top. Teams either over-build on a heavy data warehouse they don't need, or under-build on a pile of scripts that doesn't scale.
PortalJS is an open-source, agentic skills framework that helps data teams build, develop, and ship data portals — and the data infrastructure underneath them. It isn't only a frontend. The skills do two jobs:
- •Advise — given _what you're building_, _what your data is_, and _what it's for_,
they recommend an architecture: storage, compute, catalog, access, hosting, metadata.
- •Build — they scaffold that stack as plain, editable Next.js code with no lock-in.
It is opinionated but open: the recommended modern path is git + object storage (Cloudflare R2) + Parquet + DuckLake + DuckDB — an open lakehouse instead of a classic warehouse — but a traditional datastore (CKAN, a warehouse) stays a first-class option when you need it. You always own plain code.
Built and maintained in the open by Datopian and the PortalJS community.
Architecture at a glance
🧑 you describe what you want to build
│
▼
╭─ 🤖 AGENTIC SKILLS ────────────────────────────────── decide + build
│ /architect · /new-portal · /add-dataset · /add-chart · /add-map …
╰─ generates plain, editable Next.js code — no lock-in
│
▼
╭─ 🖥️ SURFACES ──────────────────────────────────────── what users see
│ 🏠 Home / 🔎 Catalog /search 📊 Showcase /@ns/slug
╰─ read data through one DataProvider contract
│
▼
╭─ 🔌 PROVIDERS ─────────────────────────────────────── pluggable backends
│ 📁 static·git 🐘 CKAN 🔭 OpenMetadata 🗂️ git-LFS + R2
╰─ swap the source without touching a page
│
▼
📦 STORAGE + COMPUTE — choose your point on the spectrum:
flat files ─▶ Git-LFS + R2 ─▶ Parquet + DuckLake + 🦆 DuckDB ─▶ warehouse / CKAN
simplest ⭐ open lakehouse (default) heaviest
☁️ Substrate — Cloudflare R2 (storage) · Workers (runtime) · D1 (catalog) · Pages (static)
object storage stays S3-compatible — R2 is the default, never a lock-inThree surfaces. Every data portal is built from three: a Home page that explains it and offers search, a Catalog (/search) to discover datasets, and a Showcase (/@<namespace>/<slug>) to explore one dataset — metadata, preview, download/API, and charts/maps. (Core concepts →)
One seam. The surfaces read data only through a DataProvider, so the source — static files today, a CKAN or lakehouse backend tomorrow — can change without touching a page.
See `ROADMAP.md` for the full model and the architecture decision framework for how /architect turns your needs into a stack.
Build a portal with your AI assistant
PortalJS ships Claude Code skills that turn a brief into a working portal.
Setup
The skills live in this repo under `.claude/commands/`. The quickest way to try them is from a clone:
git clone https://github.com/datopian/portaljs
cd portaljs
claudeClaude Code auto-discovers the slash commands from .claude/commands/ — no install step. Type / in the session to see them.
Install anywhere: the skills and template are also packaged as a Claude Code plugin
and can be installed into
~/.claude/commands/so you can run them from any project. See
Use
If you're not sure how to set up your portal, start with the advisor, then build:
/architect we have ~200 public CSVs, updated quarterly, and must publish DCAT-AP
/new-portal "Auckland Council open data portal"
/add-dataset ./data/air-quality.csv
/add-dataset https://example.com/parks.geojsonThe skills are interactive — if your brief is thin, they interview you in short rounds rather than erroring. /architect recommends a stack and hands off; /new-portal scaffolds the three surfaces; /add-dataset appends to the datasets.json manifest and the showcase renders automatically at /@<namespace>/<slug>. Run npm run dev and you have a portal.
Prefer to build by hand? Clone the canonical template — the skills are a convenience, not a requirement:
npx degit datopian/portaljs/examples/portaljs-catalog my-portalAvailable skills
| Skill | What it does |
|---|---|
| `/architect` | Recommend an architecture (storage/compute/catalog/access/hosting/metadata) from your needs, then hand off — the advisory entry point |
| `/new-portal` | Scaffold a new portal (Home + Catalog + Showcase) from a brief |
| `/add-dataset` | Add a CSV, TSV, JSON, or GeoJSON dataset — appends to the manifest; its showcase renders automatically |
| `/add-chart` | Add a chart to a dataset's showcase Views section |
| `/add-map` | Render GeoJSON on an interactive map in the showcase |
| `/connect-ckan` | Feed the catalog and showcases from a CKAN backend |
| `/deploy` | Deploy to Cloudflare Pages, Vercel, or static hosting |
| `/check-data-quality` | Audit a dataset for quality issues (schema, nulls, types) |
More skill families — metadata schemas (Frictionless/DCAT), more backends (OpenMetadata, git-LFS+R2), a DuckDB data layer, and access control — are on the roadmap. Write your own — see `.claude/AUTHORING.md`.
What's in this repo
.claude/commands/ the agentic skills (slash commands)
examples/ reference portals — portaljs-catalog is the canonical template
packages/
core/ layout/UI components (@portaljs/core)
ckan/ CKAN catalog UI + React (@portaljs/ckan)
ckan-api-client-js/ pure CKAN API client (@portaljs/ckan-api-client-js)
site/ portaljs.com — the marketing site + docs
ROADMAP.md direction, the four contracts, sequencingThe canonical template, `examples/portaljs-catalog`, is where the three surfaces and the DataProvider seam live — read it before building.
What makes it different
- •🌱 Open source, MIT, no lock-in — every skill emits plain Next.js you can fork and own.
- •🧭 Advisory, not just generative —
/architecthelps you _decide_ the infrastructure, not only scaffold a UI. - •🦆 Open lakehouse by default — git + R2 + Parquet + DuckLake + DuckDB over a heavy warehouse, with DuckDB as the query engine. A datastore/warehouse stays a supported choice.
- •☁️ Cloudflare-first, portable — R2 / Workers / D1 / Pages as the default substrate, but object storage stays S3-compatible.
- •🧩 Decoupled, any backend — one
DataProvidercontract in front of CKAN, DKAN, OpenMetadata, DataHub, GitHub, Frictionless, plain files — or your own. - •🎨 Bring your own stack — adopt the template or lift the skills and the three-surface model into an app you already have.
Examples
Reference implementations live in `examples/`:
| Example | Backend |
|---|---|
| `portaljs-catalog` | Canonical template — Home + Catalog + Showcase over a static manifest |
| `portaljs-template` | Minimal single-page starter |
| `ckan` · `ckan-ssg` | CKAN |
| `github-backed-catalog` | GitHub |
| `dataset-frictionless` | Frictionless Data Package |
| `fivethirtyeight` · `openspending` · `turing` | Real-world portals |
Community & support
- •💬 Discord — live chat and help: join the server
- •🗣️ Discussions — questions, ideas, show-and-tell: github.com/datopian/portaljs/discussions
- •🐛 Issues — bugs and feature requests: open an issue
- •📖 Docs — portaljs.com/opensource
Contributing
PortalJS is built in the open and we welcome contributions of all sizes — new skills, examples, docs, and fixes. See CONTRIBUTING.md to get started, and read ROADMAP.md and VISION.md for where the project is headed.
License
Install & Usage
mkdir -p .claude/skillsmkdir -p .claude/skills && curl -o .claude/skills/portaljs.md https://raw.githubusercontent.com/datopian/portaljs/main/SKILL.md/portaljsFrequently Asked Questions
What is portaljs?
Scaffold and extend PortalJS data portals: /new-portal, /add-dataset, /add-chart, /add-map, /deploy.
How to install portaljs?
To install portaljs, create the .claude/skills directory in your project, then run the curl command to download the skill file. Once installed, invoke it in Claude Code with /portaljs.
What is portaljs best for?
portaljs is a community categorized under General. It is designed for: deployment. Created by Datopian.