<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Tightknit Blog</title>
    <link>https://tightknit.ai/blog</link>
    <description>Product launches, community lessons, and the occasional engineering deep-dive from the Tightknit team.</description>
    <language>en-us</language>
    <atom:link href="https://tightknit.ai/rss.xml" rel="self" type="application/rss+xml" />
    <lastBuildDate>Thu, 28 May 2026 03:59:00 GMT</lastBuildDate>
    <pubDate>Mon, 13 Apr 2026 00:00:00 GMT</pubDate>
    <item>
      <title>The Practical Case for TanStack Start on Cloudflare Workers</title>
      <link>https://tightknit.ai/blog/nextjs-to-tanstack-start-cloudflare-workers</link>
      <guid isPermaLink="true">https://tightknit.ai/blog/nextjs-to-tanstack-start-cloudflare-workers</guid>
      <pubDate>Mon, 13 Apr 2026 00:00:00 GMT</pubDate>
      <dc:creator>Daniel Gomes</dc:creator>
      <category>dev</category>
      <description><![CDATA[A first-hand account of migrating a production app from Next.js to TanStack Start on Cloudflare Workers, covering routing, Vite DX, RPC service bindings, and the real tradeoffs.]]></description>
      <content:encoded><![CDATA[<h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">Summary</h4><p class="my-5 text-body-l text-neutral-08">I was recently given the challenge of migrating one of my workplace&#x27;s web applications off of NextJS and explore our platform options.</p><p class="my-5 text-body-l text-neutral-08">At Tightknit, we do our best to stay tuned in to the movements that affect the developer community: acquisitions, company mergers, and fat checks supporting open source projects. One such movement causing waves is Cloudflare&#x27;s explicit support for TanStack to run on their Workers platform. Having long been invested in the Workers ecosystem, it was an obvious combination for us to explore, one that promised to bring competitive advantages to the business.</p><p class="my-5 text-body-l text-neutral-08">The first step was to create a proof of concept and, after that, validate the complete solution. The POC itself was quite simple: create a new project and migrate one or two screens. The process was smooth, especially with the support of AI, something we embrace responsibly in our software engineering process. Even within converting just a few files, we began to notice significant differences compared to Next, the most important of which I&#x27;ll list below.</p><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">Clearer Page Lifecycle</h4><p class="my-5 text-body-l text-neutral-08">In NextJS, the page lifecycle is not obvious and a serious point of struggle for newcomers. The React lifecycle has gone through many iterations to reach the maturity it has today, and yet… you will encounter obscure boundaries, such as where metadata ends and the page begins, or where files and the router fit into the mix. This is a result of Next&#x27;s evolution over time from frontend framework to full stack platform; it&#x27;s very difficult to avoid creating these &quot;quirks&quot; along the way.</p><p class="my-5 text-body-l text-neutral-08">Enter TanStack. In TanStack, you get <em>much</em> clearer definitions coming straight from the file router, where you can explicitly define things like validations, data loading, what goes in the \&lt;head\&gt;, what the component is, and more — all hierarchically and type-safe.</p><p class="my-5 text-body-l text-neutral-08">Why? Because TanStack is not considered a framework, but rather a collection of libraries that help you build React applications. One of these libraries is the TanStack Router, a file-system-based router that makes everyone&#x27;s lives simpler. For those accustomed to NextJS and its directory-based router, you won&#x27;t have trouble with the TanStack router. It works basically the same way, with some minor syntax differences, mainly in how files are named and how route variables are retrieved.</p><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">Vite: A Very Welcome Addition</h4><p class="my-5 text-body-l text-neutral-08">Another great advantage TanStack brings is the use of Vite. While not directly related to TanStack, it is the build tool of choice in TanStack Start, which is a package of recommended libraries for a project using TanStack—almost a framework.</p><p class="my-5 text-body-l text-neutral-08">Vite, when running in the background with <code class="rounded bg-neutral-02 px-1.5 py-0.5 font-mono text-[0.9em] text-neutral-09">npm run dev</code>, allows changes we make to the file structure to be reflected in TanStack&#x27;s TypeScript immediately. So, for example, if you add a new route file named <code class="rounded bg-neutral-02 px-1.5 py-0.5 font-mono text-[0.9em] text-neutral-09">about.tsx</code>, that route instantly becomes available to be consumed in the code in a completely type-safe way.</p><p class="my-5 text-body-l text-neutral-08">It also brings benefits in the reverse direction. For instance, when you create a route file, it handles the scaffolding, filling it with the basics needed to create a new route.</p><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">RPC Calls</h4><p class="my-5 text-body-l text-neutral-08">The biggest surprise benefit was: the ability to make direct calls using Cloudflare Worker service bindings.</p><p class="my-5 text-body-l text-neutral-08">In our web app, most pages are rendered using SSR. With TanStack, our actions or data loading are done through calls to server functions, which in turn call Cloudflare workers using RPC service binding calls.</p><p class="my-5 text-body-l text-neutral-08">This configuration brought absurd speed to data loading because the RPC protocol is much leaner than the HTTP protocol, not to mention it doesn&#x27;t carry all the overhead related to NextJS server actions.</p><p class="my-5 text-body-l text-neutral-08">P.S. <em>Did you know Next server actions are executed sequentially?</em></p><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">The Weak Points</h4><p class="my-5 text-body-l text-neutral-08">But it&#x27;s not all sunshine and rainbows. We had some losses we had to work around when using TanStack.</p><p class="my-5 text-body-l text-neutral-08">The biggest one, without a doubt, was losing the image generation offered by Vercel using <code class="rounded bg-neutral-02 px-1.5 py-0.5 font-mono text-[0.9em] text-neutral-09">vercel/og</code>—for Open Graph images, for example. Our solution was to create a new worker dedicated to image generation at the Edge layer of the application, closest to the user.</p><p class="my-5 text-body-l text-neutral-08">This is definitely a workaround—a bit of a hack (&quot;gambiarra&quot;)—due to the fact that TanStack doesn&#x27;t bring any first-party library for image generation. However, the <code class="rounded bg-neutral-02 px-1.5 py-0.5 font-mono text-[0.9em] text-neutral-09">workers-og</code> library works very well on Cloudflare, runs on the Edge, and delivers satisfactory image generation results.</p><p class="my-5 text-body-l text-neutral-08">Other smaller, though less relevant, drawbacks included having to learn a completely different cache management system, as well as the debugging tool that loads in <a href="http://localhost" class="text-primary-blue-text underline underline-offset-4">localhost</a> applications. It works very well and brings different tools, but the keyboard shortcut naturally conflicts with the macOS screenshot shortcut, forcing us to customize the shortcut for a better experience.</p><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">Conclusion</h4><p class="my-5 text-body-l text-neutral-08">The final result is that we now have a much faster application than before and a stack that is much more integrated into the Cloudflare infrastructure.</p><p class="my-5 text-body-l text-neutral-08">I have nothing against Vercel or Next.js. Both brought significant improvements to software engineering and the way we build web applications, delivering the most solid developer experience we&#x27;ve seen in recent years.</p><p class="my-5 text-body-l text-neutral-08">We simply reached a point as many do where your application grows and as your traffic scales, and it comes time to evaluate vendor lock-in before finding yourself hostage to a single vendor&#x27;s ecosystem and pricing model. This migration wasn&#x27;t just a technical swap, it was a strategic move to ensure our stack supports our growth.</p>]]></content:encoded>
    </item>
    <item>
      <title>Splitting Human and AI Experiences in Community</title>
      <link>https://tightknit.ai/blog/splitting-human-and-ai-experiences-in-community</link>
      <guid isPermaLink="true">https://tightknit.ai/blog/splitting-human-and-ai-experiences-in-community</guid>
      <pubDate>Sun, 14 Dec 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Hawtof</dc:creator>
      <category>best-practice</category>
      <description><![CDATA[Explore the spectrum of customer support experiences, from transactional solutions focused on speed and efficiency to non-transactional interactions that foster human connections.]]></description>
      <content:encoded><![CDATA[<h2 class="mt-14 mb-4 text-cms-h1 font-display text-neutral-10">Transactional vs. Non-Transactional Experiences</h2><p class="my-5 text-body-l text-neutral-08">Customer support exists on a spectrum. At one end: transactional experiences built for speed and self-service. At the other: non-transactional experiences rooted in human connection.</p><h3 class="mt-12 mb-3 text-cms-h2 font-display text-neutral-10">The Core Distinction</h3><p class="my-5 text-body-l text-neutral-08"><strong class="font-medium text-neutral-10">Transactional experiences</strong> prioritize immediate problem resolution. Users need answers now. They don&#x27;t care whether a person or automated system provides the solution—only that the problem gets solved efficiently.</p><p class="my-5 text-body-l text-neutral-08"><strong class="font-medium text-neutral-10">Non-transactional experiences</strong> prioritize human connection as the path to resolution. Users seek guidance, best practices, and relationship-building alongside their answers.</p><h3 class="mt-12 mb-3 text-cms-h2 font-display text-neutral-10">The 90% vs. 100% Framework</h3><p class="my-5 text-body-l text-neutral-08">This spectrum reveals a strategic tension in customer experience design.</p><p class="my-5 text-body-l text-neutral-08">Transactional systems excel at getting customers 90% of the way to resolution. Self-service documentation, AI chatbots, and automated workflows handle the majority of common issues. Speed and scalability matter more than perfect personalization.</p><p class="my-5 text-body-l text-neutral-08">Non-transactional experiences aim for the full 100%. Human expertise fills gaps that automation misses. Community members share nuanced context. Support teams provide customized guidance. The final 10% requires understanding that only human connection delivers.</p><h3 class="mt-12 mb-3 text-cms-h2 font-display text-neutral-10">When Each Approach Wins</h3><p class="my-5 text-body-l text-neutral-08"><strong class="font-medium text-neutral-10">Choose transactional when:</strong></p><ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Users face repetitive, well-defined problems</li><li>Speed to resolution drives satisfaction</li><li>Scale demands automation</li><li>Solutions exist in documented form</li></ul><p class="my-5 text-body-l text-neutral-08"><strong class="font-medium text-neutral-10">Choose non-transactional when:</strong></p><ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Problems require contextual understanding</li><li>Best practices evolve through discussion</li><li>Relationship-building creates long-term value</li><li>Complex scenarios need human judgment</li></ul><h3 class="mt-12 mb-3 text-cms-h2 font-display text-neutral-10">The Balanced Approach</h3><p class="my-5 text-body-l text-neutral-08">The most effective support strategies don&#x27;t pick sides. They recognize when automation serves users best and when human connection becomes essential.</p><p class="my-5 text-body-l text-neutral-08">Start with transactional systems that efficiently handle common scenarios. Layer in non-transactional touchpoints where expertise and relationships matter most. Design clear escalation paths between the two.</p><p class="my-5 text-body-l text-neutral-08">This balanced model maximizes efficiency while preserving the human elements that drive deeper engagement and lasting customer success.</p>]]></content:encoded>
    </item>
    <item>
      <title>Supporting Dark Themes</title>
      <link>https://tightknit.ai/blog/improved-dark-themes</link>
      <guid isPermaLink="true">https://tightknit.ai/blog/improved-dark-themes</guid>
      <pubDate>Sun, 16 Nov 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Hawtof</dc:creator>
      <category>product</category>
      <description><![CDATA[Explore how Tightknit has integrated dark mode support, enhancing user experience with 90% coverage of dark styles, improved accessibility, and a consistent theming model.]]></description>
      <content:encoded><![CDATA[<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Working title: Supporting dark mode in Tightknit</li><li>Category: Product</li><li>Slug: dark-mode</li><li>One‑liner: We introduced dark‑mode‑aware branding sets, moved branding to root‑level CSS variables, and enabled Tailwind&#x27;s dark styles—delivering a 90% complete dark experience with minimal risk to existing sites.</li></ul><p class="my-5 text-body-l text-neutral-08">Dark mode has gone from &quot;nice to have&quot; to a baseline expectation. For communities that live in Tightknit all day, the ability to reduce glare at night, improve focus, and keep brand identity intact matters.</p><p class="my-5 text-body-l text-neutral-08">Over the past week, we shipped the first phase of dark mode across the web app and companion sites. This post breaks down what changed, why we changed it, how Orchid Security&#x27;s Dark Matter theme shaped the work, and what&#x27;s next.</p><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">The Orchid Security story: Dark Matter, real constraints</h4><p class="my-5 text-body-l text-neutral-08">Orchid Security wanted a truly dark brand aesthetic—&quot;Dark Matter&quot;—for their companion site. Early tests surfaced real problems: harsh white outlines, unreadable button text in menus, and components that ignored branding because they rendered outside the app tree.</p><p class="my-5 text-body-l text-neutral-08">We turned that feedback into a focused implementation plan:</p><ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Introduce a theme_mode on branding sets (light or dark) so dark themes don&#x27;t fight light‑biased defaults.</li><li>Move branding from scattered styles to root‑level CSS variables so Radix portals and overlays inherit the correct colors.</li><li>Activate shadcn/Tailwind dark styles via a .dark class on the branding root, then derive tokens for borders, surfaces, and text to eliminate &quot;white halo&quot; artifacts.</li></ul><p class="my-5 text-body-l text-neutral-08">After an overnight push to wire these pieces together, we got to a &quot;90% there&quot; dark experience for Orchid—good enough to unblock their launch—while tracking the last 10% of visual nits for cleanup.</p><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">What changed (for everyone)</h4><ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Per‑brand theme mode in branding sets<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>We added theme_mode and automatically infer the right mode from your background color&#x27;s luminance so sites &quot;just look right&quot; when you choose a dark background.</li></ul></li><li>Root‑level CSS variables instead of inline overrides<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Branding now compiles into CSS variables at the root and a tk-branding scope, so everything—including portals and overlay components—gets the correct colors.</li></ul></li><li>Tailwind + shadcn dark support, activated the right way<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>We toggle .dark on the tk-branding root, then use color‑mix‑based tokens for borders, surfaces, and text to avoid hard‑coded light‑mode artifacts.</li></ul></li><li>Safer defaults for existing customers<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Light‑mode tokens were tuned so changes are barely noticeable, minimizing regressions while unlocking dark mode for those who want it.</li></ul></li></ul><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">Why this approach</h4><ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Portals and overlays must inherit branding<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Root variables ensure modals, popovers, and other out‑of‑tree elements pick up brand colors consistently—no more menu dialogs stuck in light mode.</li></ul></li><li>Accessibility by design<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>We&#x27;re validating contrast and structure with Playwright + axe‑core to reduce color‑contrast issues as we extend dark mode coverage.</li></ul></li><li>Predictable theming model<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>A single source of truth (CSS variables) with a simple mode switch (.dark) is more maintainable than per‑component overrides.</li></ul></li></ul><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">What&#x27;s improved already</h4><ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Real usage, real feedback<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Orchid&#x27;s Dark Matter testing revealed outlines, dropdowns, skeletons, and dialogs that needed dark tokens. Those are now addressed or tracked with clear owners.</li></ul></li><li>90% coverage today<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Initial rollout covers core surfaces and shadcn components. Remaining rough edges include stray borders and a few default tokens that still assume light backgrounds.</li></ul></li></ul><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">What&#x27;s next</h4><ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Finish the last 10%<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Remove remaining white outlines and extend token coverage across all components and states.</li></ul></li><li>Better logo and media handling<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Ensure logos with baked white backgrounds and media in cards render correctly on dark surfaces.</li></ul></li><li>Broader automated checks<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Expand automated a11y checks to specifically test color contrast across both modes in common flows.</li></ul></li></ul><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">For developers: the gist</h4><ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Mode detection<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>theme_mode derives from branding color luminance and is stored with the branding set.</li></ul></li><li>Activation<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>We scope styles under body.tk-branding and toggle .dark to switch to dark variables. Tokens use color‑mix for borders and surfaces to maintain subtle depth in both modes.</li></ul></li><li>Why variables<ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Root variables guarantee consistent theming for portals and embedded UIs—no more one‑off overrides that miss overlays or menus.</li></ul></li></ul><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">Rollout status</h4><ul class="my-5 ml-6 list-disc space-y-2 text-body-l text-neutral-08 marker:text-neutral-05"><li>Enabled and merged; light‑mode customers should see negligible visual changes. Dark‑mode branding sets look great overall; we&#x27;re closing remaining visual gaps before calling it &quot;done.&quot;</li></ul><h4 class="mt-10 mb-2 text-cms-h3 font-display text-neutral-10">Thank you</h4><p class="my-5 text-body-l text-neutral-08">Huge thanks to Stephen and Danny for the late‑night push and reviews. Customer feedback from Orchid&#x27;s team was essential in shaping this rollout.</p>]]></content:encoded>
    </item>
  </channel>
</rss>
