Chirag's Blog
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.
Let's start with initialising the project:
1bunx create-jstack-app@latest
Options selected:
1┌ jStack CLI2│3◇ What will your project be called?4│ testing-jstack-appwrite5│6◇ Which database ORM would you like to use?7│ None8│9◇ Should we run 'bun install' for you?10│ Yes1112Using: bun1314✔ 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-appwrite2bun dev
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 DB2interface Post {3 id: number;4 name: string;5}67const 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:
.env
file in your project directory and paste in those values:1NEXT_PUBLIC_APPWRITE_PROJECT_ID=686a271700323696d2232NEXT_PUBLIC_APPWRITE_ENDPOINT=https://fra.cloud.appwrite.io/v13NEXT_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.
main
, and keep it' ID as main as well:posts
and keep its ID as posts
.name
for now: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 project23? How would you like to start? Link directory to an existing project4? Choose your organization 67610b8ee51f147ca9435? Choose your Appwrite project. [object Object]6✓ Success: 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/types23ℹ Info: Detected language: ts4ℹ Info: Directory: src/types does not exist, creating...5ℹ Info: Found 1 collections: posts6ℹ Info: Found 1 attributes across all collections7ℹ Info: Added types to src/types/appwrite.d.ts8✓ Success: Generated types for all the listed collections
Result will look something like this:
1import { type Models } from 'appwrite';23/**4 * This file is auto-generated by the Appwrite CLI.5 * You can regenerate it by running `appwrite types -l ts src/types`.6 */78export 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.
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";23const client = new Client()4 .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)5 .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!);67const databases = new Databases(client);89export { 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";67const DATABASE_ID = "main";8const POSTS_COLLECTION_ID = "posts";910export 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 }),1819 create: publicProcedure20 .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 );3031 return c.superjson(post);32 }),33});
And done! Now your JStack application is using Appwrite as its backend provider.
1bun run dev
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:
APP_DOMAIN
variable we defined earlier. For me I will keep it:1NEXT_PUBLIC_APP_DOMAIN = jstack - appwrite - template.appwrite.network;
And done! Your application should be live 🎉
You can checkout the demo application here - https://jstack-appwrite-template.appwrite.network/
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.