<?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: Mide</title>
    <description>The latest articles on DEV Community by Mide (@mystiquemide).</description>
    <link>https://dev.to/mystiquemide</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%2F4153285%2Fa3365e65-c78f-455b-b802-85b58a4ecff0.png</url>
      <title>DEV Community: Mide</title>
      <link>https://dev.to/mystiquemide</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mystiquemide"/>
    <language>en</language>
    <item>
      <title>Tessom: every upholstery offcut gets a next piece</title>
      <dc:creator>Mide</dc:creator>
      <pubDate>Sun, 04 Oct 2026 21:00:40 +0000</pubDate>
      <link>https://dev.to/mystiquemide/tessom-every-upholstery-offcut-gets-a-next-piece-4nim</link>
      <guid>https://dev.to/mystiquemide/tessom-every-upholstery-offcut-gets-a-next-piece-4nim</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/sanity-2026-09-16"&gt;Sanity Challenge, Path Two: Vibe-Code Something Strange&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Tessom is a marketplace and workshop system for upholstery fabric offcuts.&lt;/p&gt;

&lt;p&gt;Upholstery shops regularly cut fabric for a sofa, chair or other job and end up with usable material left over. Some pieces are large, valuable and completely unique, but they usually sit in a corner because listing them is harder than it sounds.&lt;/p&gt;

&lt;p&gt;An odd-shaped remnant can have flaws, a repeating pattern, a fixed direction and limited usable space. On top of that, the fabric may still belong to the original client, which means the workshop can't simply sell it.&lt;/p&gt;

&lt;p&gt;Tessom handles that whole process.&lt;/p&gt;

&lt;p&gt;Each remnant stores its dimensions, pattern repeat, direction, flaws, ownership status and fabric photo. From that information, Tessom works out what can actually be made from the remaining material.&lt;/p&gt;

&lt;p&gt;Instead of showing generic products, the shop shows cuts that really fit the available fabric, with their actual placement and price drawn against the real remnant.&lt;/p&gt;

&lt;p&gt;Offers are calculated on every read rather than stored. If the usable area changes, the available products change with it, so stale offers aren't left behind.&lt;/p&gt;

&lt;p&gt;When someone places an order, Tessom locks the exact area of fabric being used. That means the same part of a remnant can't be sold twice.&lt;/p&gt;

&lt;p&gt;I tested this directly by sending two buyers after the same cut at almost exactly the same time. One request succeeded with HTTP 200. The other received HTTP 409.&lt;/p&gt;

&lt;p&gt;The second browser updated automatically through a Sanity listener without needing a reload.&lt;/p&gt;

&lt;p&gt;Ownership consent is also part of the workflow rather than a checkbox added on top. If a remnant belongs to a client, the owner must approve it before the workshop can sell anything from it.&lt;/p&gt;

&lt;p&gt;From there, the workshop moves an order through its actual production stages:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Awaiting consent → Allocated → Cut → Sewn → Shipped&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Tessom is aimed at small upholstery workshops and customers who might want a one-off cushion, bench pad, tote or similar product made from fabric that already exists.&lt;/p&gt;

&lt;p&gt;Anyone with leftover fabric can offer it at &lt;code&gt;/submit&lt;/code&gt;: size, a photo, and optional details. The offer is stored on a private path with the contact encrypted, and nothing is listed until the workshop reviews it.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;/workshop&lt;/code&gt;, the same Groq selvage reader pre-fills the fabric name, maker, repeat and direction from the offer's photo. The workshop checks the fields, sets a value and accepts it, and the fabric enters the consent workflow under a generic owner name, never the submitter's name or email.&lt;/p&gt;

&lt;p&gt;The submitter gets a private status page.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's real
&lt;/h3&gt;

&lt;p&gt;The live project includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;remnant and allocation data stored in Sanity&lt;/li&gt;
&lt;li&gt;owner consent&lt;/li&gt;
&lt;li&gt;deterministic cut fitting&lt;/li&gt;
&lt;li&gt;order creation&lt;/li&gt;
&lt;li&gt;concurrency and conflict handling&lt;/li&gt;
&lt;li&gt;encrypted buyer contact data&lt;/li&gt;
&lt;li&gt;workflow progression&lt;/li&gt;
&lt;li&gt;live Sanity updates&lt;/li&gt;
&lt;li&gt;selvage extraction with vision&lt;/li&gt;
&lt;li&gt;workshop management&lt;/li&gt;
&lt;li&gt;production stages from allocation through shipping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The remnants, owners and makers in the demo are fictional sample data. The fabric photography comes from Unsplash.&lt;/p&gt;

