The first app in which I implemented the actual authentication lifecycle using JWTs (JSON Web Token).
Since I first met and tried web development in late 2021, authentication has been my weakest point. After 2 years of avoidance, I finally decided to take it seriously to figure out and understand how exactly authentication works; how to:
- Sign up?
- Sign in?
- Know if the user has signed in?
- Persist the session?
As bolded out, I have struggled a lot trying to understand how the last two things are done.
So, the universe has carried me to the point where I finally began building a personal project just to learn about how to solve these problems.
Moreover, my greater motivation is that I want this app to help those among you who also struggle to understand the logic behind authentication.
Therefore, I've been building this app for educational purposes.
Of course not!
What do you think I have been doing since 2021? Continuously learning about web development:
- Basics:
- HTML, CSS, JavaScript
- How the web works
- Data flow:
- What "client" and "server" exactly are
- Where data are stored (databases)
- HTTP
- How servers send data (APIs)
- How data are served (mostly JSON)
- How clients request & get data (sending HTTP requests to APIs)
- TypeScript 💙 (my favorite language by far)
- Frontend & backend libraries and frameworks:
- React
- Node.js with various libraries:
- Express
- Prisma
...and so on. It seemed like I was going a bit out of scope.
Briefly, I have learned so much about the web and discovered lots of helpful libraries & frameworks that I wanted to introduce. This app also involves lots of them, which serves my purpose.
I believe that discovering new libraries is a huge source of encouragement to learn more about web development. At least, that's the case for me. Therefore, I hope those used in this app inspire you guys:
- T3 Stack
- Next.js (a React framework): The "skeleton," so to say. Both the frontend and the backend are handled by Next.js.
- Tailwind CSS: A wonderful CSS library. Provides lots of utility classes. One of my favorites.
- tRPC: APIs could not be more fun! Seriously, one of the most fun libraries to use. I absolutely love it.
- Prisma: A dope ORM that makes it easy to manage DBs. I pretty much like it!
- I have previously wanted to introduce Drizzle ORM in this project. However, it had so many bugs that I got pretty frustrated. I think they need some time getting Drizzle to a trustable level.
- Zod: A validation library. The TypeScript that works in runtime, that's how I see Zod.
- Zustand: A very lightweight yet powerful state management library. They say Redux is so much more complicated. I have only used Zustand so far, as a third-party state management library.
- React Hook Form: A form state management library. Works nice with Zod.
- shadcn/ui: A dope UI library that provides nice components.
- React Email: Prepare emails with JSX!
- nodemailer: Send emails with ease. (Used Resend previously)
- js-cookie: Cookie API library.
- better-sqlite3: What is needed for SQLite database management.
- clsx: Makes
className
s better to write. - Framer Motion: Animation? Here it is.
- jsonwebtoken: Generate and decode JWTs.
- next-themes: Light/dark modes.
- React Icons: Self-explanatory.
- bcrypt: Used for safe password encryption.
Alright, alright — here comes the fun part!
-
Firstly, you should have NodeJS installed. You may download the installer here.
-
Then, you need to install the pnpm package manager. You may use the following commands:
- Windows (PowerShell):
iwr https://get.pnpm.io/install.ps1 -useb | iex
- Linux (POSIX):
curl -fsSL https://get.pnpm.io/install.sh | sh -
For other alternatives and more details, see pnpm docs. I'm a Windows user, and I preferred the Choco option.
- Windows (PowerShell):
To persist data, an app should use a database system. For this purpose, I used PostgreSQL in this project. So, with defaults, you should install and configure PostgreSQL, too. You can download it here.
After you satisfy these prerequisites, clone this repo to your local system. Then, all you need is the following command to finalize the installation phase:
pnpm i
This command checks the package.json
and pnpm-lock.yaml
to analyze all package dependencies and install all required packages with proper versions. See the details here.
This part is crucial for the app to run seamlessly. Create a copy of the .env.example
file and name it as .env
. Then, configure the following environment variables:
-
NEXT_HOST
(defaults tolocalhost
): Specifies the host that the app will run at. This variable doesn't actually configure the host. You might not touch it at all. -
NEXT_PORT
(defaults to3000
): Specifies the port. LikeNEXT_HOST
, it doesn't configure the port but rather serves it. To change the actual port, openpackage.json
and use the-p
flag to change the following scripts as follows:"scripts": { "dev": "next dev -p 5678", "start": "next start -p 5678" }
The value
5678
is given as an example. You may use another suitable value.As an alternative, you may not touch the scripts at all, and provide the port when running them:
pnpm dev -p 3452
pnpm start -p 3452
-
DB_HOST
(defaults tolocalhost
): The host that the database server (PostgreSQL) is running at. If you run everything locally, this may remain unchanged. -
DB_PORT
(defaults to5432
): The port that the database server is listening at. PostgreSQL's default installation sets the port to 5432. -
Database credentials:
DB_USER
,DB_PASSWORD
(default topostgres
and123456
): PostgreSQL's installer wants you to provide them anyway. Configure them accordingly. -
DB_NAME
(defaults toauthsandbox
): The database's name. You may change it however you want. -
DATABASE_URL
: This variable is generated using theDB_
-prefixed variables above. Configure them, not this. -
GMAIL_ACCOUNT_EMAIL_ADDRESS
andGMAIL_APP_PASSWORD
: The app sends verification emails using Gmail's SMTP. Please refer to the comments in.env.example
. -
ACCESS_TOKEN_DURATION
andREFRESH_TOKEN_DURATION
: The lifetime of the auth tokens. They default to 5 minutes and 1 month, respectively.
After configuring the environment variables, you should setup the Prisma stuff. Just run the following two commands:
pnpm db:generate
pnpm db:push
Then, you should be good to go.
After you complete the steps above, you should be able to run the app. First, run pnpm build
to build the app, then run pnpm start
to run the app.
If you want to modify the code and see the results immediately, you may choose to run the app in development mode: pnpm dev
.