A portable runtime for programmable URL behavior, and the framework that grows from it. Declare an application's public URL surface in YAML, add JavaScript only where declarative handlers are not enough, and run the same project locally, in a container, on your own infrastructure or on a provider adapter. When the project gets serious, add accounts, data and tools as operator-installed extensions instead of building them again. URL behavior as code.
Documentation · Concepts · The framework · For AI agents · URLCode AI · Starter · Contributing · Security
Your AI should build your application, not your framework. Coding agents rebuild the same routing, validation, middleware, policies and authentication plumbing on every project, and the person ends up owning the plumbing. URLCode represents those behaviors as a strict, portable YAML contract that both people and agents can read: the agent describes what, the runtime owns how, and generated code goes to the part that is actually the application. It is infrastructure for AI-built software, not a framework for building AI models. Why · roadmap.
URLCode needs Node.js 22.13 or later. Pick the installation channel that fits your environment:
# npm
npm install --global @jimhoyd/urlcode@latest
# Homebrew
brew tap jimhoyd-com/urlcode
brew trust jimhoyd-com/urlcode
brew install urlcode
# Generic installer (downloads a release tarball and verifies its SHA-256)
curl -fsSL https://raw.githubusercontent.com/jimhoyd-com/urlcode/main/install.sh | shFor project-local installs, exact version pins, and provenance details, see the installation guide.
urlcode init my-urls && cd my-urls
urlcode devWithout a global install, pin the runtime in the project and run the installed
copy (--no refuses to fetch anything from the registry):
mkdir my-urls && cd my-urls && npm init -y
npm install --save-dev --save-exact @jimhoyd/urlcode
npx --no --package @jimhoyd/urlcode urlcode init .
npm run devThe starter deliberately has no routes. Ask the local MCP get_context tool
(or run urlcode context in the site; the route project is app/), then add the smallest declarative route
or custom code the application needs. urlcode test runs the project's HTTP
fixtures, and urlcode studio opens a read-only page on localhost showing
what each route does and what needs attention
(review report and studio). The install guide covers the checksum-verified
script, project-local installs, the container image and signed provenance. To
work from a clone: git clone … && make dev.
version: "1"
routes:
/hello/{name}:
parameters:
- { name: name, in: path, required: true, schema: { type: string, minLength: 1, maxLength: 80 } }
function:
source: functions/hello.mjs
args: { name: { from: path, name: name } }
env:
GREETING: { value: Hello }export default function hello(request, { args, env }) {
return Response.json({ message: `${env.GREETING}, ${args.name}!` });
}Add middleware: [{ source: middleware/headers.mjs }] to wrap any handler with
await next(). Fourteen ready-made middleware patterns ship in the cookbook
and as urlcode recipes add middleware. See functions and the sandbox
and middleware.
New to the vocabulary? Read Concepts first — route, handler, middleware, policy, extension; project vs operator; trusted vs sandbox; extension vs artifact.
Start with the YAML guide and recipe book, complete field reference, and runnable 40-route cookbook. For AI-assisted authoring, use the AI guide, the bundled agent skills (authoring, operations) and llms.txt. For optional hosted reference and shared skills, use URLCode AI; its anonymous remote MCP augments, rather than replaces, the local project server. Agents can also read installed artifacts (inert extension schemas and examples) through the read-only MCP tools described in artifacts. Follow organization and readability practices as your project grows. Operators should read capacity/concurrency and the DDoS and recovery playbook. Embedding the runtime from TypeScript is covered in TypeScript. All documentation.
All of it lives in docs/ in this repository. See
the roadmap for the retired urlcode-docs site repository.
Core plus three optional bundled extensions and one artifact, one site shape. A project climbs from redirects to a full application by adding YAML; the operator wires trusted extensions in one host file outside the project. The full map, the composition contract and the rules an AI agent must follow are in the framework.
| Component | Adds | Distribution |
|---|---|---|
| urlcode (this repository) | Runtime, CLI, policies, provider adapters, extension contract | npm, GitHub Releases, Homebrew |
| auth extension | Accounts and sessions from Better Auth on one mount; auth: true routes receive the signed-in user id |
add-on on core's GitHub Release |
| store extension | Durable bounded JSON collections exposed as a typed CRUD API, with an optional audit log kept in the same database and a tap to forward it | add-on on core's GitHub Release |
| mcp extension | Declarative MCP tool server over a project-declared tool map | add-on on core's GitHub Release |
| store-schema artifact | Inert store configuration schema and example, for tooling | add-on on core's GitHub Release |
Only core is published to npm. Every add-on is released as a tarball on the
same GitHub Release, at core's version, and core pins each by URL and sha512.
A site adds them with urlcode extensions add <name> or urlcode artifacts add <name> (add-ons);
urlcode upgrade moves core and every add-on together. See package and channel
alignment.
urlcode-dynamic-link and urlcode-short were published once as
0.1.0-alpha.1 and have since been retired: both were unpublished from npm and
their repositories deleted, and neither has a direct successor. A project that
wants stored short links declares a collection through the store extension
(see docs/STORE.md) instead. Anything still pinned to
@jimhoyd/urlcode-dynamic-link@0.1.0-alpha.1
also has to deal with its exact declared peer @jimhoyd/urlcode: 0.4.0-alpha.1,
which cannot be installed beside core 0.4.0-alpha.2 and never will be.
urlcode-middleware was retired too: per-route middleware is native to
core, through the middleware: array documented in
docs/MIDDLEWARE.md. See the roadmap
for that retirement's history and migration note.
version: "1"
extensions:
auth: { version: "1", config: {} }
routes:
/go: { redirect: { url: https://example.com, status: 302 } }
/api/auth/*: { extension: auth, methods: [GET, POST] }
/private:
respond: { text: Signed in }
auth: trueThe YAML names logical extensions; it never names packages, code, databases
or credentials. urlcode init site --with auth writes the route project in
site/app/ with auth's /api/auth/* mount, the operator host site/host.mjs
and a private data/auth.secret; npx urlcode-auth migrate creates Better
Auth's tables, and urlcode serve --host-file host.mjs loads it. Browsers sign
in through Better Auth's own client. Cross-repository acceptance is tracked in
issue 58.
A project is a urlcode.yaml with version: "1". Each route has exactly one
handler: redirect, respond, page, static, download, function,
proxy, conditional or an extension mount, with optional ordered
middleware. The runtime validates the whole project before serving it,
compiles it once, and refuses anything a target cannot enforce with the route
named. Functions and middleware run trusted, in-process, with full Node
access by default; a route opts into an isolated QuickJS/WebAssembly sandbox
with a fresh heap per call and no Node, filesystem or network by declaring
sandbox: true. Either way, the env/secrets the runtime hands a route
come only from operator grants pinned to the project revision; grants govern
that injected context, not the ambient Node environment a trusted, in-process
module can reach on its own like any other code in the host.
URLCode is not a URL shortener: stored short links are declared through the
operator-installed store extension's collections, not core's job. It is not a
general Node web framework: routing, validation, middleware wiring and
policies are declared in YAML, not hand-wired; isolating a specific route's
code from the host is an explicit sandbox: true opt-in, not something every
route gets by writing a handler. It is not a provider configuration format:
infrastructure settings stay out of route YAML.
See project direction, or Concepts
for the vocabulary these two paragraphs use.
This checkout prepares the 0.6.6 core release. The auth, store
and mcp extensions and the store-schema artifact are workspace packages
released as add-on tarballs with core, not npm packages. Package availability
remains a live registry fact: see the GitHub Releases page or
npm view @jimhoyd/urlcode dist-tags. A stable core
version does not close the review and deployment evidence gaps
below. 0.4.0-alpha.1
added the extension contract, capabilities and provider conformance, strict
redirect interchange (since removed), bulk import, recipes and search, TypeScript guest
authoring, conditions, bounded proxy and signals, and the MCP read and
authoring modes. 0.4.0-alpha.2 then made function and middleware routes
run trusted and unsandboxed by default, with sandbox: true as a per-route
opt-in, and removed the native link:/dynamicLinks: YAML shape. That is a
behaviour change for existing projects with no YAML edit; read
the roadmap entry before upgrading. Use the schema and docs from
the runtime revision you run.
The roadmap separates implemented from planned, and production readiness records what is proven and what is not: provider deployments, soak and independent security review remain open.
URLCode is free and open-source software licensed under the Apache License 2.0. Commercial use, modification, redistribution and self-hosting are permitted under its terms.
urlcode init creates a bare, agent-ready site with no routes yet. The
runtime is a pinned dependency of the site; no separate checkout or global
installation is needed.
npx @jimhoyd/urlcode init my-links
cd my-links
npm install
npm run devAlready wrote urlcode.yaml? Run urlcode scaffold --project ./my-links --dry-run,
then remove --dry-run to create missing modules, pages and directories. Existing
files are preserved; code placeholders return 501 until implemented.
Scaffolding guide. Node 22.13+ installed, 22.18+ to run
the TypeScript source. The auth extension runs on the Node target only
(auth).
- Pages, files, downloads:
page,static,downloadwith MIME detection, ETags, ranges and safety limits. Assets. - HTTP: methods, validated path/query/header inputs, body limits, response headers and cookies. HTTP.
- Policies and site conventions: throttle, agents, security headers, compression, cache; robots, sitemap, favicon, security.txt, llms.txt. Policies, site.
- Conditions, proxy, signals: exact predicates with disjoint cases; a bounded HTTPS proxy and best-effort webhooks behind operator grants. Conditions, egress.
- Organization:
includesacross folders; strict CSV/JSON/YAML redirect import; searchable recipes and examples. Organization, bulk, recipes. - Checks:
validate,test,routes,audit --expect-routes,capabilities, deployment verification and a GitHub Action. Readiness, CI.
Self-hosted Node process or container first. @jimhoyd/urlcode/vercel and
@jimhoyd/urlcode/aws serve declarative projects as native handlers;
urlcode build --target cloudflare compiles redirects and declared responses
into a Worker; urlcode build --target static compiles redirects and static
files into plain objects and redirect metadata for S3 + CloudFront, with no
server at all. Each target refuses at activation or build time what it cannot
run, with the route named. None has been exercised on its provider yet; the
adapters have local conformance tests only. Operations,
capabilities, Vercel, AWS,
Cloudflare, static hosting.
llms.txt is the compact index; the framework
is the map; AI authoring is the contract with the
capability matrix and a copyable task prompt. urlcode mcp exposes read-only
inspection, validation and conversion previews over stdio, and
--allow-authoring adds project-confined authoring tools and runner tools that
execute the project's code (tooling).
URLCode AI is the optional hosted companion for
version-pinned reference and shared skills; its anonymous remote MCP endpoint is
documented in tooling.
No public application built on URLCode is currently listed. The reference
application is the private-requests proof
in this repository: owner-private records, a reviewed approval and a reviewer
permission declared over the auth and store extensions, with no application
server code. Its client is the
frontend pattern: the application's own code calling the JSON mounts with
fetch.
The two earlier
ones were built on the public runtime as ordinary consumers and have since been
retired: urlcode-docs, a static documentation site
rendered through its own middleware at build time and served through native
page/static/download routes, and urlcode-short, an account-free short-link
demo combining expiring links, QR downloads and a shadcn/ui frontend — URLCode
supplied the pages, assets and routing, the application supplied anonymous
creation, link storage and its own limits. urlcode-short's repository is
deleted, so its build retrospective is no longer reachable; what it recorded
about the gap between the runtime and a real application is carried in
principles and open decisions and roadmap.
Apache-2.0. Commercial use, modification, redistribution and self-hosting are permitted. See contributing, security, governance and the roadmap.