
PortalJS Deploy
FreeEasily deploy your PortalJS portals to the cloud.
Free · Opens the source repo
What PortalJS Deploy does
PortalJS Deploy is a command-line skill designed for developers looking to publish their PortalJS portals to PortalJS Arc, which is a managed static hosting service provided by Datopian on Cloudflare. This skill streamlines the deployment process by building a static export of your portal, uploading it to the Arc API, and providing you with a live URL for access. The deployment is straightforward and requires only a single command to target the Arc environment, making it ideal for users who want to quickly publish or redeploy their portals without complex setup.
To get started, you need a PortalJS portal directory that includes a package.json file with next as a dependency. The skill requires Node.js version 18 or higher, along with npm, curl, and tar for packaging and uploading your portal. Importantly, it handles the authentication process automatically, either by reading your PortalJS token from the environment or user credentials, which simplifies the initial setup significantly.
The skill is particularly useful for developers who are working with static sites using Next.js and want to leverage the benefits of Cloudflare's hosting. It ensures that your deployment adheres to the necessary configurations, such as setting output: 'export' in your next.config.js, and performs checks to ensure that there are no data issues before the upload. With its idempotent nature, you can redeploy your portal without worrying about overwriting existing configurations, as it will update the same slug in place.
Overall, PortalJS Deploy is a practical tool for developers focused on efficient deployment of their static portals, offering a streamlined process that minimizes manual intervention and potential errors during the deployment phase.
When to use it
Use this skill when you have a PortalJS portal ready for publishing or need to redeploy it to a live URL.
When not to use it
This skill is not suitable for dynamic server-side rendering (SSR) applications, as it only supports static exports.
What you can build with it
Deploying a New Portal
Use the skill to deploy a newly created PortalJS portal by running the command with the default slug.
Redeploying an Existing Portal
Quickly update your existing portal by rerunning the deployment command without changing the slug.
CI/CD Integration
Integrate the skill into your CI/CD pipeline for automated deployments using environment variables for the PortalJS token.
How to install PortalJS Deploy
View source1. Install with the skills CLI
npx skills add jeremylongshore/claude-code-plugins-plus-skills/portaljs-deploy --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by jeremylongshorePortalJS — Deploy
Overview
Publish an existing PortalJS portal to PortalJS Arc — Datopian's managed static
hosting on Cloudflare. Build a static export, upload it to the Arc API, and print a live
https://SLUG.arc.portaljs.com URL. Re-running redeploys the same portal (idempotent on
the slug). This is a single-target skill — it deploys to Arc only. For self-hosting, run
npm run build and upload out/ to any static host; no skill required for that path.
Arc serves static exports only — SSR is not hosted on Arc yet.
Prerequisites
- A PortalJS portal directory with a
package.jsonthat listsnextas a dependency. - Node 18+ and npm on PATH (the Arc device-login flow uses Node's global
fetch). curlandtaravailable for packaging and upload.- A PortalJS Arc token — read from
PORTALJS_TOKEN, or~/.portaljs/credentials({"token":"…"}). If neither exists, the skill signs in on demand via a device-code flow; no manual token copying required. - If the portal stores large data in Git LFS/R2, do not run
git lfs pullbefore deploying — large datasets are served from Cloudflare R2 via absolute URLs indatasets.json, not copied into the export.
Instructions
The canonical, full step-by-step workflow is
.claude/commands/portaljs-deploy.md — the
single source of truth. Read and follow it when executing. Summary:
- Gather input — portal directory (default
.) and slug (default frompackage.jsonname or directory name, slugified). Confirm the directory is a Next.js project; reject reserved slugs (www,api,admin,staging,arc). - Resolve the Arc token: read
PORTALJS_TOKEN, else~/.portaljs/credentials; if missing, run the device-authorization sign-in flow and save the returned token. - Ensure
next.config.jssetsoutput: 'export'andimages: { unoptimized: true }, then runnpm run build; stop if the build fails. - Verify the export carries no dataset bytes — run
npm run check-export(orscripts/check-export.mjs) to catch Git LFS pointer leaks and oversized data files. - Tar the
out/directory andPOSTit to$PORTALJS_ARC_API/v1/deploy?slug=<slug>with the bearer token; handle 200/401/409/400/413 responses distinctly. - Report the live URL, file count, upload size, and R2-vs-inline dataset counts.
Output
- Modified (if needed):
next.config.js— addsoutput: 'export'andimages: { unoptimized: true }when absent, preserving the rest of the config. - Created (on first sign-in):
~/.portaljs/credentials(mode0600). - Verified:
npm run buildexits 0,out/index.htmlexists, the export-hygiene check passes. - Result: the portal is live at
https://SLUG.arc.portaljs.com; re-running updates the same slug in place.
Error Handling
| Symptom | Cause | Fix |
|---|---|---|
NOT_A_PORTAL error | No next dependency found in PORTAL_DIR/package.json | Run from a valid portal directory, or pass the correct path. |
| Slug rejected | Derived slug is reserved (www, api, …) or not a valid DNS label | Pass an explicit --slug <name>. |
| Build fails (non-zero exit) | App/config error surfaced in npm run build | Print the log, fix the error, never deploy a failing build. |
check-export fails | Git LFS pointer leaked into out/, or a data file exceeds the size budget | Reference large data by absolute R2 URL via portaljs-add-dataset; don't git lfs pull before building. |
401 on upload | Token invalid, expired, or revoked | Re-run the device sign-in flow once, retry the upload; stop if it 401s again. |
409 on upload | Slug already taken by another account | Choose a different --slug. |
400 / 413 on upload | Malformed slug or export too large | Read the JSON error field and address the specific cause. |
Examples
Example 1 — Deploy the current directory with the default slug
/portaljs-deploy
Example 2 — Deploy with an explicit slug
/portaljs-deploy --slug my-open-data
Example 3 — Non-interactive deploy from CI with a token env var
export PORTALJS_TOKEN=arc_live_xxxxxxxx
/portaljs-deploy ./portals/city-budget --slug city-budget
Resources
- Full workflow:
.claude/commands/portaljs-deploy.md - Deploy internals reference:
references/reference.md - Related skills:
portaljs-new-portal,portaljs-add-dataset,portaljs-connect-ckan - PortalJS Arc dashboard (sign in, manage tokens): https://arc.portaljs.com
Frequently asked questions about PortalJS Deploy
Similar skills
Turborepo
Optimized build system for JavaScript/TypeScript monorepos.
Azure Pipelines Validation
Streamline your Azure DevOps pipeline changes locally.
Azure Developer CLI
Streamline your Azure project workflows with best practices.
Azure Container Registry CLI
Manage Azure Container Registry resources with ease.
Aspire
Build and orchestrate polyglot distributed applications seamlessly.
Vercel CLI
Manage and deploy Vercel projects from the command line.
