/////
09/06/20268 min read

The Technology Behind TechEnvolved

Engineering workspace representing our technology stack

Our Stack

  • Core Next.js 16 with App Router and Server Components
  • Styles Tailwind CSS v4
  • Deploy Vercel Edge Network
  • Data Supabase (Postgres)

Every technology choice is a trade-off. Choosing a tool because it is popular or because a tutorial used it is how codebases accumulate unnecessary complexity. Our stack is small by design: each piece earns its place by solving a specific problem well, and nothing more.

// Core_Engine: Next.js 16

The platform runs on Next.js 16. We chose it because of Server Components and the App Router, not because it is the framework everyone recommends.

The reasoning is straightforward. Most of what a content site delivers is static: article text, navigation, metadata. Sending JavaScript to the browser to render that content on the client wastes time and bandwidth. With Server Components, the heavy lifting stays on the server. The browser receives finished HTML. JavaScript is sent only for the parts of the page that actually need it.

The practical result is a fast first load and good Core Web Vitals scores without manual optimization. Search crawlers see the full content immediately, which simplifies SEO. The architecture also makes the codebase easier to reason about: data fetching happens close to where data is used, without prop drilling or global state management for things that could just be server-side queries.

We do not use the Pages Router. We do not use getStaticProps or getServerSideProps. The App Router with async Server Components covers everything we need more cleanly.

// Visual_Framework: Tailwind CSS

Our visual design follows one rule: the interface should not compete with the content. Dark background, high-contrast typography, minimal decoration. The goal is that reading an article here feels like reading in a text editor, not like browsing a marketing site.

Tailwind CSS fits this because it generates only the CSS that is actually used. There is no global stylesheet to audit, no specificity conflicts to resolve, no dead rules accumulating over time. Adding a new component does not require opening a separate CSS file. Removing one does not leave orphaned styles.

The design language we built on top of it has a few consistent choices. Borders are thin and low-opacity, used for structure rather than decoration. The background color is near-black rather than pure black, which reduces eye strain on long reads. Accent color is teal, used sparingly for active states and callouts. Typography is set in Geist, which reads cleanly at both small and large sizes.

The glassmorphism effect used in the header and some cards (background blur plus a subtle border) is intentional. It signals depth without adding visual noise. We use it only where the UI needs to float above content, not as a general decorative pattern.

// Deployment_Node: Vercel Edge Network

The site deploys to Vercel. The reason is not convenience, though it is convenient. The reason is edge infrastructure.

A server in one datacenter responds slowly to users on the other side of the world. Vercel's edge network runs the application code in datacenters distributed globally. A user in Bangkok gets a response from a node close to Bangkok. A user in London gets a response from a node close to London. The physical distance between user and server has a direct impact on latency, and this architecture minimizes it.

For a site with readers in multiple regions, this matters. Our audience includes users in Southeast Asia, Russia, Japan, and Europe. A single-region deployment would mean noticeably slower load times for most of them.

Deployment is automated: pushing to the main branch runs a build and deploys it. Previews are generated for every pull request. There is no deploy script to run manually, no server to SSH into.

// Data_Layer: Supabase

Dynamic content (blog posts published through the admin interface, comments, user data) lives in Supabase, which is a Postgres database with a REST API and real-time subscriptions built on top.

We use it because we wanted a hosted Postgres instance without managing infrastructure, and because the JavaScript client library is straightforward. The row-level security system handles authorization at the database level, which keeps the application code cleaner. We do not write custom middleware to check ownership of records.

Static content (the articles on this site, the structured pages) is stored in the codebase rather than the database. That content deploys with the site, loads instantly from the server, and requires no database query. The database is reserved for content that genuinely changes at runtime.

What We Decided Against

We evaluated and rejected several tools during the planning phase. A few worth noting:

A CMS like Contentful or Sanity. We looked at headless CMS platforms but found the abstraction unnecessary for our content structure. Articles are stored as code, which gives us full control over rendering and structure without an external dependency.

A CSS-in-JS library. We tried styled-components in an earlier version and found that the runtime cost and added build complexity were not worth it. Tailwind is faster to work with and produces smaller bundles.

A separate state management library. We have no Redux, no Zustand, no Jotai. Server Components handle the data fetching. Client-side state is managed with useState and useContext where it exists, which is in a small number of places. Global state for a content site is usually a sign of incorrect architecture, not a requirement.

This document reflects the stack as of June 2026. Technology choices change as requirements evolve. We update this when something significant changes.

Comments

Join the discussion

đź’¬

No comments here yet.

Be the first to share your perspective.

Leave a comment

Insights are welcome. Submissions are reviewed before publishing.