DEV Community

Cover image for The perfect Stack for building type-safe applications in 2025
Anmol Baranwal
Anmol Baranwal Subscriber

Posted on

The perfect Stack for building type-safe applications in 2025

Trying to pick the best tech stack in 2025 is very hard, especially with all the new frameworks that are getting released.

It's more than just type safety. You also need good performance, scalability, developer experience (DX) and decent community so you don't get stuck.

Today, we will learn why Next.js (frontend) and Encore.ts (backend) might just be the best full-stack combination for modern developers.

Let's jump in.


What is covered?

In a nutshell, we are covering these topics in detail.

  1. Why this tech stack is a solid choice.
  2. A step-by-step guide on how to get started with Next.js and Encore.
  3. Some real-world examples with source code.

Note: Encore is an open source backend framework for TypeScript and Go. In this guide, when I say Encore, I'm talking about the TypeScript version (Encore.ts).


1. Why this tech stack is a solid choice.

There are tons of awesome tech stacks out there and some of them are seriously impressive.

From what I’ve found, pairing Next.js for the frontend with Encore.ts for the backend is a winning combo.

In case you’re new to it, Encore is a backend framework and toolset that comes with a Rust runtime, API validation, integrated infrastructure, a developer dashboard and much more.

We will look at this stack through five main factors:

  • Type Safety
  • Performance
  • Developer Experience (DX)
  • Scalability
  • Extra benefits

⚡ Type Safety

Whenever you are building a production-level application, it's always better to be type-safe (even if you can work without it).

Encore has a built-in type validation and it's all done in a way, that it's fully declarative which allows it to automatically parse and validate the incoming requests. It makes sure that it matches the schema with no boilerplate.

In short, it validates stuff before it even hits that javascript layer.

Both Next.js (with TypeScript) and Encore.ts enforce static type checking, reducing runtime errors and making code easier to refactor. Encore.ts schema-first approach makes sure that API contracts remain consistent.

type-safe applications

Encore also makes your infrastructure type-aware and removes the need for connection strings or other boilerplate.

infrastructure

⚡ Performance

Next.js : With built-in features like server-side rendering (SSR), static site generation (SSG), automatic code splitting, image optimization, lazy loading, script optimization, cache, serverless functions, link optimization... (and much more), it's safe to say that performance is not a concerning factor while choosing Next.js as frontend.

There is a really nice blog on Optimizing Build Performance in Next.js by Turing.

Encore.ts : It has a very high-performance Rust runtime, achieving up to 9x the request throughput compared to Express.js and 2x compared to Fastify. It does this by providing multi-threading in Rust, and handling many operations like request validation in Rust instead of JavaScript.

As per benchmark code on GitHub, Encore.ts in terms of cold startup times, is over 5x faster than Express and 17x faster than NestJS.

encore performance benchmarks

⚡ Developer Experience

Next.js : It has a decent file system, built-in features like routing, automatic code splitting, hot module replacement and a rich plugin ecosystem, which makes DX a lot better.

Encore.ts : DX is one of the strong points in Encore, with built-in obserability (distributed tracing, metrics, logging) with a local dashboard, Automatic architecture diagrams (for a real-time overview), API Explorer (for testing your API endpoints), DevOps automation and reducing boilerplate.

developer experience

Plus deploying your application is also much easier, with as simple as pushing to a git repository, removing the need for manual steps.

deployment

⚡ Scalability

Next.js : It supports dynamic routing, and different rendering techniques like server-side rendering (SSR), static site generation (SSG), incremental static regeneration (ISR), making it useful for large, high-traffic web applications.

I was reading more about it and found an interesting article on How to Build Scalable Architecture for your Next.js Project.

Encore.ts : It improves the development of large-scale microservices applications by unifying your infrastructure with your application code and automating infrastructure provisioning and DevOps tasks.

Here's a code sample.

import { SQLDatabase } from "encore.dev/storage/sqldb";

// Create the todo database and assign it to the "db" variable
const db = new SQLDatabase("todo", {
  migrations: "./migrations",
});

