diff --git a/src/content/changelog/artifacts/2026-04-16-artifacts-now-in-beta.mdx b/src/content/changelog/artifacts/2026-04-16-artifacts-now-in-beta.mdx
new file mode 100644
index 000000000000000..251305fc973ae9e
--- /dev/null
+++ b/src/content/changelog/artifacts/2026-04-16-artifacts-now-in-beta.mdx
@@ -0,0 +1,11 @@
+---
+title: "Artifacts now in beta: versioned filesystem that can speak git"
+description: Artifacts is now available in beta as a versioned filesystem for Workers, APIs, and git-compatible workflows.
+products:
+ - artifacts
+date: 2026-04-16
+---
+
+[Artifacts](/artifacts/) is now in beta. It provides a versioned filesystem for storing and exchanging file trees across Workers, the REST API, and git-compatible clients.
+
+Use Artifacts to publish build outputs, sync repositories, and move files between tools without inventing a new packaging format. For more information, refer to [Get started](/artifacts/get-started/) and [API](/artifacts/api/).
diff --git a/src/content/directory/artifacts.yaml b/src/content/directory/artifacts.yaml
new file mode 100644
index 000000000000000..ea258e432ea891a
--- /dev/null
+++ b/src/content/directory/artifacts.yaml
@@ -0,0 +1,12 @@
+id: a9X2kP
+name: Artifacts
+
+entry:
+ title: Artifacts
+ url: /artifacts/
+ group: Developer platform
+
+meta:
+ title: Cloudflare Artifacts docs
+ description: Store, version, and share filesystem artifacts across Workers, APIs, and git-compatible tools
+ author: "@cloudflare"
diff --git a/src/content/docs/artifacts/api/artifacts-fs.mdx b/src/content/docs/artifacts/api/artifacts-fs.mdx
new file mode 100644
index 000000000000000..52bfb54127478b8
--- /dev/null
+++ b/src/content/docs/artifacts/api/artifacts-fs.mdx
@@ -0,0 +1,11 @@
+---
+title: ArtifactsFS
+description: Reference the Artifacts filesystem interface.
+pcx_content_type: reference
+sidebar:
+ order: 4
+---
+
+ArtifactsFS provides filesystem-oriented access to Artifact contents for code and tooling that expect file and directory semantics.
+
+This reference will document supported filesystem operations, path handling, and consistency expectations.
diff --git a/src/content/docs/artifacts/api/authenticated-remote-urls.mdx b/src/content/docs/artifacts/api/authenticated-remote-urls.mdx
new file mode 100644
index 000000000000000..1dbb97a78a11a8c
--- /dev/null
+++ b/src/content/docs/artifacts/api/authenticated-remote-urls.mdx
@@ -0,0 +1,11 @@
+---
+title: Authenticated remote URLs
+description: Reference authenticated remote URL support for Artifacts.
+pcx_content_type: reference
+sidebar:
+ order: 5
+---
+
+Authenticated remote URLs let tools access Artifact-backed remotes using scoped credentials.
+
+This reference will document URL formats, authentication flows, and operational considerations for remote access.
diff --git a/src/content/docs/artifacts/api/git-support.mdx b/src/content/docs/artifacts/api/git-support.mdx
new file mode 100644
index 000000000000000..1a9b28affeebcda
--- /dev/null
+++ b/src/content/docs/artifacts/api/git-support.mdx
@@ -0,0 +1,11 @@
+---
+title: Git support
+description: Reference the git-compatible workflows supported by Artifacts.
+pcx_content_type: reference
+sidebar:
+ order: 3
+---
+
+Artifacts can expose versioned filesystem content through git-compatible workflows.
+
+This reference will document supported operations, compatibility expectations, and integration constraints for git-based tooling.
diff --git a/src/content/docs/artifacts/api/index.mdx b/src/content/docs/artifacts/api/index.mdx
new file mode 100644
index 000000000000000..e8755c04fe5d158
--- /dev/null
+++ b/src/content/docs/artifacts/api/index.mdx
@@ -0,0 +1,15 @@
+---
+title: API
+description: Reference the Artifacts Workers binding, REST API, and filesystem interfaces.
+pcx_content_type: navigation
+sidebar:
+ order: 4
+ group:
+ hideIndex: true
+---
+
+import { DirectoryListing } from "~/components";
+
+Use the Artifacts API reference to understand the interfaces exposed across Workers, HTTP, git-compatible workflows, and filesystem access.
+
+
diff --git a/src/content/docs/artifacts/api/rest-api.mdx b/src/content/docs/artifacts/api/rest-api.mdx
new file mode 100644
index 000000000000000..8843a5840bb59d5
--- /dev/null
+++ b/src/content/docs/artifacts/api/rest-api.mdx
@@ -0,0 +1,487 @@
+---
+title: REST API
+description: Manage Artifacts repos and tokens over HTTP.
+pcx_content_type: reference
+sidebar:
+ order: 2
+head:
+ - tag: title
+ content: REST API · Artifacts
+---
+
+import { LinkCard, MetaInfo, Type } from "~/components";
+
+Use the Artifacts REST API to manage repos, remotes, forks, imports, and tokens from external systems.
+
+## Base URL and authentication
+
+All routes are scoped to a namespace:
+
+```txt
+/v1/api/namespaces/:namespace
+```
+
+Requests use Bearer authentication:
+
+```txt
+Authorization: Bearer
+```
+
+The following examples assume:
+
+```sh
+export ARTIFACTS_BASE_URL="https://artifacts.cloudflare.dev"
+export ARTIFACTS_NAMESPACE="default"
+export ARTIFACTS_REPO="starter-repo"
+export ARTIFACTS_JWT=""
+```
+
+## Shared types
+
+```ts
+export type NamespaceName = string;
+export type RepoName = string;
+export type Scope = "read" | "write";
+export type ArtifactToken = string;
+export type Cursor = string;
+
+export interface RepoInfo {
+ id: string;
+ name: RepoName;
+ createdAt: string;
+ source: string | null;
+ readOnly: boolean;
+}
+
+export interface RemoteRepoInfo extends RepoInfo {
+ remote: string;
+}
+
+export interface TokenInfo {
+ id: string;
+ scope: Scope;
+ createdAt: string;
+ expiresAt: string;
+}
+```
+
+## Repos
+
+### Create a repo
+
+Route: `POST /v1/api/namespaces/:namespace/repos`
+
+Request body:
+
+- `name`
+- `readOnly`
+
+Response type:
+
+```ts
+export interface CreateRepoRequest {
+ name: RepoName;
+ readOnly?: boolean;
+}
+
+export interface CreateRepoResponse {
+ id: string;
+ name: RepoName;
+ remote: string;
+ token: ArtifactToken;
+ expiresAt: string;
+}
+```
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/repos" \
+--header "Authorization: Bearer $ARTIFACTS_JWT" \
+--header "Content-Type: application/json" \
+--data '{
+ "name": "starter-repo"
+}'
+```
+
+```json
+{
+ "id": "repo_123",
+ "name": "starter-repo",
+ "remote": "https://.artifacts.cloudflare.dev/git/default/starter-repo.git",
+ "token": "art_v1_0123456789abcdef0123456789abcdef01234567?expires=1760000000",
+ "expiresAt": ""
+}
+```
+
+### List repos
+
+Route: `GET /v1/api/namespaces/:namespace/repos?limit=&cursor=`
+
+Query parameters:
+
+- `limit`
+- `cursor`
+
+Response type:
+
+```ts
+export interface ListReposQuery {
+ limit?: number;
+ cursor?: Cursor;
+}
+
+export interface ListReposResponse {
+ repos: RepoInfo[];
+ total: number;
+ cursor?: Cursor;
+}
+```
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/repos?limit=20" \
+--header "Authorization: Bearer $ARTIFACTS_JWT"
+```
+
+```json
+{
+ "repos": [
+ {
+ "id": "repo_123",
+ "name": "starter-repo",
+ "createdAt": "",
+ "source": null,
+ "readOnly": false
+ }
+ ],
+ "total": 1
+}
+```
+
+### Get a repo
+
+Route: `GET /v1/api/namespaces/:namespace/repos/:name`
+
+Response type:
+
+```ts
+export type GetRepoResponse = RemoteRepoInfo;
+```
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/repos/$ARTIFACTS_REPO" \
+--header "Authorization: Bearer $ARTIFACTS_JWT"
+```
+
+```json
+{
+ "id": "repo_123",
+ "name": "starter-repo",
+ "createdAt": "",
+ "source": null,
+ "readOnly": false,
+ "remote": "https://.artifacts.cloudflare.dev/git/default/starter-repo.git"
+}
+```
+
+### Delete a repo
+
+Route: `DELETE /v1/api/namespaces/:namespace/repos/:name`
+
+Response type:
+
+```ts
+export interface DeleteRepoResponse {
+ deleted: RepoName;
+}
+```
+
+```bash
+curl --request DELETE \
+"$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/repos/$ARTIFACTS_REPO" \
+--header "Authorization: Bearer $ARTIFACTS_JWT"
+```
+
+```json
+{
+ "deleted": "starter-repo"
+}
+```
+
+### Fork a repo
+
+Route: `POST /v1/api/namespaces/:namespace/repos/:name/fork`
+
+Request body:
+
+- `name`
+- `readOnly`
+
+Response type:
+
+```ts
+export interface ForkRepoRequest {
+ name: RepoName;
+ readOnly?: boolean;
+}
+
+export interface ForkRepoResponse extends CreateRepoResponse {
+ objects: number;
+}
+```
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/repos/$ARTIFACTS_REPO/fork" \
+--header "Authorization: Bearer $ARTIFACTS_JWT" \
+--header "Content-Type: application/json" \
+--data '{
+ "name": "starter-repo-copy"
+}'
+```
+
+```json
+{
+ "id": "repo_456",
+ "name": "starter-repo-copy",
+ "remote": "https://.artifacts.cloudflare.dev/git/default/starter-repo-copy.git",
+ "token": "art_v1_89abcdef0123456789abcdef0123456789abcdef?expires=1760003600",
+ "expiresAt": "",
+ "objects": 128
+}
+```
+
+### Import a GitHub repository
+
+Route: `POST /v1/api/namespaces/:namespace/repos/:name/import`
+
+Request body:
+
+- `url`
+- `branch`
+- `readOnly`
+
+Response type:
+
+```ts
+export interface ImportRepoRequest {
+ url: string;
+ branch?: string;
+ readOnly?: boolean;
+}
+
+export type ImportRepoResponse = CreateRepoResponse;
+```
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/repos/react-mirror/import" \
+--header "Authorization: Bearer $ARTIFACTS_JWT" \
+--header "Content-Type: application/json" \
+--data '{
+ "url": "facebook/react",
+ "branch": "main"
+}'
+```
+
+```json
+{
+ "id": "repo_789",
+ "name": "react-mirror",
+ "remote": "https://.artifacts.cloudflare.dev/git/default/react-mirror.git",
+ "token": "art_v1_fedcba9876543210fedcba9876543210fedcba98?expires=1760007200",
+ "expiresAt": ""
+}
+```
+
+## Tokens
+
+### List tokens for a repo
+
+Route: `GET /v1/api/namespaces/:namespace/repos/:name/tokens`
+
+Response type:
+
+```ts
+export interface ListTokensResponse {
+ tokens: TokenInfo[];
+}
+```
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/repos/$ARTIFACTS_REPO/tokens" \
+--header "Authorization: Bearer $ARTIFACTS_JWT"
+```
+
+```json
+{
+ "tokens": [
+ {
+ "id": "tok_123",
+ "scope": "read",
+ "createdAt": "",
+ "expiresAt": ""
+ }
+ ]
+}
+```
+
+### Create a token
+
+Route: `POST /v1/api/namespaces/:namespace/tokens`
+
+Request body:
+
+- `repo`
+- `scope`
+- `ttl`
+
+Response type:
+
+```ts
+export interface CreateTokenRequest {
+ repo: RepoName;
+ scope?: Scope;
+ ttl?: number;
+}
+
+export interface CreateTokenResponse {
+ id: string;
+ plaintext: ArtifactToken;
+ scope: Scope;
+ expiresAt: string;
+}
+```
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/tokens" \
+--header "Authorization: Bearer $ARTIFACTS_JWT" \
+--header "Content-Type: application/json" \
+--data '{
+ "repo": "starter-repo",
+ "scope": "read",
+ "ttl": 3600
+}'
+```
+
+```json
+{
+ "id": "tok_123",
+ "plaintext": "art_v1_0123456789abcdef0123456789abcdef01234567?expires=1760000000",
+ "scope": "read",
+ "expiresAt": ""
+}
+```
+
+### Validate a token
+
+Route: `POST /v1/api/namespaces/:namespace/tokens/validate`
+
+Request body:
+
+- `repo`
+- `token`
+
+Response type:
+
+```ts
+export interface ValidateTokenRequest {
+ token: ArtifactToken;
+ repo: RepoName;
+}
+
+export interface ValidateTokenResponse {
+ valid: boolean;
+ scope?: Scope;
+}
+```
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/tokens/validate" \
+--header "Authorization: Bearer $ARTIFACTS_JWT" \
+--header "Content-Type: application/json" \
+--data '{
+ "repo": "starter-repo",
+ "token": "art_v1_0123456789abcdef0123456789abcdef01234567?expires=1760000000"
+}'
+```
+
+```json
+{
+ "valid": true,
+ "scope": "read"
+}
+```
+
+### Revoke a token
+
+Route: `POST /v1/api/namespaces/:namespace/tokens/revoke`
+
+Request body:
+
+- `token`
+- `id`
+
+Provide either `token` or `id`.
+
+Response type:
+
+```ts
+export interface RevokeTokenRequest {
+ token?: ArtifactToken;
+ id?: string;
+}
+
+export interface RevokeTokenResponse {
+ revoked: true;
+}
+```
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/tokens/revoke" \
+--header "Authorization: Bearer $ARTIFACTS_JWT" \
+--header "Content-Type: application/json" \
+--data '{
+ "id": "tok_123"
+}'
+```
+
+```json
+{
+ "revoked": true
+}
+```
+
+## Errors
+
+The API can return application errors and authentication errors.
+
+```ts
+export interface ApiError {
+ error: string;
+}
+
+export interface AuthError {
+ success: false;
+ errors: Array<{
+ code: 10000;
+ message: string;
+ }>;
+}
+```
+
+## Next steps
+
+
+
+
+
+
diff --git a/src/content/docs/artifacts/api/workers-binding.mdx b/src/content/docs/artifacts/api/workers-binding.mdx
new file mode 100644
index 000000000000000..ff06a2758b05be9
--- /dev/null
+++ b/src/content/docs/artifacts/api/workers-binding.mdx
@@ -0,0 +1,517 @@
+---
+title: Workers binding
+description: Call Artifacts from a Worker service binding.
+pcx_content_type: reference
+sidebar:
+ order: 1
+head:
+ - tag: title
+ content: Workers binding · Artifacts
+---
+
+import {
+ LinkCard,
+ MetaInfo,
+ Type,
+ TypeScriptExample,
+ WranglerConfig,
+} from "~/components";
+
+Use the Artifacts Workers binding to create, inspect, import, fork, and delete repos without making raw HTTP calls from your Worker.
+
+The binding is a Worker-to-Worker RPC surface. It returns repo handles for repo-scoped operations such as token management and forking.
+
+## Configure the binding
+
+Add the Artifacts binding to `wrangler.jsonc`:
+
+
+
+```jsonc title="wrangler.jsonc"
+{
+ "services": [
+ {
+ "binding": "ARTIFACTS",
+ "service": "artifacts",
+ "entrypoint": "ArtifactsBinding",
+ },
+ ],
+}
+```
+
+
+
+Your Worker environment looks like this:
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+export interface Env {
+ ARTIFACTS: Service;
+}
+```
+
+## Shared types
+
+These are the core public types used by the binding.
+
+```ts
+export type NamespaceName = string;
+export type RepoName = string;
+export type Scope = "read" | "write";
+export type ArtifactToken = string;
+export type Cursor = string;
+
+export interface RemoteRepoInfo {
+ id: string;
+ name: RepoName;
+ createdAt: string;
+ source: string | null;
+ readOnly: boolean;
+ remote: string;
+}
+
+export interface CreateRepoResponse {
+ id: string;
+ name: RepoName;
+ remote: string;
+ token: ArtifactToken;
+ expiresAt: string;
+}
+
+export interface ListReposResponse {
+ repos: Array<{
+ id: string;
+ name: RepoName;
+ createdAt: string;
+ source: string | null;
+ readOnly: boolean;
+ }>;
+ total: number;
+ cursor?: Cursor;
+}
+
+export interface CreateTokenResponse {
+ id: string;
+ plaintext: ArtifactToken;
+ scope: Scope;
+ expiresAt: string;
+}
+
+export interface ValidateTokenResponse {
+ valid: boolean;
+ scope?: Scope;
+}
+
+export interface TokenInfo {
+ id: string;
+ scope: Scope;
+ createdAt: string;
+ expiresAt: string;
+}
+```
+
+## Binding surface
+
+```ts
+export interface ArtifactsRepoHandle {
+ info(): Promise;
+ createToken(scope?: Scope, ttl?: number): Promise;
+ validateToken(token: ArtifactToken): Promise;
+ listTokens(): Promise<{ tokens: TokenInfo[]; total: number }>;
+ revokeToken(tokenOrId: string): Promise;
+ fork(target: {
+ name: RepoName;
+ namespace?: NamespaceName;
+ readOnly?: boolean;
+ }): Promise;
+}
+
+export interface ArtifactsBinding {
+ create(
+ name: RepoName,
+ opts?: { readOnly?: boolean },
+ ): Promise;
+
+ get(name: RepoName): Promise;
+
+ list(opts?: { limit?: number; cursor?: Cursor }): Promise;
+
+ delete(name: RepoName): Promise;
+
+ import(
+ name: RepoName,
+ source: {
+ url: string;
+ branch?: string;
+ headers?: Record;
+ readOnly?: boolean;
+ },
+ ): Promise;
+}
+```
+
+## Namespace methods
+
+### `create(name, opts?)`
+
+- `name`
+- `opts.readOnly`
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function createRepo(artifacts: Service) {
+ // Create the repo and capture the initial write token.
+ const created = await artifacts.create("starter-repo");
+
+ return {
+ name: created.name,
+ remote: created.remote,
+ initialToken: created.token,
+ };
+}
+```
+
+
+
+### `get(name)`
+
+- `name`
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function getRepoHandle(artifacts: Service) {
+ // Resolve the handle once, then reuse it for repo-scoped methods.
+ const repo = await artifacts.get("starter-repo");
+
+ if (!repo) {
+ return null;
+ }
+
+ return repo;
+}
+```
+
+
+
+### `list(opts?)`
+
+- `opts.limit`
+- `opts.cursor`
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function listRepos(artifacts: Service) {
+ // Request a small page when you only need recent repo names.
+ const page = await artifacts.list({ limit: 10 });
+
+ return page.repos.map((repo) => repo.name);
+}
+```
+
+
+
+### `delete(name)`
+
+- `name`
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function deleteRepo(artifacts: Service) {
+ // Delete returns true when the repo was removed.
+ return artifacts.delete("starter-repo");
+}
+```
+
+
+
+### `import(name, source)`
+
+- `name`
+- `source.url`
+- `source.branch`
+- `source.headers`
+- `source.readOnly`
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function importRepo(artifacts: Service) {
+ // Import a public GitHub repo into Artifacts.
+ const imported = await artifacts.import("react-mirror", {
+ url: "facebook/react",
+ branch: "main",
+ });
+
+ return imported.remote;
+}
+```
+
+
+
+## Repo handle methods
+
+Use `await artifacts.get(name)` or the `repo` returned by `create()`, `import()`, or `fork()` to access repo-scoped methods.
+
+### `info()`
+
+- Returns
+
+Use `info()` when you need repo metadata, including the authenticated remote URL. The binding does not expose a separate `.remote()` method.
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function getRemoteUrl(artifacts: Service) {
+ const repo = await artifacts.get("starter-repo");
+ if (!repo) {
+ return null;
+ }
+
+ // Read the remote URL from repo metadata.
+ const info = await repo.info();
+ return info?.remote ?? null;
+}
+```
+
+
+
+### `createToken(scope?, ttl?)`
+
+- `scope`
+- `ttl`
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function mintReadToken(artifacts: Service) {
+ const repo = await artifacts.get("starter-repo");
+ if (!repo) {
+ throw new Error("Repo not found");
+ }
+
+ // Create a short-lived read token for another tool.
+ return repo.createToken("read", 3600);
+}
+```
+
+
+
+### `validateToken(token)`
+
+- `token`
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function validateToken(
+ artifacts: Service,
+ token: string,
+) {
+ const repo = await artifacts.get("starter-repo");
+ if (!repo) {
+ throw new Error("Repo not found");
+ }
+
+ // Check whether the presented token is still valid.
+ return repo.validateToken(token);
+}
+```
+
+
+
+### `listTokens()`
+
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function listRepoTokens(artifacts: Service) {
+ const repo = await artifacts.get("starter-repo");
+ if (!repo) {
+ throw new Error("Repo not found");
+ }
+
+ // Inspect active tokens for cleanup or auditing.
+ const result = await repo.listTokens();
+ return result.tokens;
+}
+```
+
+
+
+### `revokeToken(tokenOrId)`
+
+- `tokenOrId`
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function revokeToken(
+ artifacts: Service,
+ tokenId: string,
+) {
+ const repo = await artifacts.get("starter-repo");
+ if (!repo) {
+ throw new Error("Repo not found");
+ }
+
+ // Revoke by token ID or plaintext token value.
+ return repo.revokeToken(tokenId);
+}
+```
+
+
+
+### `fork(target)`
+
+- `target.name`
+- `target.namespace`
+- `target.readOnly`
+- Returns
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+async function forkRepo(artifacts: Service) {
+ const repo = await artifacts.get("starter-repo");
+ if (!repo) {
+ throw new Error("Repo not found");
+ }
+
+ // Fork into a new repo and keep the returned handle.
+ const forked = await repo.fork({
+ name: "starter-repo-copy",
+ });
+
+ return forked.remote;
+}
+```
+
+
+
+## Worker example
+
+This example combines the binding methods in one Worker route.
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+interface Env {
+ ARTIFACTS: Service;
+}
+
+export default {
+ async fetch(request: Request, env: Env): Promise {
+ const url = new URL(request.url);
+
+ if (request.method === "POST" && url.pathname === "/repos") {
+ // Create a repo and return its initial remote.
+ const created = await env.ARTIFACTS.create("starter-repo");
+ return Response.json({
+ name: created.name,
+ remote: created.remote,
+ });
+ }
+
+ if (request.method === "GET" && url.pathname === "/repos/starter-repo") {
+ const repo = await env.ARTIFACTS.get("starter-repo");
+ if (!repo) {
+ return Response.json({ error: "Repo not found" }, { status: 404 });
+ }
+
+ // Fetch the current repo metadata, including its remote URL.
+ const info = await repo.info();
+ return Response.json(info);
+ }
+
+ if (request.method === "POST" && url.pathname === "/tokens") {
+ const repo = await env.ARTIFACTS.get("starter-repo");
+ if (!repo) {
+ return Response.json({ error: "Repo not found" }, { status: 404 });
+ }
+
+ // Mint a short-lived read token for external tooling.
+ const token = await repo.createToken("read", 3600);
+ return Response.json(token);
+ }
+
+ return Response.json(
+ { message: "Use POST /repos, GET /repos/starter-repo, or POST /tokens." },
+ { status: 404 },
+ );
+ },
+} satisfies ExportedHandler;
+```
+
+
+
+## Next steps
+
+
+
+
+
+
diff --git a/src/content/docs/artifacts/concepts/best-practices.mdx b/src/content/docs/artifacts/concepts/best-practices.mdx
new file mode 100644
index 000000000000000..6fe0804841a397c
--- /dev/null
+++ b/src/content/docs/artifacts/concepts/best-practices.mdx
@@ -0,0 +1,11 @@
+---
+title: Best practices for Artifacts
+description: Follow recommended patterns for storing, organizing, and consuming Artifacts.
+pcx_content_type: concept
+sidebar:
+ order: 2
+---
+
+Use consistent naming, version promotion, and lifecycle conventions so Artifact producers and consumers can share file trees safely.
+
+This page will document recommended patterns for structuring repositories, limiting large writes, handling retention, and integrating Artifacts into deployment or agent workflows.
diff --git a/src/content/docs/artifacts/concepts/how-artifacts-works.mdx b/src/content/docs/artifacts/concepts/how-artifacts-works.mdx
new file mode 100644
index 000000000000000..827be92c3d56c90
--- /dev/null
+++ b/src/content/docs/artifacts/concepts/how-artifacts-works.mdx
@@ -0,0 +1,11 @@
+---
+title: How Artifacts works
+description: Understand the Artifacts data model and versioned filesystem behavior.
+pcx_content_type: concept
+sidebar:
+ order: 1
+---
+
+Artifacts provides a versioned filesystem abstraction for storing and exchanging file trees.
+
+This page will describe how Artifacts stores versions, addresses filesystem content, and exposes the same underlying data through Workers, the REST API, and git-compatible interfaces.
diff --git a/src/content/docs/artifacts/concepts/index.mdx b/src/content/docs/artifacts/concepts/index.mdx
new file mode 100644
index 000000000000000..77572961314dace
--- /dev/null
+++ b/src/content/docs/artifacts/concepts/index.mdx
@@ -0,0 +1,15 @@
+---
+title: Concepts
+description: Learn how Artifacts works and how to use it effectively.
+pcx_content_type: navigation
+sidebar:
+ order: 3
+ group:
+ hideIndex: true
+---
+
+import { DirectoryListing } from "~/components";
+
+Use these concepts to understand the data model, versioning behavior, and operating model for Artifacts.
+
+
diff --git a/src/content/docs/artifacts/examples/git-client.mdx b/src/content/docs/artifacts/examples/git-client.mdx
new file mode 100644
index 000000000000000..4eb145e360a6f43
--- /dev/null
+++ b/src/content/docs/artifacts/examples/git-client.mdx
@@ -0,0 +1,11 @@
+---
+title: Git client
+description: Example Artifacts integration with a git client.
+pcx_content_type: example
+sidebar:
+ order: 1
+---
+
+This example will show how a git client can clone, fetch, or push against an Artifact-backed remote.
+
+Use it as a reference for local development workflows and repository-style synchronization.
diff --git a/src/content/docs/artifacts/examples/index.mdx b/src/content/docs/artifacts/examples/index.mdx
new file mode 100644
index 000000000000000..3d1bf8718bdaf5e
--- /dev/null
+++ b/src/content/docs/artifacts/examples/index.mdx
@@ -0,0 +1,15 @@
+---
+title: Examples
+description: Explore example Artifacts integrations.
+pcx_content_type: navigation
+sidebar:
+ order: 6
+ group:
+ hideIndex: true
+---
+
+import { DirectoryListing } from "~/components";
+
+Use these examples to see how Artifacts can fit into developer tools, clients, and execution environments.
+
+
diff --git a/src/content/docs/artifacts/examples/opencode-plugin.mdx b/src/content/docs/artifacts/examples/opencode-plugin.mdx
new file mode 100644
index 000000000000000..d7916f22ff45f04
--- /dev/null
+++ b/src/content/docs/artifacts/examples/opencode-plugin.mdx
@@ -0,0 +1,11 @@
+---
+title: OpenCode plugin
+description: Example Artifacts integration with an OpenCode plugin.
+pcx_content_type: example
+sidebar:
+ order: 2
+---
+
+This example will show how an OpenCode plugin can publish or consume Artifact versions as part of an automation or agent workflow.
+
+Use it as a reference for tool integrations that need durable file trees.
diff --git a/src/content/docs/artifacts/examples/sandbox-sdk-artifacts.mdx b/src/content/docs/artifacts/examples/sandbox-sdk-artifacts.mdx
new file mode 100644
index 000000000000000..7c56bb4dabe387c
--- /dev/null
+++ b/src/content/docs/artifacts/examples/sandbox-sdk-artifacts.mdx
@@ -0,0 +1,11 @@
+---
+title: Sandbox SDK + Artifacts
+description: Example Artifacts integration with Sandbox SDK.
+pcx_content_type: example
+sidebar:
+ order: 3
+---
+
+This example will show how Sandbox SDK workloads can read from and write to Artifacts during isolated execution.
+
+Use it as a reference for build, analysis, and agent workflows that need shared versioned storage.
diff --git a/src/content/docs/artifacts/get-started/index.mdx b/src/content/docs/artifacts/get-started/index.mdx
new file mode 100644
index 000000000000000..214bef27e911b80
--- /dev/null
+++ b/src/content/docs/artifacts/get-started/index.mdx
@@ -0,0 +1,15 @@
+---
+title: Get started
+description: Start using Artifacts with Workers or the REST API.
+pcx_content_type: navigation
+sidebar:
+ order: 2
+ group:
+ hideIndex: true
+---
+
+import { DirectoryListing } from "~/components";
+
+Start here to create, inspect, and version Artifacts from Cloudflare developer workflows.
+
+
diff --git a/src/content/docs/artifacts/get-started/rest-api.mdx b/src/content/docs/artifacts/get-started/rest-api.mdx
new file mode 100644
index 000000000000000..8c0cbc25bac0d32
--- /dev/null
+++ b/src/content/docs/artifacts/get-started/rest-api.mdx
@@ -0,0 +1,158 @@
+---
+title: REST API
+description: Create an Artifact repo over HTTP.
+pcx_content_type: get-started
+sidebar:
+ order: 2
+head:
+ - tag: title
+ content: Get started - REST API
+---
+
+import { LinkCard } from "~/components";
+
+Create an Artifact namespace and repo with the REST API, then use a regular git client to push and pull content.
+
+In this guide, you will create a namespace, create a repo inside it, read back the repo remote URL, and use that remote with `git push` and `git clone`.
+
+## Prerequisites
+
+You need:
+
+- A Cloudflare account with access to Artifacts.
+- A control-plane JWT for the Artifacts API.
+- A local `git` client.
+
+## 1. Export your environment variables
+
+Set the variables used in the examples:
+
+```sh
+export ARTIFACTS_BASE_URL="https://artifacts.cloudflare.dev"
+export ARTIFACTS_NAMESPACE="starter-namespace"
+export ARTIFACTS_REPO="starter-repo"
+export ARTIFACTS_JWT=""
+```
+
+Artifacts uses Bearer authentication for control-plane requests:
+
+```txt
+Authorization: Bearer $ARTIFACTS_JWT
+```
+
+## 2. Create a namespace
+
+Create a namespace for your repos:
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces" \
+--header "Authorization: Bearer $ARTIFACTS_JWT" \
+--header "Content-Type: application/json" \
+--data "{\"name\":\"$ARTIFACTS_NAMESPACE\"}"
+```
+
+The response resembles the following:
+
+```json
+{
+ "name": "starter-namespace",
+ "createdAt": ""
+}
+```
+
+## 3. Create a repo
+
+Create a repo inside that namespace:
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/repos" \
+--header "Authorization: Bearer $ARTIFACTS_JWT" \
+--header "Content-Type: application/json" \
+--data "{\"name\":\"$ARTIFACTS_REPO\"}"
+```
+
+The response resembles the following:
+
+```json
+{
+ "id": "repo_123",
+ "name": "starter-repo",
+ "remote": "https://.artifacts.cloudflare.dev/git/starter-namespace/starter-repo.git",
+ "token": "art_v1_0123456789abcdef0123456789abcdef01234567?expires=1760000000",
+ "expiresAt": ""
+}
+```
+
+Copy the `remote` and `token` values into local shell variables:
+
+```sh
+export ARTIFACTS_REMOTE=""
+export ARTIFACTS_TOKEN=""
+```
+
+## 4. Get the repo URL again
+
+Fetch the repo metadata when you need to recover the remote URL later:
+
+```bash
+curl "$ARTIFACTS_BASE_URL/v1/api/namespaces/$ARTIFACTS_NAMESPACE/repos/$ARTIFACTS_REPO" \
+--header "Authorization: Bearer $ARTIFACTS_JWT"
+```
+
+```json
+{
+ "id": "repo_123",
+ "name": "starter-repo",
+ "createdAt": "",
+ "source": null,
+ "readOnly": false,
+ "remote": "https://.artifacts.cloudflare.dev/git/starter-namespace/starter-repo.git"
+}
+```
+
+## 5. Push your first commit with git
+
+Create a local repository and push it to the Artifacts remote:
+
+```sh
+mkdir artifacts-demo
+cd artifacts-demo
+git init -b main
+printf '# Artifacts demo\n' > README.md
+git add README.md
+git commit -m "Initial commit"
+git remote add origin "$ARTIFACTS_REMOTE"
+git -c http.extraHeader="Authorization: Bearer $ARTIFACTS_TOKEN" push -u origin main
+```
+
+## 6. Pull the repo with a regular git client
+
+Clone the same repo into a second directory:
+
+```sh
+cd ..
+git -c http.extraHeader="Authorization: Bearer $ARTIFACTS_TOKEN" clone "$ARTIFACTS_REMOTE" artifacts-clone
+git -C artifacts-clone log --oneline -1
+```
+
+You should see the commit you pushed in the previous step.
+
+## Next steps
+
+
+
+
+
+
diff --git a/src/content/docs/artifacts/get-started/workers.mdx b/src/content/docs/artifacts/get-started/workers.mdx
new file mode 100644
index 000000000000000..25cdadf86fb87fa
--- /dev/null
+++ b/src/content/docs/artifacts/get-started/workers.mdx
@@ -0,0 +1,231 @@
+---
+title: Workers
+description: Create an Artifact repo from a Worker.
+pcx_content_type: get-started
+sidebar:
+ order: 1
+head:
+ - tag: title
+ content: Get started - Workers
+---
+
+import {
+ LinkCard,
+ PackageManagers,
+ Render,
+ TypeScriptExample,
+ WranglerConfig,
+ Steps,
+} from "~/components";
+
+Create an Artifact repo from a Worker and use a standard git client to push and pull content.
+
+In this guide, you will create a Worker, bind it to Artifacts, create a repo through the Workers binding, and use the returned remote URL and token with `git push` and `git clone`.
+
+## Prerequisites
+
+
+
+You also need:
+
+- Access to the `artifacts` service in your Cloudflare account.
+- A local `git` client.
+
+## 1. Create a Worker project
+
+
+
+1. Create a new Worker project with C3:
+
+
+
+
+
+2. Move into the project directory:
+
+ ```sh
+ cd artifacts-worker
+ ```
+
+
+
+## 2. Add the Artifacts binding
+
+Open `wrangler.jsonc` and add the Artifacts service binding:
+
+
+
+```jsonc title="wrangler.jsonc"
+{
+ "$schema": "node_modules/wrangler/config-schema.json",
+ "name": "artifacts-worker",
+ "main": "src/index.ts",
+ "compatibility_date": "$today",
+ "services": [
+ {
+ "binding": "ARTIFACTS",
+ "service": "artifacts",
+ "entrypoint": "ArtifactsBinding",
+ },
+ ],
+}
+```
+
+
+
+This exposes Artifacts as `env.ARTIFACTS` inside your Worker.
+
+If you are using TypeScript, regenerate your local binding types:
+
+
+
+## 3. Write your Worker
+
+Replace `src/index.ts` with the following code:
+
+
+
+```ts
+import type { Service } from "cloudflare:workers";
+import type { ArtifactsBinding } from "artifacts";
+
+interface Env {
+ ARTIFACTS: Service;
+}
+
+export default {
+ async fetch(request: Request, env: Env): Promise {
+ const url = new URL(request.url);
+
+ if (request.method === "POST" && url.pathname === "/repos") {
+ // Read the repo name from the request body so the route is reusable.
+ const body = (await request.json().catch(() => ({}))) as {
+ name?: string;
+ };
+ const repoName = body.name ?? "starter-repo";
+
+ // Create the repo and return the remote plus initial write token.
+ const created = await env.ARTIFACTS.create(repoName);
+
+ return Response.json({
+ name: created.name,
+ remote: created.remote,
+ token: created.token,
+ expiresAt: created.expiresAt,
+ });
+ }
+
+ return new Response("Use POST /repos to create an Artifact repo.", {
+ status: 405,
+ headers: { Allow: "POST" },
+ });
+ },
+} satisfies ExportedHandler;
+```
+
+
+
+This Worker does one job: create an Artifact repo and return the values your git client needs next.
+
+## 4. Create a repo through your Worker
+
+Start local development:
+
+
+
+In a second terminal, create a repo through your Worker:
+
+```bash
+curl http://localhost:8787/repos \
+--header "Content-Type: application/json" \
+--data '{
+ "name": "starter-repo"
+}'
+```
+
+The response resembles the following:
+
+```json
+{
+ "name": "starter-repo",
+ "remote": "https://.artifacts.cloudflare.dev/git/default/starter-repo.git",
+ "token": "art_v1_0123456789abcdef0123456789abcdef01234567?expires=1760000000",
+ "expiresAt": ""
+}
+```
+
+Copy the `remote` and `token` values into local shell variables:
+
+```sh
+export ARTIFACTS_REMOTE=""
+export ARTIFACTS_TOKEN=""
+```
+
+## 5. Push your first commit with git
+
+Create a local repository and push it to Artifacts:
+
+```sh
+mkdir artifacts-demo
+cd artifacts-demo
+git init -b main
+printf '# Artifacts demo\n' > README.md
+git add README.md
+git commit -m "Initial commit"
+git remote add origin "$ARTIFACTS_REMOTE"
+git -c http.extraHeader="Authorization: Bearer $ARTIFACTS_TOKEN" push -u origin main
+```
+
+This uses the remote URL returned by Artifacts and passes the token as an HTTP authorization header for the push.
+
+## 6. Pull the repo with a regular git client
+
+Clone the same repo into a second directory:
+
+```sh
+cd ..
+git -c http.extraHeader="Authorization: Bearer $ARTIFACTS_TOKEN" clone "$ARTIFACTS_REMOTE" artifacts-clone
+git -C artifacts-clone log --oneline -1
+```
+
+You should see the commit you pushed in the previous step.
+
+## 7. Deploy your Worker
+
+Deploy the Worker so you can create repos without running `wrangler dev`:
+
+
+
+Wrangler prints your `workers.dev` URL. Use the same `curl` request against that URL to create additional repos from production.
+
+## Next steps
+
+
+
+
+
+
diff --git a/src/content/docs/artifacts/index.mdx b/src/content/docs/artifacts/index.mdx
new file mode 100644
index 000000000000000..ef468c48224bb4e
--- /dev/null
+++ b/src/content/docs/artifacts/index.mdx
@@ -0,0 +1,58 @@
+---
+title: Artifacts
+description: Store, version, and share filesystem artifacts across Workers, APIs, and git-compatible tools.
+pcx_content_type: overview
+sidebar:
+ order: 1
+ badge:
+ text: Beta
+head:
+ - tag: title
+ content: Artifacts
+---
+
+import { CardGrid, Description, LinkTitleCard } from "~/components";
+
+
+
+Store versioned filesystem artifacts that can be addressed through Workers, the REST API, and git-compatible workflows.
+
+
+
+Artifacts is in beta. Use Artifacts to persist file trees such as repositories, build outputs, checkpoints, and generated assets behind a versioned interface that works across Cloudflare developer tools.
+
+
+
+
+ Create your first Artifact with Workers or the REST API.
+
+
+
+ Learn how Artifacts works and how to structure Artifact usage.
+
+
+
+ Review the Workers binding, REST API, git support, and ArtifactsFS.
+
+
+
+ Explore metrics and queries for understanding Artifact activity.
+
+
+
+ See example integrations with git clients, OpenCode, and Sandbox SDK.
+
+
+
+ Review pricing, limits, and changelog entries for Artifacts.
+
+
+
diff --git a/src/content/docs/artifacts/observability/index.mdx b/src/content/docs/artifacts/observability/index.mdx
new file mode 100644
index 000000000000000..7345a273c1df3f5
--- /dev/null
+++ b/src/content/docs/artifacts/observability/index.mdx
@@ -0,0 +1,15 @@
+---
+title: Observability
+description: Monitor Artifact usage with metrics and queries.
+pcx_content_type: navigation
+sidebar:
+ order: 5
+ group:
+ hideIndex: true
+---
+
+import { DirectoryListing } from "~/components";
+
+Use these pages to understand Artifact health, activity, and consumption patterns.
+
+
diff --git a/src/content/docs/artifacts/observability/metrics.mdx b/src/content/docs/artifacts/observability/metrics.mdx
new file mode 100644
index 000000000000000..84f83434689955a
--- /dev/null
+++ b/src/content/docs/artifacts/observability/metrics.mdx
@@ -0,0 +1,11 @@
+---
+title: Metrics
+description: Review the metrics exposed by Artifacts.
+pcx_content_type: concept
+sidebar:
+ order: 1
+---
+
+Artifacts exposes metrics that help you understand storage growth, version activity, and request volume.
+
+This page will document the available metrics, how to interpret them, and where to view them.
diff --git a/src/content/docs/artifacts/observability/queries.mdx b/src/content/docs/artifacts/observability/queries.mdx
new file mode 100644
index 000000000000000..5ec808e740f668d
--- /dev/null
+++ b/src/content/docs/artifacts/observability/queries.mdx
@@ -0,0 +1,11 @@
+---
+title: Queries
+description: Query Artifact activity and usage data.
+pcx_content_type: concept
+sidebar:
+ order: 2
+---
+
+Use queries to analyze Artifact activity, troubleshoot access patterns, and understand how versions are being produced and consumed.
+
+This page will document the available query surfaces and example analysis workflows.
diff --git a/src/content/docs/artifacts/platform/changelog.mdx b/src/content/docs/artifacts/platform/changelog.mdx
new file mode 100644
index 000000000000000..4b3afa486e0a740
--- /dev/null
+++ b/src/content/docs/artifacts/platform/changelog.mdx
@@ -0,0 +1,13 @@
+---
+title: Changelog
+description: Review recent changes to Artifacts.
+pcx_content_type: changelog
+sidebar:
+ order: 3
+---
+
+import { ProductChangelog } from "~/components";
+
+{/* */}
+
+
diff --git a/src/content/docs/artifacts/platform/index.mdx b/src/content/docs/artifacts/platform/index.mdx
new file mode 100644
index 000000000000000..6373a10152c3d94
--- /dev/null
+++ b/src/content/docs/artifacts/platform/index.mdx
@@ -0,0 +1,15 @@
+---
+title: Platform
+description: Review pricing, limits, and changelog information for Artifacts.
+pcx_content_type: navigation
+sidebar:
+ order: 7
+ group:
+ hideIndex: true
+---
+
+import { DirectoryListing } from "~/components";
+
+Use these pages to understand platform constraints and track product updates for Artifacts.
+
+
diff --git a/src/content/docs/artifacts/platform/limits.mdx b/src/content/docs/artifacts/platform/limits.mdx
new file mode 100644
index 000000000000000..0d942b2e347bad9
--- /dev/null
+++ b/src/content/docs/artifacts/platform/limits.mdx
@@ -0,0 +1,9 @@
+---
+title: Limits
+description: Review Artifacts platform limits.
+pcx_content_type: reference
+sidebar:
+ order: 2
+---
+
+This page will document the current limits for Artifact size, version count, requests, and related operational constraints.
diff --git a/src/content/docs/artifacts/platform/pricing.mdx b/src/content/docs/artifacts/platform/pricing.mdx
new file mode 100644
index 000000000000000..374ba738ec3645c
--- /dev/null
+++ b/src/content/docs/artifacts/platform/pricing.mdx
@@ -0,0 +1,16 @@
+---
+title: Pricing
+description: Review Artifacts pricing information.
+pcx_content_type: reference
+sidebar:
+ order: 1
+---
+
+This page will document how Artifacts usage is billed, including any charges associated with storage, requests, or data transfer.
+
+Current Artifacts pricing is:
+
+| Usage type | $/unit | Included |
+| ---------- | -------------------------- | ------------------------------ |
+| Operations | $0.15 per 1,000 operations | First 10k included (per month) |
+| Storage | $0.50/GB-mo | First 1 GB included |
diff --git a/src/icons/artifacts.svg b/src/icons/artifacts.svg
new file mode 100644
index 000000000000000..c85cf737d3c7045
--- /dev/null
+++ b/src/icons/artifacts.svg
@@ -0,0 +1 @@
+