<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Srix on Medium]]></title>
        <description><![CDATA[Stories by Srix on Medium]]></description>
        <link>https://medium.com/@neosrix?source=rss-8f8324c8c33f------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*aMrOCCW6UhnJhlqnqoH6Eg.webp</url>
            <title>Stories by Srix on Medium</title>
            <link>https://medium.com/@neosrix?source=rss-8f8324c8c33f------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 17 Jun 2026 14:28:34 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@neosrix/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Every Web Project Is Seven Decisions: A Layer-by-Layer Guide to the Modern Web Stack]]></title>
            <link>https://medium.com/@neosrix/every-web-project-is-seven-decisions-a-layer-by-layer-guide-to-the-modern-web-stack-030e8b28c095?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/030e8b28c095</guid>
            <category><![CDATA[fullstack-web-development]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[css]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[svelte]]></category>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Tue, 09 Jun 2026 05:54:56 GMT</pubDate>
            <atom:updated>2026-06-09T05:59:54.465Z</atom:updated>
            <content:encoded><![CDATA[<p>Vite or Webpack? Next.js or SvelteKit? Tailwind or CSS Modules? They are not competing answers to the same question. They are answers to seven different questions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jf1GbKQXeBzb6ofY-dz65Q.png" /></figure><h3>Intro</h3><p>If you have tried to build a project recently, the sheer volume of choices in the modern web stack can look overwhelming. But let’s be honest: in the age of AI, that is no longer a blocker. You do not need to spend a weekend researching bundlers or frameworks. You can write a single prompt and have an AI spin up a fully functioning stack in a minute or two.</p><p>So if we can outsource the setup to AI in seconds, why write a guide explaining the layers?</p><p>Because if you are someone who wants to understand a little more deeply why those choices were made, “it just works” is not enough. You want to know what happens when you pick a meta-framework, and what trade-offs you are implicitly accepting. This article is not a time-saving research shortcut; the AI has already solved that. This article is for satisfying the developer curiosity to understand the map.</p><p>A web stack is not a pile of competing tools. It is a stack in the literal sense: seven layers, each one sitting on the one below it, each one answering a different question. Once you draw the map, every tool snaps into exactly one place, and the decision at each layer becomes clear.</p><p>This article is that map. I will walk through all seven layers from the bottom up, compare the real options at each one, and tell you what I picked for my own project and why. By the end you will be able to look at any new tool that launches next week and know immediately which layer it lives in and what it is actually competing with.</p><p>Here is the whole thing at a glance:</p><pre>┌───────────────────────────────────┐<br>│  Layer 7: Animation &amp; Motion      │  ← interaction polish<br>│  Layer 6: Styling                 │  ← how components look<br>│  Layer 5: UI Framework            │  ← how you write components<br>│  Layer 4: Meta-Framework          │  ← routing, SSR/SSG, data loading<br>│  Layer 3: Build Tools &amp; Bundlers  │  ← transforms source → browser-ready code<br>│  Layer 2: Server Framework        │  ← handles HTTP, APIs, business logic<br>│  Layer 1: Runtime                 │  ← the engine everything runs on<br>└───────────────────────────────────┘</pre><p>Not every project needs every layer. A static site might skip Layer 2 entirely. A backend API skips Layers 5 through 7. But understanding the full stack shows you what you are choosing, and more importantly, what you are implicitly accepting when a framework chooses for you.</p><p>Let’s start at the bottom.</p><h3>Layer 1: The engine nobody thinks about</h3><p>The runtime is the engine that executes JavaScript and TypeScript on the server. It runs your build tools, powers your dev server, and serves your app in production. Everything else in this article sits on top of it.</p><p>For fifteen years this was not a decision at all. The runtime was Node.js, period. Now there are three serious options.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3_FwU8Pdr-I-SL2PEvVnJg.png" /></figure><p><strong>Node.js</strong> is the default for a reason. Every library assumes it, every hosting platform supports it, and it is battle-tested in production everywhere. It is also the slowest of the three and still needs a transpilation step for TypeScript.</p><p><strong>Bun</strong> is the young challenger, written in Zig on top of JavaScriptCore instead of V8. Its pitch is raw speed: startup is 3 to 5 times faster, and package installs are dramatically quicker. For most projects it works as a drop-in Node replacement, though complex native modules can still hit compatibility gaps. If you maintain a large monorepo or care about CI pipeline speed, Bun is worth a serious look.</p><p><strong>Deno</strong> comes from Node’s original creator and fixes Node’s design regrets: security-first with a permissions model, native TypeScript, web-standard APIs. It is stable and pleasant, but adoption stayed smaller, and it makes the most sense if you are deploying on Deno Deploy.</p><p><strong>What I picked: Node.js.</strong> Boring answer, deliberate choice. Maximum compatibility with the rest of my stack and with Netlify. Bun would have worked as a drop-in for faster installs, and nothing in the layers above would change if I swapped it in later. That is the nice thing about the bottom layer: it is the easiest one to revisit.</p><h3>Layer 2: Do you even need a backend framework?</h3><p>One layer up sits the server framework: the thing that handles HTTP requests, API routes, middleware, and business logic. Express is the name everyone knows, but the field has changed more in the last four years than in the previous ten.</p><p>Here is the field today:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MxpMthnCmLiDxHOo80VMwA.png" /></figure><p>The pattern becomes obvious when you sort by generation:</p><pre>  Generation 1 (2010-2015):  Express, Koa, Hapi<br>                           Callback/middleware patterns, Node.js only<br>Generation 2 (2016-2021):  Fastify, NestJS<br>                           Speed + structure, still Node.js<br>Generation 3 (2022-now):   Hono, Elysia<br>                           Multi-runtime, edge-native, TypeScript-first</pre><p><strong>Express is the jQuery of backend JavaScript.</strong> It is everywhere, everyone understands it, and it is showing its age. Callback-based middleware, no built-in TypeScript, no schema validation. New projects pick it because everyone knows it, not because it is the best tool. <strong>Fastify</strong> is what Express should have become: schema-based validation, a real plugin architecture, two to three times the throughput, and Express-compatible enough to migrate to.</p><p><strong>Hono</strong> is the one I find most interesting. It is about 14KB, TypeScript-first, and runs on literally any runtime: Node, Bun, Deno, Cloudflare Workers, Lambda. If you are building for the edge or want to keep your deployment options open, Hono is the modern answer. <strong>Elysia</strong> plays the same game but goes all-in on Bun, squeezing out the highest throughput of anything on this list. And <strong>NestJS</strong> is the enterprise choice, with Angular-style decorators and dependency injection that feel instantly familiar to anyone coming from Java or Spring.</p><p>But here is the question that matters more than which framework: <strong>do you need this layer at all?</strong></p><p>Meta-frameworks (Layer 4, coming up) ship with built-in server capabilities. Next.js has API routes, SvelteKit has server endpoints, Nuxt has server routes. For a lot of projects, those are enough:</p><pre>Meta-framework routes are fine for:    You need a dedicated server framework for:<br>  - Form submissions                     - Complex business logic<br>  - Email capture                        - Microservices<br>  - Simple CRUD APIs                     - Real-time (WebSockets)<br>  - Basic authentication                 - One API serving multiple frontends</pre><p><strong>What I picked: nothing.</strong> My form submission and email capture are a couple of endpoints, and SvelteKit’s built-in server routes handle them. If the project ever grows a real backend, Hono or Fastify would be the natural addition. Skipping a layer you do not need is a feature of understanding the stack, not a shortcut.</p><h3>Layer 3: The tool you talk to every day without noticing</h3><p>Every time you run npm run dev or npm run build, you are talking to Layer 3. Build tools sit between your source code and the browser, transforming TypeScript, JSX, Svelte files, and CSS imports into optimized files a browser can actually run.</p><p>This layer went through a revolution recently, and the revolution has a one-line summary: <strong>stop bundling during development.</strong></p><pre>Generation 1 (2012-2019):  Webpack, Rollup, Parcel<br>                           Bundle everything, JS-based, slow on large projects<br>Generation 2 (2020-now):   Vite, esbuild, Turbopack, Rspack<br>                           Native ESM in dev, Rust/Go for speed, 10-100x faster</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2dUrH9u18LySQynPHstMmw.png" /></figure><p><strong>Webpack</strong> dominated for a decade, and its configuration complexity became legendary in the process. It still powers enormous codebases, but new projects rarely choose it.</p><p><strong>Vite</strong> is the current default, and it earned that position with one key insight: during development, do not bundle at all. Serve source files as native ES modules, let the browser import them directly, and only transform what is requested. The result is a dev server that starts in about 100 milliseconds whether your project has fifty files or five thousand. For production it hands off to Rollup, the bundler that pioneered tree-shaking. SvelteKit, Nuxt, Astro, and Remix all build on Vite, which tells you where the ecosystem has consolidated.</p><p><strong>esbuild</strong> is the Go-based transformer doing the heavy lifting inside Vite, 10 to 100 times faster than Webpack at raw transformation. You will probably never configure it directly. <strong>Turbopack</strong> is Vercel’s Rust-based Webpack successor, currently exclusive to Next.js. <strong>Rspack</strong> is the pragmatic one: Rust speed with Webpack-compatible configuration, built as a migration path for big Webpack projects that want speed without a rewrite.</p><p><strong>What I picked: Vite.</strong> Honestly, I did not pick it. SvelteKit picked it for me, and that is the most important lesson of this layer: in 2026, your meta-framework usually decides your bundler. You choose this layer indirectly.</p><h3>Layer 4: The decision that makes the other decisions</h3><p>This is the big one. The meta-framework is the orchestration layer: routing, server-side rendering, static generation, data loading, deployment. It is the thing you actually npm create when you start a project, and it reaches down to pick your bundler and up to dictate your UI framework.</p><p>If you only think hard about one layer, make it this one.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_VREW67THSAC0WJYU6w2bg.png" /></figure><p>The names matter less than the three architectures hiding underneath them:</p><p><strong>Ship the full runtime.</strong> Next.js, Nuxt, and Remix send the framework to the browser along with your code. Every user downloads React or Vue itself, then your application on top. Consistent and predictable, but you start with a baseline of framework weight before writing a feature.</p><p><strong>Compile the framework away.</strong> SvelteKit takes the opposite approach: Svelte components become plain vanilla JavaScript at build time, and no framework ships to the browser at all. The framework exists only on your machine.</p><p><strong>Islands.</strong> Astro and Fresh render the page as static HTML and ship JavaScript only for the specific components that need interactivity. A page that is 90 percent static gets 90 percent less JavaScript. For content-heavy sites this is the theoretically optimal architecture, and Astro deserves special mention because it is framework-agnostic: you can write your islands in React, Svelte, Vue, or Solid, mixed in one project.</p><p><strong>What I picked: SvelteKit.</strong> And I will be honest about the road not taken: for a site that is 80 percent static content, Astro was arguably the more “correct” choice on pure architecture. I went with SvelteKit because my interactive parts (the timeline, the assessment flow) are stateful enough that I wanted one coherent app model rather than scattered islands, the Netlify adapter is first-class, and the compile-away approach gets me most of Astro’s weight savings anyway. When two options are this close, ergonomics win.</p><h3>Layer 5: How you actually write components</h3><p>The UI framework defines how you author components and manage state. Here is the twist that most comparison articles miss: <strong>by the time you reach this layer, the decision is usually already made.</strong> Pick SvelteKit and you write Svelte. Pick Next.js and you write React. Astro is the only mainstream escape hatch that lets you mix.</p><p>So why understand this layer at all? Because it should inform your Layer 4 choice, not follow from it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JkQZz9UMrPc4aBda_BwcFg.png" /></figure><p>The numbers are interesting, but the mental models are where these frameworks really differ. Here is the same counter with derived state in all four:</p><pre>// React: state is a function call, re-renders the whole component<br>const [count, setCount] = useState(0);<br>const doubled = useMemo(() =&gt; count * 2, [count]);<br><br>// Svelte 5: state is a variable, the compiler tracks dependencies<br>let count = $state(0);<br>let doubled = $derived(count * 2);<br><br>// Vue 3: state is wrapped in ref(), the template tracks dependencies<br>const count = ref(0);<br>const doubled = computed(() =&gt; count.value * 2);<br><br>// Solid: state is a signal, fine-grained updates, no re-renders<br>const [count, setCount] = createSignal(0);<br>const doubled = () =&gt; count() * 2;    </pre><p><strong>React</strong> asks you to learn its rules: re-render cycles, dependency arrays, memoization, the rules of hooks. In exchange you get the largest ecosystem and job market in front-end history. <strong>Vue</strong> softens those edges with the Composition API and is enormously popular outside the US. <strong>Solid</strong> keeps React’s look but replaces the virtual DOM with fine-grained signals, so updates touch exactly the DOM nodes that changed. And <strong>Svelte</strong>, especially since version 5 introduced runes, lets you write nearly plain JavaScript: a variable marked $state is reactive, and the compiler figures out the rest at build time.</p><p><strong>What I picked: Svelte 5.</strong> For a content-heavy site, shipping a ~2KB compiled output instead of a ~44KB runtime is a real difference users feel on slow connections. The syntax is also simply less code: no hooks, no dependency arrays, no memoization rituals. The trade-off is a smaller ecosystem and a niche job market, which matters for hiring on a team but not for a solo project.</p><h3>Layer 6: Where the religious wars happen</h3><p>Styling is the layer with the widest spread of philosophy, and the only one where developers get genuinely angry at each other. The options span a full spectrum from total control to total abstraction:</p><pre>Full control &lt;-------------------------------------------------------------&gt; Full abstraction<br>Plain CSS → CSS Modules → Open Props → Vanilla Extract → Tailwind/UnoCSS → styled-components<br>  ↑                                                                              ↑<br>  Write every rule yourself                                     Never write a CSS rule    </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wSgjajzw4_SqTyoCHQk2nA.png" /></figure><p><strong>Tailwind</strong> dominates new projects, and it is still controversial. You write utility classes like text-lg bg-blue-500 p-4 directly in your markup instead of authoring CSS files. Critics call it inline styles with extra steps. In practice it eliminates three chronic problems at once: naming things, dead CSS accumulating forever, and specificity wars. Version 4 became a Vite plugin, so even the PostCSS configuration is gone.</p><p><strong>CSS Modules</strong> are the sane middle ground: write normal CSS, get automatically scoped class names, never worry about leaks. <strong>styled-components</strong> pioneered CSS-in-JS but is falling out of favor because of its runtime cost; the industry has moved decisively toward build-time solutions like <strong>Vanilla Extract</strong>, which gives you fully typed styles in .css.ts files with zero runtime. <strong>UnoCSS</strong> is the efficiency play: Tailwind-compatible class names, but it generates only the CSS you actually use, on demand.</p><p>One footnote worth knowing if you go the Svelte route: Svelte components have built-in scoped styles. Plain CSS inside a &lt;style&gt; tag is automatically scoped to that component, like CSS Modules with zero setup. You can use it alongside Tailwind for the cases utilities handle awkwardly.</p><p><strong>What I picked: Tailwind CSS v4.</strong> Utility-first is simply fast for a solo project, there is no custom CSS file to maintain, and the Vite plugin makes setup a one-liner in SvelteKit. I keep Svelte’s &lt;style&gt; blocks in reserve for anything genuinely custom.</p><h3>Layer 7: The polish layer</h3><p>The top of the stack: how things move. Animation gets dismissed as decoration, but transitions are often what separates a site that feels professional from one that feels like a homework assignment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zUlMYHwd2h5tjt2xEAeuQQ.png" /></figure><p>The practical reality: most projects need enter/exit transitions, hover effects, and maybe a scroll-triggered reveal. That is it. CSS animations cover 80 percent of those cases in any framework. <strong>GSAP</strong> is the professional tool when you genuinely need timelines and scroll choreography, which is why marketing agencies live in it. <strong>Framer Motion</strong> is excellent but heavy; notice that it weighs as much as React itself. And the browser-native <strong>View Transitions API</strong> is quietly making page-level transitions free.</p><p><strong>What I picked: Svelte’s built-in transitions.</strong> fly, slide, and fade are part of the framework, compiled in at zero added bundle weight, and they cover everything my timeline and assessment flow need. This was the layer where choosing Svelte at Layer 5 paid a second dividend.</p><h3>The hidden rule: one choice, five consequences</h3><p>If you zoom back out, a pattern emerges that no single-layer comparison will show you. <strong>The meta-framework is the keystone decision.</strong> Choose Layer 4 and you have implicitly chosen Layers 1, 3, and 5, plus the natural shape of Layer 2:</p><pre>Pick this...     ...and you get<br>─────────────────────────────────────────────────────<br>SvelteKit    →   Svelte + Vite + built-in endpoints<br>Next.js      →   React + Turbopack + API routes<br>Nuxt         →   Vue + Vite + server routes<br>Astro        →   Any UI + Vite + built-in endpoints<br>Fresh        →   Preact + esbuild + Deno handlers</pre><p>Only styling and animation remain genuinely independent choices.</p><p>This is why “Vite vs Next.js” is a confused question: Vite is Layer 3 and Next.js is Layer 4, and choosing Next.js means choosing Turbopack, while choosing almost anything else means choosing Vite. The tools were never alternatives. They are answers to different questions, occasionally bundled together.</p><p>For quick reference, here is how I would map common project types to stacks:</p><pre>Project type                  Stack I would reach for<br>──────────────────────────────────────────────────────────────<br>Content/marketing site        SvelteKit or Astro + Tailwind<br>SaaS with complex UI          Next.js or SvelteKit + Tailwind<br>Enterprise app, large team    Next.js or Angular + CSS Modules<br>Performance-critical SPA      SolidStart or SvelteKit<br>Blog/docs site                Astro + Tailwind<br>API-first backend             Fastify or Hono<br>Edge/serverless API           Hono<br>Enterprise backend            NestJS<br>Prototype / MVP               SvelteKit or Next.js + Tailwind<br>Heavy scroll animation site   Astro + GSAP</pre><h3>What I actually shipped</h3><p>Here is the full stack for my project, layer by layer:</p><pre>Layer 1 | Runtime:         Node.js<br>Layer 2 | Server:          SvelteKit built-in (no dedicated framework)<br>Layer 3 | Bundler:         Vite 7<br>Layer 4 | Meta-framework:  SvelteKit 2<br>Layer 5 | UI framework:    Svelte 5<br>Layer 6 | Styling:         Tailwind CSS 4<br>Layer 7 | Animation:       Svelte built-in transitions<br>          Deployment:      Netlify (via adapter)</pre><p>The result for a content-heavy site with interactive components: roughly <strong>16KB of JavaScript shipped to the browser, versus 90KB or more</strong> for the equivalent React stack, before I write a single feature. No animation library, no CSS files to maintain, no backend to deploy. Two of the seven layers (server framework and animation library) turned out to be layers I did not need at all, and knowing the map is what made skipping them a confident decision instead of a guilty one.</p><p>That is the real payoff of thinking in layers. The next time a shiny new tool tops Hacker News, you will not ask “should I switch to this?” You will ask “which layer is this, and is it better than what that layer already gives me?” Most of the time the answer is no, and you can get back to building.</p><p>If you keep one thing from this article, keep the diagram. Seven layers, seven questions, one decision that drives the rest. The JavaScript ecosystem is not chaos. It just needed a map.</p><h3>Conclusion</h3><p>By mapping your tools to these seven layers, you can build with confidence, avoid the hype cycle, and design web applications built to last.</p><p>If you enjoyed this layer-by-layer breakdown of the modern web stack, follow me here on Medium and subscribe to get notified of my future pieces.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=030e8b28c095" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Linux Sidecar: How I Turned My iPad Into a Second Display for Ubuntu.]]></title>
            <link>https://medium.com/@neosrix/linux-sidecar-how-i-turned-my-ipad-into-a-second-display-for-ubuntu-965d0f73f4dc?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/965d0f73f4dc</guid>
            <category><![CDATA[streaming]]></category>
            <category><![CDATA[ipad]]></category>
            <category><![CDATA[digital-nomads]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[productivity-hacks]]></category>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Sat, 23 May 2026 12:47:51 GMT</pubDate>
            <atom:updated>2026-05-25T03:36:17.498Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Apple’s Sidecar lets MacBook users extend their desktop to an iPad. Linux gets the same thing, eventually, once you understand that it’s not straightforward.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CdgGsXaT2EmNCV-a2bCUmw.jpeg" /></figure><blockquote><strong><em>TL;DR.</em></strong><em> A Linux laptop can use an iPad as a real, draggable second display over local Wi-Fi using a hardware HDMI dummy plug, a passive USB-C hub, Sunshine on the laptop, and Moonlight on the iPad. The non-obvious gotcha is the </em>type<em> of USB-C-to-HDMI adapter you use, which is what most of this article is about. If you just want the working recipe, jump to section </em><strong><em>The setup that ended up working</em></strong><em> at the end. If you want the gotcha that cost me two bad hardware buys, read on.</em></blockquote><p>I work on a <a href="https://dl.dell.com/content/manual4620045-xps-17-9730-setup-and-specifications.pdf?language=en-us">Dell XPS 17 9730</a> running Kubuntu. At my desk I have a 5K external monitor and the laptop’s own 4K panel, which is plenty of room for code, notes, browsers, and chat side by side. The problem starts the moment I leave that desk. At a hotel, in a café, on a flight: one screen. Coding with a terminal and a documentation tab open and a Slack window pinging? You’re constantly Alt-Tabbing. It’s fine for casual use. It’s brutal for real work.</p><p>I already carry an iPad on every trip. So the question that nagged me for months: surely there’s a way to use the iPad as a second screen for my Linux laptop, the way macOS users do with Sidecar.</p><p>The answer turned out to be yes, but only after a winding path that included two pieces of hardware I assumed were broken, one operating-system rename that ate a chunk of time, and a fairly deep dive into how USB-C-to-HDMI adapters actually work. This is that story, with enough technical detail that if you’re trying the same thing, you can skip the parts I got wrong.</p><h3>Why not just buy a portable monitor?</h3><p>The obvious question, and one I sat with. Reasons I went the iPad route:</p><ul><li>I’m already carrying the iPad. A portable monitor is another brick in the bag.</li><li>Portable monitors that are big enough to be useful (15&quot;+) weigh about as much as the laptop again.</li><li>iPads have genuinely good panels (ProMotion, P3 colour, brightness levels portable monitors can’t touch) for less money than an equivalent monitor.</li><li>The iPad doubles as an iPad. The monitor only ever monitors.</li></ul><p>So the goal: stream part of my desktop to the iPad over local Wi-Fi, with low latency, in a way the operating system treats as a real, draggable second display, not a remote-desktop mirror.</p><h3>Why software-only didn’t work</h3><p>The first instinct on Linux is to find a software solution. The ecosystem is crowded: Xvfb, Xephyr, VNC, kernel EDID overrides, compositor virtual outputs, kernel virtual KMS. On a vanilla X11 desktop most of these would work. On my specific stack (KDE Plasma 6 + Wayland + NVIDIA Optimus), the options thinned fast, and the two I seriously tried both failed in instructive ways.</p><h3>Attempt 1: KDE’s built-in virtual output</h3><p>KDE Plasma 6 ships its own virtual-output API. You can ask the compositor to add a synthetic screen at any resolution:</p><pre>kscreen-doctor --add-virtual-output --resolution 2360x1640@60</pre><p>I picked iPad Air resolution so the captured stream would match the target exactly. The command ran cleanly. What happened next was specific enough to my stack that it didn’t match any of the textbook NVIDIA-Wayland virtual-output failure modes online. I dropped this path and went lower.</p><h3>Attempt 2: VKMS, the Virtual Kernel Mode Setting module</h3><p>If the compositor wouldn’t give me a usable virtual screen, the next layer down is the kernel itself. Linux ships a module called <strong>VKMS</strong> whose entire job is to expose a synthetic DRM/KMS device: no physical hardware behind it, just a CPU-memory framebuffer with simulated vblank timing.</p><pre>sudo modprobe vkms enable_cursor=1 enable_writeback=1</pre><p>It loaded cleanly. The kernel announced it:</p><pre>[drm] Initialized vkms 1.0.0 for vkms on minor 0<br>faux_driver vkms: [drm] fb1: vkmsdrmfb frame buffer device</pre><p>A new DRM device appeared at /dev/dri/card0. Sunshine, the streaming server I&#39;d settled on, saw it and attached:</p><pre>sunshine.log: /dev/dri/card0 -&gt; vkms</pre><p>This part worked. Sunshine could capture from VKMS. But the moment it tried to encode the captured frames, the architecture broke down.</p><p>Hardware video encoders (VAAPI on the Intel iGPU, NVENC on the NVIDIA dGPU) expect to consume frames that already live in <strong>GPU memory</strong>. The mechanism is called a DMA-buf import: Sunshine hands the encoder a file descriptor, the encoder maps it into its own address space without copying, and the encode runs at zero-copy speed.</p><p>VKMS framebuffers don’t live in GPU memory. They live in plain system RAM, simulated by the CPU. There is no DMA-buf file descriptor you can hand to a hardware encoder that points back at a VKMS frame. So Sunshine’s options reduced to:</p><ol><li><strong>Software encode (libx264)</strong>, which defeats the entire point of using a low-latency streaming protocol</li><li><strong>CPU to GPU memcpy then hardware encode</strong>, which is even slower than option 1</li></ol><p>Either way, the smooth low-latency stream I wanted was off the table.</p><p>The kernel was also unhappy about VKMS under any real load. It kept emitting vkms_vblank_simulate: vblank timer overrun warnings, meaning the synthetic 60Hz vblank timer couldn&#39;t keep up.</p><p>That’s when I gave up on software. I ordered the dummy plug.</p><h3>What’s a dummy HDMI plug?</h3><p>A dummy HDMI plug is a small piece of plastic and silicon that fits in an HDMI port and asserts to the host “yes, I am a monitor, here is my EDID.” It contains nothing more than a tiny EEPROM holding monitor identification data and a hot-plug-detect pull-up.</p><p>Why does this exist? Mining rigs use them so headless GPUs render at full resolution. Render farms use them so workstation GPUs don’t downclock when no monitor is attached. Streaming setups use them so the OS believes a second display exists, gives it a piece of the desktop, and lets you drag windows onto it.</p><p>They’re cheap (about ₹400, or US$5) and they sounded like the most boringly reliable way to make Linux think a monitor was connected.</p><h3>The XPS 17 has no HDMI port</h3><p>A wrinkle I should have noticed sooner: the Dell XPS 17 is USB-C only. Four Thunderbolt 4 ports, no HDMI socket on the chassis. So before I could plug a dummy plug into anything, I needed a USB-C-to-HDMI adapter to <em>create</em> an HDMI port to plug it into.</p><p>I already owned a <strong>Dell DA20</strong>, Dell’s official small USB-C-to-HDMI/USB-A adapter, the kind that comes in laptop docking-station kits. Naturally I used that.</p><p>It didn’t work. I plugged the dummy plug into the DA20’s HDMI port and waited for a third display to appear in KDE’s display settings. Nothing happened. xrandr showed only my existing two screens. No new connector enumerated.</p><p>I assumed the dummy plug was defective and ordered a second one from a different brand. It also did nothing.</p><p>At this point I had two presumed-defective dummy plugs, a working-looking adapter, and a broken theory.</p><h3>The single piece of knowledge that explains everything</h3><p>Here is what I wish I’d known before clicking “buy” on either of those plugs.</p><p><strong>There are two completely different breeds of USB-C-to-HDMI adapter</strong>, sold under indistinguishable marketing. Reviews rarely mention which is which. They are not interchangeable for headless or dummy-plug use cases.</p><h3>Active adapters (what the Dell DA20 is)</h3><p>Inside the housing is a silicon chip called an <strong>LSPCON</strong> (Level Shifter / Protocol Converter), typically a Parade PS176 or a MegaChips equivalent. The signal flow is:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vxYSnQ2b2umFO_y4Hw37vg.png" /></figure><p>The LSPCON is not just a translator; it’s a <em>gatekeeper</em>. When something is plugged into the HDMI end, the LSPCON:</p><ol><li>Powers the EDID EEPROM on the sink (over HDMI pin 18, +5V)</li><li>Reads the EDID over the DDC/I²C lines</li><li><strong>Validates it</strong>, checking checksums, supported modes, and extension blocks</li><li><strong>Only if validation passes</strong>, asserts hot-plug-detect upstream toward the laptop</li></ol><p>If the EDID looks malformed (bad checksum, modes the LSPCON doesn’t know how to translate to HDMI 2.0, sloppy I²C timing) the LSPCON quietly refuses to assert HPD. The laptop never sees a hot-plug event. No new connector enumerates. <strong>No error message anywhere.</strong> It just silently doesn’t work.</p><p>A real monitor handshakes loosely enough that this validation almost always passes. A cheap HDMI dummy plug, with its mass-cloned reference EDID firmware, often does not. That’s why both my dummy plugs failed identically through the DA20: they probably ship the same reference EDID under different brand stickers, and the Parade chip in the DA20 rejects it.</p><p>The LSPCON exists in the DA20 because Dell wanted to guarantee HDMI 2.0 / 4K@60Hz bandwidth on every USB-C port, regardless of whether the laptop’s own port can output HDMI signaling natively. It’s a feature for real monitors. It’s the wrong silicon for a dummy plug.</p><h3>Passive adapters</h3><p>No chip. Just a PCB that remaps USB-C pins to HDMI pins, with light voltage level shifting on copper. The signal flow:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n3MQl8TRQYPvMRLPMVrCWw.png" /></figure><p>This is part of the DisplayPort Alt Mode spec, sometimes called HDMI Alt Mode. The source GPU does the HDMI signaling natively rather than going via DisplayPort first. <strong>There is no chip in the middle inspecting the EDID.</strong> The DDC/I²C lines run straight through the cable to the GPU’s own HDMI receiver.</p><p>GPU HDMI receivers are far more lenient than LSPCONs. They’ll accept the same malformed dummy-plug EDID an LSPCON rejects.</p><p>The test that distinguishes them: plug a dummy plug into the adapter’s HDMI port. If a connector lights up in your OS, the adapter is passive (or has a permissive LSPCON). If nothing happens, it’s a strict active adapter.</p><p>I happened to have an old generic USB-C hub in a drawer with a passive HDMI port. I tried the same dummy plug in that hub. The connector lit up immediately, claimed 3840×2160@60 as native, and KDE auto-arranged it as an extension of my desktop.</p><p>Both dummy plugs worked through this hub. Both had been rejected by the DA20.</p><p><strong>The dummy plugs were never defective.</strong> The DA20 wasn’t broken either. They’re each fine for their intended use cases. The dummy plugs need a passive path; the DA20 needs a real monitor.</p><h3>The streaming layer: Sunshine + Moonlight</h3><p>With a virtual display lit up, the streaming layer was the next problem. I chose the <strong>Sunshine</strong> server + <strong>Moonlight</strong> client combination. Sunshine is an open-source implementation of NVIDIA’s discontinued GameStream protocol, and Moonlight is the matching client, with apps for iOS, Android, tvOS, Windows, Linux, and most embedded platforms.</p><p>Why this combo and not, say, Steam Link or Parsec or VNC?</p><ul><li><strong>Latency.</strong> Moonlight on a local Wi-Fi network gives roughly 20 to 50ms glass-to-glass at 1080p. VNC is multiples of that.</li><li><strong>Hardware encoding.</strong> Sunshine targets VAAPI (Intel/AMD), NVENC (NVIDIA), and AMF (AMD). The encode is essentially free on any modern GPU.</li><li><strong>Per-output capture.</strong> I can point Sunshine at a specific DRM connector (the dummy plug) while my real screens stay private.</li><li><strong>Native iPad client.</strong> Moonlight for iOS is polished, free, no subscription, no telemetry.</li></ul><p>Setup was straightforward: install the Sunshine AppImage on the laptop, pair the iPad to it via a 4-digit PIN over Sunshine’s local web UI, done. On first launch Sunshine auto-detected the Intel iGPU’s VAAPI encoders and picked h264_vaapi. NVENC didn&#39;t even get tried, because the discrete NVIDIA GPU was asleep in runtime suspend, and the dummy plug lives on the integrated GPU side anyway.</p><p>One wrinkle worth knowing. Rather than running the AppImage directly, it’s better to extract it first and grant the binary Linux file capabilities. AppImages, when launched normally, self-mount to a temporary path under /tmp each time they start. That works for running the app, but it makes it awkward to apply persistent file capabilities, and Sunshine needs two of them to perform at its best:</p><pre>./Sunshine.AppImage --appimage-extract<br># the AppImage extracts into a directory called squashfs-root<br># move/rename it to wherever you want it to live permanently, e.g. ~/sunshine-app<br>mv squashfs-root ~/sunshine-app<br>sudo setcap cap_sys_admin,cap_sys_nice+p ~/sunshine-app/usr/bin/sunshine<br>~/sunshine-app/AppRun</pre><p>The two capabilities matter for different reasons. CAP_SYS_ADMIN lets Sunshine perform KMS direct capture without running as root, which is the lowest-overhead capture path on Linux. CAP_SYS_NICE lets it set realtime scheduling priority for the encoder thread, which keeps frame timing consistent under load. Without the second one, you&#39;ll see a CAP_SYS_NICE capability is missing warning in the log and visible frame-pacing jitter during streams.</p><p>Sunshine’s bundled AppRun --install script does this setcap step plus a few related setup tasks (udev rules for virtual input devices, a systemd user service), so running that once after extraction is usually the cleanest path: ~/sunshine-app/AppRun --install.</p><p>Aside: Sunshine when run from an extracted AppImage has a separate quirk on KDE. Its tray icon comes up as an empty slot because the binary requests an icon by name (dev.lizardbyte.app.Sunshine-tray) that lives at a non-standard path inside the AppImage tree. The fix is to copy the relevant SVGs into the user&#39;s hicolor icon directory and clear KDE&#39;s icon cache.</p><h3>The aspect-ratio rabbit hole</h3><p>The stream worked. The picture had black bars.</p><p>Setting Moonlight’s resolution to match the iPad’s panel did nothing. I switched the host’s dummy-plug display to a 4:3 mode. Now there were black bars on <strong>all four sides</strong>: a tidy rectangle floating in the middle of the iPad screen, surrounded by black.</p><p>The streaming pipeline preserves aspect ratio at every stage. So:</p><pre>Host display (3840×2160, 16:9 = 1.78:1)<br>    ↓  Sunshine captures host canvas<br>Encoded video (in container at whatever resolution Moonlight requested)<br>    ↓  scaling preserves the source aspect<br>    ↓  non-matching aspect = bars baked into the encoded video<br>Decoded on iPad<br>    ↓  scaled to fit the iPad panel, aspect preserved<br>iPad screen (2388×1668, ≈1.43:1, not 16:9, not 4:3, an oddly-specific in-between)</pre><p>When I “fixed” the bars by switching the host to 4:3 (1.333:1), the host source was now narrower than what Moonlight was requesting (it was still set to a 16:9 preset like 1080p). Sunshine therefore encoded a 4:3 image into a 16:9 container with black bars on the left and right. That 16:9 encoded video then hit the iPad screen (1.43:1), and got <em>more</em> bars on top and bottom from that mismatch. Pillarbox plus letterbox equals picture-frame.</p><p>The fix is to align <strong>all three</strong> aspects:</p><ol><li>Set the host display to a 4:3 mode (closest available to iPad’s 1.43:1)</li><li>In Moonlight, use <strong>Custom Resolution</strong> at the same 4:3 width and height</li><li>Reconnect the stream</li></ol><p>After that, only thin left/right bars remained on the iPad, about 3.4% per side, from the unavoidable 4:3-vs-1.43:1 residual. Visible if you look for them, invisible during actual use.</p><h3>The setup that ended up working</h3><p>For reference, the working configuration:</p><ul><li><strong>Laptop:</strong> <a href="https://dl.dell.com/content/manual4620045-xps-17-9730-setup-and-specifications.pdf?language=en-us">Dell XPS 17 9730</a>, Kubuntu, KDE Plasma 6.5 on Wayland, Intel Iris Xe iGPU and NVIDIA RTX 4060 dGPU</li><li><strong>Dummy plug:</strong> <a href="https://www.amazon.in/dp/B07FB8GJ1Z">BUYMINERS.CA HDMI Dummy Plug, 4K@60Hz EDID</a> (the brand barely matters once you’re on a passive path; this one is confirmed working)</li><li><strong>Adapter:</strong> <a href="https://www.amazon.in/dp/B09CPJV3B4">5-in-1 USB-C Hub (Type-C to 4K HDMI + Ethernet + USB 3.0)</a> with a <strong>passive</strong> HDMI port (<em>not</em> the Dell DA20)</li><li><strong>Server:</strong> Sunshine, AppImage launched via its AppRun script</li><li><strong>Client:</strong> Moonlight on iPad Pro 11&quot;</li><li><strong>Host display mode:</strong> 1400×1050 (4:3) at 60Hz</li><li><strong>Moonlight stream resolution:</strong> Custom 1400×1050</li><li><strong>Audio + keyboard:</strong> flow through Moonlight automatically.</li><li><strong>Total extra weight in the bag:</strong> a few grams (one small hub plus one small dummy plug, both stay assembled together)</li></ul><p>The physical chain at the destination, in order:</p><pre>laptop USB-C port  ←  the hub  ←  dummy plug (in the hub&#39;s HDMI port)</pre><p>The dummy plug <strong>stays plugged into the hub’s HDMI port permanently</strong>. It never leaves the hub. The whole “hub + dummy plug” assembly travels as one unit. At a destination, you plug only the hub’s USB-C cable into a free port on the laptop. That single physical action lights up the virtual display, and from there Moonlight on the iPad picks up the stream over Wi-Fi.</p><p><em>If you have a Linux laptop, an iPad, and a long flight coming up: try it. The path is shorter than it sounds, as long as you know which adapter to buy.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=965d0f73f4dc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Same Model, Same Prompt, Different Output. The Fix Was Prompt Specificity.]]></title>
            <link>https://medium.com/@neosrix/same-model-same-prompt-different-output-the-fix-was-prompt-specificity-d8890c7c0709?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/d8890c7c0709</guid>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Fri, 03 Apr 2026 17:56:33 GMT</pubDate>
            <atom:updated>2026-04-03T17:56:33.027Z</atom:updated>
            <content:encoded><![CDATA[<p>I’ve been building <a href="https://ainativeorgs.com">ainativeorgs.com</a>, a SvelteKit landing site with an interactive self-assessment tool. Recently, I needed to add Google Analytics tracking across the site. Simple enough task. I decided to use <a href="https://sculptor.imbue.com">Sculptor by Imbue</a>, which spins up autonomous coding agents that work in isolated branches.</p><p>I gave the same prompt to two separate agents. Same model (Claude Pro Max). Same codebase. Same instructions.</p><p>The results were structurally identical, and subtly, importantly different.</p><p>This article is about what I learned from that experiment, and why the lesson isn’t “run everything twice.”</p><h3>The Setup</h3><p>I created two Sculptor agents, each on their own branch:</p><ul><li><strong>Agent A</strong>: ran first</li><li><strong>Agent B</strong>: ran second, identical prompt</li></ul><p>Both agents needed to:</p><ol><li>Add the Google Analytics gtag snippet</li><li>Create a centralized analytics module</li><li>Wire up event tracking across landing page components and the assessment flow</li></ol><p>Both agents delivered working code. Both created an analytics.ts module with helper functions. At a glance, the output looked nearly identical.</p><p>Then I diffed the branches.</p><h3>What Was the Same</h3><p>The high-level architecture was identical. Both agents made the same macro decisions:</p><ul><li>Inline the gtag snippet in src/app.html</li><li>Create src/lib/analytics.ts as the centralized tracking module</li><li>Instrument the core components: Hero, Footer, AssessmentCTA, and the assessment page</li><li>Track the same categories of user actions: assessment flow, CTA clicks, email capture, external links</li></ul><p>Agent B went further and also instrumented HowItWorks and ParadigmTeaser, giving it broader tracking coverage. But the architecture and approach were the same.</p><p>Neither agent invented a novel architecture. They converged on the obvious, correct approach. This is actually reassuring. It means the fundamentals are reliable.</p><h3>Where They Diverged</h3><p>The differences were in the details. And in analytics, the details are everything.</p><h3>Difference 1: When Does “Assessment Start” Fire?</h3><p>This was the most consequential difference.</p><p><strong>Agent A</strong> tracked assessment start on the user’s first interaction, specifically when they click their first answer:</p><pre>// Agent A: Track on first interaction<br>let hasTrackedStart = $state(false);<br><br>function selectOption(questionId: string, optionIndex: number) {<br>  if (!hasTrackedStart) {<br>    trackAssessmentStart();<br>    hasTrackedStart = true;<br>  }<br>  trackQuestionAnswer(questionId, currentIndex);<br>  // ...<br>}</pre><p><strong>Agent B</strong> tracked it on page load, the moment someone lands on /assess:</p><pre>// Agent B: Track on page load<br>import { onMount } from &quot;svelte&quot;;<br><br>onMount(() =&gt; {<br>  trackAssessmentStart();<br>});</pre><p>Why does this matter? Because of the funnel.</p><p>With Agent B’s approach, you can measure:</p><pre>Page visit (100%) → First answer (72%) → Completion (45%) → Email (18%) → Booking (6%)</pre><p>With Agent A’s approach, your funnel starts at “First answer.” You’ll never know that 28% of visitors bounced before answering a single question. That’s often the most actionable insight. Maybe your first question is intimidating, or the page loads too slowly, or the CTA copy set the wrong expectation.</p><p><strong>Agent B’s approach is correct for analytics.</strong> Agent A’s approach is a subtle bug that looks like a feature.</p><h3>Difference 2: How They Structured the Analytics API</h3><p>This is where the two agents made the most visibly different design choices.</p><p><strong>Agent A</strong> created a single, generic function for all CTA tracking:</p><pre>// Agent A: One function, free-form strings<br>export function trackCTAClick(ctaName: string, location: string): void {<br>  trackEvent(&quot;cta_click&quot;, {<br>    cta_name: ctaName,<br>    location: location,<br>  });<br>}</pre><p>Used like:</p><pre>onclick={() =&gt; trackCTAClick(&quot;take_assessment&quot;, &quot;hero&quot;)}<br>onclick={() =&gt; trackCTAClick(&quot;book_conversation&quot;, &quot;footer&quot;)}<br>onclick(() =&gt; trackCTAClick(&quot;book_diagnostic&quot;, &quot;results_page&quot;)}</pre><p><strong>Agent B</strong> created separate, purpose-built functions:</p><pre>// Agent B: Separate functions per CTA type<br>export function trackAssessmentCTAClick(location: CTALocation): void {<br>  trackEvent(&quot;cta_click&quot;, {<br>    event_category: &quot;cta&quot;,<br>    event_label: &quot;take_assessment&quot;,<br>    cta_location: location,<br>  });<br>}<br>export function trackBookingCTAClick(location: CTALocation): void {<br>  trackEvent(&quot;cta_click&quot;, {<br>    event_category: &quot;cta&quot;,<br>    event_label: &quot;book_conversation&quot;,<br>    cta_location: location,<br>  });<br>}</pre><p>My initial reaction was that Agent B’s approach was clearly better because of type safety. But when I looked more closely, I realized Agent A’s labels were actually correct. The footer button says “Book a Conversation.” The results page button says “Book a 30-Minute Diagnostic.” These are different CTAs with different copy. Tracking them with different names is the right call.</p><p>So this turned out to be a genuine style difference, not a correctness issue. Agent A went with fewer, more flexible functions. Agent B went with more structured, specialized functions. Both are defensible choices. For a small site with a handful of CTAs, Agent A’s simplicity is arguably the better tradeoff. For a larger site where dozens of developers are adding tracking calls, Agent B’s structure would matter more.</p><p>The lesson here is subtler than “one is right and one is wrong.” It’s that <strong>you have to actually read the output in context</strong> before judging which approach is better. I almost dismissed Agent A’s version as buggy when it was actually doing the right thing.</p><h3>Difference 3: Event Richness</h3><p><strong>Agent A</strong> sent minimal data:</p><pre>// Agent A: Just the basics<br>export function trackQuestionAnswer(<br>  questionId: string,<br>  questionIndex: number<br>): void {<br>  trackEvent(&quot;question_answer&quot;, {<br>    question_id: questionId,<br>    question_number: questionIndex + 1,<br>  });<br>}</pre><p><strong>Agent B</strong> sent richer context:</p><pre>// Agent B: Full context for analysis<br>export function trackQuestionAnswer(<br>  questionId: string,<br>  questionIndex: number,<br>  totalQuestions: number<br>): void {<br>  trackEvent(&quot;question_answer&quot;, {<br>    event_category: &quot;assessment&quot;,<br>    event_label: questionId,<br>    question_index: questionIndex,<br>    total_questions: totalQuestions,<br>    progress_percent: Math.round(<br>      ((questionIndex + 1) / totalQuestions) * 100<br>    ),<br>  });<br>}</pre><p>With Agent B, you can immediately build a drop-off chart by progress percentage. With Agent A, you need to hardcode the total question count in your analytics dashboard configuration. Small difference, but it’s the kind of thing that determines whether you actually build that dashboard or just say “I’ll get to it later.”</p><h3>Difference 4: External Link Tracking</h3><p>An interesting case where Agent A actually had one better idea:</p><pre>// Agent A: Tracks the URL too<br>export function trackExternalLink(linkType: string, url: string): void {<br>  trackEvent(&quot;external_link_click&quot;, {<br>    link_type: linkType,<br>    link_url: url,<br>  });<br>}<br><br>// Agent B: Only tracks the type<br>export function trackExternalLinkClick(linkType: ExternalLinkType): void {<br>  trackEvent(&quot;external_link_click&quot;, {<br>    event_category: &quot;outbound&quot;,<br>    event_label: linkType,<br>    link_type: linkType,<br>  });<br>}</pre><p>Agent A captured the actual URL being clicked. More useful for debugging. A nice touch that Agent B missed.</p><h3>What Caused the Divergence?</h3><p>When I saw that Agent B produced better output on funnel tracking, my first thought was: <em>“It did better because it was the second attempt. Maybe there’s some learning happening.”</em></p><p>Nope. These are completely independent agents. No shared memory. No context from the first run. <strong>This is correlation, not causation.</strong></p><p>LLMs are non-deterministic. The same prompt can produce different design decisions each time. But that variation isn’t random noise. It shows up most when the prompt leaves room for interpretation.</p><p>Which led me to my second idea: <strong>what if I just run every task through two agents and pick the better output?</strong></p><p>I seriously considered this. But it breaks down fast:</p><ul><li><strong>Double the cost.</strong> Twice the compute, twice the review time, for every task.</li><li><strong>Diffing is real work.</strong> Comparing the two analytics implementations took genuine effort: reading both, reasoning about design tradeoffs, checking consistency across components. For a larger feature, the diff itself becomes a project.</li><li><strong>It treats the symptom, not the cause.</strong> The agents didn’t diverge because of bad luck. They diverged because my prompt was underspecified.</li></ul><h3>What Actually Works: Better Prompts</h3><p>The real fix is giving the agent the context it needs upfront. If my original prompt had been:</p><blockquote><em>Add Google Analytics tracking. Track assessment start on page load (not on first interaction) so we can measure the full funnel. Include progress percentage in question answer events. Use GA4 event categories and labels.</em></blockquote><p>Both agents would have converged on the better implementation.</p><p><strong>Where this matters most</strong> (spend the extra five minutes on your prompt):</p><ul><li>Analytics and tracking</li><li>Authentication and authorization</li><li>Data models and schemas</li><li>APIs and contracts</li></ul><p><strong>Where first pass is fine</strong> (don’t overthink it):</p><ul><li>Wiring up UI components</li><li>Standard CRUD operations</li><li>Configuration and styling</li></ul><p>The quality bottleneck isn’t the model. It’s the prompt. Your domain knowledge about what makes analytics data clean or what makes auth code secure is exactly what the AI doesn’t have. The more of it you encode upfront, the less the output varies, and the less it matters whether you run the task once or ten times.</p><p><em>I’m building </em><a href="https://ainativeorgs.com"><em>AI Native Orgs</em></a><em> to help engineering teams transform how they work with AI. If you’re navigating the shift from ad-hoc AI usage to AI-native engineering practices, </em><a href="https://ainativeorgs.com/assess"><em>take the assessment</em></a><em> to see where your team stands.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d8890c7c0709" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[I Rebuilt My 2023 Programming-Language Comparison Tool Using 2026 AI Agents]]></title>
            <link>https://medium.com/@neosrix/i-rebuilt-my-2023-programming-language-comparison-tool-using-2026-ai-agents-93ede6bd9781?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/93ede6bd9781</guid>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Wed, 28 Jan 2026 04:36:59 GMT</pubDate>
            <atom:updated>2026-01-28T04:36:59.271Z</atom:updated>
            <content:encoded><![CDATA[<p>In May 2023, I shipped a small web app that compares programming languages side-by-side by <em>concept</em>. <a href="https://medium.com/@neosrix/comprehensive-comparison-of-popular-programming-languages-ef5e7c2e3bd3">https://medium.com/@neosrix/comprehensive-comparison-of-popular-programming-languages-ef5e7c2e3bd3</a></p><p>It ended up being useful in a very practical way. Teams evaluating migrations (Python → Rust, JS → Go, etc.) used it to decode the learning curve without jumping across docs and blog posts.</p><p>Two years later, AI tooling changed enough that I didn’t want this project to stay “stuck in 2023”.</p><p>So I tore it down and rebuilt it using modern agentic workflows.</p><p>It’s live now at <a href="https://programming-languages.com"><strong>programming-languages.com</strong></a>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FdGyq-Bat7ds%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdGyq-Bat7ds&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FdGyq-Bat7ds%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/0989a212830a117e9779c67b9e930b4d/href">https://medium.com/media/0989a212830a117e9779c67b9e930b4d/href</a></iframe><h3>What changed in the rebuild</h3><p>This wasn’t a cosmetic cleanup. The rebuild touched the foundations:</p><ul><li>Refactored the codebase for maintainability</li><li>Standardized the UI and navigation</li><li>Added comprehensive tests</li><li>Improved SEO structure and analytics instrumentation</li></ul><p>In 2023, AI felt like “generate a snippet.”<br>In 2026, it feels like “do real maintenance.”</p><p>I used Antigravity (Google’s AI IDE) with Gemini 3 Pro, plus background agents (Codex) to drive the rebuild.</p><h3>A quick SEO lesson: GitHub Pages wasn’t reliable for crawling</h3><p>The original version started on <strong>GitHub Pages (github.io)</strong>.</p><p>It was perfect for shipping quickly, but I noticed something frustrating: crawlability and indexing were not reliable for this project.</p><p>And for a tool like this, discoverability is part of the product. You want people to land directly on concept pages from search.</p><p>So I moved:</p><ol><li>GitHub Pages → <strong>Netlify</strong></li><li>Netlify → <strong>a dedicated domain</strong></li></ol><p>That last step mattered the most. The project now lives at <strong>programming-languages.com</strong>.</p><h3>A 2026 superpower: SEO + analytics became “one-shot easy”</h3><p>One of the biggest breakthroughs for me was how much of SEO and analytics is now straightforward with agents.</p><p>Things that used to take hours of fiddly effort became closer to:</p><ul><li>clear instruction</li><li>one pass</li><li>quick review</li><li>done</li></ul><p>Not everything is automatic, but the “activation energy” is dramatically lower.</p><h3>Another surprise: JavaScript started feeling like TypeScript</h3><p>This is unintuitive, but real.</p><p>When you work with agents instead of human peers, even JavaScript code comes out more structured and consistent.</p><p>In my head it started feeling “TypeScript-like” because:</p><ul><li>fewer sloppy shortcuts</li><li>more repeatable patterns</li><li>more predictable refactors</li></ul><p>It’s not a replacement for TypeScript. It’s a shift in baseline quality when an agent is maintaining the code.</p><h3>Automated browser testing became part of my workflow</h3><p>Antigravity’s automated browser testing helped a lot during the rebuild.</p><p>Not just unit tests. Real flow validation:</p><ul><li>navigate concepts</li><li>search within a concept</li><li>confirm the UI behaves correctly</li></ul><p>This is now a permanent part of how I build.</p><h3>I started saving agent summaries as Git commit context</h3><p>Another habit I’m keeping:</p><p>At the end of an activity, the agent summarizes what it changed and why. I store that summary in the Git commit message (or body).</p><p>It improves the repo instantly:</p><ul><li>richer commit context</li><li>decision trail for later</li><li>better “why” documentation without extra work</li></ul><h3>Try it and tell me what to add next</h3><p>If you’re comparing languages or planning a migration, try it:</p><p><a href="https://programming-languages.com">Programming Language Comparison - Side by Side Concept Reference</a></p><p>And if you’re doing a migration right now, what’s the one concept you always end up googling? That’s what I should prioritize next.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=93ede6bd9781" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From Chaos to Coop: Rethinking How India Drives]]></title>
            <link>https://medium.com/@neosrix/from-chaos-to-coop-rethinking-how-india-drives-83bf1ef1605b?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/83bf1ef1605b</guid>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Fri, 22 Aug 2025 07:34:27 GMT</pubDate>
            <atom:updated>2025-09-02T12:30:35.543Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>From Chaos to Co-op: Rethinking How India Drives</strong></h3><h3>🚦 In a Rush? Here’s the 2-Minute Read</h3><p>India’s traffic isn’t just a problem of potholes and poor signals, it’s a behavioral crisis. From our work at RoadsenseAI, where we analyzed real traffic footage through dash-mounted phones, we saw patterns emerge that go beyond rules a nd deep into culture.</p><p>This article explores:</p><ul><li><strong>What makes a Smart Driver</strong> in India — not just obedient, but cooperative, predictable, and respectful.</li><li>How we can <strong>build a movement</strong> of certified smart drivers with social recognition and peer influence.</li><li>Why we should <strong>reframe bad driving as rude behavior</strong>, much like cutting in line.</li><li>A proposal for <strong>vehicle-based fine multipliers</strong>, making traffic penalties meaningful across income groups.</li><li>How <strong>delivery and cab platforms</strong> externalize bad driving and should be held accountable.</li><li>The surprising link between <strong>queue culture and road behavior</strong>, and how fixing one helps the other.</li><li>Visual nudges like <strong>red-marked no-stop zones</strong>, inspired by global best practices like London’s yellow box junctions.</li><li>A vision for shifting from <strong>zero-sum to co-op driving</strong>, where honks become signals of gratitude, not aggression.</li></ul><p>These ideas aren’t about stricter enforcement , they’re about creating <strong>a culture of cooperation</strong> on Indian roads.</p><p>⏱️ <strong>Got more time?</strong> Read the full piece below, about a <strong>15-minute deep dive</strong> into how behavior, incentives, and design can transform our streets.</p><h3><strong>Setting the Stage</strong></h3><p>From 2019–2020, I co-founded and led a startup called RoadsenseAI. Our bold idea was to put “Eyes on the Wheels” by installing a simple app on the smartphones of Uber and Ola drivers. These phones, mounted on dashboards and already in use for Google Maps navigation, quietly recorded what the driver saw through the windshield. Our backend processed the video streams, extracting real-world intelligence that was valuable to traffic police, real estate developers, and insurance companies.</p><p>In essence, while Google crawls the web, RoadsenseAI crawls the roads. It created a dynamic, visual index of India’s ever-evolving traffic, streets, and urban behaviors.</p><p>This article is about the insights we gleaned from this experiment and how they can seed large-scale change in India’s traffic ecosystem.</p><h3><strong>Behavioral Change Begins with Critical Mass</strong></h3><p>One of the more audacious ideas we developed was to define and reward a new class of drivers: <strong>good drivers</strong>. Here’s how:</p><p><strong>Defining a Smart Driver</strong></p><p>Before we talk about building a tribe of smart drivers, we must first ask: What exactly is a smart driver in the Indian context?</p><p>A smart driver is not merely someone who avoids getting caught for violations. They are not just compliant — they are <strong>conscious, cooperative, and culturally aware</strong>. In a traffic ecosystem full of unpredictability and stress, the smart driver stands out by making choices that benefit not just themselves but everyone around them.</p><p><strong>Core Behavioral Traits of a Smart Driver</strong></p><ul><li><strong>Respectful Merging</strong>: Yields when appropriate, avoids aggressive cut-ins.</li><li><strong>Lane Loyalty</strong>: Stays within lane boundaries unless required to switch, and signals clearly.</li><li><strong>Predictability</strong>: Uses indicators, avoids sudden stops or swerves.</li><li><strong>Queue Discipline</strong>: Waits in line, doesn’t bypass or jump ahead unfairly.</li><li><strong>Kindness on the Road</strong>: Makes room for others, especially ambulances, pedestrians, and cyclists.</li><li><strong>Patience at Intersections</strong>: Doesn’t honk unnecessarily or edge forward aggressively.</li><li><strong>No Honk Policy</strong>: Reserves honking only for genuine warnings.</li><li><strong>Peer Reinforcement</strong>: Educates co-passengers or peers on smart behavior where possible.</li></ul><h3><strong>Building the Smart Driver Tribe</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WQ7a85bLIsqiwN5PoW81PQ.png" /></figure><p><strong>Self-Certifying Training Program</strong><br> We start with a training or course area where drivers watch a video on smart driving principles. They then practice these principles in a controlled environment. We record their driving session and provide them with that video as a positive artifact of their behavior. Upon completion, drivers receive a physical sticker for their vehicle — identifying them as a certified smart driver.</p><p><strong>QR Code Verification</strong><br> Each sticker includes a QR code that links to a central database. When scanned, it displays details about the driver’s certification, the date they were certified, and the car number. This allows community partners (like parking facilities or toll booths) to verify the certification and grant benefits such as reserved parking or discounted tolls.</p><p><strong>Community Rewards and Visibility</strong><br> By making smart drivers easily identifiable, we encourage a culture of respect on the road. Other drivers can see and anticipate that these drivers follow traffic rules, promoting a cooperative driving environment.</p><p>Additionally, this recognition can serve as a form of social capital. Certified smart drivers can use their status as a point of pride on dating sites, job applications, or community forums — showcasing it as a positive character trait that reflects responsibility, respect, and civic-mindedness.</p><p><strong>Iterative Experimentation</strong><br> We can also offer a lighter version — like watching a YouTube video and answering questions — to expand participation. Over time, we refine the certification process based on feedback.</p><p>If we reach a tipping point with this tribe, their influence can reshape social norms on the road.</p><h3><strong>Don’t Be Rude: A New Vocabulary for Driving</strong></h3><p>Telling people not to speed or cut lanes isn’t working. Instead, we need to <strong>reframe bad driving as rude behavior</strong>.</p><p>Because when you make anti-social driving culturally unacceptable, it triggers a shift deeper than rules can.</p><p>We already call people rude for cutting in line at a buffet or interrupting someone mid-sentence. The same needs to be true when someone honks needlessly, bypasses a queue, or refuses to yield. It’s not just unsafe. It’s inconsiderate.</p><p>This reframing turns the conversation from law enforcement into social etiquette. From “don’t break the rules” to “don’t be rude.”</p><p>Currently, we are competing against billions spent by three powerful cultural forces:</p><ul><li><strong>Movies</strong> that idolize high-speed chases, defiance of traffic norms, and rebellious anti-heroes behind the wheel. Think of the <em>Fast &amp; Furious</em> franchise, <em>Need for Speed</em>, or countless Bollywood action sequences.</li><li><strong>Gaming</strong>, where titles like <em>Grand Theft Auto</em>, <em>Burnout</em>, and <em>Asphalt</em> reward chaotic or ultra-aggressive driving styles.</li><li><strong>The high-performance car industry</strong>, which markets speed and power as status symbols, glorifying 0–100 km/h acceleration and track-style handling, even in urban cars.</li></ul><p>We need counter-narratives that associate speeding and lane-cutting not with thrill or power, but with selfishness, rudeness, and immaturity. Culture shapes conduct. If we want better roads, we must start by reshaping what people admire behind the wheel.. We need new cultural narratives that associate speeding and lane-cutting not with thrill, but with selfishness and rudeness.</p><h3><strong>Vehicle-based fine multiplier</strong></h3><p>One idea borrowed from behavioral economics is the concept of income-adjusted fines, used in some European countries like Finland and Switzerland. These are often calculated based on a person’s daily income, ensuring that a fine for reckless behavior stings equally for a millionaire and a minimum-wage worker.</p><p>In India, however, the divide between the haves and the have-nots is vast, and formal income records are often missing or unreliable. A more practical and culturally attuned alternative is to use the vehicle type as a proxy for economic status.</p><p>We propose a <strong>vehicle-based fine multiplier</strong> system:</p><ul><li>Entry-level hatchbacks pay the base fine.</li><li>SUVs and higher-end sedans pay <strong>2x</strong>.</li><li>Premium and luxury vehicles (e.g., BMWs, Audis, Mercedes) pay <strong>5x</strong>.</li></ul><p>This system reflects the owner’s likely financial capacity while being easy for law enforcement to verify and implement. By linking penalties to the visible, tangible asset (the car), it aligns consequences with affordability — and discourages the wealthy from treating fines as trivial fees.</p><p>The underlying principle is simple: bad behavior should hurt more for those who can absorb a bigger hit.</p><h3><strong>Externalizing the Damage: Holding Platforms Accountable</strong></h3><p>Companies like Swiggy, Zomato, Ola, and Uber have built their empires on a gig economy backbone — drivers and delivery partners who are technically “independent” but functionally essential. In their quest for speed and volume, these platforms incentivize faster turnarounds, more trips, and tighter delivery windows — often pushing their partners into violating traffic rules.</p><p>This is a form of <strong>externalization</strong>, much like how manufacturing industries pollute while expecting the community or the Government to absorb the damage. In this case, the community pays — in the form of congestion, accidents, stress, and eroded public norms.</p><p>We propose a simple but powerful shift: <strong>if a ride-hailing or delivery driver violates traffic rules, the platform pays 10x the fine.</strong></p><p>This would:</p><ul><li>Push platforms to invest in better training, education, and behavioral nudges</li><li>Drive innovation in real-time tracking, route optimisation, and behavior-aware incentives</li><li>Force companies to align with public interest, not just profit per kilometre</li></ul><p>The moment these costs hit a platform’s bottom line, their priorities will change. And as they improve their partners’ driving behaviors, they contribute directly to the <strong>critical mass of cooperative road users</strong> — shaping the culture through scale.</p><p>This isn’t just policy. It’s structural behavior design.</p><h3><strong>How We Queue Is How We Drive</strong></h3><p>Could one of the deeper reasons for poor road behavior in India stem from how we behave in queues? There seems to be a striking resemblance between how people navigate traffic and how they navigate public lines. Both are shaped by early exposure, informal social rules, and survival instincts in crowded environments. This observation raises an important question worth exploring further: Is our chaotic road behavior an extension of our queue culture?</p><p>From a young age, children observe chaotic queue dynamics: people skipping lines, crowding each other, and the tallest or loudest pushing through. Over time, this trains the subconscious belief that survival depends on aggressively asserting one’s place, not waiting one’s turn.</p><p>This same logic then plays out on the roads: lane-cutting, tailgating, honking, and refusing to yield. In both queues and traffic, <strong>the lack of mutual respect and perceived fairness leads to stress, anxiety, and rule-breaking</strong>.</p><p>To truly reform road behavior, we need to address how people queue in everyday life — in small restaurants, bus stops, ticket counters, and hospitals. We propose a multi-pronged approach:</p><ul><li>Encourage the creation of a <strong>free, publicly available set of space design templates</strong> — contributed by architects and urban designers — that promote single-file discipline with natural spacing. These designs should be simple, modular, and adaptable for use by small shops, restaurants, bus stops, and public venues, enabling them to implement better queue systems without incurring significant costs.</li><li>Encourage designs that reduce ambiguity — e.g., painted footprints, rope dividers, staggered markers.</li><li>Pair design with nudges: signage that reminds people that “respect starts here,” or even community recognition for shops with good queue practices.</li></ul><p><strong>Queue Dynamics, Not Just Lane Discipline</strong></p><p>When you fix queues, you fix driving. They are cognitively and culturally linked.</p><ul><li>Design and implement <strong>visible, behavioral queues</strong> at entry points</li><li>Avoid aggressive merging by pre-defining entry zones</li><li>Move from gap driving to lane driving</li></ul><p>It’s a mindset shift, not just an infrastructure challenge. Changing how people wait in line might be the most foundational step toward changing how they behave on the road.</p><h3><strong>Red-marked no-stop zones</strong></h3><p>These are specially designated areas — particularly near U-turns, intersections, and signal junctions — where stopping is absolutely prohibited. The road surface itself will be <strong>literally painted in red</strong>, acting as a strong visual and psychological signal, similar to the yellow box junctions used in cities like London or Singapore. These markings are meant to communicate clearly that the area must always remain free-flowing — no stopping, no idling, and no waiting. Such bottleneck points often become the root cause of peak-hour traffic chaos when even a single two-wheeler or auto rickshaw halts, blocking others from taking turns or clearing the junction. The red paint on the road enforces a zero-tolerance policy: these are not parking spaces, not waiting zones, and not areas to pause when traffic ahead is stalled. If you can’t move forward, you stop <em>before</em> the red — it is meant only for moving vehicles.</p><p>To reinforce this, we propose a community-enforced model: anyone should be able to capture a short video of a violation and submit it to a public portal. This data could be verified using timestamp/location metadata, and verified contributors would be rewarded with small credits or incentives. The goal isn’t surveillance for punishment, but to make it socially and economically risky to violate obvious common-sense rules. This builds a <strong>critical mass of behavior change</strong> — when everyone expects accountability, everyone behaves better.</p><h3><strong>From Zero-Sum to Cooperative Driving</strong></h3><p>Driving on Indian roads often feels like a zero-sum game: if one driver gains, others must lose. For example, if the vehicle in front slows down, the immediate assumption is that the driver is incompetent — prompting the next driver to aggressively overtake, often from the wrong side, only to get stuck behind a two-wheeler or incoming traffic. No one wins, but the urge to ‘get ahead’ dominates.</p><p>Contrast this with driving behavior in countries like the US, where the mindset resembles a co-op game: people yield, trust the intentions of others, and collaborate to ensure a smoother experience for everyone. There’s an unspoken social contract — to trust, to wait, and to flow together.</p><p>To shift Indian roads from zero-sum to cooperative dynamics, we need new cultural cues and reinforcements. One such idea is to <strong>reverse the emotional role of honking</strong>. Instead of aggressive or intimidating honks, what if we had a second tone — a softer, lighter ‘thank-you honk’? Either through a dedicated button or by modulating the intensity of the horn press (soft press = gratitude tone, hard press = alert tone), we could create auditory signals of appreciation.</p><p>Imagine driving through a city where you hear frequent tones of gratitude, kindness, and acknowledgement. This could reinforce co-op game dynamics subconsciously — making drivers feel calmer and more connected.</p><p><strong>Co-op Game Signals</strong>: Thank-you honks or lights when someone lets you go. It’s not just about utility, it’s about signalling that we’re in this together.</p><p><strong>Next Steps</strong></p><p>We’ll be expanding this article with visuals. If you’re a policymaker, technologist, or someone who believes traffic is solvable, let’s connect.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=83bf1ef1605b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Blender + Claude on Linux: A Friendly Companion for Creative Exploration]]></title>
            <link>https://medium.com/@neosrix/blender-claude-on-linux-a-friendly-companion-for-creative-exploration-7be812707c77?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/7be812707c77</guid>
            <category><![CDATA[claude]]></category>
            <category><![CDATA[blender]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[mcp-server]]></category>
            <category><![CDATA[ubuntu]]></category>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Mon, 21 Jul 2025 09:00:32 GMT</pubDate>
            <atom:updated>2025-07-22T05:47:07.456Z</atom:updated>
            <content:encoded><![CDATA[<p>A few weeks ago at the SMOL Hackathon in Bangalore, I met one of the guest judge <a href="https://github.com/ahujasid">Siddharth Ahuja</a> . He shared about his side project: <a href="https://github.com/ahujasid/blender-mcp"><strong>Blender MCP</strong></a>.</p><p>What blew my mind wasn’t just the elegance of the project , it was how something so small, so focused, had quietly gone viral within niche creative communities. Blender MCP is essentially a bridge between <strong>Anthropic’s Claude</strong> (a powerful AI assistant) and <strong>Blender</strong>, the much-loved 3D creation suite.</p><p>As someone who’s dabbled in creative tools for years, I’ve always found Blender powerful but <em>intimidating</em>. The learning curve feels steep, the UI a little too layered. But the promise of conversational assistance inside Blender? That got me curious.</p><h3>Wait… Claude inside Blender?</h3><p>Yes. With Blender MCP, you can talk to Claude (via Claude Desktop) while working inside Blender. Imagine asking:</p><blockquote><em>“Can you help me model a low-poly tree?”<br> “What’s the fastest way to rig this character?”<br> “Give me color palette ideas based on this HDRI.”</em></blockquote><p>It turns Claude into your co-pilot for 3D creation.</p><p>But there was a small challenge: I use <strong>Linux</strong>, specifically <strong>Kubuntu</strong>. And Claude Desktop hasn’t officially been released for Ubuntu.</p><p>So here’s a quick guide for fellow Linux users to get this running.</p><h3>Installing Claude Desktop on Ubuntu (Debian-based)</h3><p>I found <a href="https://github.com/aaddrick/claude-desktop-debian"><strong>aaddrick’s Claude Desktop for Debian</strong></a> — a FOSS project that lets you install Claude Desktop as a .deb package. Basically downloads the windows installer , extracts the electron binaries required and repacks them for Linux electron and builds Ubuntu installer. I even asked Claude itself to audit the code for anything suspicious, it passed the vibe check. Following instructions will build you a .deb installer. I would recommend this instead of appimage binary because of better system integration.</p><pre># Clone this repository<br>git clone https://github.com/aaddrick/claude-desktop-debian.git<br>cd claude-desktop-debian<br><br># Build the package (Defaults to .deb and cleans build files)<br>./build.sh<br><br># Replace VERSION and ARCHITECTURE with the actual values from the filename<br># sudo dpkg -i ./claude-desktop_VERSION_ARCHITECTURE.deb   <br>sudo dpkg -i ./claude-desktop_0.12.16_amd64.deb</pre><h3>Fixing MCP Config for Linux</h3><p>Check <a href="https://github.com/ahujasid/blender-mcp">https://github.com/ahujasid/blender-mcp</a> for configuring MCP on claude. The default config for Blender MCP didn’t work out of the box. Here’s the working configuration that finally got everything talking. You need to replace the command path with the location of uvx on your system.</p><pre>whereis uvx<br>uvx: /home/srix/.local/bin/uvx</pre><pre><br>{<br>  &quot;mcpServers&quot;: {<br>    &quot;blender&quot;: {<br>      &quot;command&quot;: &quot;/home/srix/.local/bin/uvx&quot;,<br>      &quot;args&quot;: [&quot;blender-mcp&quot;]<br>    }<br>  }<br>}</pre><h3>How It Works — The Architecture</h3><p>Once you have Claude Desktop and Blender MCP set up, the magic happens through a light weight MCP server and an addon (server) inside blender.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*R4h2JkqVlb4U_G3jh2jOMA.png" /></figure><p>Essentially, Claude Desktop acts as the front-end assistant. When you ask something, the request is routed to the Blender MCP server, which then talks to a Blender Addon (running inside Blender itself) via a TCP socket. The Addon, in turn, executes API calls inside Blender — or fetches assets from sources like PolyHaven or Sketchfab.</p><p>It’s a clever, modular setup. Lightweight. Hackable. Extendable.</p><h3>Tiny UX Note</h3><p>One small UX issue I noticed: Blender addon integration button says <strong>“Connecting to MCP Server”</strong>, which feels misleading . It’d be better as <strong>“Listening to MCP Server”</strong>.</p><h3>Installing Blender</h3><p>If you don’t already have Blender installed:</p><pre>sudo apt install blender</pre><p>Or get the latest version directly from <a href="https://www.blender.org/download/">blender.org</a>. Make sure to enable scripting and the MCP addon.</p><h3>See it in Action</h3><p>Here’s a short video clip of Blender MCP in action — Claude assisting while I generate an animation sequence:</p><iframe src="https://cdn.embedly.com/widgets/media.html?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DRJkot8k3Xw4&amp;type=text%2Fhtml&amp;schema=google&amp;display_name=YouTube&amp;src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FRJkot8k3Xw4" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/deb57daf7ec41d28cdaf4ad7d08728f5/href">https://medium.com/media/deb57daf7ec41d28cdaf4ad7d08728f5/href</a></iframe><h3>Why This Matters for Artists</h3><p>This tool isn’t about making AI do your work , it’s about removing friction. When the tools fade into the background, <strong>play and flow emerge</strong>. That’s when great art happens.</p><p>If Blender ever felt “too technical” for you, give this a spin. Claude becomes your whispering muse. Ask questions, get inspiration, explore faster.</p><p>And if you’re building tools like this, please keep going. These are the bridges that make creation more inclusive and delightful.</p><p>🔗 <strong>Links:</strong></p><ul><li><a href="https://github.com/ahujasid/blender-mcp">Blender MCP GitHub</a></li><li><a href="https://github.com/aaddrick/claude-desktop-debian">Claude Desktop Debian Installer</a></li><li><a href="https://www.anthropic.com/index/claude">Claude by Anthropic</a></li></ul><p>If you try it out or have questions, drop a comment . Let’s keep hacking creativity forward.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7be812707c77" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From a cafe in New York]]></title>
            <link>https://medium.com/@neosrix/from-a-cafe-in-new-york-06f5c201eba3?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/06f5c201eba3</guid>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Mon, 07 Apr 2025 05:34:21 GMT</pubDate>
            <atom:updated>2025-04-07T05:52:11.287Z</atom:updated>
            <content:encoded><![CDATA[<p>I was sitting in the Bluespoon Café, Downtown Manhattan, <br>at a corner table,<br>watching the uniquely different traits of the human forms <br>crossing my café through the glass wall.</p><p>It is a café located at the corner of a busy intersection.<br>There was construction work happening all around. <br>Scaffolds raised on the walkway making the intersection look smaller than it was. <br>Creating new mazes to be negotiated by already busy New Yorkers and baffled tourists frequently staring at their phones, <br>reassuring themselves they are in the right direction toward their destiny.</p><p>The café has great coffee. Great sandwich.<br>What differentiates a tourist from a New Yorker?<br>Walking speed, the dressing, staring at phone,<br>and a slight hint of subtle expression of annoyance.</p><p>Annoyed at what?<br>As a tourist I am excited about everything NYC has put on display.<br>The tall buildings with vintage motifs and gargoyles<br>give me an impression that someone took an old European city<br>and pulled the buildings vertically.</p><p>In the night the buildings dazzle with lights.<br>Maybe someone is working, watching TV,<br>making decisions that will change others’ lives<br>or tallying their results in trading stocks.</p><p>If I squint my eyes I may even see a flying car<br>like that one in the popular sci-fi movies like Fifth Element or Star Wars.<br>Something about the tall buildings all around you, everywhere,<br>installs a weird sense of diminished size<br>in stature and also in ego.</p><p>Navigating the tall, ridiculously tall, 3D space<br>feels weird and feels like I am in a computer game<br>with artificially rendered buildings.</p><p>The contrasting aging subway that connects<br>every posh area of downtown Manhattan<br>grounds you, rather undergrounds you.</p><p>Dressing up, yes, the people in the city dress up.<br>They pay attention to what they wear, how they wear,<br>I am sure they know why they wear.<br>My interest is trying to guess why they wear what they wear.<br>Like a detective piecing together the clues of a crime scene,<br>I try to guess the story of a passerby.</p><p>Tourists are easy to call out.<br>They are not of big interest to me.<br>However, the New Yorkers — they are a different breed.</p><p>The city is cold.<br>Just out of snow when I visited.<br>I see everyone wearing appropriate levels of layers.<br>Except for many tourists.<br>They either wear too many or too few.<br>Me, on the too-little side.</p><p>Why dress up?<br>How do they know how to dress up?<br>Not for me.<br>They don’t know a traveller from India<br>is sitting in the café and watching them in amusement.<br>Like performers in a Broadway show.<br>Or maybe the Broadway shows are the inspiration.<br>When so many avenues of creativity flow through your city<br>like Broadway shows, art galleries, science, universities,<br>it rubs on you whether you want it or not.<br>Like the cold wind that embraces you<br>and welcomes you when you step out of the subway<br>whether you want it or not.</p><p>In me it installed a sense of writing.<br>As if it is a serious offence if I don’t chronicle this.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=06f5c201eba3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Observations in using AI-assisted coding using ChatGPT.]]></title>
            <link>https://medium.com/@neosrix/observations-in-using-ai-assisted-coding-using-chatgpt-62133af1e377?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/62133af1e377</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[chatgpt]]></category>
            <category><![CDATA[developer]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Wed, 31 May 2023 11:58:59 GMT</pubDate>
            <atom:updated>2023-05-31T11:58:59.876Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*nxgns21yTlwmwedv" /><figcaption>Photo by <a href="https://unsplash.com/@jupp?utm_source=medium&amp;utm_medium=referral">Jonathan Kemper</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><blockquote>ChatGPT is quicker than search. But that’s not the point.</blockquote><p>Searching for a solution while coding is inefficient.</p><p>Firstly, It takes time to read the multiple sites that Google serves as a result, including stack overflows pages, blogs, videos etc. Some might be correct, but outdated. For example, if you are looking for string interpolation in Python and land up in a blog that explains the same for Python versions previous to 3.6, it may recommend str.format() or % formatting instead of fstrings. All solutions will work with the latest Python. However, fstrings are more readable. Processing this and choosing relevant information takes time.</p><p>Secondly, the cost of context switching. Context switching breaks focus and flow state. Switchback takes time, and frequent switches may cause mental fatigue.</p><p>The fastest way to get help while coding is to ask an expert next to you (assuming you got one). An expert&#39;s answer usually has the following characteristics.</p><ul><li><strong>Solution</strong>: The solution to your question. Sometimes experts may even share a code on Slack with you.</li><li><strong>Explanation</strong>: Explain the rationale for arriving at the answer. They don&#39;t want you to come again with similar questions and take their time. So they invest in explaining the thinking process.</li><li><strong>Caution</strong>: May inform you about the most common mistake you may make while implementing the solution. (because very likely they also made it)</li><li>If you repeat the same query on another day, the expert may still provide the solution but might omit some information and add some new one.</li></ul><blockquote>ChatGPT is this expert.</blockquote><p>Thanks to the integration of ChatGPT into VScode with Github Co-PilotX, there&#39;s minimal context switching required. In the following section, I will explain with an example the above characteristics.</p><h3>Let’s analyse a solution.</h3><p>I asked ChatGPT for a solution for an error in using Openai API in Python. Following is what ChatGPT replied.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/801/1*-OY-lhtfOJFXHZh3Wp8KlA.png" /></figure><p>The first paragraph starts with <strong>Explaining</strong> the rationale.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/599/1*vWFiyCm5EIg5ge8UuTBx-Q.png" /></figure><p>Then the <strong>Solution</strong> is provided step by step in three bullet points.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/635/1*OECEvbS_vwJ0QwR_O1rJNw.png" /></figure><p>Followed by <strong>Caution</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/635/1*JO3gcOc-GV3QgnG7TQOrzQ.png" /></figure><p>I started a side project, <a href="https://medium.com/@neosrix/comprehensive-comparison-of-popular-programming-languages-ef5e7c2e3bd3">Comprehensive Comparison of Programming Languages</a>, to understand coding from scratch using ChatGPT, including creating system diagrams. This article is the outcome of the observations during that project.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=62133af1e377" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Comprehensive Comparison of Programming Languages]]></title>
            <link>https://medium.com/@neosrix/comprehensive-comparison-of-popular-programming-languages-ef5e7c2e3bd3?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/ef5e7c2e3bd3</guid>
            <category><![CDATA[chatgpt4]]></category>
            <category><![CDATA[developer-tools]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[learning-to-code]]></category>
            <category><![CDATA[programming-languages]]></category>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Tue, 30 May 2023 10:57:40 GMT</pubDate>
            <atom:updated>2026-01-27T09:13:24.951Z</atom:updated>
            <content:encoded><![CDATA[<p>tldr: If you are looking for a side-by-side comparison of popular programming languages (20+ languages added), visit <a href="https://programming-languages.com">https://programming-languages.com</a></p><p>I started learning Rust recently. Began with the excellent material on the rust-lang website <a href="https://doc.rust-lang.org/book/">https://doc.rust-lang.org/book/</a>. Though I learnt a lot going through it, I found something missing. I have deep expertise in Python and C# and wish a side-by-side comparison of concepts in these languages existed. I believe it will help me compare and understand the implementation of the same concept in Rust faster. Of course, I searched online and found a few useful sites like <a href="https://github.com/evmorov/lang-compare">evmorov</a>. Extending on <a href="http://Evgenii Morozov">Evgenii Morozov</a>’s approach created a webpage where one can compare language concepts side-by-side. The content is generated using ChatGPT.</p><p>visit <a href="https://programming-languages.com">https://programming-languages.com</a></p><p>(old url <a href="https://srix.github.io/prog-lang-compare/">https://srix.github.io/prog-lang-compare/</a>)</p><figure><a href="https://srix.github.io/prog-lang-compare/"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oYM-eI5-GT9ucrF4kH3VrQ.png" /></a></figure><p>The project was built entirely using ChatGPT (GPT-4) for content and assisted coding. In a way, it helped me understand what are the nitty gritty in building a product from scratch using ChatGPT and Github Co-Pilot. Currently, it supports more than 20+ programming languages including Dart , Go , Groovy , Haskell , Java 20 , JavaScript — ECMAScript 2021 , Julia , Kotlin , Lua , MATLAB , Objective-C , PHP , Perl , Python 3.10 , R , Ruby , Rust 1.55 , Scala , Swift , TypeScript , Visual Basic .NET.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FQ5ni89rWglI%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DQ5ni89rWglI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FQ5ni89rWglI%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/52449cfb4f4d13b70be6717898e93257/href">https://medium.com/media/52449cfb4f4d13b70be6717898e93257/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ef5e7c2e3bd3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[When I tried setting up the G Suite email account for a business domain, G Suite threw a weird…]]></title>
            <link>https://medium.com/@neosrix/when-i-tried-setting-up-the-g-suite-email-account-for-a-business-domain-g-suite-threw-a-weird-be5cece72afe?source=rss-8f8324c8c33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/be5cece72afe</guid>
            <category><![CDATA[google]]></category>
            <category><![CDATA[g-suite]]></category>
            <category><![CDATA[adsense]]></category>
            <dc:creator><![CDATA[Srix]]></dc:creator>
            <pubDate>Wed, 15 May 2019 13:33:45 GMT</pubDate>
            <atom:updated>2019-05-15T13:33:45.157Z</atom:updated>
            <content:encoded><![CDATA[<h3>G Suite rejected my subscription. Guess why!</h3><p>I have been a long term Google G Suite user and like that product. Recently I was creating an account for a new domain and was rejected with a peculiar reason.</p><p>When I tried setting up the G Suite email account for a business domain <a href="https://www.RoadSenseAI.com">RoadSenseAI.com</a> , G Suite threw a weird error “Sorry, We’ve got dibs on that one.” and didn’t allow me to proceed. I didn’t find any details on the internet. So raised a support ticket with Google.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/967/1*Hd8fyWfYmqK58kN5sEXXbw.png" /><figcaption>Sorry, We’ve got dibs on that one.</figcaption></figure><p>I received a prompt call from Google support shortly. The support personnel was himself surprised at the error message and politely put me on hold for 15 minutes. When he resumed the call, he gave me a peculiar reason and said it was not possible to subscribe to G Suite with this domain name. For a moment I thought it was ridiculous. So asked him to send a mail with the reason.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/689/1*iDsVfV7EGRf3AmvsJnwfBw.png" /></figure><blockquote>Thank you for answering my call.</blockquote><blockquote>I understand that you’re trying to sign up for G Suite using the domain name <a href="http://roadsenseai.com/">roadsenseai.com</a> and you’re getting the following error message: “Sorry, we’ve got dibs on that one!”</blockquote><blockquote>You will not be able to register with that domain name as Google has a program named AdSense and your domain has the word “adsense”. I hope that I was helpful by clarifying this to you.</blockquote><blockquote>Since there are no further actions that our team is able to take to further assist you I will close this case.</blockquote><blockquote>Have a lovely rest of the week!</blockquote><p>This was a complete disappointment for me. I enquired about the process to escalate or appeal, hoping G Suite will approve on case by case basis on such situations. Unfortunately, I was told, no such process exists.</p><p>My guess is Google is paranoid about Domain squatting and similar techniques impacting their AdSense product and rejecting all domains containing the AdSense product name.</p><p>I am sharing this so, if anybody getting “Sorry, We’ve got dibs on that one.” will be aware of the reason and not waste time on figuring out the root cause. Also hoping that Google may take this as feedback and have a special case by case approval rather sweepingly rejecting all such domains.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=be5cece72afe" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>