2026
KOJA Paper Box + KDB
The operating system for a three-person stationery shop. AI that drafts, translates and watches stock, with a person always in the loop. 285 releases in about 100 days.

- Goal
- Run a Seoul-to-US stationery shop with a team of three
- Role
- Partner. Product design, product owner, AI direction
- Tools
- Claude Code, Claude API, Shopify, Vercel, Neon
- Timeline
- June to September 2026, still shipping
Results
- $21.5k
- revenue through the store in its first months
- 596 orders
- run through the dashboard, in 6 countries
- 285 releases
- shipped to production in about 100 days
- 3 people
- doing the work of a fulfillment, support and ops team
The problem
KOJA Paper Box sells Korean and Japanese stationery to people in the US, Canada and the UK. There are three of us. Silas runs fulfillment and customer support, and I design and build the tools we run on.
When orders took off, the business lived in six places at once. Shopify had the orders. A Google Sheet had the money. A Korean supplier's website had the stock. Customer email sat in a shared inbox. Tasks lived in Discord. Nobody could answer "are we making money?" or "did anyone reply to her?" without opening all six.
So I designed one tool for all of it, and shipped it the same week.

What KDB is
KDB, the KOJA Dashboard, is where the business actually runs. Revenue and profit by two-week sprint. Orders and fulfillment. Expenses and the partner payout split. A product catalogue that talks to Shopify and to our Korean suppliers. A support board fed by the inbox. Tasks, a calendar, a blog planner and a team wiki.
Every tab came from a real moment. A teammate hits a wall in Discord, I turn it into a spec, and the fix usually ships the same day.

Designing AI features people can trust
Most of KDB's hardest design problems were about AI and automation doing real work on a live store. My rule was simple: the machine can do the tedious part, but a person always sees what it did and owns anything a customer will see.
- Pull a shop page. Paste a Korean supplier's page and every product lands with its photos, translated names, options and a KOJA SKU. Many of those listings are images only, so Claude reads the description images and writes the specs. Nothing goes to the store until someone reviews it and presses push, and it always lands as a draft.
- Voice as a prompt. I wrote the KOJA voice as a reusable prompt layer: who we sound like, the words we never use, before and after examples, and a checklist for catching machine-sounding writing. Product copy, support replies and blog posts all draw on the same file, so a voice change lands everywhere at once.
- Drafts, never sends. The AI drafts support replies and blog posts. A human sends the email and publishes the post. That is a product rule, not a setting.
- Dry run first. Anything that changes a live listing, like adding a size to a product, runs as a preview that lists exactly what will change. The real run only happens after a yes.
- Warn before overwriting people. Silas edits listings directly in Shopify. When a push would have replaced her photos, we changed the product: pulling now mirrors Shopify one to one, keeps anything local greyed out instead of deleting it, and never stores a photo twice.
Automation you can see
Our supplier kept selling out. One popular planner sold out overnight and we had already oversold it. So I designed a stock watch: tick a product and KDB reads the supplier's stock once a day and the moment someone buys it, then sets our Shopify stock by a rule the team agreed on. Sold out there means zero here. One or two left means we list one. Otherwise we cap at six.
The design work was in making the agent legible. Every variant shows what the supplier has left next to what we list, and when it last looked. A variant it can't confidently match says "not matched" and is left alone rather than guessed. A sell-out pings its own Discord channel. And a person can always override it: untick the watch and the stock is yours again.

Workflow tools for a small team
Support was the part that hurt most. Mail came in faster than we could track it. The support board turns every customer email into a case, threads replies onto it, and gives each case a 12-hour timer that pauses while we wait on the customer. Moving a case to Solved now asks how it was solved, so the next person to open it knows what happened. Newsletters and review alerts stay out: only real customer folders become cases.


One system, not a pile of screens
With a new feature most days, consistency had to be designed in rather than policed. KDB has one set of patterns and reuses them: tables that fit their box with columns you can drag to resize, a save lock with a progress bar so nobody double-submits, one card style for tasks and cases, light and dark themes from the same tokens, and deep links so a shared URL opens the exact product.
The documentation is part of the system too. Three living docs sit next to the code: what it is for, how it is built, and an API reference. A test fails when the API and its reference drift apart, so the doc the AI reads is always true.

