Skip to content
Development
Command

/portaljs-architect

Recommend a data-portal architecture (storage, compute, catalog, access, hosting, metadata) from your needs, then hand off to the build skills. The advisory entry point.

From plugin
portaljs
2.3k25 skills25 commands
Install
> /plugin marketplace add datopian/portaljs
> /plugin install portaljs@datopian-portaljs

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/portaljs-architect

Context preview

What this command does when you run it.

Recommend a data-portal architecture (storage, compute, catalog, access, hosting, metadata) from your needs, then hand off to the build skills. The advisory entry point.

Command definition

portaljs-architect.md
description: Recommend a data-portal architecture (storage, compute, catalog, access, hosting, metadata) from your needs, then hand off to the build skills. The advisory entry point.
allowed-tools: Read, Write, Bash

/portaljs-architect

The **advisory** skill. Before scaffolding anything, it works out *what* to build: given what you're building, what your data is, and what it's for, it recommends a concrete architecture and then hands off to the build skills (`/portaljs-new-portal`, `/portaljs-add-dataset`, `/portaljs-connect-ckan`, …). It **decides**; it does not build.

The skill is **interactive**: if the brief is thin it interviews you in short rounds, echoes an architecture brief for confirmation, and **never dead-ends on missing input** — every question has a sensible default; say **"use defaults"** to take them.

See [the decision framework](../../site/content/docs/architecture/decision-framework.md) and [ROADMAP.md](../../ROADMAP.md) for the full model this skill encodes.

What it recommends — six slots

Every recommendation fills six slots. The **bold** option is the default when nothing pulls you off it.

| Slot | Options (default in **bold**) | |------|-------------------------------| | **Storage** | repo files · **Git-LFS + R2** · Parquet on R2 · CKAN datastore / warehouse | | **Catalog** | `datasets.json` · git + Frictionless · **DuckLake** · backend-native | | **Compute** | papaparse preview · **DuckDB** (Wasm → server) · warehouse engine | | **Access** | **static (public)** · runtime + backend RBAC | | **Hosting** | **Cloudflare Pages** (static) · Cloudflare Workers (runtime) · any static host | | **Metadata** | **Frictionless** profile · extended · custom · multi-profile + DCAT |

Opinionated default stack: `git + giftless/R2 + Parquet + DuckLake + DuckDB`, static on Cloudflare Pages, Frictionless metadata. Storage stays **S3-compatible**, so R2 is the default but never a hard lock-in.

The two build-time knobs this skill sets

Six slots describe the architecture, but two of them resolve to concrete values the build skills read directly. Name both explicitly in the brief — they are what gets *built*:

  • **Data tier** — where a dataset's *bytes* live: `inline | LFS | external`. This is the

Storage slot made concrete, and it is **per-dataset routing** `/portaljs-add-dataset` applies (see its source-then-size matrix):

  • **inline** — bytes committed to `public/data/`. A fenced exception only: the template's

bundled sample data, or an OSS self-host with no R2 creds. Get-started-fast, zero creds.

  • **LFS** — bytes stream to Cloudflare R2 via Giftless (Git LFS); a ~134 B pointer stays

in git. **The default for any data the user adds**, regardless of size or format.

  • **external** — bytes already live at a URL (R2 or 3rd-party); the manifest records the

absolute URL and copies nothing (passthrough). Parquet-on-R2 queried in place lives here.

  • **Query mode** — how the showcase *computes* over a dataset: the `DATA_QUERY` constant in

`lib/datasets.ts`, `flat | duckdb`. This is the Compute slot made concrete, and it is **portal-wide**:

  • **duckdb** — load the file into in-browser DuckDB-Wasm and expose a SQL query view

(filter/aggregate/join, no server). **The template default** — every portal ships the SQL editor out of the box. A Parquet resource always renders the query view regardless; `duckdb` renders it for CSV/TSV too.

  • **flat** — fetch + preview the file with papaparse. Lightest; a *downgrade* from the

default for a preview-only portal that never needs querying.

Steps

1. Interview the user (skip rounds already answered by `$ARGUMENTS`)

Parse `$ARGUMENTS` first and pre-fill anything it specifies. Then ask only for what's missing, **one round at a time** (wait for each answer). Tell the user they can reply "use defaults".

**Round 1 — What are you building?**

Round 1 of 4 — the portal.
1. What kind of portal? (open-data portal · internal data catalog · research/project
   data site · public-sector portal with harvesting obligations · something else)
2. Who runs it — one team/publisher, or several?

**Round 2 — What is your data?**

Round 2 of 4 — the data.
1. Roughly how big? (KBs/MBs · GBs · TBs)
2. What shape? (tabular CSV · geospatial/GeoJSON · documents · mixed)
3. How often does it change? (rarely, by hand · regularly · continuously)
4. How many datasets? (a handful · dozens · hundreds+)
5. Any of it private / access-controlled? (no, all public · yes)

If the user points at actual files or a directory, inspect them to ground the answers instead of guessing — e.g. size and row counts:

# Replace PATHS with the files/dirs the user named.
du -sh PATHS 2>/dev/null
for f in PATHS; do [ -f "$f" ] && printf '%s: ' "$f" && { wc -l < "$f" 2>/dev/null || echo '?'; }; done

**Round 3 — What is it for?**

Round 3 of 4 — the purpose (pick any that apply).
  - publishing & discovery (people find and download datasets)
  - analytics / querying (filter, aggregate, join the data)
  - redistribution / machine-to-machine harvesting (e.g. DCAT to data.europa.eu)
  - compliance with a metadata standard (DCAT-AP, a national or domain profile)

**Round 4 — Constraints.**

Round 4 of 4 — constraints (all optional; Enter to skip).
  - team size / SQL comfort?
  - budget sensitivity?
  - cloud preference? (default: Cloudflare — R2/Workers/Pages, S3-compatible)
  - any existing backend to keep? (e.g. a CKAN or OpenMetadata instance)

**Defaults if a round is skipped:** open-data portal · single publisher · MBs of tabular CSV that changes rarely · a few-to-dozens of datasets · all public · publishing & discovery · Cloudflare, no existing backend.

2. Derive the recommendation

Fill the five slots by applying these rules (first match wins per slot; otherwise use the default):

**Storage · Catalog · Compute** (by data volume + query needs): | Situation | Storage | Catalog | Compute | |

Read more
Ships withportaljs

🌀 AI-native framework for building data portals. Scaffold a full portal from a brief and load datasets in minutes with agentic skills — any backend (CKAN, GitHub, Frictionless).

Get the whole plugin