&lt;p&gt;Payments and transactional emails aren't implemented. After an order is placed, the workshop would currently contact the buyer manually.&lt;/p&gt;

&lt;p&gt;The offer engine itself doesn't use AI. Rectangle fitting and allocation are deterministic because there was no reason to introduce a model into something that can be calculated and independently verified.&lt;/p&gt;

&lt;p&gt;The AI-assisted part is the selvage reader inside Studio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/HU9j5eTUA84" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Live project: &lt;a href="https://tessom.midelabs.xyz" rel="noopener noreferrer"&gt;https://tessom.midelabs.xyz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't need an account.&lt;/p&gt;

&lt;p&gt;No sign-up.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;/shop&lt;/code&gt;, pick a fabric and order a cut with any name and email.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;/workshop&lt;/code&gt;, enter the PIN &lt;code&gt;tessom-judges-2026&lt;/code&gt; and move the order to cut, sewn and shipped.&lt;/p&gt;

&lt;p&gt;To try the intake side, open &lt;code&gt;/submit&lt;/code&gt;, offer a fabric with a photo, then find it under &lt;strong&gt;Offered fabric&lt;/strong&gt; in &lt;code&gt;/workshop&lt;/code&gt;. Press &lt;strong&gt;Read selvage photo&lt;/strong&gt;, then &lt;strong&gt;Accept&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On the board, press &lt;strong&gt;Copy owner link&lt;/strong&gt; on an Awaiting consent card to try the owner's approve or decline page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/mystiquemide/tessom" rel="noopener noreferrer"&gt;https://github.com/mystiquemide/tessom&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The README maps the main judging criteria to their implementation and includes the tests behind the failure cases I tried to break.&lt;/p&gt;

&lt;p&gt;The project currently has 302 tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Sanity
&lt;/h2&gt;

&lt;p&gt;Sanity is the source of truth for the inventory, ownership, allocations, orders and workshop state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structured remnants
&lt;/h3&gt;

&lt;p&gt;Each remnant records the information the offer engine needs to make a real decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dimensions&lt;/li&gt;
&lt;li&gt;pattern repeat&lt;/li&gt;
&lt;li&gt;fabric direction&lt;/li&gt;
&lt;li&gt;flaws&lt;/li&gt;
&lt;li&gt;ownership&lt;/li&gt;
&lt;li&gt;image&lt;/li&gt;
&lt;li&gt;existing allocations&lt;/li&gt;
&lt;li&gt;current workflow state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The offer engine reads that structured content and fits product templates into the remaining usable space.&lt;/p&gt;

&lt;p&gt;Offers aren't persisted as documents. They're derived from the current remnant state every time they're requested.&lt;/p&gt;

&lt;p&gt;That means an offer can't stay visible after another customer has consumed the area it depended on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Allocation and concurrency
&lt;/h3&gt;

&lt;p&gt;The remnant owns its allocations, so the sold area lives in one authoritative place.&lt;/p&gt;

&lt;p&gt;When an order is placed, the order route writes the new allocation using the remnant's Sanity revision.&lt;/p&gt;

&lt;p&gt;If two buyers attempt to reserve the same area at the same time, only one revision can win.&lt;/p&gt;

&lt;p&gt;The other request fails instead of silently creating a double booking.&lt;/p&gt;

&lt;p&gt;I also kept the allocation guard and area-lock validation based on the same rules so the two checks can't disagree about whether a cut is available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Privacy
&lt;/h3&gt;

&lt;p&gt;Orders use private document paths, and buyer contact details are encrypted before being stored.&lt;/p&gt;

&lt;p&gt;The public Sanity dataset can expose the inventory needed by the storefront without exposing buyer information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sanity Workflows
&lt;/h3&gt;

&lt;p&gt;Consent and production aren't represented as loose status strings.&lt;/p&gt;

&lt;p&gt;They move through real workflow stages:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Awaiting consent → Allocated → Cut → Sewn → Shipped&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sanity Workflows 0.36 is still early access and doesn't provide the background runtime I needed, so every application route that mutates an order also advances the corresponding workflow itself.&lt;/p&gt;

&lt;p&gt;Inside Studio, the official Workflows plugin exposes the live instances in both table and board views.&lt;/p&gt;

&lt;h3&gt;
  
  
  Studio selvage reader