// Then, query the database using db.query, db.exec, etc.
Enter fullscreen mode Exit fullscreen mode

It also provides a visual tool known as Flow that gives you an always up-to-date view of your entire system, helping you reason about your microservices architecture and identify which services depend on each other and how they work together.

encore flow visual tool

Encore.ts is cloud-agnostic by default, which means that it provides an abstraction layer over cloud provider APIs to prevent vendor lock-in. As your requirements evolve, you can adjust the provisioned infrastructure without changing your application code. That is insanely useful!

⚡ Extra benefits

Next.js : The detailed docs and active community support is the reason so many developers prefer working with Next.js It also has a lot of plugins, tutorials and resources available. You can check Awesome Next.js which has 10k+ stars on GitHub.

Encore.ts : Encore takes care of cloud infrastructure and DevOps for you. This allows developers to create production-ready backends quickly, using tools like microservices, Postgres, and Pub/Sub, all without the usual complexity and DevOps hassle.

encore working

 

There are more amazing things you can do, so please check Next.js docs and Encore.ts docs.

If you are very new to Encore, I highly recommend watching this official tutorial.


2. A step-by-step guide on how to get started with Next.js and Encore.

In this section, we will be talking about how to get started with Next.js and Encore.ts.

According to the official docs, you can use a starter template to set things up quickly. I’ve followed the same template and you can check it out if you are interested.

encore.ts next.js template

Step 1: Installing the Encore CLI

To develop locally with Encore, you first need to install the Encore CLI. This is what provisions your local development environment and runs your Local Development Dashboard complete with logs, tracing and API documentation.

You can use any of the following commands (Linux, Windows, macOS in order).

curl -L https://encore.dev/install.sh | bash
iwr https://encore.dev/install.ps1 | iex
brew install encoredev/tap/encore
Enter fullscreen mode Exit fullscreen mode

encore cli installed

They also provide ts_llm_instructions.txt, a set of pre-made instructions to help LLM powered tools like Cursor and GitHub Copilot to understand how to use Encore. It made things a lot easier whenever I had doubts while using Cursor.

Step 2: Clone the repo and create a new application.

First, clone the template repository using the following command.

git clone --depth=1 https://github.com/encoredev/nextjs-starter.git
Enter fullscreen mode Exit fullscreen mode

Then, navigate to the backend directory, install dependencies and create a new Encore application.

cd nextjs-starter/backend 
npm install # Install dependencies 
encore app init # Create a new Encore application.
Enter fullscreen mode Exit fullscreen mode

During setup, you will be prompted to sign up for a free cloud account. It's completely free so I recommend doing that. You will also need to select a version, I'm choosing TypeScript for this guide.

cloud deployments

Make sure you switch to the backend directory before running encore app init. I initially forgot so I had to do it again.

encore app init

Once the setup is complete, you will get the Application ID and Cloud Dashboard URL. Just note these as you will need them later.

Step 3: Run your Encore application.

Now, you need to start your encore application inside the backend directory using the command encore run.

encore run

Go to frontend/package.json and replace {{ENCORE_APP_ID}} with your actual Encore application ID. You can also find this ID in encore.app.

"gen": "encore gen client {{ENCORE_APP_ID}} --output=./app/lib/client.ts --env=local"
Enter fullscreen mode Exit fullscreen mode

Step 4: Generate a new request client

Navigate to the frontend directory, open a new terminal window and generate a new request client using this command.

npm run gen # Inside the frontend directory
Enter fullscreen mode Exit fullscreen mode

Running this command will generate the request client at (frontend/app/lib/client.ts) for your application. This enables communication between your frontend and backend.

Before proceeding, make sure the Encore app is running inside the backend directory. If not, you can restart it using encore run. Now, run the Next.js frontend as usual.

cd frontend 
npm install 
npm run dev
Enter fullscreen mode Exit fullscreen mode

Once it's running, open http://localhost:3000 in your browser to see your application in action.

encore frontend nextjs

Similarly, you can access http://localhost:9400 to view Encore's local developer dashboard. Here you can see API Explorer, Service Catalog, Infra, Flow (visual tool), Snippets and more.

encore local development dashboard

local infrastructure

local infrastructure

 

The local dashboard has small demos at the start so you won't get stuck for sure.

Make sure to keep the contract between the backend and frontend in sync by regenerating the request client whenever you make a change to an Encore endpoint.

It can be done by running npm run gen.

Step 5: Deploying the Backend with Encore Cloud.

I'm assuming you have a GitHub repo with the code changes.

Open your app in the Encore Cloud Dashboard.

encore cloud

Go to your app settings and set the Root Directory to backend. It's because the encore.app file is in the backend directory.

backend

In the integrations, connect your account to GitHub, which will open GitHub where you can grant access to the relevant repositories (s).

Once connected to GitHub, pushing code will trigger deployments automatically.

link app to github

link your app to github

link your app to github

 

You can read more about deploying applications with Encore Cloud on the docs.

confirmation message

confirmation message

 

You can track the deployment progress in the Cloud Dashboard. Once complete, your app will be live in the cloud! 🎉

successfully deployed

cloud deployed

Step 6: Deploying the Frontend with Vercel.

We will use Vercel for frontend deployment. Just create a new project on Vercel and point it to your GitHub repo.

In the project settings, set the root directory to frontend.

choosing frontend as root directory in vercel

Once deployed, your frontend should be live!

deployed frontend

Handling CORS Issues

Let's talk a little about CORS configuration too.

If you are running into CORS (Cross-Origin Resource Sharing) issues when calling your Encore API from your frontend then you may need to specify which origins are allowed to access your API (via browsers).

You do this by configuring the global_cors key in the encore.app file, which has the following structure:

global_cors: {
  // allow_origins_without_credentials specifies the allowed origins for requests
  // that don't include credentials. If nil it defaults to allowing all domains
  // (equivalent to ["*"]).
  "allow_origins_without_credentials": [
    "<ORIGIN-GOES-HERE>"
  ],

  // allow_origins_with_credentials specifies the allowed origins for requests
  // that include credentials. If a request is made from an Origin in this list
  // Encore responds with Access-Control-Allow-Origin: <Origin>.
  //
  // The URLs in this list may include wildcards (e.g. "https://*.example.com"
  // or "https://*-myapp.example.com").
  "allow_origins_with_credentials": [
    "<DOMAIN-GOES-HERE>"
  ]
}
Enter fullscreen mode Exit fullscreen mode

You can read the docs for more information on CORS configuration.

In the next section, we will be taking some examples of applications you can build using this tech stack.


3. Use cases and examples with source code.

We can build lots of innovative apps with Encore and Next.js, so let's explore a few that stand out. The first three have source code and the last two are just example ideas you can build.

Building an Uptime Monitor

You can build an uptime monitoring system that notifies you when your website goes down so you can fix it before your users notice.

The app will use an event-driven architecture and the final result will look something like this.

Uptime Monitor

Here is the automatically generated diagram of the backend architecture, where white boxes are services and black boxes are Pub/Sub topics.

backend architecture diagram

You can check the GitHub repository.

 

URL Shortener

You can build a URL shortener with a REST API and PostgreSQL database. It will also help you learn how to create REST APIs with Encore and test your app locally.

In short, you need to implement the /url endpoint to shorten URLs using randomBytes for unique IDs. Set up a PostgreSQL database with a migration file to store the original and shortened URLs. Then you need to modify the API to insert data into the database upon shortening a URL.

Next, add an endpoint to retrieve the original URL by querying the database with the short ID. Test the API using the local development dashboard and include a /url listing endpoint to fetch all stored URLs.

You can check the GitHub repository.

 

LLM Chat Room

Just to be clear, you don't need a frontend part for this, but it's a good way to improve your knowledge of Encore.

You can create a chat application that integrates Large Language Models (LLMs) like OpenAI's GPT and Anthropic's Claude with chat platforms such as Slack and Discord. It helps you build AI bots with unique personalities that can engage with users.

chatty bot

This is a microservices-based application, with each service handling a specific aspect of the chatbot ecosystem. The services use a combination of Encore APIs, pub/sub messaging and WebSocket communication to orchestrate the flow of messages between chat platforms and LLM providers.

system design

system design

 

You can check the GitHub repository.

 

✅ AI Blog Generator

A blog writing assistant that generates articles based on user input, allows editing and publishing as well.

Tech stack:

  • Next.js for frontend UI with an editor like Tiptap or Lexical.
  • Encore.ts for backend API to handle text generation requests.
  • OpenAI API (GPT-4) for generating article drafts.
  • Resend for email notifications when articles are ready.
  • Supabase for storing drafts and published articles.

Example Flow:

  • Users enter a topic and AI generates a draft.
  • They edit, refine and publish within the app.
  • Email notifications are sent when it's ready.

 

✅ Notion-style application for collaboration

A simple Notion-like app for real-time collaboration on notes and tasks.

Tech Stack

  • Next.js with WebSockets for real-time updates.
  • Encore.ts backend with Redis for live data synchronization.
  • PostgreSQL for persistent data storage.
  • Clerk/Auth.js for authentication.
  • UploadThing for file storage (for adding images to notes).

Example Flow

  • Users create and share workspaces.
  • Live sync across devices with WebSockets.
  • Access controls ensure only authorized users can edit.

 

These should be enough to get you started.

If you're looking for a really nice crash course, you can refer to this video!


To be honest, no tech stack can be perfect but Encore and Next.js is definitely one of the best and recommended way to build full-stack applications.

Let me know if you have any other ideas.

Have a great day! Until next time :)

You can check
my work at anmolbaranwal.com.
Thank you for reading! 🥰
profile of Twitter with username Anmol_Codes profile of GitHub with username Anmol-Baranwal profile of LinkedIn with username Anmol-Baranwal

Ending GIF waving goodbye

Top comments (13)

Collapse
 
bobbyiliev profile image
Bobby Iliev

Nice! Great post as always 👏

Collapse
 
anmolbaranwal profile image
Anmol Baranwal

Thanks for reading, Bobby! 🙌 Appreciate it.

Collapse
 
dfordp profile image
Dilpreet Grover

Encore.ts seems a great framework. I will check it. Thanks for sharing ❤️🔥

Collapse
 
anmolbaranwal profile image
Anmol Baranwal

Thanks for reading Dilpreet! I was really surprised by how easy the docs are and getting those pre-made instructions for the cursor made life so much easier.

Collapse
 
syakirurahman profile image
Syakir

Great post, Anmol 🔥

Collapse
 
anmolbaranwal profile image
Anmol Baranwal

Thanks Syakir! 🔥 Time to build something nice :)

Collapse
 
yashksaini profile image
Yash Kumar Saini

Great guide Anmol,

Collapse
 
serhiyandryeyev profile image
Serhiy

Fundamental work! Thanks!

Collapse
 
steven_ramirez_9a9a24610d profile image
Steven Ramirez

Good article but, ultimately, I must agree in the negative. Considering the number of well established, properly typed, server side languages, TS seems like the worst choice. And with regards to performance and scalability, anything React related is always a poor choice.

Collapse
 
naclcaleb profile image
Caleb H.

Hot take: anyone looking specifically for a “type-safe” stack should avoid JS/TS on the backend, it’s not truly typed!

Collapse
 
cmacu profile image
Stasi Vladimirov

Similarly anyone looking for reactive stack should avoid react on the frontend since it’s not truly reactive…

Collapse
 
syeo66 profile image
Red Ochsenbein (he/him)

Nah, Goth-Stack does it for me

Collapse
 
cmacu profile image
Stasi Vladimirov

You lost me at next/react… in 2025… I guess if you are looking for the least performant solution with the worst memory then it’s a decent choice.