<?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"><channel><title><![CDATA[The Real Stack]]></title><description><![CDATA[This blog is about the stack that I use which is TanStack Start, Directus, Tailwindcss v4, Shadcn, Zustand and Coolify.]]></description><link>https://blog.northernrangedigital.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>The Real Stack</title><link>https://blog.northernrangedigital.com</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 14 May 2026 15:49:05 GMT</lastBuildDate><atom:link href="https://blog.northernrangedigital.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[ What is Coolify and Why Would You Use It? ]]></title><description><![CDATA[webdev

devops

selfhosted

coolify

vps

docker

opensource




🎬 This article is a companion to my YouTube video. Watch it here:

https://www.youtube.com/watch?v=oFmJYMk1iCg


Introduction
In the l]]></description><link>https://blog.northernrangedigital.com/what-is-coolify-and-why-would-you-use-it</link><guid isPermaLink="true">https://blog.northernrangedigital.com/what-is-coolify-and-why-would-you-use-it</guid><dc:creator><![CDATA[Wade Thomas]]></dc:creator><pubDate>Thu, 14 May 2026 03:46:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69cb0eea9fffa74740a240a6/145a1ad9-02ee-4acb-a1f7-8b9d872f0dc0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ul>
<li><p>webdev</p>
</li>
<li><p>devops</p>
</li>
<li><p>selfhosted</p>
</li>
<li><p>coolify</p>
</li>
<li><p>vps</p>
</li>
<li><p>docker</p>
</li>
<li><p>opensource</p>
</li>
</ul>
<hr />
<blockquote>
<p>🎬 This article is a companion to my YouTube video. Watch it here:</p>
</blockquote>
<p><a class="embed-card" href="https://www.youtube.com/watch?v=oFmJYMk1iCg">https://www.youtube.com/watch?v=oFmJYMk1iCg</a></p>