&lt;/h3&gt;

&lt;p&gt;I also built a custom Studio action called &lt;strong&gt;Read selvage photo&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A user can open a remnant and run the tool against its fabric image.&lt;/p&gt;

&lt;p&gt;The server fetches the image from Sanity and sends the image bytes to Groq Vision.&lt;/p&gt;

&lt;p&gt;It attempts to extract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;printed fabric name&lt;/li&gt;
&lt;li&gt;maker&lt;/li&gt;
&lt;li&gt;pattern repeat&lt;/li&gt;
&lt;li&gt;direction&lt;/li&gt;
&lt;li&gt;supporting evidence&lt;/li&gt;
&lt;li&gt;confidence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is only a suggestion.&lt;/p&gt;

&lt;p&gt;Nothing is written back to the remnant until the user presses &lt;strong&gt;Apply suggestions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the photo doesn't contain readable selvage information, the tool returns null values rather than inventing an answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live updates
&lt;/h3&gt;

&lt;p&gt;The storefront listens for relevant Sanity changes.&lt;/p&gt;

&lt;p&gt;When an allocation changes, another open browser can update its available cuts without reloading the page.&lt;/p&gt;

&lt;p&gt;Getting this working required both Sanity CORS configuration and adding the Sanity API host to the application's CSP &lt;code&gt;connect-src&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Build Process
&lt;/h2&gt;

&lt;p&gt;I started Tessom in Codex and finished it in Claude Code.&lt;/p&gt;

&lt;p&gt;Rather than asking either tool to build the entire product in one shot, I kept a written task list and moved through it one task at a time.&lt;/p&gt;

&lt;p&gt;Each task had three basic requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;implement the scoped change&lt;/li&gt;
&lt;li&gt;add or update tests&lt;/li&gt;
&lt;li&gt;pass the gate before moving on&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Changing the idea
&lt;/h3&gt;

&lt;p&gt;Tessom wasn't the idea I started the challenge with.&lt;/p&gt;

&lt;p&gt;My first concept was an agent that sold to EU buyers. I dropped it and replaced it on October 2 after validating the offcut problem.&lt;/p&gt;

&lt;p&gt;One detail changed the project significantly: large remnants often still belong to the customer whose furniture was upholstered.&lt;/p&gt;

&lt;p&gt;That made consent one of the core system states rather than a simple permission field.&lt;/p&gt;

&lt;p&gt;I also made an early decision to keep the offer engine deterministic. Fitting known shapes into known dimensions doesn't need an LLM, and deterministic logic made the result much easier to test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the backend
&lt;/h3&gt;

&lt;p&gt;The first major Codex prompt was essentially:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fan out multiple sub-agents to complete the remaining backend tasks. Inspect the code first, stay within your assigned scope, run your own checks, audit your work and report back. Do not accept an agent's work simply because it claims the task is complete. Verify the implementation and evidence yourself. When you reach the frontend, stop.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That final instruction mattered.&lt;/p&gt;

&lt;p&gt;The agents built the project scaffold, schemas, offer engine, order route and workflow layer, then stopped before visual design so I could choose the direction myself.&lt;/p&gt;

&lt;p&gt;I carried the plan and a small project memory file between Codex and Claude Code so a new session didn't need the architecture explained again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Review loops
&lt;/h3&gt;

&lt;p&gt;The review passes ended up improving the project more than the initial generation.&lt;/p&gt;

&lt;p&gt;After each backend wave, I ran fresh agents against the implementation instead of asking the agent that wrote the code to approve its own work.&lt;/p&gt;

&lt;p&gt;The test count moved from:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;13 → 69 → 80 → 97 → 137 → and 302 by the end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Those reviews caught issues that would otherwise have appeared during the demo, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stale shipping decisions&lt;/li&gt;
&lt;li&gt;buyer contact information being readable through the public dataset&lt;/li&gt;
&lt;li&gt;replayed keyed orders that weren't actually idempotent&lt;/li&gt;
&lt;li&gt;streamed request bodies bypassing the intended size limit&lt;/li&gt;
&lt;li&gt;a Sanity consistency race&lt;/li&gt;
&lt;li&gt;overlapping cut-plan labels&lt;/li&gt;
&lt;li&gt;route-specific layout mistakes&lt;/li&gt;
&lt;li&gt;missing production configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the frontend, I used separate audits for design, page planning, UX, conversion, microcopy and hackathon judging.&lt;/p&gt;

&lt;p&gt;The microcopy review alone changed around 20 strings and forced the product to settle on consistent language around &lt;strong&gt;cuts&lt;/strong&gt;, &lt;strong&gt;offcuts&lt;/strong&gt; and &lt;strong&gt;panels&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The hostile judge-style review is also what pushed me to add live Sanity updates and the Vision tool inside Studio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Intake
&lt;/h3&gt;

&lt;p&gt;I also added a public &lt;code&gt;/submit&lt;/code&gt; form and tested it end to end in a throwaway Sanity dataset before touching production.&lt;/p&gt;

&lt;p&gt;An offer is stored on a private &lt;code&gt;submissions.&lt;/code&gt; path with an encrypted contact, so the public dataset returns none of it. The workshop reviews it in a panel on the board, can run the same selvage reader on the offer's photo, and accepts it to create the owner and remnant and start the consent workflow.&lt;/p&gt;

&lt;p&gt;The owner is created under a generic name such as &lt;code&gt;Client 3fa9&lt;/code&gt;, so the submitter's real name and email never reach the public data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where the models got stuck
&lt;/h3&gt;

&lt;p&gt;The build wasn't clean.&lt;/p&gt;

&lt;p&gt;I initially asked for GPT-5.6 Luna Max sub-agents, but an orchestration skill interpreted the request differently and started another model.&lt;/p&gt;

&lt;p&gt;I stopped the run, corrected the model selection and restarted the same work lanes without throwing away the files that were already valid.&lt;/p&gt;

&lt;p&gt;I also caught several cases where the models followed an incomplete specification too literally.&lt;/p&gt;

&lt;p&gt;For example, the initial page plan forgot the logo and favicon, so the generated navigation had neither.&lt;/p&gt;

&lt;p&gt;The workshop navigation also showed a link back to the workshop while the user was already on that page, and a shared footer leaked into routes where it didn't belong.&lt;/p&gt;

&lt;p&gt;The final fix was to stop patching each page independently and move those rules into the layout itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Things that actually broke
&lt;/h3&gt;

&lt;p&gt;A few implementation bugs shaped the final architecture.&lt;/p&gt;

&lt;p&gt;Groq Vision initially worked with only one of the models I tested, and remote Sanity image URLs returned HTTP 403. The working implementation fetches the Sanity image server-side and sends the image as base64 data.&lt;/p&gt;

&lt;p&gt;The first generated offers were also priced too low to survive the margin floor because my templates didn't include labour minutes and fill costs.&lt;/p&gt;

&lt;p&gt;When four products overlapped on the same fabric, every cut-plan label rendered at once and became unreadable. Labels now appear only for the active offer.&lt;/p&gt;

&lt;p&gt;Reseeding also failed because Sanity documents with active references couldn't simply be deleted. The working reset order became: seed the base data, remove dependent orders and workflow instances, then bootstrap again.&lt;/p&gt;

&lt;p&gt;One CSS rule caused a particularly annoying bug:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;margin: 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It was applied globally to headings outside Tailwind's layers and silently overrode spacing utilities across the interface.&lt;/p&gt;

&lt;p&gt;The first production deployment failed too. The Vercel project had no framework preset, so the build system looked for a &lt;code&gt;dist&lt;/code&gt; output directory that didn't exist.&lt;/p&gt;

&lt;p&gt;Those failures are also why I kept a short project memory file containing decisions and known gotchas. When I moved between sessions and tools, the next agent could continue from the actual state of the build rather than rediscovering the same problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sanity Project Details
&lt;/h2&gt;

&lt;p&gt;Project ID:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;59g78icb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dataset:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;production&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The dataset has public read access for the storefront content required by the demo.&lt;/p&gt;

&lt;p&gt;Example query:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://59g78icb.api.sanity.io/v2025-02-19/data/query/production?query=*%5B_type%3D%3D%22remnant%22%5D%7Btitle%2Cstatus%7D" rel="noopener noreferrer"&gt;View remnant data&lt;/a&gt;&lt;br&gt;
&lt;/p&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;-G&lt;/span&gt; &lt;span class="s1"&gt;'https://59g78icb.api.sanity.io/v2025-02-19/data/query/production'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-urlencode&lt;/span&gt; &lt;span class="s1"&gt;'query=*[_type=="sanity.workflow.instance"]{_id,currentStage}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devchallenge</category>
      <category>sanitychallenge</category>
      <category>sanity</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
