One source of truth for the origins and route paths that link the extension.dev fleet together.
A cross-app link is two halves: the host (which app) and the path (which route inside it). Hardcode either and the day an app moves or a route is renamed, every caller drifts. This package keeps both halves in one place so a link a tool hands back can never point at a route the app router no longer serves.
@extension.dev/urls/paths- pure, environment-free route builders. Safe to call from any runtime (Next.js, Vite SPAs, Node, the bundled MCP) because they read no environment and only encode path shapes.@extension.dev/urls/origins- the host resolver. Each runtime names its env vars differently, so this module never reads the environment itself: the caller passes in whatever overrides it has and gets back a full origin set, with local-dev hosts derived from the Caddy proxy map when the environment looks local, and production hosts otherwise.@extension.dev/urls/userland- whole-URL builders for the public build viewer. userland is the one app whose production host is per-workspace (<workspace>.extension.dev), so its two halves cannot be chosen independently and it gets its own module rather than apathsentry.
npm install @extension.dev/urlsimport { resolveOrigins } from "@extension.dev/urls/origins";
import { consoleProjectPath, ConsoleProjectPage } from "@extension.dev/urls/paths";
const origins = resolveOrigins({
// Pass only the vars this runtime actually has; the rest derive.
www: process.env.EXTENSION_DEV_API_URL,
});
// A full link is `origins.<app> + <pathBuilder>(...)`.
const buildsUrl =
origins.console +
consoleProjectPath({ workspace: "acme", project: "toolbar" }, ConsoleProjectPage.builds);Set a single local override and every unset origin follows it to the dev proxy:
resolveOrigins({ www: "http://localhost:3100" }).console;
// -> "http://console.extension.localhost"The public build viewer takes whole URLs, because the workspace lives in the host in production and in the path locally:
import { userlandBuildUrl } from "@extension.dev/urls/userland";
userlandBuildUrl({ workspace: "acme", project: "toolbar" }, "abc1234");
// -> "https://acme.extension.dev/toolbar/builds/abc1234"
userlandBuildUrl({ workspace: "acme", project: "toolbar" }, "abc1234", {
base: resolveOrigins({ www: "http://localhost:3100" }).userland,
});
// -> "http://userland.extension.localhost/acme/toolbar/builds/abc1234"| Package | Use it to |
|---|---|
@extension.dev/mcp |
Give an AI agent hands: scaffold, run, inspect, and publish extensions |
@extension.dev/skill |
Teach agents the judgment half: cross-browser rules, gotchas, playbooks |
@extension.dev/deploy |
Ship to the Chrome, Firefox, and Edge stores from CI or a terminal |
@extension.dev/artifact-integrity |
Verify artifacts and gate CI on tampered bytes before they ship |
All of it rides on Extension.js, the open-source cross-browser extension framework.