<hr />
<h2>Introduction</h2>
<p>In the last video, we talked about the VPS and why it is a compelling option for hosting your web applications. I mentioned a tool called Coolify that makes managing a VPS significantly easier. In this video, we are going to dive deeper into what Coolify actually is, what it does, and why I think it is one of the best tools available for developers and small teams who want the power of a VPS without the complexity of managing one from scratch.</p>
<hr />
<h2>What is Coolify?</h2>
<p>Coolify is a free, open-source, self-hostable platform as a service — or PaaS. Think of it as your own personal Heroku or Render, but running on your own server. This means you own your infrastructure, your data, and your costs.</p>
<p>The best way to understand Coolify is to compare it to the alternatives. Platforms like Heroku, Render, and Railway are fully managed PaaS solutions. They abstract away all the server complexity — you push your code and it runs. The trade-off is cost and control. As your app scales, the bills grow quickly and you have limited control over the underlying infrastructure.</p>
<p>Coolify gives you the same developer experience — push your code and it deploys — but on a VPS that you control. You get the simplicity of a managed platform with the economics and control of a VPS.</p>
<hr />
<h2>What Does Coolify Do?</h2>
<h3>Git Integration</h3>
<p>Connect your GitHub, GitLab, or Bitbucket repository and Coolify will automatically deploy your app every time you push to your main branch. No manual deployments, no SSH commands — just push your code and it is live.</p>
<h3>Dockerized Deployments</h3>
<p>Every application Coolify deploys runs in a Docker container. This means your apps are isolated, portable, and consistent across environments. You do not need to know Docker deeply to use Coolify — it handles the containerization for you.</p>
<h3>Automatic HTTPS</h3>
<p>Coolify integrates with Let's Encrypt to automatically provision and renew SSL certificates for all your applications. Every app gets HTTPS out of the box with zero configuration on your part.</p>
<h3>Built-in Reverse Proxy</h3>
<p>Coolify uses Traefik as its built-in reverse proxy and web server. It automatically routes traffic to the right application based on the domain name. You can run multiple applications on the same VPS and Coolify handles the routing between them.</p>
<h3>Database Management</h3>
<p>Coolify can deploy and manage databases alongside your applications — PostgreSQL, MySQL, MongoDB, Redis and more. You can spin up a database with a few clicks and connect it to your application without any manual configuration.</p>
<h3>Environment Variables</h3>
<p>Manage your environment variables securely through the Coolify dashboard. No more manually editing .env files on the server.</p>
<h3>Monitoring and Logs</h3>
<p>Coolify provides basic monitoring and real-time log streaming for all your applications directly from the dashboard. You can see what your app is doing without SSH-ing into the server.</p>
<h3>Backups</h3>
<p>Coolify supports automated database backups to S3-compatible storage. Your data is protected without any manual backup scripts.</p>
<hr />
<h2>Why Would You Use Coolify?</h2>
<h3>You want the economics of a VPS without the complexity</h3>
<p>A \(6 to \)10 per month VPS with Coolify can run multiple applications that would cost hundreds of dollars per month on Heroku, Render, or Railway. For a startup or indie developer this is a significant saving.</p>
<h3>You want full control over your infrastructure</h3>
<p>With Coolify you own everything. Your data stays on your server. You choose your hosting provider. You are not locked into any platform's pricing or terms of service.</p>
<h3>You want a great developer experience</h3>
<p>Coolify's dashboard is clean and intuitive. Deploying an application is genuinely just a few clicks. It does not feel like managing a server — it feels like using a modern PaaS.</p>
<h3>You are running multiple projects</h3>
<p>One VPS with Coolify can host multiple applications, multiple databases, and multiple domains. Instead of paying for separate hosting for each project, you consolidate everything onto one server.</p>
<hr />
<h2>What Are the Limitations?</h2>
<ul>
<li><p><strong>You are responsible for your server</strong> — if your VPS goes down, your apps go down.</p>
</li>
<li><p><strong>Some configuration is still required</strong> — especially for custom setups, firewalls, and advanced networking.</p>
</li>
<li><p><strong>It is self-hosted</strong> — meaning you need to keep Coolify itself updated and maintained.</p>
</li>
<li><p><strong>Not ideal for very large scale</strong> — for enterprise applications with massive traffic you may need dedicated infrastructure beyond a single VPS.</p>
</li>
</ul>
<hr />
<h2>How Do You Get Started?</h2>
<p>Getting Coolify up and running is surprisingly straightforward. In the next video I will walk you through the complete setup — from provisioning a VPS to having Coolify installed and your first application deployed.</p>
<p>All you need to get started is:</p>
<ul>
<li><p>A VPS with at least <strong>2GB RAM</strong> and <strong>2 CPU cores</strong></p>
</li>
<li><p>A domain name</p>
</li>
<li><p>About 30 minutes of your time</p>
</li>
</ul>
<hr />
<h2>Conclusion</h2>
<p>Coolify bridges the gap between the simplicity of managed platforms and the power and economics of a VPS. For developers and small teams who want to own their infrastructure without being overwhelmed by server management, it is genuinely one of the best tools available right now.</p>
<p>In the next video we will get our hands dirty and set up Coolify from scratch. See you there.</p>
<hr />
<h2>References</h2>
<ul>
<li><p><a href="https://coolify.io/">Coolify Website</a></p>
</li>
<li><p><a href="https://coolify.io/docs">Coolify Documentation</a></p>
</li>
<li><p><a href="https://github.com/coollabsio/coolify">Coolify GitHub</a></p>
</li>
</ul>
<hr />
<p>🔔 <em>Subscribe to my YouTube channel for the full series on building a modern web app back end from scratch.</em></p>
]]></content:encoded></item><item><title><![CDATA[Back-End Web Development — VPS vs Vercel vs Netlify subtitle: The tools I use to power my web applications and why I chose them.]]></title><description><![CDATA[🎬 This article is a companion to my YouTube video. Watch it here:

https://www.youtube.com/watch?v=jxMMyRrWcyk


Introduction
Every great web application with millions of users has an even greater ba]]></description><link>https://blog.northernrangedigital.com/back-end-web-development-vps-vs-vercel-vs-netlify-subtitle-the-tools-i-use-to-power-my-web-applications-and-why-i-chose-them</link><guid isPermaLink="true">https://blog.northernrangedigital.com/back-end-web-development-vps-vs-vercel-vs-netlify-subtitle-the-tools-i-use-to-power-my-web-applications-and-why-i-chose-them</guid><dc:creator><![CDATA[Wade Thomas]]></dc:creator><pubDate>Tue, 12 May 2026 01:16:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69cb0eea9fffa74740a240a6/4f3518c6-fa54-4c05-b1d4-1ff922b6a7ac.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<hr />
<blockquote>
<p>🎬 This article is a companion to my YouTube video. Watch it here:</p>
</blockquote>
<p><a class="embed-card" href="https://www.youtube.com/watch?v=jxMMyRrWcyk">https://www.youtube.com/watch?v=jxMMyRrWcyk</a></p>

