<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Lojik Labs — Field notes</title>
    <link>https://wearelojik.com/blog</link>
    <description>Solo builder notes on AI-native software from Lojik Labs.</description>
    <language>en-us</language>
    <lastBuildDate>Mon, 13 Apr 2026 12:00:00 GMT</lastBuildDate>
    <atom:link href="https://wearelojik.com/rss.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>One builder per vertical — the math that changed</title>
      <link>https://wearelojik.com/blog/one-builder-per-vertical</link>
      <guid isPermaLink="true">https://wearelojik.com/blog/one-builder-per-vertical</guid>
      <description>A twelve-person team in 2022 is one engineer plus Claude Code in 2026. Here&apos;s the spreadsheet that made us bet the company on it.</description>
      <content:encoded><![CDATA[<p>The cost of building software collapsed sometime in 2024. Most of the industry still hasn&#39;t priced that in.</p>
<p>When we started Lojik Labs, the default shape of a consumer product team was six to twelve people — a backend engineer, a mobile engineer, a frontend engineer, a designer, a product manager, plus the PM tax. That team could ship maybe one major feature a month, service 50k users, and break even on $30k MRR.</p>
<p>We now ship the same feature in a week. One person.</p>
<h2>What &quot;one builder per vertical&quot; actually means</h2>
<p>Every product in our portfolio has exactly one engineer. Not &quot;tech lead plus a contractor.&quot; Not &quot;me plus my cofounder doing design.&quot; One person owns the schema, the API, the UI, the infra, the ops, the support queue.</p>
<p>The only shared resource is the infrastructure layer — Supabase org, Vercel team, Sentry project, the auth/billing pattern library we copy into every new product.</p>
<h2>Why this works now</h2>
<p>Three things changed at the same time, and they compound:</p>
<ol>
<li><strong>AI collapsed syntax cost.</strong> Writing CRUD code, wiring up auth, porting between APIs — this is 80% of an engineer&#39;s week at most companies. Claude does it in minutes. What you spend time on is <em>judgment</em>: what to build, what to cut, what to defend.</li>
<li><strong>Infrastructure got free.</strong> Supabase, Vercel, Clerk, Stripe — the boring parts of software used to cost a platform team. Now they cost $50/month per product until you have real revenue.</li>
<li><strong>Distribution got weirder.</strong> Niche markets stopped being reachable by ad spend. They got reachable by WhatsApp, by Reddit threads, by one well-placed Twitter post. That rewards operators who understand the niche, not marketing teams who optimize funnels.</li>
</ol>
<h2>What it doesn&#39;t work for</h2>
<p>Horizontal SaaS with a million competitors. Anything where the moat is sales muscle. Anything that needs 24/7 human support from day one.</p>
<p>It works for vertical software — clinic scheduling in Spanish, bar-crawl coordination on a specific college campus, sportsbooks in Mexico. Markets too small for a16z but big enough for one engineer to live well off.</p>
<h2>The studio model</h2>
<p>Lojik Labs is the meta-layer: shared Supabase org, shared auth pattern, shared design system, shared Claude Code workflows, shared legal. Each product gets one builder who keeps 25–40% of their vertical&#39;s upside.</p>
<p>We&#39;re testing the hypothesis that a well-run studio of solo builders outperforms a single well-staffed startup at this scale. The portfolio is eleven products deep so far. We&#39;ll tell you in 2027 how it went.</p>
]]></content:encoded>
      <pubDate>Sun, 12 Apr 2026 12:00:00 GMT</pubDate>
      <author>diego.gonzap@wearelojik.com (Diego González Zapiain)</author>
      <category>Thesis</category>
      <category>Solo builder</category>
      <category>AI-native</category>
      <category>Studio model</category>
    </item>
    <item>
      <title>The Claude Code workflow that runs eleven products</title>
      <link>https://wearelojik.com/blog/claude-code-solo-workflow</link>
      <guid isPermaLink="true">https://wearelojik.com/blog/claude-code-solo-workflow</guid>
      <description>Orchestrator in main context, specialists in subagents, MCPs over CLI, skills over memory. The concrete setup I use to own an entire vertical alone.</description>
      <content:encoded><![CDATA[<p>I don&#39;t write much code anymore. I orchestrate. Here&#39;s the actual setup.</p>
<h2>The mental model</h2>
<p>Claude Code is a team, not a tool. The main conversation is the orchestrator — it routes, decides, and synthesizes. Specialized agents do the work in isolated contexts. MCPs handle service calls. Skills encode workflows.</p>
<p>If I&#39;m reading files or writing Python, something&#39;s wrong with my routing.</p>
<h2>The four-tier hierarchy</h2>
<table>
<thead>
<tr>
<th>Tier</th>
<th>What lives here</th>
<th>Why</th>
</tr>
</thead>
<tbody><tr>
<td>Main context</td>
<td>Architecture decisions, skill routing, synthesis</td>
<td>Preserves &quot;session state&quot; across interactions</td>
</tr>
<tr>
<td>Subagents</td>
<td>Implementation, exploration, verification</td>
<td>Isolates token usage, parallelizes work</td>
</tr>
<tr>
<td>MCPs</td>
<td>Service calls (Supabase, Sentry, Vercel, PostHog)</td>
<td>Structured output beats parsing CLI stdout</td>
</tr>
<tr>
<td>Skills</td>
<td>Packaged workflows (ship, review, investigate, qa)</td>
<td>Forces discipline where I&#39;d otherwise cut corners</td>
</tr>
</tbody></table>
<h2>What this looks like in practice</h2>
<p>&quot;Ship the new booking flow&quot; isn&#39;t me writing code. It&#39;s:</p>
<ol>
<li><code>/ship</code> skill routes me through test → review → commit → PR</li>
<li><code>security-reviewer</code> agent audits the diff in parallel</li>
<li><code>mcp__plugin_supabase_supabase__apply_migration</code> runs the schema change</li>
<li><code>mcp__plugin_vercel_vercel__</code> triggers the preview deploy</li>
<li>I read the agent reports, approve or iterate</li>
<li>Main context writes a handoff note to <code>tasks/session-state.md</code> for the next session</li>
</ol>
<p>Total time from &quot;ship it&quot; to merged PR: roughly 20 minutes for a typical feature. Most of that is me reading agent output.</p>
<h2>The rule that actually matters</h2>
<p><strong>Delegate before you explore.</strong> The default trap is to start reading files to &quot;get context&quot; before routing. By the time you&#39;re oriented, you&#39;ve burned 40% of your session on grep output that a subagent could have produced in parallel.</p>
<p>If a task will touch 2+ files, spawn an agent. If it needs deep codebase exploration, spawn an <code>Explore</code> agent. You write the prompt, it does the reading, you read the summary.</p>
<h2>What I don&#39;t use Claude Code for</h2>
<ul>
<li>Naming variables. I name things; AI picks boring names.</li>
<li>Product decisions. AI has no skin in the game.</li>
<li>Writing this post. I write the ideas, AI edits for tightness.</li>
</ul>
<p>The skill ceiling of this workflow isn&#39;t &quot;prompt better.&quot; It&#39;s &quot;understand your own product better, so your taste scales.&quot; AI is leverage on judgment, not a substitute for it.</p>
]]></content:encoded>
      <pubDate>Fri, 10 Apr 2026 12:00:00 GMT</pubDate>
      <author>diego.gonzap@wearelojik.com (Diego González Zapiain)</author>
      <category>Craft</category>
      <category>Claude Code</category>
      <category>AI-native</category>
      <category>Workflow</category>
      <category>Orchestration</category>
    </item>
    <item>
      <title>Case study: MediVoz — an AI receptionist for Mexican clinics</title>
      <link>https://wearelojik.com/blog/medivoz-whatsapp-clinics-mexico</link>
      <guid isPermaLink="true">https://wearelojik.com/blog/medivoz-whatsapp-clinics-mexico</guid>
      <description>Why a market too small for US healthtech — private clinics in Guadalajara and Monterrey — is exactly the shape of opportunity AI-native solo builders should want.</description>
      <content:encoded><![CDATA[<p>Private clinics in Mexico have a problem US healthtech won&#39;t solve: the receptionist leaves at 6pm, patients text WhatsApp at 9pm, and nobody answers until the next morning. The clinic loses the appointment.</p>
<p>MediVoz picks up that WhatsApp thread, books the appointment, syncs to the clinic&#39;s calendar, and sends a reminder the day before. In Spanish, with the regional courtesies. No human involved unless something unusual happens.</p>
<h2>Why US healthtech can&#39;t serve this market</h2>
<p>Rectangular economics. A typical US healthtech sale is $8–15 per patient per month, contracted annually, routed through a Zocdoc or SimplePractice sales team. That motion doesn&#39;t make sense for a 2-doctor clinic in Tepic charging 600 pesos per consult.</p>
<p>The actual ACV we can hit is ~$40/month per clinic, pay-as-you-go, WhatsApp-first onboarding. No US cap-table company is going to build that stack.</p>
<h2>The architecture</h2>
<ul>
<li><strong>Voice layer</strong>: Twilio SIP trunk into a Deepgram streaming ASR, Claude Sonnet for intent + response, ElevenLabs for TTS. Median latency around 700ms with barge-in detection so the agent yields when the patient starts talking.</li>
<li><strong>WhatsApp layer</strong>: Twilio&#39;s WhatsApp Business API. Same Claude prompt, different modality.</li>
<li><strong>Calendar layer</strong>: Supabase Postgres with RLS scoped per clinic, integrated with Google Calendar so doctors see appointments in whatever tool they already use.</li>
<li><strong>Ops</strong>: Sentry + PostHog for per-clinic observability, BullMQ for appointment reminders.</li>
</ul>
<h2>What took the longest</h2>
<p>Not the voice stack. Not the prompt. The hard work was the <em>cultural</em> part — training Claude to handle the specific formalities Mexican patients expect (&quot;Con mucho gusto&quot;, &quot;Para servirle&quot;), to recognize when a patient is in distress vs just confused, and to know when to escalate to a human operator.</p>
<p>We spent two weeks labeling conversations. The voice pipeline took three days.</p>
<h2>What I&#39;d tell another solo builder</h2>
<p>Find the market where the product is &quot;technology US companies already have, but adapted for a context US companies don&#39;t understand.&quot; That&#39;s not one-off work. That&#39;s every Spanish-speaking country, every language, every underserved vertical.</p>
<p>It requires you to care about the niche — to have family in Guadalajara, to text in Spanish slang, to know why a clinic that takes <em>solo efectivo</em> can&#39;t use Stripe. Taste is a moat. So is location.</p>
]]></content:encoded>
      <pubDate>Wed, 08 Apr 2026 12:00:00 GMT</pubDate>
      <author>diego.gonzap@wearelojik.com (Diego González Zapiain)</author>
      <category>Case Studies</category>
      <category>MediVoz</category>
      <category>Healthcare</category>
      <category>Mexico</category>
      <category>Voice AI</category>
    </item>
    <item>
      <title>Building a cinematic scroll-frame sequence in plain HTML</title>
      <link>https://wearelojik.com/blog/scroll-frame-sequence-webp</link>
      <guid isPermaLink="true">https://wearelojik.com/blog/scroll-frame-sequence-webp</guid>
      <description>241 WebP frames, one canvas, a lerp-smoothed scroll target, and a parallel-chunked loader. How the wearelojik.com hero sequence ships at 4MB total with no framework.</description>
      <content:encoded><![CDATA[<p>The scroll sequence on our homepage runs 241 frames across a 300vh runway. Total weight: 4MB. No framework. Here&#39;s how it works.</p>
<h2>The naive approach (don&#39;t do this)</h2>
<p>You put 241 <code>&lt;img&gt;</code> tags in the DOM, each with <code>position: absolute</code>. You toggle <code>opacity</code> as the user scrolls. It looks fine on a MacBook and dies on an iPhone — layout thrashing, memory bloat, GPU stalls while compositing two hundred layers.</p>
<h2>What we do instead</h2>
<p>One <code>&lt;canvas&gt;</code>. Draw one frame at a time. Two-stage load: critical batch first (covers state-1 and state-2 entry), then 6 parallel workers chew through the rest in the background.</p>
<pre><code class="language-js">function loadFrame(idx) {
  return new Promise((res) =&gt; {
    if (images[idx]) return res();
    const img = new Image();
    img.decoding = &quot;async&quot;;
    img.onload = () =&gt; { images[idx] = img; res(); };
    img.onerror = () =&gt; res();
    img.src = `/frames/frame_${String(idx + 1).padStart(4, &quot;0&quot;)}.webp`;
  });
}
</code></pre>
<p>Plain <code>new Image()</code>, not <code>createImageBitmap</code>. Safari stalls on bitmap creation; the decoded image cache is fast enough after the first paint.</p>
<h2>The lerp that sells it</h2>
<p>A raw scroll-to-frame mapping feels stepped. You scroll half a line and the canvas jumps two frames.</p>
<p>The fix is a lerp between a scroll-derived target and a rendered value that chases it:</p>
<pre><code class="language-js">function tick() {
  const diff = targetFrame - renderedFrame;
  if (Math.abs(diff) &lt; 0.01) {
    renderedFrame = targetFrame;
    lerpRunning = false;
  } else {
    renderedFrame += diff * 0.14;
  }
  const idx = Math.round(renderedFrame);
  if (idx !== cur &amp;&amp; images[idx]?.complete) {
    draw(idx);
    cur = idx;
  }
  if (lerpRunning) requestAnimationFrame(tick);
}
</code></pre>
<p>A lerp factor of 0.14 at 60fps is roughly a 6-frame settle. Any faster and you lose the tactile weight that hides frame stepping. Any slower and it feels laggy.</p>
<h2>File format</h2>
<p>WebP at quality 78. Ran the sequence through <code>cwebp</code> with <code>-q 78 -m 6</code> and it took the total from 33MB (JPEG) to 4MB. On real 4G connections the critical batch (first 40 frames) lands in under 1.5s.</p>
<h2>The blend-mode trick</h2>
<p>The source video had a grey volumetric-light haze around the glass subject. Straight image rendering showed the haze competing with page background.</p>
<p>The fix: <code>mix-blend-mode: screen</code> plus an aggressive <code>filter: brightness(0.55) contrast(1.75)</code>. Screen-blend drops dark pixels into the page bg. Crush the grey haze to near-black <em>before</em> the blend and only the bright glass plus the light shaft paint through. Costs one GPU layer composite. Looks expensive, isn&#39;t.</p>
<h2>Reduced motion</h2>
<p>On <code>prefers-reduced-motion: reduce</code>, we skip the whole system — replace the canvas with a single static image at frame 120, collapse the 300vh runway to <code>auto</code>, show only the first text state. No rAF loop, no scroll listener, no accessibility violation.</p>
<p>Framework-less doesn&#39;t mean primitive. It means you understand every line.</p>
]]></content:encoded>
      <pubDate>Sun, 05 Apr 2026 12:00:00 GMT</pubDate>
      <author>diego.gonzap@wearelojik.com (Diego González Zapiain)</author>
      <category>Engineering</category>
      <category>Performance</category>
      <category>Canvas</category>
      <category>WebP</category>
      <category>Scroll</category>
    </item>
  </channel>
</rss>