CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/Cowork
Cowork/2026-04-29Intermediate

Designing the One Page You Open Every Morning — Building Living Dashboards with Cowork Artifacts and MCP

Cowork Artifacts promote a chat answer into a re-openable page that fetches live MCP data. Here is how I design pages that replace recurring questions.

cowork13artifactsmcp18dashboard2automation95

"I asked Claude the exact same question yesterday." If that thought has crossed your mind, you have already discovered the limit of one-shot chat answers. Counts of unread alerts, the queue of pull requests waiting on you, the priority list of in-flight tasks — these change every day, so an answer given once is stale by the next morning.

Cowork's Artifacts feature exists to break this loop. It promotes a chat reply into a re-openable page, and gives that page a way to call your MCP connectors fresh whenever you open it. Below is how I think about designing one of these pages so it earns its place as something you open every morning.

The real difference between a chat reply and an Artifact

A normal chat answer is a snapshot of one moment. If you ask Claude to count your unread Slack messages and a new one arrives three seconds later, the answer is already wrong. An Artifact, by contrast, is an independent HTML page where the code is persisted and where window.cowork.callMcpTool can fetch the latest data each time the page loads.

In practice I split work like this:

  • One-shot reply is fine when the question is conceptual, retrospective, or genuinely a one-time summary
  • Promote to an Artifact when you can already feel that you will ask the same question tomorrow, when the underlying data shifts with time, or when several MCPs need to be combined into one view

The signal "I'm probably going to ask this again" is the cue to create an Artifact.

Probe the MCP response shape before you write a single line

The first wall every Artifact author hits is that the MCP tool response does not look like the public API documentation. Slack's MCP wrapper for "search messages" may stringify the body, Linear's MCP for "list issues" may rename fields, and an array you expected at data.messages may actually live under data.results.

The reliable habit is to call the MCP tool once in chat with a minimal payload, look at the raw shape, and only then build the parser around that shape.

// After observing the real shape, write the parser to match
const response = await window.cowork.callMcpTool({
  server: "slack",
  tool: "search_messages",
  args: { query: "in:#alerts", limit: 10 }
});
 
// Some MCP wrappers stringify into content[0].text
const data = typeof response.content?.[0]?.text === "string"
  ? JSON.parse(response.content[0].text)
  : response;
 
// The official API may say data.messages, but the wrapper may flatten to data.results
const items = data.results ?? data.messages ?? [];

Skip this step and you will spend an evening debugging an empty array. I learned this the slow way with Linear.

A working example: the morning "open work" page

Here is a minimal page that combines Slack alerts and the open Linear tasks assigned to you, suitable as the first thing you open after coffee.

<div id="root">
  <h2>Open this morning</h2>
  <section id="slack"><p>Loading…</p></section>
  <section id="linear"><p>Loading…</p></section>
</div>
<script>
async function loadSlack() {
  const r = await window.cowork.callMcpTool({
    server: "slack",
    tool: "search_messages",
    args: { query: "in:#alerts after:yesterday", limit: 20 }
  });
  const data = JSON.parse(r.content?.[0]?.text ?? "{}");
  const items = data.results ?? [];
  document.getElementById("slack").innerHTML = items.length
    ? `<h3>Slack #alerts (${items.length})</h3><ul>${
        items.map(m => `<li>${m.user}: ${m.text}</li>`).join("")
      }</ul>`
    : "<h3>Slack: clean ✅</h3>";
}
async function loadLinear() {
  const r = await window.cowork.callMcpTool({
    server: "linear",
    tool: "list_my_issues",
    args: { state: "open" }
  });
  const data = JSON.parse(r.content?.[0]?.text ?? "{}");
  const items = data.issues ?? [];
  document.getElementById("linear").innerHTML = `<h3>Assigned to me</h3>${
    items.map(i => `<div>${i.priority} - ${i.title}</div>`).join("")
  }`;
}
Promise.allSettled([loadSlack(), loadLinear()]);
</script>

One click on this page each morning gives you the live state of both systems in the same view.

Three pitfalls worth knowing in advance

A few things will trip you up if you build Artifacts the way you would build a regular web app.

1. The MCP can be disconnected when the page opens

Users sometimes switch accounts or revoke a connector after the Artifact was authored, and callMcpTool then throws. I always wrap the page in a try/catch and render a clear "reconnect required" message instead of letting the page go silent. A blank screen is interpreted as "this is broken," which is the wrong feeling for a tool you rely on daily.

