React Express Auth Template Overview
Follow along with the React Express + Auth Template repository here!
This repository is a full-stack starter for apps that need user accounts and authentication. It uses a React frontend, an Express server, and Postgres accessed through the pg package.
Table of Contents
Application Overview
This template provides the auth foundation for applications that need users. The backend includes:
A
userstable schema initializer (server/db/init.js)A
Usermodel (server/models/User.js) that runs SQL queries withpgAuth and user endpoints for registration, login, profile lookup, updates, and logout
The users table looks like this:
id(primary key)username(unique)password_hash(bcrypt hash)created_atupdated_at
With this functionality, users can:
Register (create) a new user account with a username and password
Log in using their credentials
View a list of all users
View a single user's page
Update their username (and only their own)
Log out
The frontend is intentionally minimal so teams can build on top of it.
Getting Started
Create your repo
If you are working on a team, first make sure your team has a GitHub Organization for your project.
Select Use this template and choose Create a new repository.
Clone your repo and open it in your editor.
Getting to know the folder structure
At the root:
frontend/— React appserver/— Express app + Postgres access
Important server directories/files:
server/index.js— server entrypoint and route wiringserver/controllers/— route handler logicserver/models/User.js— database model methodsserver/db/pool.js— shared Postgres pool (pg)server/db/init.js— one-time schema initialization script
Configure your database and environment variables
Before building features, create a local Postgres database and configure the server environment variables.
Create a Postgres database with a name of your choice.
In
server/, create.envby copyingserver/.env.template.Update values to match your local Postgres setup.
Replace
SESSION_SECRETwith your own random string.
Example:
How DB connection works:
If
PG_CONNECTION_STRINGis present,server/db/pool.jsuses it.Otherwise, the pool uses
PG_HOST,PG_PORT,PG_USER,PG_PASS, andPG_DB.
Kickstart the project
From the project root, run:
You can also run:
After initialization, start both apps in separate terminals:
Recommended Approach for Building
Work from database -> model -> controllers -> frontend.
This minimizes blockers because frontend behavior depends on server routes, and server routes depend on database behavior.
Testing Along the Way
Database schema: run
npm run db:init, then inspect tables withpsql, TablePlus, or Postico.Model: call model methods from a scratch script and confirm DB state.
Controllers / Endpoints: use Postman or Insomnia and verify DB changes.
Adapters / Components: interact with the frontend and confirm API + DB behavior.
Database
The project uses Postgres directly through pg (node-postgres). There is no Knex, and there are no migration/seed folders in this refactor.
Database Initialization
server/db/init.js creates the users table if it does not exist.
Run it with:
Core schema:
Database Access with pg
pgserver/db/pool.js creates a shared Pool from pg.
Model queries use parameterized SQL with $1, $2, etc:
This approach keeps SQL injection protections while staying close to native SQL.
The Server Application
Server Overview
server/index.js wires middleware and routes:
cookie-sessionfor auth cookiesexpress.json()for JSON request parsingauth routes under
/api/authuser routes under
/api/usersstatic frontend serving from
frontend/dist
User Model
server/models/User.js encapsulates user data access:
User.create(username, password)User.list()User.find(id)User.findByUsername(username)User.update(id, username)
The model constructor stores password_hash privately so user instances can be returned safely without exposing hashes.
Controllers and API endpoints
Auth routes:
POST /api/auth/registerPOST /api/auth/loginGET /api/auth/meDELETE /api/auth/logout
User routes (protected):
GET /api/usersGET /api/users/:idPATCH /api/users/:id
Creating New Users: Securing Passwords with Bcrypt
Before insertion, plain-text passwords are hashed using bcrypt (SALT_ROUNDS = 12). Only the hash is stored in password_hash.
Logging In: Authentication and Authorization
Auth flow:
Login verifies username + password.
On success,
req.session.userIdis set.Protected routes use middleware to ensure a valid session.
Update route authorization ensures users can only update their own profile.
Front-end
Frontend Utils
frontend/src/utils/fetchingUtils.js provides shared fetch behavior for API calls.
Adapters
Adapters in frontend/src/adapters/ isolate API request logic from components:
auth-adapter.jsuser-adapter.js
Example Page Component
Pages in frontend/src/pages/ implement route-level UI:
Home.jsxLogin.jsxSignUp.jsxUsers.jsxUser.jsx
Current User Context
frontend/src/contexts/CurrentUserContextProvider.jsx stores the authenticated user in app state and exposes it via context.
Deploying
For deployment:
Set production environment variables (
SESSION_SECRET,PG_CONNECTION_STRING, etc.).Build frontend assets.
Run
npm run db:initagainst the target database at least once.Start the server with
npm start.
Last updated