<hr />
<h2>Introduction</h2>
<p>Every great web application with millions of users has an even greater back end — and it has to be. Accessing your app over a prolonged period of time will test the integrity, availability, and speed of your back end. Backend technology can be inexpensive, or it can cost you thousands of dollars. So what's the deal here?</p>
<p>Let me warn you that this channel is highly opinionated. I am sharing the tools that I use and how I use them.</p>
<p>For my back end that powers my web apps, I use <strong>Directus</strong> for my headless CMS, supported by a <strong>PostgreSQL</strong> and <strong>Redis</strong> database, hosted on a <strong>VPS</strong>, and managed by <strong>Coolify</strong>. Wow, that is a mouthful — and in this series we will explore how they all work together.</p>
<p>So let's tackle each technology one at a time, starting with the VPS.</p>
<hr />
<h2>What is a VPS?</h2>
<p>A Virtual Private Server, known as a VPS, is a virtual environment created on a physical server. Think of it like an apartment building — everyone shares the same physical structure, but each unit has its own private space, utilities, and security.</p>
<p>While multiple VPS instances share a physical server, be careful not to confuse this with shared hosting. Each VPS is allocated its own dedicated resources, which are restricted to that VPS for as long as it is active. Therefore, the performance of a VPS is not directly affected by the usage of other VPS instances, but rather by the underlying performance of the physical server itself.</p>
<hr />
<h2>What are the Benefits of a VPS?</h2>
<p>There are several benefits to consider when deciding on virtual private server hosting:</p>
<ul>
<li><p><strong>Greater control</strong> — Compared to minimum shared hosting, you have root access and can fully customize your server environment.</p>
</li>
<li><p><strong>Dedicated resources</strong> — Allocated CPU, memory, and storage help ensure consistent performance.</p>
</li>
<li><p><strong>Scalability</strong> — You can easily scale resources up or down to accommodate changing traffic and application demands.</p>
</li>
<li><p><strong>Cost-effectiveness</strong> — A VPS typically offers a balance between the affordability of shared hosting and the power of a dedicated server.</p>
</li>
<li><p><strong>Improved security</strong> — Isolation from other users on the same physical server enhances security.</p>
</li>
<li><p><strong>Choice of operating system</strong> — You can choose the operating system that best suits your needs, such as Linux or Windows.</p>
</li>
</ul>
<hr />
<h2>How Does it Stack Up Against Vercel or Netlify?</h2>
<h3>Vercel</h3>
<p>Vercel offers minimal setup with Git integration and fast deployment right out of the box. It has a free Hobby plan, but it is strictly for personal, non-commercial use. Once your app grows and needs to scale, you will need to move to a paid plan.</p>
<p>The Pro plan starts at <strong>$20 per user per month</strong>, and also covers serverless functions. Despite the name, serverless code still runs on a physical server — however, the infrastructure management, such as scaling, security patching, and provisioning, is handled entirely by the cloud provider.</p>
<p>The main factor to watch carefully is cost. Vercel uses usage-based billing, and costs can escalate quickly — especially since Turbo build machines became the default for new Pro projects in February 2026, at <strong>\(0.126 per build minute</strong>. A moderate team workflow can generate over <strong>\)400 per month</strong> in build costs alone, before bandwidth and compute charges. I have seen some alarming Vercel bills shared online by customers, which means you need to fully understand the pricing model before you commit.</p>
<h3>Netlify</h3>
<p>Netlify has historically been more suited to static sites and composable web applications. Composable applications are software systems built from independent, interchangeable modules rather than a single rigid codebase. Netlify also has Git integration, customizable build plugins, and serverless functions.</p>
<p>Netlify moved to a credit-based pricing model in September 2025, designed to simplify metered billing. As of April 2026, the Pro plan costs <strong>\(20 per month</strong> and now includes unlimited team member seats, which is an improvement over the previous per-seat model. However, teams working on active projects with real traffic can burn through their credit allocation quickly, and credit pack add-ons at <strong>\)10 per 1,500 credits</strong> mean teams can regularly spend \(40 to \)80 or more per month beyond the base subscription. Your overall control is also more limited compared to a VPS, and you will still face a monthly cost as your app grows.</p>
<h3>The VPS</h3>
<p>VPS prices can grow as your app grows, but in my experience at a slower and more predictable rate — with no surprise charges. However, if you manage a VPS yourself, it requires understanding web servers, firewalls, operating systems, caching, and more. It can get complex very quickly and may cause you to spend more time managing the server than building and scaling your app.</p>
<p>That is why some developers and business owners hire a team to handle it. Small teams may not have the budget for a dedicated infrastructure team, so they often opt for a more convenient managed solution.</p>
<hr />
<h2>Coolify — The Game Changer</h2>
<p>There is one tool that I think is worth mentioning and is a genuine game changer — and that is <strong>Coolify</strong>.</p>
<p>Coolify is a self-hostable platform that makes managing your VPS significantly easier. It offers:</p>
<ul>
<li><p>✅ Git integration</p>
</li>
<li><p>✅ Dockerized container deployments</p>
</li>
<li><p>✅ Automatic HTTPS</p>
</li>
<li><p>✅ Built-in web server with no manual configuration required</p>
</li>
</ul>
<p>This makes the VPS a very real and competitive option worth considering. If you choose a solid hosting provider and pair it with the right tools, you can make this an absolute dream to work with.</p>
<p>Now don't get me wrong — even with Coolify there are some configurations you will have to make. But I do believe a VPS is a great solution for a startup, mid-size, or enterprise scaled app with the right tools.</p>
<hr />
<h2>Conclusion</h2>
<p>Stay with me in this series and we will definitely explore the possibilities. See you in the next video.</p>
<hr />
<h2>References</h2>
<ul>
<li><p><a href="https://cloud.google.com/learn/what-is-a-virtual-private-server">Google Cloud — What is a VPS</a></p>
</li>
<li><p><a href="https://aws.amazon.com/what-is/vps/">AWS — What is a VPS</a></p>
</li>
<li><p><a href="https://www.ibm.com/think/topics/vps">IBM — VPS</a></p>
</li>
<li><p><a href="https://www.scalahosting.com/blog/what-is-a-vps-technical-explanation/">Scala Hosting — VPS Explained</a></p>
</li>
<li><p><a href="https://www.dreamhost.com/blog/beginners-guide-vps/">DreamHost — Beginner's Guide to VPS</a></p>
</li>
<li><p><a href="https://vercel.com/pricing">Vercel Pricing</a></p>
</li>
<li><p><a href="https://www.netlify.com/pricing/">Netlify Pricing</a></p>
</li>
<li><p><a href="https://bejamas.com/blog/self-hosting-vs-vercel-and-netlify-which-solution-is-right">Bejamas — Self Hosting vs Vercel and Netlify</a></p>
</li>
</ul>
<hr />
<p><em>🔔 Subscribe to my YouTube channel for the full series on building a modern web app back end from scratch.</em></p>
]]></content:encoded></item><item><title><![CDATA[Connecting TanStack Start to Directus with the SDK ]]></title><description><![CDATA[If you're using Directus as your headless CMS and TanStack Start for your frontend, you don't need to write manual fetch calls or build your own auth headers. The Directus SDK handles all of it cleanl]]></description><link>https://blog.northernrangedigital.com/connecting-tanstack-start-to-directus-with-the-sdk</link><guid isPermaLink="true">https://blog.northernrangedigital.com/connecting-tanstack-start-to-directus-with-the-sdk</guid><category><![CDATA[tanstack]]></category><category><![CDATA[Directus-sdk]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Wade Thomas]]></dc:creator><pubDate>Tue, 31 Mar 2026 01:54:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69cb0eea9fffa74740a240a6/0aa7460a-a3d3-4a32-9b54-1d95133c9ea4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you're using Directus as your headless CMS and TanStack Start for your frontend, you don't need to write manual fetch calls or build your own auth headers. The Directus SDK handles all of it cleanly.</p>
<p>Here's how I structure a single <code>directus.ts</code> file that covers authentication, typed data fetching, filtering, CRUD operations and file uploads.</p>
<h2>Installing the SDK</h2>
<pre><code class="language-bash">npm install @directus/sdk
</code></pre>
<h2>Setting Up the Client</h2>
<p>Create the client once and export it. Passing your schema type as a generic is what unlocks end-to-end type safety across every request.</p>
<pre><code class="language-typescript">import type { Product, Navigation, CartItem, Order } from '@/types';
import {
  authentication,
  createDirectus,
  rest,
  readItems,
  createItem,
  updateItem,
  deleteItem,
  readMe,
  updateMe,
  deleteUser,
  uploadFiles,
  registerUser as registerUserDirectus,
} from '@directus/sdk';