2. Slow data sources drag down the whole page

If you await Promise.all over three MCP calls, the slowest call sets the time-to-paint for the entire page. Switch to Promise.allSettled and let each section flip from "Loading…" to its result independently. The perceived speed difference is dramatic.

3. Browser storage simply does not work

localStorage and sessionStorage are unsupported in the Artifact runtime. In-memory variables are usually enough. If you genuinely need state that survives a reload, persist it back through MCP — store the user's filter preference in a Notion page, a Linear custom field, or a small KV connector — rather than fighting the runtime.

How to grow an Artifact rather than build it

The Artifacts I actually rely on were not designed in one shot. They started as the smallest possible page — sometimes one section, one connector — and gained features only after I had used them for a few days and could feel exactly what was missing.

When the gap becomes obvious ("I keep wishing this had a priority filter"), ask Claude to extend it with update_artifact. The diff-style updates are cheap, and the page evolves with your actual usage rather than with a guess about future needs.

Pair this with the Cowork scheduled tasks design guide and you can have overnight automation feed Linear or Notion, while morning Artifacts simply visualize the result. That two-layer split keeps the Artifact code small and the data fresh.

A side benefit of growing rather than designing is that you stop trying to predict what features matter. The first version of my morning page only counted Slack alerts. After a week I noticed I always followed up by checking who pinged me directly, so I added a "mentions" section. After another week I noticed I never read the alert section before the mentions, so I reordered them. None of those changes would have shown up in a clean-room design.

When an Artifact stops being the right answer

Artifacts are powerful, but they are not the right shape for everything. After running half a dozen of them in production for myself, the pattern I see is that an Artifact is the right tool only when three conditions hold at once: the question is recurring, the data is remote, and the visualization layer adds value over a list of facts.

If any one of those is missing, a different tool is usually a better fit. Recurring questions that read from local files belong in a regular skill. One-off analyses, even of remote data, are better as chat replies because there is no return visit to amortize the build cost. Recurring questions where a one-line summary is enough should probably be a scheduled task that posts the result somewhere you already look — Slack, email, or a Notion page — rather than another tab to open.

The honest test before promoting a chat reply is to ask: "Will I open this page tomorrow?" If you cannot say yes with confidence, keep it as a chat reply. The cost of a half-finished Artifact you never reopen is higher than the cost of asking the same question twice.

Versioning and ownership over time

The longer an Artifact is in your workflow, the more it accumulates assumptions that drift. The Linear field your filter depends on may be renamed; the Slack channel may be archived; a connector may be migrated to a new MCP server. None of these are obvious until the page renders empty.

Two habits prevent slow-motion breakage. The first is to log a visible timestamp on the page itself — something as simple as Last updated: ${new Date().toLocaleString()} in the corner. When that stops moving you know the page is no longer reaching the data source. The second is to keep the parser tolerant: prefer data.results ?? data.messages ?? [] over a single hard-coded path, so a connector renaming a field surfaces as a degraded view, not a crash.

Both habits sound trivial, and both have saved me a morning of "why is this empty?" investigations.

A small first step

The simplest entry point is to pick one recurring question you currently re-ask in chat — yes, just one — and promote it to an Artifact. Forget the "perfect dashboard" vision; build the smallest page that answers that one question.

What changes is the shape of the relationship: from "asking Claude over and over" to "opening the page Claude and I built together." That shift is what Artifacts are really for.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Cowork2026-07-17
It Worked on My Machine, but Nobody Could Trigger It — Four Assumptions I Stripped Out of a Cowork Plugin
I bundled four working automation skills into a plugin and shared it. Only one of them ever fired. Here is how I measured skill trigger rate, and the four assumptions — vocabulary, paths, connections, and naming — I had to strip out before it was portable.
Cowork2026-03-27
Cowork Skills × Scheduling: Advanced Automation Patterns and Techniques
Master Cowork's skill and scheduling capabilities. Learn 5 real-world automation patterns: sales reports, daily standups, KPI monitoring, meeting notes, and smart customer follow-ups.
Cowork2026-07-12
The Night a Connector Grew Write Tools, Your Unattended Job Could Quietly Send Something
The moment a connector update quietly adds write tools, a job you run unattended can suddenly send email or delete files. Here is how to build a gate that snapshots a connector's tool surface, diffs it, and stops unapproved writes before they run — drawn from indie development.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →