Chirag's Blog

JStack + Appwrite: A Match Made in Heaven for Modern Web Development

July 6, 2025

If I had a penny for each time a youtuber has launched his own tech stack, I would have 2 pennies, which isn't much but its weird that it happened twice.

I am talking about T3 Stack launched a while back by everyone's favourite Theo, but recently a new player has entered the market called JStack, by Josh who is the lead Devrel at Upstash. To be fair, its not even that recent, but as always I am late to the party I try to give a framework time to mature and gather feedback from community before giving it a shot.

So, did I prefer JStack over T3 stack? Did it have more compatibility with Appwrite, my favourite backend provider? Can it be hosted on Appwrite Sites? Let's find out.

Getting Started

Let's start with initialising the project:

1bunx create-jstack-app@latest

Options selected:

1┌ jStack CLI
2
3◇ What will your project be called?
4│ testing-jstack-appwrite
5
6◇ Which database ORM would you like to use?
7│ None
8
9◇ Should we run 'bun install' for you?
10│ Yes
11
12Using: bun
13
14✔ testing-jstack-appwrite scaffolded successfully!

Let's just quickly run a dev server to see what we get out of the box:

1cd cd testing-jstack-appwrite
2bun dev

JStack landing page

Initialising Project

On skipping the ORM option, the stack still sets up a /src/server folder with an example posts router. But it only mocks the DB using an array which does not persist:

1// Mocked DB
2interface Post {
3 id: number;
4 name: string;
5}
6
7const posts: Post[] = [
8 {
9 id: 1,
10 name: "Hello World",
11 },
12];

We skipped the ORM option because Appwrite provides built-in schema management through its SDK, eliminating the need for a separate ORM layer. To get started, let's head over to https://cloud.appwrite.io to set up our project.

If you are using Appwrite for the first time, I highly recommend you check out our Start with Web docs.

Here is a quick setup guide:

New project model (Appwrite)

New platform screen (Appwrite)

Project ID and endpoint (Appwrite)

1NEXT_PUBLIC_APPWRITE_PROJECT_ID=686a271700323696d223
2NEXT_PUBLIC_APPWRITE_ENDPOINT=https://fra.cloud.appwrite.io/v1
3NEXT_PUBLIC_APP_DOMAIN=localhost # we will change it later
1bun add appwrite

This covers up on how to initialize Appwrite in normal Next.js project. Now we need to configure our Appwrite databases according to the project. For this demo, let's create a Posts collection to shift the mock database JStack uses as an example to Appwrite.

Defining Schema

Create database (Appwrite)

Create string attribute (Appwrite)

Create permissions

Syncing Types

That's it, we are all set with configuration on the Appwrite Console. Now let's set it up in our project. I will also take the help of the Appwrite CLI to help me set up things faster. You can learn more about how to install it by following the installation docs.

Once done, run:

1testing-jstack-appwrite appwrite init project
2
3? How would you like to start? Link directory to an existing project
4? Choose your organization 67610b8ee51f147ca943
5? Choose your Appwrite project. [object Object]
6Success: Project successfully linked. Details are now stored in appwrite.json file.
7Would you like to pull all resources from project you just linked? Yes

Once done, let's utilize the last Types Generation feature to sync our defined types:

1appwrite types src/types
2
3Info: Detected language: ts
4Info: Directory: src/types does not exist, creating...
5Info: Found 1 collections: posts
6Info: Found 1 attributes across all collections
7Info: Added types to src/types/appwrite.d.ts
8Success: Generated types for all the listed collections

Result will look something like this:

1import { type Models } from 'appwrite';
2
3/**
4 * This file is auto-generated by the Appwrite CLI.
5 * You can regenerate it by running `appwrite types -l ts src/types`.
6 */
7
8export type Posts = Models.Document & {
9 name: string;
10}

Obviously pretty small for now, but a really helpful feature once the project expands and more collections are defined.

Configuring Code

Final steps are to connect the Appwrite backend with our tech stack. For that let's create a simple appwrite.ts file in src/lib folder:

1import { Client, Databases, ID } from "appwrite";
2
3const client = new Client()
4 .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
5 .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!);
6
7const databases = new Databases(client);
8
9export { client, databases };

Now, we can modify the original post-router.ts file to use the defined database:

1import { z } from "zod";
2import { j, publicProcedure } from "../jstack";
3import { databases } from "@/lib/appwrite";
4import { type Posts } from "@/types/appwrite";
5import { ID } from "appwrite";
6
7const DATABASE_ID = "main";
8const POSTS_COLLECTION_ID = "posts";
9
10export const postRouter = j.router({
11 recent: publicProcedure.query(async ({ c }) => {
12 const posts = await databases.listDocuments<Posts>(
13 DATABASE_ID,
14 POSTS_COLLECTION_ID,
15 );
16 return c.superjson(posts.documents.at(-1) ?? null);
17 }),
18
19 create: publicProcedure
20 .input(z.object({ name: z.string().min(1) }))
21 .mutation(async ({ c, input }) => {
22 const post = await databases.createDocument<Posts>(
23 DATABASE_ID,
24 POSTS_COLLECTION_ID,
25 ID.unique(),
26 {
27 name: input.name,
28 },
29 );
30
31 return c.superjson(post);
32 }),
33});

And done! Now your JStack application is using Appwrite as its backend provider.

Testing

1bun run dev

Recent posts image

Appwrite console showing data

Deploying your application

Until recently, to deploy your Next.js application, you had pretty low choices. But no more Appwrite Sites. Now, you can have your backend and frontend hosted on Appwrite.

Check out these docs on how to get started with Sites - https://appwrite.io/docs/advanced/self-hosting/sites

Let's deploy your application using Sites:

Selecting repository screen

Add environment variables screen

1NEXT_PUBLIC_APP_DOMAIN = jstack - appwrite - template.appwrite.network;

And done! Your application should be live 🎉

Deployment successful screenshot

You can checkout the demo application here - https://jstack-appwrite-template.appwrite.network/

Conclusion

Let's start by answering the question the blog began with: Do I prefer JStack over T3 Stack? I'm sorry, Theo, but I do.

JStack solves the fundamental problems I have always had with Next.js:

The most noticeable difference between T3 Stack and JStack is how light they are, mainly due to the inclusion of the TRPC protocol in T3 Stack. Most projects do not require it, and it makes the code 10x more complicated to maintain, in my opinion.

So, give JStack a shot if you are starting with a new project (or want to spend a weekend migrating your existing stack to it). Huge shoutout to Josh for creating this wonderful stack. And lastly, give Appwrite a chance to be your next all in one cloud platform, both for your backend and frontend needs.

Sources: