<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hsin Yen Chung</title>
    <description>The latest articles on DEV Community by Hsin Yen Chung (@hsin_yenchung_5562e7d5c9).</description>
    <link>https://dev.to/hsin_yenchung_5562e7d5c9</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3866306%2F0115b75f-35b8-44ac-8cab-307c9180295c.JPG</url>
      <title>DEV Community: Hsin Yen Chung</title>
      <link>https://dev.to/hsin_yenchung_5562e7d5c9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hsin_yenchung_5562e7d5c9"/>
    <language>en</language>
    <item>
      <title>What Happens After the Agent Finishes? — Introducing Agent CONT'D</title>
      <dc:creator>Hsin Yen Chung</dc:creator>
      <pubDate>Sat, 01 Aug 2026 22:11:43 +0000</pubDate>
      <link>https://dev.to/hsin_yenchung_5562e7d5c9/what-happens-after-the-agent-finishes-introducing-agent-contd-2en5</link>
      <guid>https://dev.to/hsin_yenchung_5562e7d5c9/what-happens-after-the-agent-finishes-introducing-agent-contd-2en5</guid>
      <description>&lt;p&gt;Today, we are opening the first founding beta for Agent CONT'D.&lt;/p&gt;

&lt;p&gt;Our team uses Claude, Codex, ChatGPT, and custom agents every day.&lt;br&gt;
Creating the first draft is becoming easier.&lt;br&gt;
The difficult part is what happens after the agent finishes.&lt;/p&gt;

&lt;p&gt;A useful document stays inside one agent session.&lt;br&gt;
A teammate reviews it in Drive, GitHub, Slack, or email.&lt;br&gt;
The feedback becomes separated from the agent.&lt;br&gt;
The next person—or the next agent—starts without the decisions that came before.&lt;/p&gt;

&lt;p&gt;We built Agent CONT'D to test a different workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An agent creates project work&lt;/li&gt;
&lt;li&gt;A teammate reviews and comments&lt;/li&gt;
&lt;li&gt;The agent reads and addresses the feedback&lt;/li&gt;
&lt;li&gt;The approved work remains available to the team&lt;/li&gt;
&lt;li&gt;Another person or agent continues from it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We are looking for small AI-native teams already using Claude, Codex, ChatGPT, OpenClaw, or custom agents.&lt;/p&gt;

&lt;p&gt;Bring one real artifact:&lt;br&gt;
• A PRD&lt;br&gt;
• A research report&lt;br&gt;
• A technical specification&lt;br&gt;
• Project documentation&lt;br&gt;
• A client deliverable&lt;/p&gt;

&lt;p&gt;I am looking for teams willing to use Agent CONT'D on real work and tell us exactly where it breaks.&lt;/p&gt;

&lt;p&gt;Sign up here: &lt;a href="https://studio.spuree.com/waitlist" rel="noopener noreferrer"&gt;https://studio.spuree.com/waitlist&lt;/a&gt;&lt;br&gt;
Join our Discord: &lt;a href="https://discord.com/invite/mmTZvAPkFq" rel="noopener noreferrer"&gt;https://discord.com/invite/mmTZvAPkFq&lt;/a&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/company/continuity-contd" rel="noopener noreferrer"&gt;https://www.linkedin.com/company/continuity-contd&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agentcontd</category>
      <category>aiagents</category>
      <category>claudecode</category>
      <category>humanintheloop</category>
    </item>
    <item>
      <title>One Markdown File, 15 Landing Pages: Separate Your Copy From Your Design</title>
      <dc:creator>Hsin Yen Chung</dc:creator>
      <pubDate>Tue, 14 Jul 2026 16:58:07 +0000</pubDate>
      <link>https://dev.to/hsin_yenchung_5562e7d5c9/one-markdown-file-15-landing-pages-separate-your-copy-from-your-design-1k6i</link>
      <guid>https://dev.to/hsin_yenchung_5562e7d5c9/one-markdown-file-15-landing-pages-separate-your-copy-from-your-design-1k6i</guid>
      <description>&lt;p&gt;Our homepage went through &lt;strong&gt;fifteen complete redesigns&lt;/strong&gt; last week. Not Figma mockups — fifteen deployed, pixel-complete pages. A quiet dark "review suite." A blueprint spec sheet. A research paper. A sticker poster with a yellow highlighter headline.&lt;/p&gt;

