{"slug": "show-hn-portaljs-ai-native-open-source-framework-for-data-portals", "title": "Show HN: PortalJS – AI-native, open-source framework for data portals", "summary": "Datopian released PortalJS, an open-source, AI-native framework for building data portals that uses agentic skills to recommend architecture and scaffold Next.js code. The framework includes Claude Code commands for creating portals, adding datasets, and deploying, aiming to simplify data infrastructure decisions for teams.", "body_md": "**The AI-native framework for building data portals.**\n\nDescribe the portal you want — your agent helps you choose an architecture, scaffolds it, and loads your data.\n\n[Docs](https://www.portaljs.com/docs)\n·\n[Discussions](https://github.com/datopian/portaljs/discussions)\n·\n[Report a bug](https://github.com/datopian/portaljs/issues/new)\n\n[\n](https://www.npmjs.com/package/create-portaljs)[\n](https://github.com/datopian/portaljs/stargazers)[\n](https://discord.gg/krmj5HM6He)[\n](/datopian/portaljs/blob/main/license)\n\n**Create a portal** — one command, nothing to install beyond Node 22+:\n\n```\nnpm create portaljs@latest my-portal\ncd my-portal\nnpm run dev      # → http://localhost:3000\n```\n\nYou get the three surfaces — Home, a Catalog (`/search`\n\n), and a dataset Showcase\n(`/@<namespace>/<slug>`\n\n) — over sample data. Plain, editable Next.js, no lock-in. Add your\nown CSV/JSON to `datasets.json`\n\nand it renders automatically.\n\n**Build it with your AI assistant** — PortalJS ships [Claude Code](https://claude.com/claude-code)\nskills that do the assembly. Install them once (into `~/.claude/commands`\n\n):\n\n```\ncurl -fsSL https://raw.githubusercontent.com/datopian/portaljs/main/scripts/install-portaljs-skills.sh | bash\n```\n\nThen, in a Claude Code session from any directory:\n\n```\n/portaljs-architect    not sure what stack you need? start here\n/portaljs-new-portal   \"Auckland Council open data portal\"\n/portaljs-add-dataset  ./data/air-quality.csv\n```\n\n`/portaljs-new-portal`\n\nscaffolds the three surfaces; `/portaljs-add-dataset`\n\n(or `/portaljs-add-resource`\n\n) loads data;\n`/portaljs-connect-ckan`\n\npoints it at a CKAN backend; `/portaljs-deploy`\n\nships it. ([All skills + install →](/datopian/portaljs/blob/main/.claude/INSTALL.md))\n\n**Prefer the bare template** — plain Next.js, no AI, no lock-in:\n\n```\nnpx tiged datopian/portaljs/examples/portaljs-catalog my-portal\ncd my-portal && npm install && npm run dev      # → http://localhost:3000\n```\n\nYou get Home, a Catalog (`/search`\n\n), and a dataset Showcase (`/@<namespace>/<slug>`\n\n) over\nsample data. Add your own CSV/JSON to `datasets.json`\n\nand it renders automatically.\n\n⭐ If it's useful, a star helps others find it.\n\nBuilding 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.\n\nPortalJS is an **open-source, agentic skills framework that helps data teams build,\ndevelop, and ship data portals — and the data infrastructure underneath them.** It isn't\nonly a frontend. The skills do two jobs:\n\n**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.\n\nIt is **opinionated but open**: the recommended modern path is git + object storage\n(Cloudflare R2) + Parquet, queried with [DuckDB](https://duckdb.org/) — an open lakehouse\ninstead of a classic warehouse. For living, incremental tables you can layer on\n[DuckLake](https://ducklake.select/), and a traditional datastore (CKAN, a warehouse)\nstays a first-class option when you need it. You always own plain code.\n\nBuilt and maintained in the open by [Datopian](https://www.datopian.com/) and the\nPortalJS community.\n\n```\n        🧑  you describe what you want to build\n        │\n        ▼\n╭─ 🤖  AGENTIC SKILLS ──────────────────────────────────  decide + build\n│   /portaljs-architect · /portaljs-new-portal · /portaljs-add-dataset · /portaljs-add-chart · /portaljs-add-map …\n╰─  generates plain, editable Next.js code — no lock-in\n        │\n        ▼\n╭─ 🖥️  SURFACES ────────────────────────────────────────  what users see\n│   🏠 Home /      🔎 Catalog /search      📊 Showcase /@ns/slug\n╰─  read data through one DataProvider contract\n        │\n        ▼\n╭─ 🔌  PROVIDERS ───────────────────────────────────────  pluggable backends\n│   📁 static·git     🐘 CKAN     🔭 OpenMetadata     🗂️ git-LFS + R2\n╰─  swap the source without touching a page\n        │\n        ▼\n📦  STORAGE + COMPUTE  —  choose your point on the spectrum:\n\n      flat files  ─▶  Git-LFS + R2  ─▶  Parquet on R2 + 🦆 DuckDB  ─▶  warehouse / CKAN\n      simplest                       ⭐ open lakehouse (default)        heaviest\n                                     (+ DuckLake for living tables)\n\n☁️  Substrate  —  Cloudflare R2 (storage) · Workers (runtime) · D1 (catalog) · Pages (static)\n     object storage stays S3-compatible — R2 is the default, never a lock-in\n```\n\n**Three surfaces.** Every data portal is built from three: a **Home** page that explains\nit and offers search, a **Catalog** (`/search`\n\n) to discover datasets, and a **Showcase**\n(`/@<namespace>/<slug>`\n\n) to explore one dataset — metadata, preview, download/API, and\ncharts/maps. ([Core concepts →](https://www.portaljs.com/docs/core-concepts))\n\n**One seam.** The surfaces read data only through a `DataProvider`\n\n, so the source — static\nfiles today, a CKAN or lakehouse backend tomorrow — can change without touching a page.\n\nSee [ ROADMAP.md](/datopian/portaljs/blob/main/ROADMAP.md) for the full model and the\n\n[architecture decision framework](https://www.portaljs.com/docs/architecture/decision-framework)for how\n\n`/portaljs-architect`\n\nturns your needs into a stack.PortalJS ships [Claude Code](https://claude.com/claude-code) skills that turn a brief into\na working portal.\n\nInstall the skills once into your personal scope so they're available from **any**\ndirectory:\n\n```\ncurl -fsSL https://raw.githubusercontent.com/datopian/portaljs/main/scripts/install-portaljs-skills.sh | bash\n```\n\nRestart Claude Code (or open a new session) and type `/`\n\nto see them. See\n[ .claude/INSTALL.md](/datopian/portaljs/blob/main/.claude/INSTALL.md) for other install options (versioned plugin, or\nrunning straight from a clone of this repo).\n\nIf you're not sure how to set up your portal, start with the advisor, then build:\n\n```\n/portaljs-architect    we have ~200 public CSVs, updated quarterly, and must publish DCAT-AP\n/portaljs-new-portal   \"Auckland Council open data portal\"\n/portaljs-add-dataset  ./data/air-quality.csv\n/portaljs-add-dataset  https://example.com/parks.geojson\n```\n\nThe skills are **interactive** — if your brief is thin, they interview you in short rounds\nrather than erroring. `/portaljs-architect`\n\nrecommends a stack and hands off; `/portaljs-new-portal`\n\nscaffolds the three surfaces; `/portaljs-add-dataset`\n\nappends to the `datasets.json`\n\nmanifest and\nthe showcase renders automatically at `/@<namespace>/<slug>`\n\n. Run `npm run dev`\n\nand you\nhave a portal.\n\n**Prefer to build by hand?** The skills are a convenience, not a requirement — scaffold the\ntemplate directly with the CLI:\n\n```\nnpm create portaljs@latest my-portal\n```\n\n(Or grab the bare template with no prompts: `npx tiged datopian/portaljs/examples/portaljs-catalog my-portal`\n\n.)\n\n| Skill | What it does |\n|---|---|\n`/portaljs-architect` |\n\n`/portaljs-new-portal`\n\n`/portaljs-add-dataset`\n\n`/portaljs-add-resource`\n\n`/portaljs-add-chart`\n\n`/portaljs-add-map`\n\n`/portaljs-add-geo`\n\n`/portaljs-define-schema`\n\n`/portaljs-add-dcat`\n\n`/portaljs-connect-ckan`\n\n`/portaljs-check-data-quality`\n\n`/portaljs-migrate`\n\n`/arcgis-to-portaljs`\n\n`/data.json`\n\n, export every FeatureService layer via the ArcGIS REST API, convert to the serverless dual tier (PMTiles + GeoParquet), push to R2, and write a source-vs-derived parity report.`/portaljs-deploy`\n\n`<slug>.arc.portaljs.com`\n\nURL.Large-data scaling — big files pushed to Cloudflare R2 via Git LFS — already ships in\n`/portaljs-add-dataset`\n\n. More skill families — metadata schemas (Frictionless/DCAT), more\nbackends (OpenMetadata), a browser DuckDB query layer, and access control — are on the\n[roadmap](/datopian/portaljs/blob/main/ROADMAP.md). Write your own — see [ .claude/AUTHORING.md](/datopian/portaljs/blob/main/.claude/AUTHORING.md).\n\n```\n.claude/commands/    the agentic skills (slash commands)\nexamples/            reference portals — portaljs-catalog is the canonical template\npackages/\n  core/              layout/UI components            (@portaljs/core)\n  ckan/              CKAN catalog UI + React          (@portaljs/ckan)\n  ckan-api-client-js/ pure CKAN API client            (@portaljs/ckan-api-client-js)\nsite/                portaljs.com — the marketing site + docs\nROADMAP.md           direction, the four contracts, sequencing\n```\n\nThe canonical template, [ examples/portaljs-catalog](/datopian/portaljs/blob/main/examples/portaljs-catalog), is where\nthe three surfaces and the\n\n`DataProvider`\n\nseam live — read it before building.- 🌱\n**Open source, MIT, no lock-in**— every skill emits plain Next.js you can fork and own. - 🧭\n**Advisory, not just generative**—`/portaljs-architect`\n\nhelps you*decide*the infrastructure, not only scaffold a UI. - 🦆\n**Open lakehouse by default**— git + R2 + Parquet queried with DuckDB, over a heavy warehouse; add DuckLake for living/incremental tables. A datastore/warehouse stays a supported choice. - ☁️\n**Cloudflare-first, portable**— R2 / Workers / D1 / Pages as the default substrate, but object storage stays S3-compatible. - 🧩\n**Decoupled, any backend**— one`DataProvider`\n\ncontract in front of[CKAN](https://ckan.org/),[DKAN](https://getdkan.org/),[OpenMetadata](https://open-metadata.org/),[DataHub](https://datahubproject.io/), GitHub,[Frictionless](https://frictionlessdata.io/), plain files — or your own. - 🎨\n**Bring your own stack**— adopt the template or lift the skills and the three-surface model into an app you already have.\n\nReference implementations live in [ examples/](/datopian/portaljs/blob/main/examples):\n\n| Example | Backend |\n|---|---|\n`portaljs-catalog` |\n\n**Canonical template**— Home + Catalog + Showcase over a static manifest`portaljs-template`\n\n[·](/datopian/portaljs/blob/main/examples/ckan)`ckan`\n\n`ckan-ssg`\n\n`github-backed-catalog`\n\n`dataset-frictionless`\n\n[·](/datopian/portaljs/blob/main/examples/fivethirtyeight)`fivethirtyeight`\n\n[·](/datopian/portaljs/blob/main/examples/openspending)`openspending`\n\n`turing`\n\n- 💬\n**Discord**— live chat and help:[join the server](https://discord.gg/krmj5HM6He) - 🗣️\n**Discussions**— questions, ideas, show-and-tell:[github.com/datopian/portaljs/discussions](https://github.com/datopian/portaljs/discussions) - 🐛\n**Issues**— bugs and feature requests:[open an issue](https://github.com/datopian/portaljs/issues/new) - 📖\n**Docs**—[portaljs.com/docs](https://www.portaljs.com/docs)\n\nPortalJS is built in the open and we welcome contributions of all sizes — new skills,\nexamples, docs, and fixes. See [CONTRIBUTING.md](/datopian/portaljs/blob/main/CONTRIBUTING.md) to get started, and read\n[ROADMAP.md](/datopian/portaljs/blob/main/ROADMAP.md) and [VISION.md](/datopian/portaljs/blob/main/VISION.md) for where the project is headed.", "url": "https://wpnews.pro/news/show-hn-portaljs-ai-native-open-source-framework-for-data-portals", "canonical_source": "https://github.com/datopian/portaljs", "published_at": "2026-07-15 12:34:32+00:00", "updated_at": "2026-07-15 12:48:10.668583+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-agents"], "entities": ["Datopian", "PortalJS", "Claude Code", "Next.js", "DuckDB", "Cloudflare R2", "CKAN"], "alternates": {"html": "https://wpnews.pro/news/show-hn-portaljs-ai-native-open-source-framework-for-data-portals", "markdown": "https://wpnews.pro/news/show-hn-portaljs-ai-native-open-source-framework-for-data-portals.md", "text": "https://wpnews.pro/news/show-hn-portaljs-ai-native-open-source-framework-for-data-portals.txt", "jsonld": "https://wpnews.pro/news/show-hn-portaljs-ai-native-open-source-framework-for-data-portals.jsonld"}}