Hang tight while we fetch the video data and transcripts. This only takes a moment.
Connecting to YouTube player…
Fetching transcript data…
We’ll display the transcript, summary, and all view options as soon as everything loads.
Next steps
Loading transcript tools…
Breaking down my current tech stack | Theo - t3․gg | YouTubeToText
YouTube Transcript: Breaking down my current tech stack
Skip watching entire videos - get the full transcript, search for keywords, and copy with one click.
Share:
Video Transcript
Video Summary
Summary
Core Theme
The author details their evolving technology stack, moving away from the original T3 stack to a new, more modular, and enjoyable development approach, emphasizing practical choices and the reasoning behind them.
Mind Map
Click to expand
Click to explore the full interactive mind map • Zoom, pan, and navigate
My stack's been in a bit of flux lately
if you haven't noticed. If you've been
around since my channel started, you
know that it all began with the T3
stack, the stack that I built my
business on top of, Ping. You know, the
video call app that I still use for all
my collabs. That went really well. And I
love the stack so much that I wanted to
share it with the world. And that's kind
of what led to this channel existing. I
could never have guessed where it would
take me. And I certainly wouldn't have
guessed where my stack would end up,
too. As such, I want to take the time to
break down with y'all what the current
state of my stack is, what happened to
the T3 stack, and how do I recommend
building today because it's very
different than it was before, and it's
incredibly different from how I ever
would have imagined it being. I'm very
happy with where my stack has ended up.
It has made building more fun and more
exciting than it's ever been for me. I'm
very happy with where we've landed, but
I also think there will be some pieces
that surprise you guys. From my choice
to no longer really use SQL to my slow
migration away from Nex.js server
components and most importantly TRPC.
The place I've landed is weird. The
place I've landed is also really really
fun and surprisingly works well with
vibe coding too which is a cool benefit
of the way that I like to think about
building. Turns out when everything in
your codebase is a file, not some weird
config in some dashboard AI is way
better at it than it would be navigating
some stupid page. This video is going to
include everything from the packages I
use, the frameworks I build around, the
services I integrate, and most
importantly, the way I think about all
of these things as I am building and
designing my applications and their
infrastructure. This isn't meant to be a
do this or else so much as how I make
the decisions I make as I build the
stacks up for my things. And most
importantly, why I love Flutter so much.
Seriously though, this is going to be a
fun one. I'm very excited to dive into
all of this with you, but I can't give
away these secrets for free. Okay, I
can, but I would like to make some
money. So, quick word from today's
sponsor and then we'll dive right in.
It's easier than ever to go from a mock
of a UI to an actual working
application. You just drop it in your
favorite AI tool and it will spit out
the code. But how do you find the right
reference point? How do you find the
best place to start when you're trying
to add a new view to your application?
It's not as easy as it sounds. I know
we've all been there. Hunting through
Google images trying to find the right
reference, installing 15 apps on your
phone, hoping you can get the right
inspiration to solve this design
problem. Today's sponsor, Mobin, blew me
away as soon as I first tried it. I
subbed live in my ad read because I
tried it and was like, "Oh my god, I
need this." Mobin's built up a beautiful
collection of over 500,000 screens
across over a thousand iOS, Android, and
web applications. Designers at tons of
companies are using them, be it huge
ones like Uber or small ones like T3
Chat. Yes, it's very useful to us. I'll
just show you my actual account because
I use it all the time. There are
different categories. You can go between
apps and sites. They have a whole
separate section for websites now, which
is great. Let's say that we want some
inspiration for our shopping app. Let's
take a look at the different guided
tours that exist in current shopping
apps. Here we can see how Walmart does a
tour for how scanning works. Or if we
scroll, we can see how IKEA does their
shopping experience and app. You can
learn from any of these super quick. And
when you find something you like, you
can copy the image with command C, pop
into your editor of choice, commandV,
say, make it look like this, and it will
make it look like that. Do you see how
insanely useful that can be? Whether
you're a vibe coder or a professional
designer or anything in between, having
good references is more essential now
than ever, and finding them is way too
hard, unless you're using Mobin. If
Mobin cost a hundred bucks a month, I
wouldn't think twice. But they're only
$10. That's an insane value for what you
get. And I've been blown away. There's
no question in my mind that this is the
best source ever for design inspiration.
And if you're looking to get inspired
and build better applications, check
them out now at soyv.link/mobin.
Let's start by breaking down the pieces
of your stack. You have the database API
layer. The API layer being the thing
that lets clients or even services
access the data in the database and
write to and from it. You have your off
layer could be rolled your own, could be
using a package, could be a service. You
have client framework. That's the actual
code that runs on the client and the
framework you use to define it. You have
your style system. This can be a couple
different things. It could be how you
use CSS, but it could also be the way
that you define the components directly.
Your package management and generally
workspace management nowadays. I find
that npm and pmppm more and more do a
lot of things that you might not have
before. Package management's become a
very complex thing. And then you have
the additional services, things like the
backend host, the database host,
analytics, plus the host for that. And
there's a couple optional things like
monor repos. I think that covers most of
it. I could stick language in here, but
you know my take. If it could be in
Typescript and it isn't, there's a good
chance you're being irresponsible
because you have to have client code
somewhere. And if you could use the same
language for both, that's really cool.
Believe me, I wish I could just say
Elixir as my answer for all of these,
but I can't. I need to be realistic. I
think this covers all the pieces that I
want to break down here. Let's start
with the client framework. So, this one
the thing I've been thinking about a lot
lately. Realistically speaking, I'm
going to use React still. That's not
because other things aren't good or cool
so much as React supported by
everything. Every library, every
compiler, every bundler, every editor,
every AI vibe coding agent, everything
supports React. If it can be done in the
web, there's a package for it for React
almost certainly at this point. It is
what it is. You can have all the
feelings you want, but there are few
ecosystems that are both as composable
and comprehensive as React is. But
that's not such a simple thing anymore
because React is just a piece. It's not
the whole equation. And it's kind of two
different directions you can go with it.
Those are obviously Gatsby and create
react app.
And how do you pick between these two?
Obviously I am trolling here. The real
options are Nex.js and Vit. And more and
more a new challenger has been
approaching. Tanstack start. Which way
weary traveler? You guys know me. You
know that I've historically went down
one of these paths much more than the
others. And if I'm being honest, still
kind of the case. I still find myself
gravitating towards Nex.js for various
reasons that we will discuss
momentarily, but I do see myself looking
at Tanstack start in the Tanstack router
ecosystem more and more every day. But
Vit's in a really good state, too. And
if I just want something small and
simple, like if I'm doing a sandbox or a
side project or anything where I don't
need a statically rendered homepage, Vit
can be really nice. So, we got next, Vit
and Tanstack as the main options here.
There's another way I would recommend
thinking about this though. I would
think of this less as the like bundler
or the init command and more as the
different paths for routers. Nex.js is
the router for next tanstack starts
router is tanstack router in vit gives
you a lot of options but realistically
the option you're picking is react
router. Believe me I wish more than
anybody that people used minimal
powerful routers like wder more. I
[ __ ] love wer great piece of software
but they don't. They use React Router.
React router is in a really good state
nowadays, too. Makes all the sense in
the world. So, you really got to pick a
router you want alongside the generative
details that you want too. Like the
first question I would ask when you're
trying to pick between these is, do you
want any static pages? So, you can have
the classic like homepage.com and then app.homepage.com
app.homepage.com
where homepage.com is made in [ __ ] I
don't know web flow or some [ __ ] and
then the app.homepage.com homepage.com
is your Vbased React application. See
this all the time. You'll see it on most
of the things that I talk about in my
content. And if you do that, you can use
Web Flow or a framework like Astro or
even go set it up in WordPress. Who
cares? When you separate these things,
you now don't have to think as much
about how you make some parts static and
some parts dynamic because you don't
want your homepage to be a single page
app Vappa
content. You want your homepage to be an
HTML file that has the correct content
in it. You absolutely want that. So if
you do want these in the same project,
which I often do, if you look at
something like upload thing, we have a
static homepage with a lot of cool
dynamic parts like our ride animation
here and whatnot, but it is a static
HTML page. If I turn off JavaScript, it
will still load and show content. But
then when you go to the dashboard, it
becomes much more of a traditional
dynamic application. So if you want some
page to be static and you don't want to
do this split between different domains
for the different parts of your app,
your best bet for sure is going to be
something like next or tanstack start.
Tanstack start is still very early and
figuring out the details between the
parts, but it's getting there really
fast. Definitely keep an eye on it. But
if you really want a good minimal
homepage with all the SEO and [ __ ]
figured out, and at the same time have a
dynamic app that is using the same code,
can use the same components, the same
everything, the magic that you want
there is most easily done in Nex.js. So
if you want a static homepage and
dynamic everything else, or maybe you
want your blog to be built and compiled
in a static set of things, that's all in
a good state. And if you want to go
really far with it, a thing I'm probably
going to be setting up soon is
multiszone. Multiszone lets you have
different Next.js projects that are
different sub paths on one greater
Next.js project. So I can have three
different package JSONs for three
different Next apps. One is the blog,
one's the dashboard, one's the homepage,
and all of them are being routed through
multiszone in one next app. Which means
that your build times for your blog
aren't going to affect the build times
for your dynamic app. And believe it or
not, the build times for the blog are
often worse because parsing markdown in
JavaScript sucks for a bunch of reasons.
You get the point though. There's a lot
of opportunity in next to vary how
static and dynamic different things are
and a lot of different dimensions that
they've already solved for where if you
care about this, it's very beneficial.
But if your eyes are glazing over at
this part of the video, that's fine.
Just go use Vit. Vit and React Router
are a great combo and I've been using
them more and more for my side projects
and one-off things. They're a really
good set of tools. They might not help
when you want to fix your SEO or have a
nice landing page, but they're very easy
to work with otherwise. So once you
figured out this part, I'd argue the
decision gets a lot easier. If you do
want static pages, I'd still highly
recommend Next. You should think about
Tanzac Start. The React Router and Remix
ecosystem probably won't help you much
here. And Remix is in crazy flux right
now. I wouldn't bet on that at all at
the moment. They're about to change
everything about it. React Router is
still fine in a minimal enough depth. I
wouldn't recommend against it, but
Remix, which is the framework that the
React router team built as an
alternative to Next, I'd stay away for
now. They're actually moving off React
entirely for the next version. So, we'll
see how that goes. Cool. So, I think you
understand how I pick between these two.
If I want a marketing page, we go next.
If I don't, we go V. Easy enough. Where
do we go now? Up or down? Feel like
down's a lot easier. You guys can
already guess what my style system is. I
have a whole bunch of videos breaking
down how I think about styles. Tailwind
plus Shaden. Mind you, we've customized
the [ __ ] out of our Shad CNN, but same
difference. You know what we're doing
here? Shad CNN kind of solved all the
things I complained about three years
ago in my previous CSS video. It's a
really good combination of the behaviors
of the way CSS works and your style
system. They combine really well there.
And next, cuz we're here and it's easy.
Package management. I'm still on PNPM. I
know. I know the bun people. The bun
people don't have big monor repos. Bun
is not a pleasant experience in a monor
repo. It's made progress, but it's not
there yet. And when you're using stuff
like turbo repo, getting turbo repo and
bun to play nice when you're bundling
various packages throughout, not worth
it. And honestly, I find myself reaching
for PNPM more and more even on single
package and single package JSON stuff,
just cuz I don't want to remember to
switch between the two different
commands. I remember back in the day
there was a package called NAN that was
npm and yarn and it would look at the
lock file in the directory and use
whichever one was for that project. And
now I need bnpm which uses bun or pnpm
depending on which one the project's
using. Oh, AntFu has knee and I bet knee
would actually work pretty well for this
too. Yeah, knee is probably what I want.
Use the lock file to make sure you're
using the right package manager. Using
knee would probably get me using bun a
lot more. I should definitely consider
this. You get the idea. I'm on PNPM for
monorba support. If you're still on npm
or yarn, please stop. You're hurting
yourself way more than you need to. Both
PNPM and bun will cache the packages you
install in a global cache, so you don't
have to do a network request every time
you install. If you're reinstalling
packages, making changes, or spinning up
multiple projects, if you have more than
like three projects on your computer
right now, and you're not using PNPM or
bun, you're being irresponsible.
Just straight up. So yeah, it's time.
Kill npm and yarn. I stayed on npm way
longer than I should have. I had moved
from yarn to npm when it got good
enough. Now I'm on PNPM always now. Make
the switch. Next part is easy enough.
I'm just going to say it. I know we
broke up, but I'm still on Versel. There
are so many little things they get right
that are so annoying if you try to do
them elsewhere. From how preview
environments work to the power of fluid
compute for a serverless environment
without giving up on Node. I feel like
the other options I would have would
require a lot more work or compromise.
Like Cloudflare would be cheaper and
would have slightly better performance
characteristics for things like these
longunning agentic workloads and T3
chats inference endpoints because cloud
workers as I've mentioned in far too
many videos now are an abstraction level
higher than what Verscell does because
every request on Verscell goes to a
Linux instance that is yours. So it's
virtualized at like the Linux container
level where with Cloudflare it's
virtualized as different service workers
in V8 many layers above the kernel. That
means that when your request doesn't
need CPU cuz it's waiting for something
else to happen. Someone else's request
can go to somebody else's code on the
same box on the same V8 instance and
resolve it. Which means that Cloudflare
doesn't care about how much time your
request takes. They only care about how
much compute the request uses. Which
means for things that are long duration,
low compute like AI inference where I'm
just sitting there waiting for the
OpenAI API to respond with tokens, it
doesn't matter if that request takes 20
minutes. I'm only going to be build for
like a tenth of a second. Cloudflare
makes more sense for some of these
workloads, but it's also not Node. And I
know they keep making the Node
compatibility better. They do, but they
also absolutely [ __ ] don't. And at
the same time, the process of deploying
on Cloudflare is still comically harder
than Versel. If I want to put a project
on Verscell, I don't even use the CLI. I
go to the Verscell homepage, I click the
new project button, I click the GitHub
repo, and now it's up. That's it. If I
want to do things on Cloudflare, I have
a day ahead of me. If I'm not starting
with Cloudflare's like worker templates,
I'm screwed. If you're not starting with
the Wrangler starting points, good luck.
Have fun. And even then, the amount of
hell I've went through to try and get
like an API endpoint to serve next to
static assets without them clobbering
each other when they made the Cloudflare
pages to Cloudflare workers migration. I
had three Cloudflare employees trying to
help me debug it. All of them were
wrong. I had to read the source code for
Wrangler to figure out why they were
adding random hashes to my bundles that
weren't supposed to be there. Like there
was legitimately a point where I
understood Cloudflare's deployment
process better than the people working
on Wrangler did because I was trying so
hard to figure this out. And I'm not
saying it's not worth it and I'm not
saying it's not easy for some of you
guys for some things. What I'm saying is
the software I build, which has backends
and frontends and they have to relate to
each other doesn't work great on
Cloudflare without a decent bit of
effort. Hell, [ __ ] environment
variables didn't work until two weeks
ago. you had to use their alternative
way of thinking about environments until
literally last week where they finally
added V support. So yeah, Cloudflare is
fine as long as you're willing to put up
with all that friction. But Versella is
fine, too. And now that we have the
price difference with fluid compute,
which I've talked about in many videos,
go watch them if you haven't and you're
interested. Verscell is cheaper than
running your own lambdas. If that
statement sounds stupid, either you
don't understand fluid comput so you
should go watch that video or you don't
want to admit that people can build
better solutions on top of other things.
It's crazy that like if we were to have
a spectrum of cost where on the left is
most expensive and on the right here is
least expensive that previously it was
Versel, Lambda, $5 VPS and Cloudflare.
The really crazy thing that happened
with Fluid Compute is Verscell moved
here. It's still more expensive than a
$5 VPS for a lot of different workloads,
but it's cheaper than Lambda because on
AWS, one Lambda resolves one request. On
Verscell, one Lambda resolves as many
requests as it can in the time it's
alive for. They built that abstraction
layer. Verscell is now cheaper. They
make a ton of sense for a ton of
different scales. And if you want node
infinite scale up and down, incredible
preview deployments and experience there
and all the other things I've talked
about, they're really worth it. Still,
call me a shill you want. Verscell has
cost me more money than any individual
company have ever talked about because
the old sponsor deal I was getting
[ __ ] fleeced. So no, I'm saying this
because I believe it and moving off for
sale will be a sad day for us and
honestly we were considering it heavily.
When I saw how bad our bills were going
to be for all the durations that we were
hitting for T3 chat, I was ready to exit
and then fluid compute happened and
dropped our bill by 90%. Now I don't
care that much. You get the idea. So I'm
in versel. I'm sticking with them for a
while. Now, we need to talk about the
one that if you've been around for the
last couple months, you already know,
but if you haven't, this might come as a
huge surprise. We have DB Host and DB.
They are the same for me now. So, I'll
start up here. I got Convex pled. Never
thought I'd see the day. I talked so
much [ __ ] to those guys four years ago
because previously instead of convex, I
had a whole different set of stuff I
would use. So I would use my SQL on
planet scale and I would hit it through
Prisma or Drizzle mostly drizzle. I
would then define endpoints in tRPC. If
I needed live updates I would put those
in pusher or U web soocket and then I
would use react query on the client to
pull this all together. Notice how I
didn't change anything on the convex
side. Instead of my SQL or another SQL I
use convex. Instead of planet scale and
other host I use convex. Instead of an
OM like presle I use convex. Instead of
tRPC or some other API definition layer,
I use convex. Instead of pusher for some
live update layer that just comes in,
I'm using convex. And instead of react
query, I'm using the built-in convex uh
use query and use mutation. I [ __ ]
wish they named them differently. It is
what it is. There's a couple quirks with
them, but for the most part, they're
really nice. In particular, the
optimistic update path is incredible for
them. I never thought I would do this
because a huge part of why I like the T3
stack and why I made it in the first
place is that modular nature. The point
is that you can pick which parts you
want, ignore the ones you don't, and
change the ones you want different
things out of. And I changed them all to
convex. I don't want this to just be yet
another convex glazing video, and it's
very hard to not do that. Believe me,
I'm very fun at parties nowadays. You
get the idea, though. Let's just go
through and put convex everywhere that
they need to be here. Convex. Convex. I
still use TRPC when I need things that
aren't in my convex layer. Doesn't
happen that much nowadays, honestly. DB
host convex.
Well, I think that hits all the things
here that are convex. You might be
thinking about the O layer, though.
Doesn't convex have O? Yeah, and they
kind of hate it. Talked to them a lot.
They're not proud of their off package.
It works kind of. I never got it
working. Not sure how much of that was
their fault versus mine, but it was way
easier for me to use pretty much every
other option. We should probably break
down those options. The O layer. The
main two paths you can take here are a
service or package. You can roll it
entirely yourself. And I hope you
understand how stupid that is to do
because there's a lot of pieces of O
that you will get wrong if you do it
yourself. You should use a package. And
believe it or not, I have been pretty
deep down both of these recently. For
packages, you have options like open
off, which if you're not familiar with
is by DAX in the SST crew. They also
make open code. You have next off, which
is now known as OJS. I've been through
it with offjs. I wouldn't recommend it
nowadays. You had Luchia off, but it's
dead now. Don't touch it. Cool
documentation, good things to learn
from, but don't use it. Then you have
the most important one, Better Off.
Better off is really good. I'm also an
investor, so account for some bias.
We'll talk about them more momentarily.
On the services side, you have Ozero.
Please don't use Ozero, but you have
better options, which are also again
both sponsors, Clerk and Work OS. Since
this side is the easiest for me to talk
about, I'm going to start with it. To
put it very simply, if your goal is to
get O working as quick as possible with
all the nicities you need, like
organization management, subscriptions
and payments handled, the little button
in the corner a user can click to have
all their information come out and
customize their profile and whatever,
all those types of things. If you want
to not think about off, just get it
working with payments and everything
handled, Clerk is going to make your
life much better. I still default most
of my projects to clerk. When I make a
new thing and it needs off, clerk is the
happiest path there by far. So, if you
want everything handled for you from
payments to the components the user see,
easy paths to implement most of the
things you'd ever want and a reasonable
price with some really good deals
included like the the fact that a user
doesn't count towards your user limit
until they've shown up twice. If they
show up once and then don't show up
again for the rest of the month, the
first 24 hours of a user session are
free. So if they show up 25 hours later,
then they count. But if they sign in
once and never again, they don't count
towards the user limits. Very generous.
I really like that policy because it
keeps a random surge of users from
costing you money. Work OS I recommend
if you want to be ready for enterprise.
Not that you're an enterprise company,
but you might be selling to them. If you
want to deal with things like SAL and
Octa and all the other stuff that they
handle with their admin portal, you've
almost certainly seen an ad now cuz Work
OS has bought a lot of ads on the
channel. They're the solution when the
company you want to work with cares more
about O than you do. If you want a
company that has a person whose job is
setting up O to integrate into your
service so that they can use it with
their company, work OS is by far the
easiest way to handle all of that
[ __ ] So I would say Clerk, if
you're getting started,
you want payments handled because their
subscription stuff built into Clerk is
really, really good. And man, I I wish
it was there when we started T3 Chat. It
would have made life much easier. you
benefit from the built-in components
and most importantly you just want to
get back to building your app. These are
the reasons you pick Clark. Whereas with
work OS, a little different. You want to
sell to enterprises. You're tired of
SAML, Octa, and all these other things.
And of course, you want a solution that
scales to sizes like OpenAI, Cursor, and
more. Because yes, OpenAI, Cursor, and
so many of these other companies are
using work OS. I am regularly surprised
how many businesses are on work. Planet
Scale, Versel, a lot of the other things
we talk about all on work OS. Hopefully
this makes it pretty easy to decide
between these two if you do want to go
the service route. But there is a new
player that complicates things. Better
off. Better off is a very interesting
solution because on one hand it is meant
to be a better open- source set of
packages to build your off layer
comparable or comparable to things like
next open etc. But they're also a YC
backed startup that has plans to build
services and monetize and more. I'm very
excited about the future of better off.
It's why I invested. They know what
they're doing. They're building awesome
stuff right now. They don't have the
cloud platform. You're expected to
attach Better O to another database,
probably the database you're already
using for your app. Better will work
with pretty much any database you would
reasonably be using. It works with most
web frameworks. They have support for
[ __ ] everything. Better's really
good, but since they don't have a hosted
platform like Convex and Work OS do,
integration into other hosted platforms
kind of becomes your problem, which
means for something like Convex, it's
your problem. Thankfully, this is being
worked on. I know for a fact that both
Convex and Better Off are investing
heavily in making a happy path here. One
of the things that's so cool about
Convex is their concept of components
where you can have different and when I
say component, I don't mean the thing in
React kind of similar, kind of
different. Components in Convex are
structures of behaviors that you would
want to live in your database and API
layer. So if you want to add work
pooling so that you can parallelize
tasks but only up to a certain amount.
If you want to make sure only 10 of a
task can be running at a given time, you
can install their workpool component
that spins up like a sub table in the
database that manages all of that. It's
in a little drop down in their dashboard
and also gives you these pieces of code
and logic that you can use in your
convex queries and mutations. The convex
better off packages are implementing
better off in convex using components
which is very exciting. the idea that I
could npm install add two lines of code
to my app.config.ts
file and now better off and all of the
tables and things it needs are
integrated into convex without me having
to maintain any of it. Very very
exciting because it's kind of the
missing piece if I wanted to make a
template right now. If you took even
something like the T3 chat codebase,
just PNPM install PNPM rundev, if you
haven't already signed into Convex, a
link pops up that says, "Hey, you need
to sign into Convex to keep going." And
you do it. It doesn't matter if you're
on my team or not since all of the
config in a Convex project is just the
Convex folder. I have my image studio
project here. Here's my Convex config. I
have models, my schema. Here's the table
definition for the project. It's just
here. Here are the different models that
I have access to. This is just source
code that is run by all these things.
The only pieces that are missing here
are the API keys for the services that
I'm hitting through the convex
endpoints. Specifically, in this case,
foul cuz that's where all my AI
generation is occurring. Since all of
this just lives as code, you don't need
access to my convex. You don't need
access to my configurations on AWS or
any of these other things. You just run
npm install and rundev. Sign into a
random GitHub account on Convex and
you're good to go. But then you want to
add O and then it stops being so simple
very quickly. Stops being so simple
because if you want that O in the
database yourself, you got to define a
lot of schema. And if you want the O
somewhere else, you got to put a lot of
time into dashboards. One of the pointed
goals of my set of tooling is to avoid
time in dashboards when building. You
can spend all the time you want in your
analytics dashboard when you're done
building, but you shouldn't have to be
navigating UIs to update your project.
both because I hate doing that. I like
my source code being the source of all
the behaviors, but also because AI is
much better at it, too. Good luck vibe
coding your way through the Superbase
dashboard. That's why they have all
these MCPs because it's the only way to
change things. And once you have those
dashboards, you also have a bunch of
state you have to deal with that isn't
in your codebase. That part in
particular terrifies me that I could run
a project at a different time and have
it behave entirely differently because
it's relying on some config somewhere
that isn't actually in the codebase.
That genuinely horrifies me. And a big
part of how I design my stack is to
avoid those types of things. But right
now, Oth is one of those things because
you need to get it from somewhere.
Convex plus better off is promising the
solution that I'm looking for here,
which is that all of the O management
will just be part of the Convex
deployment. What that looks like is a
little bit chaotic. See all of the
fields that they have to add in order to
handle the things that may or may not
come from the user object. and you have
the account separate verification
two-factor like all of this is necessary
for pretty much every user in your
project. One of the reasons I like O
services because I like not having to
deal with all this [ __ ]
But once the better off convex
integration is more stabilized, this is
going to be very very good. And I am so
excited because none of this code will
even live in your codebase. This is all
just going to come from their package.
And then when you set up convex just by
running the dev command in any of these
templates, these will all be defined for
you automatically. So I would expect in
the near future if I'm going to do
something like create T3 app again and
go harder on that, it's going to happen
when better off and convex is a much
more stable happy path. And I know this
is the path that Convex is betting on
too. They don't want to maintain their O
components anymore. They want better off
to do that and to have a really happy
integration story. And God, if they
figure out the Stripe part, too, it's
going to be very, very good. Speaking of
which, we should probably talk about the
payments part because what's the point
of building if you can't get paid,
right? Payments.
I'll be straight up. If you're not using
Stripe, you're being irresponsible. To
be clear, I don't mean using Stripe
directly necessarily because there are a
lot of other options. My CTO is really
hyped on Autumn. They're a YCbacked
company that lets you configure all of
your prices and all of the stuff that
people can do in your app and pay for as
an autumn.config.typescript
file and then it will handle the
configuration for both dev and prod as
well as all the data management, the
syncing, the making sure users are in a
good state for you. Autumn is very very
promising. It's also open source,
handles all the [ __ ] I've been
through it with Stripe web hooks as I'm
sure many of you know. I did a whole ass
video and GitHub repo how to stay sane
implementing Stripe. This went so well
that Stripe actually invited me to speak
at a company all hands with the CEO.
They took my feedback seriously and I'm
sure they're working on it still some
amount. But I am tired of waiting as I'm
sure many of you are as well. I've
gotten endless positive feedback about
this project. It has over 5K stars and
almost every day somebody hits me up
thanking me for this. It's become one of
the best things that honestly ever
happened to Stripe because now there's a
path to do it right to manage the web
hooks to make sure that things stay in
sync and to keep it all from screwing
over your database. Very nice. Generally
speaking, when I have my application DB,
I want the data in it to be frankly
application data. What I don't want in
my application DB is things that aren't
application data. Those are things like
O data. The next time I have to think
about [ __ ] session tokens in my app
DB, I'm going to move to a [ __ ] farm.
I'm done with that [ __ ] That's a
separate concern for a separate place.
Right now in T3 chat, we have our off
through open in a KV that is fully
separated from everything else in our
app. Our off layer is an isolated micros
service that we own ourselves running on
Cloudflare that just manages the token
passing and then everything else is done
inside of T3 chat with our database on
convex. In the future, we'll probably
move to work OS because we want to sell
to enterprises and it'll make that path
much easier. But for now, we keep that
data far away. The reason I'm talking
about this now is I think the same thing
about payment data. Right now, all of
the data around your subscription
status, the state of payments, and all
of that doesn't live in our convex
database on T3 chat. We keep all of that
of the user subscription. And whenever a
web hook comes in, we update it. And
whenever the user requests it and we
don't have it, we double check and write
it in the KV at that time. All of this
is detailed in the Stripe
recommendations. If you are wanting to
do vanilla stripe, I highly recommend
reading this even if you don't end up
using it just to make sure your
implementation methods are lining up
with all the different annoying edge
cases and bugs and [ __ ] you'll hit
because Stripe's web hooks, they're
something, man. That's all I'll say
about it. All that said, I'm
increasingly interested in solutions
like Polar and Autumn. I don't want to
deal with this [ __ ] the same way I don't
want to deal with off [ __ ] These are
both very, very interesting projects to
me. I'd recommend at least looking into
the two before making a decision. Be
careful with this part, too. You don't
want a solution that makes it harder for
users to pay for things. This is the
most important part of your app is
managing payments. Don't screw this part
up. Put extra Karen. And it's s that I
can't just like build something into the
template cuz it's not that easy. But if
I was, I'd probably put in Autumn cuz I
like those guys. I can bully them to do
whatever I need them to do. Regardless,
all of these things are built on top of Stripe.
Stripe.
I'd recommend sticking with that. Oh,
also, uh, Clerk's solution here is good,
too. So, if you haven't picked your off
solution yet, and you want the users to
be the ones subscribing, like it's a
very direct onetoone relationship. Clerk
makes that very easy to do for not too
much money. Really good option. Check it
out. What do we have left? Analytics.
It's a big one. And my answers, not
quite as big. Post Hog. I like these
guys so much that I bullied them into
sponsoring me. I've been using Post Hog
for almost four years now. They're an
open- source set of analytics tools and
all the things you need for building
product from feature flags, session
replays, and more. I mostly use the
analytics. I very occasionally will use
the experiments and feature flag parts.
I also like the AI analytics piece, but
it's mostly a wrapper around their
existing analytic stuff. Very happy with
these guys. I don't like any of the
other options. I'll still occasionally
do things with plausible. I like these
guys quite a bit. They're also open
source. They're all elixir based, which
is cool, but it's just for web
analytics. And web analytics and product
analytics are very different things.
Product analytics are figuring out how
many users go through these flows and
where do they churn. If you want to know
things on a per user basis of any form,
you want product analytics. If you want
to know which page people go to on
general and which sources they're coming
from in general, that's when something
like plausible makes sense. Plausible is
an alternative to something like Google
Analytics. Post is an alternative to mix
panel, amplitude, and all these much
heavier analytics platforms. If you
don't know the difference between
product analytics and web analytics, you
probably want product analytics. If you
do know the difference and you know you
want web analytics, plausible is really
cool. If users don't sign in, you
probably want plausible. If users do
sign in, you probably want Post Hog.
That said, Post Hog's been building a
lot of the web analytics things as well
recently, so it's even harder to pick.
You can't really go wrong with Postto.
Let's keep gunning through these capture
rate limiting, etc. I have feelings on
this. Other people asked, so I decided
to put it in here. We're still using H
Capture. I'm not sure how long for,
though. I've gotten weird vibes talking
with them in general. They really want
to cut some deal where they give us a
discount on T3 chat for an ad, but those
are different businesses with no
overlap, and I try to explain it to them
and they get like angry at me for it.
So, that sucked. On top of that, I still
had to implement way too much [ __ ]
myself in order to make it a good
experience. and the documentation was
super unclear. The false positive rates
are significantly lower than they were
with recapture and the integration was
slightly less bad than recaptures, but
none of them are even close to good
developer experience. Chat's already
figured out where we're going with this.
Verscell's bot ID is a really, really
good option. Obviously, only useful if
you're already on Verscell, but if you
are on Verscell, it's pretty crazy.
There's a lot about Cloudflare that I
will defend. a lot about Cloud 4 that I
do not like. Turnstyle is such a [ __ ]
show. I cannot in good faith even like
say it without saying that. Like I
cannot mention Turnstyle without making
sure you're aware of how shitty an
experience it is for both developers and
users. If you're not showing the
Turnstyle widget on the page with a big
Cloudflare logo, there's like a 40%
chance it's going to fail. The invisible
mode doesn't [ __ ] work and they don't
have an invisible to visible promotion
path. So, you're [ __ ]
I cannot recommend anyone use Turnstyle
in its current state. I know they're
working on it, but it is a [ __ ] show. Of
these options, it like turnstyle cost us
business investments, tons of new users,
and so much more. Turn style was a [ __ ]
show for us. I highly recommend avoiding
it. And it ruins the developer
experience, too, because when you have
it on in dev, it just randomly injects
[ __ ] into the JS to test if you have a
debug flag or not to know if you're on a
real client. I've been through it with
Turnstyle. I could do like a 2hour video
about it. I'll cut it here. Just know it
[ __ ] sucks. That's all I'll say.
Watch my captures video to learn more in
detail about the hell that is Turnstyle.
What's cool about Bot ID is they've kind
of found the balance between something
like Turnstyle and something like H
Capture or Recapture. The benefit of
Turnstyle is that it's like entirely
free. You can only have a certain number
of widgets for different sites before
they make you go to the enterprise plan,
but it will authenticate as many users
as you want for free once you have it
set up. Something like H capture or
recapture is quite a bit more expensive.
Charges a dollar per thousand requests.
What's interesting here is you might
have noticed we have both of those
options. We have basic analysis which is
free. That's their alternative to
turnstyle. And they have deep analysis
for bot ID on Versell which is much more
comparable to something like H capture
or recapture for the dollar per thousand
checks. So you have both. And they're
even working on making it easier to
programmatically change which one for
different routes. I've been talking with
them a bunch about it cuz obviously they
want us to move and honestly I really
want to move. If I was building today,
this is probably what I would have
picked. And the integration is probably
the best part. Like compared to every
other solution, it's such a simple
integration. Like I had to write
probably a thousand lines of JS, debug a
bunch of different packages, none of
which worked, and spend two days sanity
checking to get recapture v3 working. If
anybody tells you it's easier than that,
that their implementation is broken. I
promise you. Whereas with bot ID, I go
to my next config. I wrap it with bot ID.
ID.
And now when I admit it in the
instrumentation client, I can specify to
protect different routes and different
methods on said routes. And now I'm
done. Now the client is all handled. You
might have to Okay, you have to put in
the bot ID client somewhere in your
React code. Just be on the route. And
now whenever somebody goes to one of
those protected routes or sends a
request to one of them, it will handle
everything for you. No weird plugging
between parts. You just use the
component. You make the config and
you're done. And when you're ready to
check const verification equals await
check bot ID. If verification isbot fail
them. This is so much better. It's so
comically better. Somebody asked will
bot ID still work if you turn off JS?
No. Nothing will [ __ ] work if you
turn off JS. Would you to put an
anti-DOS layer?
Most decent solutions handle that for
you. They either put Cloudflare in front
for you for the DOS protection or they
built their own thing that's even
better. Versel's firewall is much better
than Cloudflare's nowadays. So, I'm very
happy with the one that exists there.
So, and to be very clear, DOS protection
and bot protection are different things.
DOS protection is making sure that when
you get a huge surge of obviously fake
traffic that you block it before your
code is hit. Bot protection is making
sure that when your code is hit that
you're verifying if the user is a human
or not in order to prevent them from
sending something or doing something
automated. So for something like T3
chat, we don't put bot protection on
most of our endpoints. When you're
trying to get your user data or you're
trying to update something in the
database, we don't check if you're a bot
or not for those things. But if you're
trying to do something expensive, which
in our case is generate a message,
that's when we run our capture checks
because we want to make sure the
expensive thing can't be automated and
spammed. And we learned that one the
hard way. There is one other company
that I've been eyeing for all of this.
They're a recent sponsor and also an old
investment of mine. They took a while to
get all the pieces together, but they've
absolutely done it now. And again, one
of those things I wish existed when I
built T3 Chat. Arcjet is painless
security for all of the different [ __ ]
It's so much nicer to integrate than
most other solutions. If you want to do
like bot detection, rate limiting, email
validation, DOS protection, all this
[ __ ] They have all of it with a really
good SDK. You define the arcjet helper.
You can define a detect bot rule. So,
this will check if it's a bot or not.
And you can even choose to allow certain
categories like search engines. You can
have token buckets which make sure users
are only doing certain numbers of things
and choose how you identify a user. You
get the idea. It's a really cool
programmatic way to define security
layers in your application. I like these
guys a lot. They're building cool stuff.
Highly recommend checking it out if you
haven't. There's a reason I let them
sponsor and there's a reason I invested.
I think they're pretty cool. All that
said, if you're not on Versell, H
capture or ARCJet, if you are on Versel,
bot ID is really promising. DOS
protection, if you're not already on
Versel or Cloudflare, that's your
problem. Figure it out yourself. Rate
limiting. Every use case for rate
limiting is so different. That's your
problem. That's the core. We use convex
for the database. We use convex for the
app layer because again convex deploys
real code. Most things are going on
there now. I I don't really define a
whole lot of endpoints in Nex.js
anymore. But if I do need to for various
reasons, I still reach for TRRPC. O
layer varies a lot. I am hopeful for
better off soon. Otherwise, clerk work
OS. We've been over why client framework
react plus V or next. Next if you want
static pages, V if you don't. Tanstack
start coming very soon. style system.
Tailon and Chaden. Watch any of my other
videos to know why. Package management.
PNPM. Once mooras are better handled
than bun, we'll take it more seriously.
Until then, I have no issues with PNPM.
I'm very happy with it. It's one of the
few pieces of software that doesn't
really fail me ever. Back in host, still
on Versell also for all my web assets.
It's very convenient. Database host
Convex really convenient. They do all
those layers for me. And also now Convex
is built on top of Planet Scale, which
used to be my favorite database host. So
I get all the speed and scale benefits
that I would get from planet scale
without having to do it myself.
Analytics and the analytics host Postto
hog capture rate limits etc versus bot
ID or hc capture or arcjet payments
stripe or of course the alternatives
that are built on top of it autumn or
polar. One last piece here file upload.
Hopefully you guys know what we use for
this upload thing. I will say convex
solution is pretty good. The catch with
Convex is that it doesn't handle public
versus private files really at all.
Upload thing is a much more inclusive
file management and uploading solution.
Similar to how something like better off
is significantly better at O than Convex
off is. I'd say they're very similar in
that regard. The difference being you
don't have to config to get file
uploading working if you're doing it
with either tool. You do have to
configure a lot to get off working
regardless of what you're using. upload
thing will give the best experience for
file upload for your users, for fetching
said files, for managing private files,
for scaling to large numbers of files,
for making the DX of when a file upload
is completed and all of that good upload
thing will be the best solution by far
without [ __ ] your bandwidth as well.
Convex's file upload is fine, too,
though. Hell, in the image studio I'm
building right now, I'm using convex off
just cuz it was one less thing to add
and it made stuff pretty easy to do. I
even know where that would be configured.
configured.
Okay, the more I'm looking at this, I'm
realizing that I really should have used
upload thing because like all of this
code to fetch the image, make sure we
got the right HTTP response, convert the
blob, make sure we have the file size
annotated properly, all that. We handle
all this in upload thing. You hand us a
URL and we'll process the file for you.
So, I probably should have used upload
thing for this. But at least I can call context.sto.sstore
context.sto.sstore
the blob and then grab the URL by doing
context.sto.get URL. This is also the
thing I was talking about before though
where this URL you get is a permanent
URL. You can't really do a temporary
signed URL or anything like that. So
checks and balances. The goal of
everything above is that you can use
these regardless of what your answer is
on all these parts, but we can go into
these parts. Monor repos are a necessary
evil. I still wish they were much
better. Turbo repos made it much better.
Still not where I would want it to be,
but at least it's not the hell it was
before. mobile. You guys know we'll be
on Expo and React Native for a long ass
time. And if you want a really good
showcase of a React Native Expo app,
keep an eye out. T3 Chat's going to be
better than every other AI chat app, and
it's going to be built in React Native.
Effect if you need it. I'm starting to
get effect pled. I I know the value, but
it's also caused us enough problems like
like, okay, to be frank, I only see the
effect stuff when it's causing us
problems because I'm not in the details
of the code bases anymore. Like by the
time Julius is effectifying the
codebase, I've kind of had to move bore
to a management position anyways, but
effects incredible piece of software.
It's capable of a lot. It has made
things much better for us around error
management. And god, the [ __ ] stuff
that we can do with introspecting on
traces, the UIs we now have access to to
see every single thing that happened
during a generation or during a user
request all in axiom just with the
traces in hotel that were spitting out
of effect for free is incredible. So
it's absolutely been worth it for us. KV
store, I find that the use of KVs is
always some specific integration thing.
Like the KVS that we're using right now
for T3 chat are worker KV for open off.
So we have that isolated O thing.
Ideally you'd have an off solution
doesn't need that. We also use one for
our stripe storage which is upstally
you don't need that because you have a
payment provider that handles it
something like autumn or clerk or polar.
So again if you need it and then the IDE
I'm still on cursor. I find that it
matters less and less every day. Other
tools are catching up. Things like kilo
code, rue code, client, and more are
making VS Code really good. The fact
that C-Pilot's now open source and more
and more of what makes it work well in
the editor is accessible to extensions.
A lot of progress is being made in the
IDE space, but cursor is still my best
experience. That's the one that's the
most reliable that does the most. Even
though I love T-Max in my CLI in
general, I like managing my projects in
my CLI. I don't like writing code in it.
Still was never a Vim guy. So, I'm not
into stuff like Cloud Code, Open Code,
ADER, Codeex, and all that. And I guess
one last one, background agents. My
answer to that one is TBD. I've not been
happy with any of the current solutions.
I've tried most of them. They've not
been good for me. Maybe in the future,
we have something for that, but right
now, meh. There's a bunch of other
things that I use all of the time to
make our teams more efficient. things
like Discord for all our comms, graphite
for all our code reviews, code rabbit
for leaving feedback in said code
reviews, so much more. We've already
went really deep on things that aren't
necessarily my stack. I want to make
sure the value and the focus stays up
here. The pieces that I recommend
building with and that I personally
choose to build with today. And once
again, the point of this isn't that you
should copy paste it and use it for all
your projects. The point of this is to
show you how I think about the pieces I
use for my stack and to look at the ones
I tend to reach for and figure out which
pieces are useful to you and which ones
are not. If you take this whole stack,
copy paste it and use it and find
success with it. Awesome. I'm really
happy to hear. But never feel bad about
deleting parts that aren't necessarily
as useful for you, swapping things
around based on what your needs are, and
doing whatever you need to stack. The
point of it is that it's modular, that
all the parts are meant to be swapped
and interchanged. Even as I went
through, I showed you how I swap
different parts around depending on what
I'm building. I'm much less interested
in people copying my stack and much more
interested in people thinking about
their stack in this way. A more modular
approach around what you're trying to
build and how you're trying to assemble
those parts together. This is how I
assembled them today and it's very
different from how I did last year and
it's very different from how I did it 3
years before. And hopefully this way of
building things is useful to you as
well. Hope this was helpful. Can't wait
to figure out what database I move to next.
Click on any text or timestamp to jump to that moment in the video
Share:
Most transcripts ready in under 5 seconds
One-Click Copy125+ LanguagesSearch ContentJump to Timestamps
Paste YouTube URL
Enter any YouTube video link to get the full transcript
Transcript Extraction Form
Most transcripts ready in under 5 seconds
Get Our Chrome Extension
Get transcripts instantly without leaving YouTube. Install our Chrome extension for one-click access to any video's transcript directly on the watch page.