Publishing concepts
How artifacts, entry files, limits, immutable versions, and slugs work.
Artifacts are static files or folders
artifact.cafe hosts static artifacts for review. It does not run SSR, backend processes, cron jobs, or serverless functions for the artifact. Claimed artifacts can use Artifact Data for bounded shared records.
Entry file detection
- The CLI and API use
index.htmlwhen it exists as HTML. - If the folder root has exactly one HTML file, they use that file.
- With multiple root HTML files, pass
--entry file.html(API:entryPath). - With no HTML entry, publishing generates a review page: images display inline, PDFs open in the browser's native viewer, CSVs show the first rows as a table, Markdown renders as a reading page, and other files get a download link. Multiple files get a file listing. Every uploaded file keeps its direct URL.
Publish a single file with npx artifact-cafe@latest publish ./report.pdf, or a folder with publish ./out. Single-file publishes store .artifactcafe/config.json in the file's parent directory, so publishing that file again creates a new version of the linked artifact.
Use publish ./report.md for Markdown. Headings, lists, tables, task lists, links, images, quotes, and code blocks render as HTML that reviewers can select and comment on. .md, .markdown, and API uploads with text/markdown are supported. Raw HTML is displayed as text. Previews show up to 1 MiB with a notice for larger files; the complete original remains downloadable.
Link previews
When someone pastes a review link into X, Slack, Telegram, or Discord, the preview card is built from your artifact. By default it shows the title over a generated artifact.cafe card. Your entry file can take that over:
<meta name="description" content="One line about what this is.">
<meta property="og:image" content="og.png">
<meta name="author" content="Ada Lovelace">- The description also accepts
og:description, and the byline also acceptsarticle:author. Pass--descriptionon publish to override whatever the document says. og:imagemust be a file in the folder you published:og.png,./og.png, and/assets/og.pngall work. Remote URLs anddata:are refused, so artifact.cafe never serves preview imagery it did not store.- The image has to be a PNG, JPEG, WebP, or GIF under 5 MB, and it has to be in the version you are publishing. A path that does not resolve falls back to the generated card rather than shipping a broken preview. 1200x630 is a good size.
- Each version gets its own preview URL, so publishing v2 re-unfurls instead of showing a cached v1 card.
- Only the entry file is read, so a
?page=deep link shares the same card as the artifact. - Password-protected, workspace, and private artifacts always unfurl as the locked card. The fetcher that builds a preview is anonymous, so it never sees your description, image, or byline (see Password protection).
Ignored and blocked paths
The CLI skips repo metadata, common dependency folders, local artifact credentials, env files, private keys, symlinks, unsafe paths, and zero-byte files.
Limits
- Maximum file size: 100 MB.
- Maximum total artifact size: 250 MB.
- Maximum files per publish: 1,000.
- Publish sessions expire after 1 hour.
- Anonymous publishing is limited to 15 publishes per IP per hour and 20 per day. Signing in with an API key raises this.
- Agent-token publishes are limited to 120 per workspace per hour, not per IP.
- Anonymous artifacts expire 24 hours after their last publish by default unless claimed (see Tokens and auth).
Versions are immutable
A publish always creates a new version. Comments stay pinned to the version where reviewers made them, so v1 feedback remains v1 feedback after you publish v2.
Temporary artifacts
For a one-off preview, set a lifetime explicitly:
npx artifact-cafe@latest publish . --title "Layout comparison" --expires-in 1h --json
npx artifact-cafe@latest expiration --in 7d --json
npx artifact-cafe@latest expiration --keep --jsonDurations are positive whole numbers followed by m, h, or d, such as
30m, 1h, or 7d. Time starts when publishing finishes. JSON includes
autoDeleteAt (the explicit deadline) and expiresAt (the effective expiry).
Share the returned expiry, including its timezone, alongside the review URL.
An ordinary republish preserves the temporary deadline. An explicit
--expires-in, or expiration --in, resets the selected lifetime from now.
Managers can also extend or keep an artifact from Settings → General →
Lifetime, or by clicking the clock in the review toolbar. Visitors can view
the deadline there; managers get Set expiry, followed by Keep permanently.
On phones, the panel and its actions use the available width. Hiding review
tools hides the clock. Plain mode has no toolbar; use settings to manage its
lifetime.
Keep permanently clears the explicit temporary deadline. An owned artifact
then has no automatic expiry; its link, versions, and comments are preserved.
The CLI equivalent is expiration --keep. For an anonymous artifact, that
command clears only its temporary deadline: claim it to remove the separate
24-hour retention too.
At expiry, new access stops on both origins, including old versions and Artifact Data, and the artifact disappears from lists and search. Daily background cleanup removes every version, comment, file, and data record; failed cleanup is retried. Deletion has no restore window. Already downloaded copies or pages loaded in a browser cannot be recalled.
Owned artifacts have no expiry unless you set one. Anonymous artifacts still have their existing 24-hour retention; the earlier applicable deadline wins. Claiming removes anonymous retention but preserves a temporary deadline. Clearing the temporary deadline alone does not claim an artifact. Moving folders/workspaces, commenting, and viewing do not change its deadline.
Publish into a workspace
Sign in with artifact-cafe login, then target a workspace handle and folder name:
npx artifact-cafe@latest publish . --workspace acme --folder specsThe workspace owns the artifact, and each version records the member who published it. The resolved workspace and folder are stored in .artifactcafe/config.json, so the next bare publish creates v2 in the same place. Run artifact-cafe workspaces --json to list the workspaces available to the current account.
For new artifacts, destination priority is explicit flags, a project-level
artifact-cafe.json, then a human-only terminal picker. Agents and --json
never prompt: without project context they use your
personal workspace, the safest
non-shared destination, when signed in; signed-out publishing remains
anonymous. --folder on its own targets a folder in Personal.
{
"workspace": "acme",
"folder": "specs"
}The project file is safe to commit and excluded from uploads. It supplies team
context for fresh checkouts and agents; .artifactcafe/config.json remains the
gitignored binding for one specific artifact and may contain its publish token.
Slugs
The API derives new artifact slugs from the title, adding a random suffix for uniqueness. Claimed owners can update the title or slug through owner-only API behavior; changing a slug changes the review URL.
Publishing with an agent token
When a runtime provides an aat_ agent token
as ARTIFACT_CAFE_API_KEY, publish without --workspace or --folder. The
token selects one workspace and overrides account placement defaults. No
prompt or login is needed in a non-TTY shell. The artifact is owned from birth;
the CLI saves an artifact binding without a publish or claim token. The
artifact defaults to unlisted, so anyone with the link can review it without
an account, even though it belongs to a team workspace.