const directusUrl =
  import.meta.env.VITE_DIRECTUS_URL ??
  process.env.VITE_DIRECTUS_URL ??
  'https://your-directus-url.com';

const directus = createDirectus(directusUrl)
  .with(authentication('session', { credentials: 'include' }))
  .with(rest({ credentials: 'include' }));
</code></pre>
<p>Using <code>authentication('session')</code> with <code>credentials: 'include'</code> means cookies are handled automatically — no manual token management needed.</p>
<h2>Fetching Data with Full Type Safety</h2>
<p>Each collection gets its own exported async function with a typed return value.</p>
<pre><code class="language-typescript">export async function getProducts(): Promise&lt;Product[]&gt; {
  const items = await directus.request(readItems('products'));
  return items as Product[];
}
</code></pre>
<h2>Filtering is First-Class</h2>
<p>The SDK's filter syntax maps directly to Directus's query engine — no raw query strings, no URL building.</p>
<pre><code class="language-typescript">export async function getProductsByCategory(
  category: string
): Promise&lt;Product[]&gt; {
  const items = await directus.request(
    readItems('products', {
      filter: { category: { _eq: category } },
    })
  );
  return items as Product[];
}
</code></pre>
<h2>What Else is Covered</h2>
<p>The same client and pattern covers the full CRUD surface:</p>
<ul>
<li><p><code>readItems</code> — fetch collections</p>
</li>
<li><p><code>createItem</code> — insert records</p>
</li>
<li><p><code>updateItem</code> — update records</p>
</li>
<li><p><code>deleteItem</code> — delete records</p>
</li>
<li><p><code>uploadFiles</code> — handle file uploads</p>
</li>
<li><p><code>readMe</code> / <code>updateMe</code> / <code>deleteUser</code> — user profile management</p>
</li>
<li><p><code>registerUser</code> — user registration</p>
</li>
</ul>
<p>All importable directly from <code>@directus/sdk</code> — the SDK provides typed functions and you bring your own collection types for end-to-end type safety.</p>
<h2>Using it in a TanStack Start Loader</h2>
<p>TanStack Start's file-based routing and loader pattern pairs perfectly with this setup. Data is fetched server-side and ready before the component renders.</p>
<pre><code class="language-typescript">export const Route = createFileRoute('/products')({
  loader: () =&gt; getProducts()
});
</code></pre>
<p>No boilerplate, no custom wrappers, no type assertions. One file, full coverage.</p>
<hr />
<p>If you're evaluating Directus as a headless CMS for a TanStack Start project this setup gets you up and running quickly with a clean, maintainable data layer from day one.</p>
]]></content:encoded></item><item><title><![CDATA[Why I Chose Directus as My Backend]]></title><description><![CDATA[When I started building the Demo Store — a full stack e-commerce app with TanStack Start — I needed a backend that could handle data, authentication, file storage, and an admin interface without stitc]]></description><link>https://blog.northernrangedigital.com/why-i-chose-directus-as-my-backend</link><guid isPermaLink="true">https://blog.northernrangedigital.com/why-i-chose-directus-as-my-backend</guid><category><![CDATA[directus]]></category><category><![CDATA[Docker compose]]></category><dc:creator><![CDATA[Wade Thomas]]></dc:creator><pubDate>Tue, 31 Mar 2026 01:44:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69cb0eea9fffa74740a240a6/2c088656-5985-46b6-97a8-69780af38e4d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I started building the <a href="https://demostore.northernrangedigital.com">Demo Store</a> — a full stack e-commerce app with TanStack Start — I needed a backend that could handle data, authentication, file storage, and an admin interface without stitching together multiple services.</p>
<p>Directus ticked every box. Here's why I chose it, how I set it up, and what it looks like in practice.</p>
<h2>How Directus Compares to Other CMS Options</h2>
<p>There are plenty of headless CMS options out there. Here's how Directus stands out:</p>
<table>
<thead>
<tr>
<th></th>
<th>Directus</th>
<th>Strapi</th>
<th>Contentful</th>
<th>Sanity</th>
</tr>
</thead>
<tbody><tr>
<td>Self-hostable</td>
<td>✅</td>
<td>✅</td>
<td>❌</td>
<td>❌</td>
</tr>
<tr>
<td>Free to use</td>
<td>✅ under $5M revenue</td>
<td>✅ open source</td>
<td>❌ paid tiers</td>
<td>❌ paid tiers</td>
</tr>
<tr>
<td>SQL DB support</td>
<td>✅ any existing SQL DB</td>
<td>✅ PostgreSQL, MySQL, MariaDB, SQLite</td>
<td>❌</td>
<td>❌</td>
</tr>
<tr>
<td>Built-in auth</td>
<td>✅</td>
<td>✅</td>
<td>❌</td>
<td>❌</td>
</tr>
<tr>
<td>REST + GraphQL</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
</tr>
<tr>
<td>Admin dashboard</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
</tr>
</tbody></table>
<p>Strapi is a strong alternative and supports multiple SQL databases too. The key difference for me was that Directus connects directly to <strong>any existing database</strong> — you point it at a database you already have and it works. There's no schema migration system to manage and no framework-specific setup. Contentful and Sanity are cloud-only, which means you don't own your data and you're subject to their pricing as you scale.</p>
<h2>Setting Up Directus with Docker Compose</h2>
<p>I run Directus on a VPS managed by Coolify. The entire setup lives in a single Docker Compose file. Here's the full config I use for the demo store:</p>
<pre><code class="language-yaml">services:
  directus:
    image: 'directus/directus:11.15.4'
    ports:
      - '8055:8055'
    volumes:
      - './uploads:/directus/uploads'
      - './extensions:/directus/extensions'
    environment:
      SECRET: '${SECRET}'
      MARKETPLACE_TRUST: all

      # Database
      DB_CLIENT: pg
      DB_HOST: '${DB_HOST}'
      DB_PORT: '5432'
      DB_DATABASE: '${DB_DATABASE}'
      DB_USER: '${DB_USER}'
      DB_PASSWORD: '${DB_PASSWORD}'

      # Redis Cache
      CACHE_ENABLED: 'false'
      CACHE_AUTO_PURGE: 'true'
      CACHE_STORE: redis
      REDIS: '${REDIS_URL}'

      # CORS
      CORS_ENABLED: 'true'
      CORS_ORIGIN: '${CORS_ORIGIN}'
      CORS_CREDENTIALS: 'true'

      # Email via Resend SMTP
      EMAIL_TRANSPORT: smtp
      EMAIL_SMTP_HOST: smtp.resend.com
      EMAIL_SMTP_PORT: 465
      EMAIL_SMTP_USER: resend
      EMAIL_SMTP_PASSWORD: '${EMAIL_SMTP_PASSWORD}'
      EMAIL_SMTP_SECURE: 'true'
      EMAIL_FROM: contact@yourdomain.com

      # Auth
      USER_REGISTER_REQUIRE_EMAIL_VERIFICATION: 'true'
      USER_REGISTER_URL_ALLOW_LIST: '${USER_REGISTER_URL_ALLOW_LIST}'
      PASSWORD_RESET_URL_ALLOW_LIST: '${PASSWORD_RESET_URL_ALLOW_LIST}'

      # Google OAuth
      AUTH_PROVIDERS: google
      AUTH_GOOGLE_DRIVER: openid
      AUTH_GOOGLE_ISSUER_URL: 'https://accounts.google.com'
      AUTH_GOOGLE_CLIENT_ID: '${AUTH_GOOGLE_CLIENT_ID}'
      AUTH_GOOGLE_CLIENT_SECRET: '${AUTH_GOOGLE_CLIENT_SECRET}'
      AUTH_GOOGLE_IDENTIFIER_KEY: email
      AUTH_GOOGLE_ALLOW_PUBLIC_REGISTRATION: 'true'
      AUTH_GOOGLE_DEFAULT_ROLE_ID: '${AUTH_GOOGLE_DEFAULT_ROLE_ID}'
      AUTH_GOOGLE_REDIRECT_ALLOW_LIST: '${AUTH_GOOGLE_REDIRECT_ALLOW_LIST}'
      AUTH_GOOGLE_MODE: session

      # Session &amp; Cookies
      SESSION_COOKIE_SECURE: 'true'
      SESSION_COOKIE_SAME_SITE: lax
      REFRESH_TOKEN_COOKIE_SECURE: 'true'
      REFRESH_TOKEN_COOKIE_SAME_SITE: lax

      # Extensions
      EXTENSIONS_AUTO_RELOAD: 'true'
      EXTENSIONS_PATH: /directus/extensions
