Bassam Ismail
Engineering

A Home for AI Artifacts: The Platform We Built So Nothing Leaves the Company

9 min read

The assistant hands you a finished dashboard, and for ten seconds it feels done. Then you have to turn a chat artifact into a link your team can open tomorrow, which is where AI-generated artifacts stop feeling like magic and start needing infrastructure.

For a while the answer was a scattering of external services. Drop it on a preview host. Paste it into a sharing tool. Push it somewhere with a public link. Each one works, and each one comes with the same taxes: you sign in again, you generate a token or a share key, and the link quietly expires or the free tier reaps it. For an internal artifact built from internal context, every one of those services means the thing now lives on someone else's machine.

So we built a place for them to live instead.

TL;DR

This is Part 1 of a series on an internal platform for publishing AI-generated artifacts. The team makes something with an AI, and instead of reaching for an external host (with its own login, token generation, and expiring links) they publish it to a durable URL on a company subdomain that is already behind our sign-in. The headline feature is that you never leave the assistant to do it: you say "deploy this," and an MCP server takes the artifact live and hands back a URL. Part 2 is how the whole thing runs as one Go binary on one small box. Part 3 is the serverless version we built first and had to walk back.

What it actually is

The platform does one job: take a bundle of files and serve it at a stable URL. Hand it the output directory of an artifact, and it gives you <project>.<zone> and keeps it there. No build step it has to understand. No framework it has to support. Files in, URL out.

The structure around that is deliberately small. Work is organized into groups (a team, an initiative) which contain projects, and each project owns a subdomain. Publishing again just replaces the project's active version, so updating a live artifact is the same gesture as creating one, and the URL never changes out from under whoever you shared it with. It keeps the last several versions, so rolling back is picking an older one, not redeploying from scratch.

Two things make it a platform rather than a folder on a server, and both are about removing friction that external services charge you for:

  • Authentication is already handled. Every authed URL sits behind the company's Google sign-in, gated to our domain. Nobody generates a token or manages a share password to view internal work. You are signed in or you are not. For the cases that genuinely need outside eyes, there is an explicit, time-boxed share link, and a separate public zone for things meant to be open. The default is "internal and already authenticated."
  • Nothing expires by accident. A published artifact stays published until someone removes it. There is no free-tier clock, no preview window that lapses over a weekend, no "this deployment has been archived." Durability is the point.

At the time of writing it holds roughly sixty projects and close to ten thousand files, a couple of gigabytes in all. That is not big. It does not need to be. It needs to be there, the same URL, every time someone clicks it.

How the publish path actually works for AI-generated artifacts

When the MCP server receives a deploy call, it collects the artifact files, bundles them, and hands them off to the platform's API as a versioned upload. Here is what that path looks like and where the key pieces live:

THE DEPLOY PATHMCP serverdeploy callBundlezip + manifestPOST version/projects/:id/versionsStore + indexS3 + metadataSubdomain router→ active versionServedbehind SSO[ files keyed by version hash; the project record tracks the active version ]

A rough picture of the metadata the platform keeps per project:

project
  id             string   // stable, used in subdomain
  group_id       string   // org grouping
  active_version string   // hash of current bundle
  versions[]
    version_hash string
    uploaded_at  timestamp
    file_count   int
    size_bytes   int
  auth_mode      enum     // internal | share_link | public
  share_token    string?  // set only for time-boxed external links
  share_expires  timestamp?

The subdomain router reads active_version on each request and streams files from object storage. Promoting an older version to active is one metadata write: the URL never changes. Auth is checked at the router layer before any file is served, so there is no path to artifact content without passing the SSO gate.

The loop that makes it stick

The feature that changed how people actually used it is that you do not leave the assistant to publish.

The platform exposes an MCP server, so the AI tools people already work in can talk to it directly. You finish an artifact in the assistant, say "deploy this," and the assistant calls the platform. Mid-flight it asks the two questions it needs: which group, then which project. You answer in the same conversation, and it comes back with the live URL. The thing you just made is now a link you can drop in a channel, behind the same sign-in as everything else.

MAKE AN ARTIFACT, GET A DURABLE URLthe deploy-this loopAI makes an artifactapp, report, dashboard"deploy this"via the MCP serverpick group / projectasked mid-flightbundle storedfiles to object storagelive URL<project>.<zone>, behind SSO[ No external host, no token, no expiry. ]