&lt;p&gt;They all say &lt;em&gt;exactly&lt;/em&gt; the same thing, because all fifteen read their copy from one markdown file.&lt;/p&gt;

&lt;p&gt;Here's the whole thing in 60 seconds:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Ga5Z6geruPI"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Don't take my word for it — the winner is live at &lt;a href="https://workupai.com" rel="noopener noreferrer"&gt;workupai.com&lt;/a&gt;, and the fourteen runners-up are still deployed at their version URLs. Compare the &lt;a href="https://workupai.com/v5" rel="noopener noreferrer"&gt;blueprint spec sheet&lt;/a&gt;, the &lt;a href="https://workupai.com/v12" rel="noopener noreferrer"&gt;research paper&lt;/a&gt;, and the &lt;a href="https://workupai.com/v1" rel="noopener noreferrer"&gt;original&lt;/a&gt; against the sticker-poster homepage: same words, different worlds.&lt;/p&gt;

&lt;p&gt;This post is about the pattern that made that possible, why it killed our longest-running meeting, and how you can steal it. (It's a follow-up to &lt;a href="https://dev.to/hsin_yenchung_5562e7d5c9/how-our-designer-ships-front-end-changes-without-writing-code-5936"&gt;how our designer ships front-end changes without writing code&lt;/a&gt; — same philosophy, applied to our own landing page. The page sells &lt;a href="https://spuree.com" rel="noopener noreferrer"&gt;Spuree&lt;/a&gt;, our review-and-memory layer for AI-generated work, but it lives at &lt;a href="https://workupai.com" rel="noopener noreferrer"&gt;workupai.com&lt;/a&gt; — we give marketing experiments their own domain so we can rebuild them freely, behind their own infra, without ever touching the product site. Spuree becomes relevant again at the very end.)&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem: copy debates and design debates in the same room
&lt;/h2&gt;

&lt;p&gt;Every landing-page review I've ever sat in mixes two arguments that have nothing to do with each other:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"The headline should mention the team, not just the agent" &lt;em&gt;(a copy problem)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;"It feels too corporate, can it be more playful?" &lt;em&gt;(a design problem)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When both live in the same React components, every change is entangled. You can't compare two designs fairly because they drifted to slightly different words. You can't fix a sentence without someone re-opening the color conversation.&lt;/p&gt;

&lt;p&gt;So we physically separated them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The workflow in 30 seconds
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;All copy lives in &lt;code&gt;content/vme.md&lt;/code&gt;&lt;/strong&gt; — one markdown file, plain &lt;code&gt;key: value&lt;/code&gt; lines. Anyone can edit it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each design is one self-contained page&lt;/strong&gt; — &lt;code&gt;src/app/v1/page.tsx&lt;/code&gt; … &lt;code&gt;v15/page.tsx&lt;/code&gt;. Every page reads the same file at build time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A floating "versions" menu&lt;/strong&gt; on every page lets anyone click between all fifteen designs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feedback comes as rankings&lt;/strong&gt; ("I like v7 &amp;gt; v9 &amp;gt; v8"), and the next batch of designs mines the winners' DNA and drops the losers'.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shipping the winner is one line&lt;/strong&gt; — the root page re-exports the chosen version.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No CMS. No feature flags. Not a single client component. The whole thing is a Next.js static export.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Framework&lt;/td&gt;
&lt;td&gt;Next.js (App Router), &lt;strong&gt;React Server Components only&lt;/strong&gt; — we wrote zero client components&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Styling&lt;/td&gt;
&lt;td&gt;Tailwind CSS v4 — each version gets its own scoped design tokens in &lt;code&gt;globals.css&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fonts&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;next/font&lt;/code&gt; for Google fonts (a different display face per design) + our brand OTFs via &lt;code&gt;@font-face&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Copy&lt;/td&gt;
&lt;td&gt;One markdown file + a ~120-line parser (&lt;code&gt;fs.readFileSync&lt;/code&gt; at build time)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;output: "export"&lt;/code&gt; — static files in &lt;code&gt;out/&lt;/code&gt;, no server to run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting&lt;/td&gt;
&lt;td&gt;S3 (private bucket) + CloudFront (Origin Access Control, HTTP/2+3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNS / TLS&lt;/td&gt;
&lt;td&gt;Route 53 + ACM (DNS-validated, auto-renews)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IaC&lt;/td&gt;
&lt;td&gt;Terraform/OpenTofu — the whole &lt;code&gt;infra/&lt;/code&gt; folder is nine small &lt;code&gt;.tf&lt;/code&gt; files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analytics&lt;/td&gt;
&lt;td&gt;Plausible — one script tag, enabled at build time via env var&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The agent&lt;/td&gt;
&lt;td&gt;Claude Code — generated the variants, the parser, the infra, and most of this post's material&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The deliberate constraint: &lt;strong&gt;everything renders at build time.&lt;/strong&gt; Every page is fully readable with JavaScript disabled — the only JS on the wire is Next's own runtime, because we wrote no client components. It's also why sixteen routes cost nothing to host: this site's AWS bill rounds to pocket change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core trick: copy is data
&lt;/h2&gt;

&lt;p&gt;The copy file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## hero&lt;/span&gt;

kicker: The review and memory layer for AI-generated creative
headline: AI made drafts cheap. _Feedback is still scattered across your team._
subheadline: Creative Engine pulls client notes into one shared, searchable place...
cta-primary: See the review loop

&lt;span class="gu"&gt;## problem&lt;/span&gt;

headline: The AI workflow breaks right after generation.
items:
&lt;span class="p"&gt;
-&lt;/span&gt; Drafts get dumped into Slack, email, or Telegram.
&lt;span class="p"&gt;-&lt;/span&gt; Feedback scatters across meeting notes, chat threads, and someone's memory.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A ~120-line parser turns it into &lt;code&gt;{ section: { key: value | values[] } }&lt;/code&gt; with &lt;code&gt;fs.readFileSync&lt;/code&gt; in a Server Component — build-time only, nothing shipped to the client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;PageContent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// "## section" starts a section, "key: value" sets a string,&lt;/span&gt;
  &lt;span class="c1"&gt;// "- item" appends to the last list. That's the whole grammar.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The one detail I'd call genuinely reusable: &lt;strong&gt;emphasis is part of the copy, but its style belongs to the design.&lt;/strong&gt; The &lt;code&gt;_underscores_&lt;/code&gt; in the headline mark &lt;em&gt;which words&lt;/em&gt; get the special treatment. Each page decides &lt;em&gt;what&lt;/em&gt; that treatment is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// v1: white-to-grey gradient        withEm(headline, "text-gradient")&lt;/span&gt;
&lt;span class="c1"&gt;// v2: hollow outlined display type  withEm(headline, "v2-outline")&lt;/span&gt;
&lt;span class="c1"&gt;// v15: yellow marker highlight      withEm(headline, "v15-mark")&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the copywriter controls emphasis placement; the designer controls what emphasis &lt;em&gt;means&lt;/em&gt;. Nobody steps on anyone.&lt;/p&gt;

&lt;p&gt;(One war story: our markdown formatter silently rewrote &lt;code&gt;*asterisks*&lt;/code&gt; to &lt;code&gt;_underscores_&lt;/code&gt; and broke the emphasis rendering. The fix — accept both, but ignore intra-word underscores so &lt;code&gt;final_final_v3.png&lt;/code&gt; survives. Budget an hour for that class of bug.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Where fifteen designs came from
&lt;/h2&gt;

&lt;p&gt;I didn't design fifteen pages. I fed an AI coding agent &lt;strong&gt;real references&lt;/strong&gt; and let it extract the design DNA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;our previous waitlist page (rendered it headless, pulled the fonts and layout patterns)&lt;/li&gt;
&lt;li&gt;a landing page we admired (fetched its &lt;em&gt;shipped CSS&lt;/em&gt; — found the exact accent &lt;code&gt;#B6FC34&lt;/code&gt; and font stack, no guessing)&lt;/li&gt;
&lt;li&gt;screenshots of our actual product UI and login screen (that's where the cream-confetti-and-charcoal family came from)&lt;/li&gt;
&lt;li&gt;our older marketing repo (lifted the brand font files and Tailwind tokens directly)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each batch was three variants. Then the feedback loop did the real work: after "v7 &amp;gt; v9 &amp;gt; v8," the next three versions pushed the v7/v9 direction further and dropped v8's entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rankings beat reactions.&lt;/strong&gt; "Make it pop" gives an agent nothing. "A &amp;gt; B &amp;gt; C" gives it a gradient to descend.&lt;/p&gt;

&lt;h2&gt;
  
  
  The version switcher: zero JavaScript
&lt;/h2&gt;

&lt;p&gt;Every page gets a floating menu from the root layout. It's just a &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element — works in a static export, no hydration, no state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"group fixed right-5 bottom-5 z-50"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"... [&amp;amp;::-webkit-details-marker]:hidden"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;versions&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"absolute bottom-full right-0 mb-2 ..."&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;VERSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also stripped version links out of every page's header and footer once this existed — one switching mechanism, defined once.&lt;/p&gt;

&lt;p&gt;(After shipping the winner we gated the switcher and the &lt;code&gt;/versions&lt;/code&gt; index behind a build-time flag — visible in dev, absent from production builds unless &lt;code&gt;NEXT_PUBLIC_SHOW_VERSIONS=1&lt;/code&gt;. The variant URLs stay live for posts like this one; the comparison chrome doesn't follow visitors around.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Shipping the winner
&lt;/h2&gt;

&lt;p&gt;When the team picked v15, promotion was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./v15/page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The old homepage moved to &lt;a href="https://workupai.com/v1" rel="noopener noreferrer"&gt;&lt;code&gt;/v1&lt;/code&gt;&lt;/a&gt;. Nothing was deleted — fourteen alternates are still browsable, which turns out to be great for onboarding ("here's what we considered and why we didn't pick it").&lt;/p&gt;

&lt;h2&gt;
  
  
  How it deploys
&lt;/h2&gt;

&lt;p&gt;Infra is provisioned once with &lt;code&gt;terraform apply&lt;/code&gt; (S3, CloudFront, Route 53, ACM). After that, deploying is one script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# scripts/deploy.sh (condensed)&lt;/span&gt;
&lt;span class="nv"&gt;NEXT_PUBLIC_PLAUSIBLE_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DOMAIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; npm run build

&lt;span class="c"&gt;# pass 1: hashed assets — cache forever&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;sync &lt;/span&gt;out/ &lt;span class="s2"&gt;"s3://&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--delete&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--exclude&lt;/span&gt; &lt;span class="s2"&gt;"*.html"&lt;/span&gt; &lt;span class="nt"&gt;--exclude&lt;/span&gt; &lt;span class="s2"&gt;"*.txt"&lt;/span&gt; &lt;span class="nt"&gt;--exclude&lt;/span&gt; &lt;span class="s2"&gt;"*.xml"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-control&lt;/span&gt; &lt;span class="s2"&gt;"public,max-age=31536000,immutable"&lt;/span&gt;

&lt;span class="c"&gt;# pass 2: HTML — never cache&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;sync &lt;/span&gt;out/ &lt;span class="s2"&gt;"s3://&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--delete&lt;/span&gt; &lt;span class="nt"&gt;--exclude&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include&lt;/span&gt; &lt;span class="s2"&gt;"*.html"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt; &lt;span class="s2"&gt;"*.txt"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt; &lt;span class="s2"&gt;"*.xml"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-control&lt;/span&gt; &lt;span class="s2"&gt;"no-cache"&lt;/span&gt;

aws cloudfront create-invalidation &lt;span class="nt"&gt;--distribution-id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DISTRIBUTION_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--paths&lt;/span&gt; &lt;span class="s2"&gt;"/*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three details that matter more than they look:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Two-pass sync for caching.&lt;/strong&gt; Next's hashed assets (&lt;code&gt;/_next/static/...&lt;/code&gt;) are immutable, so they get &lt;code&gt;max-age=31536000,immutable&lt;/code&gt;. HTML gets &lt;code&gt;no-cache&lt;/code&gt; so a deploy is visible immediately. Skipping this split is how you end up with users staring at a stale page for a day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A 10-line CloudFront Function for pretty URLs.&lt;/strong&gt; Static export writes &lt;code&gt;/v7&lt;/code&gt; as &lt;code&gt;v7.html&lt;/code&gt;, but browsers request &lt;code&gt;/v7&lt;/code&gt;. One viewer-request function bridges the gap — no server needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is &lt;em&gt;the&lt;/em&gt; gotcha of S3 + CloudFront + &lt;code&gt;output: "export"&lt;/code&gt; — without it, every route except &lt;code&gt;/&lt;/code&gt; 404s and you'll lose an evening to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Analytics is a build-time decision.&lt;/strong&gt; The deploy script injects &lt;code&gt;NEXT_PUBLIC_PLAUSIBLE_DOMAIN&lt;/code&gt;, so local builds never track visits and production builds always do. No env drift, no "why is localhost in our analytics."&lt;/p&gt;

&lt;p&gt;Total moving parts: an S3 bucket, a CDN, one function, one shell script. There's no CI pipeline yet on purpose — &lt;code&gt;scripts/deploy.sh&lt;/code&gt; from a laptop is honest about what this stage of a startup needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I've learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Same copy, many skins turns taste into a fast decision.&lt;/strong&gt; When every variant reads identically, "which one?" takes minutes. The moment wording differs between options, people argue about words while believing they're arguing about design.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Copy is a supply chain.&lt;/strong&gt; Our hero names a problem ("feedback is scattered"), the problem section itemizes it, the solution section cancels each item &lt;em&gt;using the same nouns&lt;/em&gt;, and the CTA lands the theme. If a later section can't reuse an earlier section's vocabulary, one of them is wrong. This is also why one shared file works at all.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The markdown-as-CMS pattern is absurdly cheap.&lt;/strong&gt; ~120 lines of parser bought us: non-devs editing production copy, pure design A/B comparisons, and copy fixes that propagate to fifteen pages in one commit. I'd reach for this long before a headless CMS on any marketing site.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Steal it
&lt;/h2&gt;

&lt;p&gt;The recipe, condensed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Move every headline, list, and CTA label into one &lt;code&gt;content/*.md&lt;/code&gt; file with a trivial &lt;code&gt;key: value&lt;/code&gt; grammar.&lt;/li&gt;
&lt;li&gt;Make each design a self-contained page that reads it at build time.&lt;/li&gt;
&lt;li&gt;Mark emphasis in the copy; style it per design.&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; version menu in the layout.&lt;/li&gt;
&lt;li&gt;Give feedback as rankings, ship the winner as a re-export.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Full disclosure: this workflow is also our product
&lt;/h2&gt;

&lt;p&gt;The landing pages in this post sell &lt;a href="https://spuree.com" rel="noopener noreferrer"&gt;Spuree Creative Engine&lt;/a&gt; — and the loop the copy describes is the loop I just walked you through, productized: your agent drafts, you &lt;strong&gt;share a client-safe review link&lt;/strong&gt; (not a zip in a Slack thread), feedback lands &lt;strong&gt;pinned on the work itself&lt;/strong&gt;, and every approval becomes &lt;strong&gt;per-client memory&lt;/strong&gt; your agent reads before the next draft — from Claude Code, Codex, or OpenClaw.&lt;/p&gt;

&lt;p&gt;Who it's for, concretely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Freelance devs shipping agent output to clients&lt;/strong&gt; — stop being the human clipboard between your agent and your client, and stop re-teaching your agent each client's taste after every revision round. One review link out, pinned feedback back, and the approval is remembered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agencies and brand studios&lt;/strong&gt; — you're running this loop across many clients at once: campaign assets, product imagery, storyboards, social creative, character and IP canon. Creative Engine keeps a &lt;strong&gt;separate brand memory per client&lt;/strong&gt;, so what Client A approved in March is what your agent drafts from in June — and no client ever repeats a note. The sign-off itself becomes the brand guideline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the multi-version trick from this post is becoming a feature. We're opening up &lt;strong&gt;HTML hosting on Creative Engine&lt;/strong&gt; — upload your site or campaign variants, get shareable links and a version switcher, and collect client feedback on each one, with none of the S3/CloudFront setup you just read about. Freelancers: test landing page directions with your client before committing. Agencies: send three homepage directions as &lt;em&gt;one link&lt;/em&gt; and let the client leave feedback where you'll actually find it. If you'd want that, say so in the comments — early access is going out to people who ask.&lt;/p&gt;




&lt;p&gt;If you want to go deeper on any piece — the parser, the reference-driven design generation, the Terraform for the S3 + CloudFront setup, or how this plugs into the Slack + Claude Code workflow from the last post — drop a comment. Happy to share code.&lt;/p&gt;

&lt;p&gt;And if you try this and get stuck — the routes 404 behind CloudFront, the emphasis markers break, the parser eats your copy — &lt;strong&gt;drop a comment too. I'll help you debug it.&lt;/strong&gt; That's not politeness; comments about where this pattern fails are exactly what makes the next post better.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>aws</category>
      <category>ai</category>
    </item>
    <item>
      <title>How Our Designer Ships Front-End Changes Without Writing Code</title>
      <dc:creator>Hsin Yen Chung</dc:creator>
      <pubDate>Sat, 11 Apr 2026 22:35:15 +0000</pubDate>
      <link>https://dev.to/hsin_yenchung_5562e7d5c9/how-our-designer-ships-front-end-changes-without-writing-code-5936</link>
      <guid>https://dev.to/hsin_yenchung_5562e7d5c9/how-our-designer-ships-front-end-changes-without-writing-code-5936</guid>
      <description>&lt;p&gt;Our product designer Zain just shipped a front-end change to our web app without writing a single line of code. He typed a request in Slack, and 10 minutes later there was a PR with a live preview environment.&lt;/p&gt;

&lt;p&gt;This post breaks down exactly how we built this system at &lt;a href="https://spuree.com/waitlist" rel="noopener noreferrer"&gt;Spuree&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Video walkthrough:&lt;/strong&gt; &lt;a href="https://youtu.be/7_8cApBGWss" rel="noopener noreferrer"&gt;https://youtu.be/7_8cApBGWss&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Workflow in 30 Seconds
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Zain types a request in our #ai-coding Slack channel&lt;/li&gt;
&lt;li&gt;Spuree AI Coder (our AI agent) receives the message&lt;/li&gt;
&lt;li&gt;Agent creates a Linear ticket automatically&lt;/li&gt;
&lt;li&gt;Agent spins up a Claude Code sub-agent in a git worktree&lt;/li&gt;
&lt;li&gt;Sub-agent implements the change, runs prettier, commits&lt;/li&gt;
&lt;li&gt;Agent opens a PR on GitHub&lt;/li&gt;
&lt;li&gt;CI/CD spins up a preview environment&lt;/li&gt;
&lt;li&gt;Zain clicks the preview link, verifies the change visually, and approves — or asks for another iteration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No IDE. No git commands.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;OpenClaw&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;A self-hosted AI agent for automating daily workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Anthropic's coding CLI — does the actual implementation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linear&lt;/td&gt;
&lt;td&gt;Ticket tracking — auto-created per request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub&lt;/td&gt;
&lt;td&gt;PRs, CI/CD, preview environments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slack&lt;/td&gt;
&lt;td&gt;Interface for the team&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spuree&lt;/td&gt;
&lt;td&gt;Storage for agent output, backups, team sharing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  How It Started: A Mac Mini and One Install
&lt;/h2&gt;

&lt;p&gt;A few months ago, I installed OpenClaw on a 2018 Mac mini — a gift from a friend. One line to install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; openclaw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I named it Chung.&lt;/p&gt;

&lt;p&gt;Like onboarding a new employee, I taught it my workflows step by step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How I review PRs&lt;/li&gt;
&lt;li&gt;How I track Linear tickets&lt;/li&gt;
&lt;li&gt;How I monitor tech blogs&lt;/li&gt;
&lt;li&gt;How I summarize YouTube videos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each workflow became a &lt;strong&gt;reusable skill&lt;/strong&gt; — a markdown file with instructions, scripts, and configuration that the agent follows.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Coding Skill: &lt;code&gt;claude-code-pr&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is the skill that powers the designer workflow. Here's what it does:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Creates a Linear ticket
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.linear.app/graphql &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: &lt;/span&gt;&lt;span class="nv"&gt;$LINEAR_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"query": "mutation { issueCreate(input: { ... }) { ... } }"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent extracts the &lt;code&gt;branchName&lt;/code&gt; from Linear's response — this ensures branch naming is consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Creates a git worktree
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$REPO_DIR&lt;/span&gt;
git fetch origin main
git worktree add &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-wt-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LINEAR_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt; origin/main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Worktrees let us work on multiple features in parallel without switching branches in the main repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Spins up Claude Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$WORKTREE_DIR&lt;/span&gt;
claude &lt;span class="nt"&gt;--dangerously-skip-permissions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Heads up:&lt;/strong&gt; The &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; flag lets Claude Code execute commands without asking for confirmation — file writes, terminal commands, all of it. We use this because the agent runs on a dedicated Mac mini with no sensitive data. If you're following along, only use this flag in sandboxed or isolated environments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent sends a structured prompt with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The requirements from the Slack message&lt;/li&gt;
&lt;li&gt;A mandatory completion checklist (commit, PR, cleanup)&lt;/li&gt;
&lt;li&gt;Formatting rules (run prettier before committing)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Creates a PR
&lt;/h3&gt;

&lt;p&gt;Claude Code commits, pushes, and creates a PR with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Summary of changes&lt;/li&gt;
&lt;li&gt;Linear ticket link&lt;/li&gt;
&lt;li&gt;Testing instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CI/CD automatically creates a preview environment from the PR.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Designer reviews
&lt;/h3&gt;

&lt;p&gt;The preview URL appears in Slack. Designer clicks it, verifies the change visually, and approves — or asks for another iteration.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Else the Agent Does
&lt;/h2&gt;

&lt;p&gt;The coding skill is just one of many. Our agent runs cron jobs throughout the day:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cron Job&lt;/th&gt;
&lt;th&gt;Schedule&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Morning AI Digest&lt;/td&gt;
&lt;td&gt;8am daily&lt;/td&gt;
&lt;td&gt;Searches for AI/tech news, sends bullet summary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hacker News Summary&lt;/td&gt;
&lt;td&gt;9am daily&lt;/td&gt;
&lt;td&gt;Pulls HN front page, summarizes top stories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tech Blog Monitor&lt;/td&gt;
&lt;td&gt;9am daily&lt;/td&gt;
&lt;td&gt;Checks RSS feeds + scrapers for new articles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PR Watcher&lt;/td&gt;
&lt;td&gt;Every 30 min&lt;/td&gt;
&lt;td&gt;Notifies about new PRs with code review summary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video Summarizer&lt;/td&gt;
&lt;td&gt;On demand&lt;/td&gt;
&lt;td&gt;Transcribes YouTube videos, generates summaries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  From Personal Assistant to Team Tool
&lt;/h2&gt;

&lt;p&gt;After a few months, I realized everything was trapped on one machine. No backup. No team access. No way for others to comment on the agent's output.&lt;/p&gt;

&lt;h3&gt;
  
  
  The migration:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Backed up everything&lt;/strong&gt; — memory, skills, cron jobs, config&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uploaded the backup to Spuree&lt;/strong&gt; (our storage platform)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spun up an EC2 instance&lt;/strong&gt; on AWS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Downloaded and restored&lt;/strong&gt; the backup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adjusted file paths&lt;/strong&gt; (Mac → Linux differences)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connected to Slack&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Spuree AI Coder was born. Now the whole team has access to the same workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent output has a home
&lt;/h3&gt;

&lt;p&gt;The key insight: agent output needs to be &lt;strong&gt;searchable, shareable, and backed up&lt;/strong&gt; — just like any other work product.&lt;/p&gt;

&lt;p&gt;When our agent creates something important — a strategy doc, a feature spec, meeting notes — it uploads it to Spuree automatically. Team members get a link, comment on it, and the agent creates the next version based on their feedback.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I've Learned
&lt;/h2&gt;

&lt;p&gt;Managing a team in the AI era, the gap between product, design, and engineering gets smaller — but only if you give your agents a proper setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Memory that persists&lt;/strong&gt; — the agent needs to remember context across sessions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills that are reusable&lt;/strong&gt; — turn workflows into shareable, version-controlled instructions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output that's shareable&lt;/strong&gt; — agent work needs a home where teams can collaborate on it&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenClaw&lt;/strong&gt;: &lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;github.com/openclaw/openclaw&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spuree waitlist&lt;/strong&gt;: &lt;a href="https://spuree.com/waitlist" rel="noopener noreferrer"&gt;spuree.com/waitlist&lt;/a&gt; — we'll share the skills and help you set up&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;I'm Steven, Head of Engineering at Spuree. We're building a storage platform for the age of AI agents. If you have questions about the setup, drop a comment — happy to go deeper on any part of this.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>productivity</category>
      <category>openclaw</category>
    </item>
  </channel>
</rss>