</code></pre>
<p>A few things worth noting:</p>
<ul>
<li><p><strong>PostgreSQL</strong> is the database — <code>DB_CLIENT: pg</code> tells Directus to use it</p>
</li>
<li><p><strong>Resend</strong> handles all transactional email via SMTP — verification emails, password resets</p>
</li>
<li><p><strong>Google OAuth</strong> is configured via OpenID Connect — users can register and log in with their Google account</p>
</li>
<li><p><strong>Session cookies</strong> are secure and SameSite lax — works cleanly with TanStack Start on a separate domain</p>
</li>
<li><p>All sensitive values are environment variables — never hardcoded</p>
</li>
</ul>
<blockquote>
<p><strong>Note:</strong> In my setup PostgreSQL runs as a separate service managed independently by Coolify — that's why it's not included in this Compose file. If you prefer to keep everything together, you can add PostgreSQL directly to the same file:</p>
</blockquote>
<pre><code class="language-yaml">  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: '${DB_DATABASE}'
      POSTGRES_USER: '${DB_USER}'
      POSTGRES_PASSWORD: '${DB_PASSWORD}'
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:
</code></pre>
<p>Then set <code>DB_HOST</code> to <code>postgres</code> in your Directus environment variables to point it at the service name. Either approach works — separate or combined is a matter of preference.</p>
<h2>The Admin Dashboard and Collections</h2>
<p>Once Directus is running, you access the admin dashboard at your Directus URL. This is where you build your data model visually.</p>
<p>For the demo store I created the following collections:</p>
<ul>
<li><p><strong>products</strong> — name, description (WYSIWYG), price, sale price, category, images, slug</p>
</li>
<li><p><strong>categories</strong> — name, slug, description</p>
</li>
<li><p><strong>orders</strong> — user, items, total, status</p>
</li>
<li><p><strong>order_items</strong> — order, product, quantity, price</p>
</li>
<li><p><strong>navigation</strong> — links and structure for the site nav</p>
</li>
</ul>
<p>Each collection maps directly to a PostgreSQL table. Directus generates the REST and GraphQL API automatically. No boilerplate, no migrations to write by hand.</p>
<p>The WYSIWYG editor on the <code>description</code> field outputs HTML — I cover how to render that safely in React in a later post in this series.</p>
<h2>Roles and Permissions</h2>
<p>This is where Directus really shines for production apps. Every collection and field can have granular permissions set per role.</p>
<p>For the demo store I set up three roles:</p>
<p><strong>Public</strong> — unauthenticated visitors</p>
<ul>
<li><p>Can read <code>products</code>, <code>categories</code>, <code>navigation</code></p>
</li>
<li><p>Cannot read <code>orders</code>, <code>order_items</code>, or any user data</p>
</li>
</ul>
<p><strong>Authenticated User</strong> — logged in customers</p>
<ul>
<li><p>Can read all public collections</p>
</li>
<li><p>Can read and create their own <code>orders</code> and <code>order_items</code></p>
</li>
<li><p>Can read and update their own user profile</p>
</li>
<li><p>Cannot read other users' data</p>
</li>
</ul>
<p><strong>Admin</strong> — full access</p>
<ul>
<li><p>Full CRUD on all collections</p>
</li>
<li><p>Access to the Directus admin dashboard</p>
</li>
</ul>
<p>The permissions are configured in the Directus admin panel under <strong>Settings → Roles &amp; Permissions</strong>. You set them visually — no code required. Each role gets a matrix of read, create, update, delete permissions per collection, and you can even restrict access to specific fields within a collection.</p>
<h2>What Directus Handles For the Demo Store</h2>
<ul>
<li><p>✅ All product and category data via REST API</p>
</li>
<li><p>✅ User registration with email verification</p>
</li>
<li><p>✅ Login with email/password and Google OAuth</p>
</li>
<li><p>✅ Password reset via email</p>
</li>
<li><p>✅ Order management</p>
</li>
<li><p>✅ File and image storage and serving</p>
</li>
<li><p>✅ Role-based access control</p>
</li>
<li><p>✅ Admin dashboard for managing all content</p>
</li>
</ul>
<p>All from a single self-hosted instance running on a $20/month VPS.</p>
<hr />
<p>In the next post I'll cover how I connect TanStack Start to Directus using the SDK — setting up the client, typed data fetching, and filtering collections.</p>
<p>➡️ <a href="https://blog.northernrangedigital.com/connecting-tanstack-start-to-directus-with-the-sdk">Next: Connecting TanStack Start to Directus with the SDK</a></p>
]]></content:encoded></item><item><title><![CDATA[Building a Full Stack E-Commerce App with TanStack Start and Directus ]]></title><description><![CDATA[I built a full stack e-commerce demo store — products, categories, cart sync, user authentication, email verification, protected routes, rich text content, and a complete admin dashboard to manage it ]]></description><link>https://blog.northernrangedigital.com/building-a-full-stack-e-commerce-app-with-tanstack-start-and-directus</link><guid isPermaLink="true">https://blog.northernrangedigital.com/building-a-full-stack-e-commerce-app-with-tanstack-start-and-directus</guid><category><![CDATA[tanstack]]></category><category><![CDATA[directus]]></category><category><![CDATA[shadcn]]></category><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[Zustand store]]></category><category><![CDATA[coolify vps hosting]]></category><dc:creator><![CDATA[Wade Thomas]]></dc:creator><pubDate>Tue, 31 Mar 2026 01:28:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69cb0eea9fffa74740a240a6/f7c98980-de3c-496b-ad6a-3b1ffc62f9ec.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I built a full stack e-commerce demo store — products, categories, cart sync, user authentication, email verification, protected routes, rich text content, and a complete admin dashboard to manage it all.</p>
<p>The live demo is at <a href="https://demostore.northernrangedigital.com">demostore.northernrangedigital.com</a>.</p>
<p>This series documents the entire stack I used to build it, the decisions I made along the way, and the patterns I've settled on for building full stack apps. Everything is grounded in real code from a real project.</p>
<h2>The Stack</h2>
<ul>
<li><p><strong>TanStack Start</strong> — full stack React framework with file-based routing, SSR, loaders and type-safe navigation</p>
</li>
<li><p><strong>Directus</strong> — headless CMS and backend, self-hosted on a VPS, handling data, auth, file storage and the admin dashboard</p>
</li>
<li><p><strong>PostgreSQL</strong> — the database underneath Directus</p>
</li>
<li><p><strong>Tailwind CSS v4</strong> — styling, with the Typography plugin for rich text rendering</p>
</li>
<li><p><strong>Shadcn UI</strong> — component library built on top of Tailwind</p>
</li>
<li><p><strong>Zustand</strong> — client-side state management for auth and cart</p>
</li>
<li><p><strong>Coolify</strong> — self-hosted deployment platform managing the frontend, Directus and PostgreSQL via Docker Compose</p>
</li>
<li><p><strong>Resend</strong> — email delivery for verification and password reset, configured via SMTP in Docker Compose</p>
</li>
</ul>
<h2>Why This Stack</h2>
<p>I wanted a setup that was flexible, cost-effective, and production-ready without stitching together five different paid services. Everything runs on a single VPS for around $20/month — Directus handles the backend, authentication, file storage and admin UI all in one place, and Coolify handles deployments automatically when I push code.</p>
<p>The result is a full stack that scales from a weekend project to a production app without changing tools or blowing up the infrastructure bill.</p>
<h2>What This Series Covers</h2>
<p>Each post in this series covers a specific part of the stack with real code from the demo store:</p>
<ol>
<li><p><strong>Why I chose Directus as my backend</strong> — what it offers, how it's licensed, and when it's the right fit</p>
</li>
<li><p><strong>Connecting TanStack Start to Directus with the SDK</strong> — setting up the client, typed data fetching, filtering</p>
</li>
<li><p><strong>Metadata, data loading and loading skeletons in TanStack Start</strong> — head, loader and pendingComponent</p>
</li>
<li><p><strong>Protecting routes with Zustand</strong> — auth store, hydration, layout route guards</p>
</li>
<li><p><strong>Directus auth out of the box</strong> — registration, login, email verification and password reset</p>
</li>
<li><p><strong>Rendering rich text safely</strong> — DOMPurify, html-react-parser and Tailwind Typography</p>
</li>
</ol>
<hr />
<p>If you're evaluating TanStack Start, Directus, or this kind of self-hosted setup for your next project, this series is built for you. Every post includes real code, real decisions, and honest tradeoffs.</p>
<p>Let's build.</p>
]]></content:encoded></item></channel></rss>