Building it
KDB started on June 22 as a single web page on top of our Google Sheet: orders, expenses, and the profit split between partners. The sheet was the database because that is where the team already was. It was the right first step and the wrong second one. By September the sheet was the bottleneck, so in one day I moved every dataset onto a real database and turned the sheet into a read-only mirror. Nobody had to change how they worked, and nothing was lost.
The shape today:
- One page, one API. The whole interface is a single page that loads fast and works on a phone. Behind it sit a dozen serverless functions on Vercel, grouped by job: data, products, support, blog, wiki, sync. The hosting plan once capped us at 12 functions, so related actions share an endpoint instead of each getting their own.
- Postgres as the source of truth. Neon Postgres holds every row: orders, expenses, payouts, tasks, support cases, products, variants and settings. Photos live in Vercel Blob, with Google Drive as the long-term archive. The schema creates itself on first run, so a fresh copy of the site sets itself up.
- Real accounts. Personal logins with admin and member roles, plus a separate robot login that can use the API but can never administer it.
The integrations
Most of KDB's value is in what it connects. Each integration exists because someone was copying something by hand.
- Shopify. Orders sync every hour and on demand. Products go both ways: pushed as drafts, pulled back one to one, photos included. Stock is written straight to the store, and a Shopify webhook tells us the moment an order lands.
- Korean suppliers. The pull tool reads supplier pages, prices them with our markup and today's exchange rate, and the stock watch checks them daily.
- Claude. Translation, reading image-only product descriptions, and drafting copy in the KOJA voice.
- Zoho Mail. Customer email becomes support cases every ten minutes, and replies thread onto the right case.
- Discord. New cases, customer replies, timers about to run out and supplier sell-outs each ping the right person or channel.
- Meta. One button pulls the day's ad spend so the profit numbers are real.
- Google. The old sheet stays as a readable mirror and Drive keeps every product photo.

Where agents come in next
KDB was designed so an agent could use it the way a teammate does, and one already does. Claude works the live dashboard over the same API the page uses: it files tasks, checks supplier stock, writes blog drafts and plans product changes. It does that as the robot login, with no admin rights, reading an API reference that a test keeps honest.
The guardrails I designed for people turned out to be exactly what agents need:
- Dry run, then confirm. Anything that changes the store shows its plan first.
- Draft, never send. An agent can write to a customer. Only a person sends it.
- Say what gets overwritten. Before touching work a teammate did by hand, list what would be replaced or lost, and wait.
- Leave it alone when unsure. An unmatched variant is skipped, not guessed.
The next agents are the ones the team keeps asking for in Discord. A support agent that drafts a reply into each new case with the order already looked up, for a person to edit and send. A restock agent that watches sell-outs and sales speed and proposes what to reorder. A listing agent that turns a supplier link into a finished, reviewed Shopify listing. And a Monday brief that reads the whole business and says what changed. The hard part of each is not the model. It is designing where the human steps in, and making every step the agent took easy to see and undo.
How I worked
I work spec first. Every change starts as a short written intent: the problem, what done looks like, what is out of scope. Then I build it with Claude Code, review the diff and the live result, and ship. Every release gets a version and a plain-language changelog, and nothing goes to production without my review.
That loop is why 285 releases in about 100 days felt calm instead of chaotic. It also meant I could explore several solutions in parallel and throw away the weak ones cheaply. The Sales mix chart went from request to live in one morning. Grouping by brand, by type and by product were all on the table. I picked by type, then tuned the rules against every real order until nothing important landed in Other.
What I would do differently
- Put our own time into the cost of every order. At first the dashboard treated packing as free. On paper, a small item with a 50% margin looked great. In practice it took 15 minutes to pick, pack and label, and that 50% was about $3, so we were paying ourselves roughly $12 an hour and spending the day on orders that couldn't fund the business, with less time left for the ones that could. It put real stress on the team, and we had to change our strategy over one missing line in the cost model. Now every product carries its packing time, priced at an hourly rate, and the margins you see are the real ones.
- Design for the people outside the tool first. The photo overwrite happened because I designed for people using KDB, and Silas works in Shopify. Now every change that touches the store starts with "who else edits this, and where?"
- Name the rules out loud earlier. Product categories started as keyword rules I tuned against real orders. It works, but a category field on each product would have been clearer to the team from day one.
- Measure support, not just sales. We track revenue to the cent. We should have tracked time to first reply from the start.
Role and collaborators
I'm one of KOJA's three partners. I designed KDB end to end: working sessions with the team, flows, interaction design, visual design, the AI behaviours and their guardrails, and the product decisions. I directed the build with Claude Code as my engineering partner and shipped to production myself. Silas and SonWoo were my users, testers and harshest critics, which is exactly what a tool like this needs.
Stack: Vercel serverless functions, Neon Postgres, Vercel Blob, the Shopify Admin API and webhooks, the Claude API, Zoho Mail, the Meta Marketing API, Google Sheets and Drive, and Discord.