That last hop is the whole pitch. Most external alternatives break the loop: you leave the assistant, open a browser, log into something, wait, and copy a link that has a clock on it. Here the distance from "the AI finished" to "here is the internal URL" is one sentence, and the result does not evaporate.

That loop is also what set the technical constraints the rest of the series is about. Asking "which group, which project" mid-deploy means holding a streamed connection open while the user thinks. Publishing an artifact means accepting an upload that could be a handful of files or a few dozen megabytes. Both turned out to be things the first architecture was bad at. That is Part 3.

A few things this platform is not designed for, and where it would need real work before you trusted it there: public or product-facing workloads (it is built around internal SSO assumptions), large binary assets or anything requiring server-side rendering, abuse or quota enforcement beyond basic API key scoping, and version retention at serious scale (the current policy keeps the last several versions; it is not an audit log). If your artifact needs to be public and high-traffic, the external preview hosts this replaces are still the right answer for that specific case.

Who it is for

This is an org tool, not a personal one, and that shapes the design throughout. Sign-in is gated to the company domain, so "who can publish and who can view" is answered by who works here. Groups and projects exist because dozens of people are putting artifacts somewhere and they need to not collide. There are API keys for automation and admin keys for the people who run it.

That multi-tenant reality is why "just handle auth for me" is the load-bearing feature. When one person hosts one artifact, an external link is fine. When a whole engineering org is continuously turning AI sessions into shareable things, the per-artifact login-and-token tax compounds into real friction, and the "this link expired" failure mode starts losing work. A small internal platform that knows who you are and keeps what you published removes both problems at once.

This sits in the same family of internal AI tooling as Tracking what the LLM costs in a one-person app: the useful part is not only that the model can produce something, but that the surrounding system makes the work accountable, durable, and boring enough to use.

What the rest of the series covers

This part is the what and the why. The next two are the how.

Part 2 is the architecture: the platform runs as a single Go binary on one small box behind a reverse proxy, serving the API, the auth flow, the MCP server, and every project subdomain from one process. It is a deliberately unfashionable design, and most of the interesting decisions are about why one box is enough and how it stays that way.

Part 3 is the part I am least proud of and learned the most from. The first version of this was serverless: API Gateway, a fleet of Lambdas, a managed user pool, all in CDK. It was the obvious default, and then the platform's own job started fighting it. That part covers the decision to leave, what the rewrite cost, and the bugs that came with porting it. The same lesson shows up in Building Press, Part 3: The prompts are data, not code: the shape of the workflow matters more than the fashionable default.

FAQ

Why not just use the AI tool's built-in sharing or a preview host?

For one-off, personal, public things, those are great and I still use them. The friction shows up at org scale and with internal content: external sharing means another login, a generated token or share key, a link with an expiry, and the artifact living outside the company. When a whole team does this dozens of times a week, "handle auth automatically and never expire the link" stops being a nicety and becomes the reason the tool gets used.

Is this just an internal Vercel or Netlify?

It rhymes with them in that you push files and get a URL, but the framing is different. Those are general static-hosting platforms; this is specifically a home for AI-generated artifacts, designed around the "deploy this from inside the assistant" loop and around being already-authenticated and durable by default. The deploy primitive is similar; the product it is part of is not.

What does "AI-generated artifact" actually mean here?

Anything an assistant produces that is more useful as a running page than as text in a chat: a single-page app, an interactive chart or dashboard, a formatted report, a doc with working links. The platform does not care how the files were made. In practice most of what it holds started life in an AI session, which is why the publishing loop is built to start from inside one.

Where should internal AI artifacts be hosted?

If they are built from internal context and meant for internal readers, they should live behind the same sign-in boundary as the rest of the company's tools. A public preview host is convenient, but it moves both the artifact and the access-control problem somewhere else.

Many preview and sharing products are optimized for temporary collaboration, free-tier limits, or public demos. That is reasonable for disposable work, but it is a poor fit for artifacts a team expects to open next week, next quarter, or during a review.

  1. Part 1A Home for AI Artifacts: The Platform We Built So Nothing Leaves the CompanyYou're here
  2. Part 2One Binary, One Box
  3. Part 3Walking Back from Serverless