The /shared directory contains Zod schemas used between frontend and backend.
cd shared
npm installcd backend
npm installCreate the .env file in the backend directory with the following content:
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
NODE_ENV="development"
FRONTEND_ORIGIN="http://localhost:3000"
POSTGRES_PRISMA_URL="postgresql://postgres:summer@localhost:5432/mydb?schema=public"
POSTGRES_URL_NON_POOLING="postgresql://postgres:summer@localhost:5432/mydb?schema=public"
PORT=4000
KEY1="<generate_with_openssl_rand_hex_32>"
KEY2="<generate_with_openssl_rand_hex_32>"
RESEND_API_KEY="Dummy Resend API Key"
AUTH_SECRET="<generate_with_openssl_rand_hex_32>"
AUTH_SALT="next-auth.session-token"
CRON_SECRET="<generate_with_openssl_rand_hex_32>"
BLOB_READ_WRITE_TOKEN="<development_vercel_blob_token>"
BOOTSTRAP_ADMIN_EMAIL="admin@example.com"
BOOTSTRAP_ADMIN_NAME="Local Admin"
BOOTSTRAP_ADMIN_PASSWORD="<local_admin_password>"
Note that the following variables should be changed to match your local setup:
POSTGRES_PRISMA_URL: postgres://:@localhost:/?schema=schemaPOSTGRES_URL_NON_POOLINGRESEND_API_KEYis shared in the development team.AUTH_SECRETmust match the frontendAUTH_SECRET(same value).AUTH_SALTmust benext-auth.session-token(the session cookie name used by the frontend in this repo).CRON_SECRETmust match the frontendCRON_SECRET(same value).BLOB_READ_WRITE_TOKENis required for file uploads and must be a valid Vercel Blob token. Do not commit it.BOOTSTRAP_ADMIN_EMAIL,BOOTSTRAP_ADMIN_NAME, andBOOTSTRAP_ADMIN_PASSWORDare used bynpm run db:bootstrapto create the first admin only when it does not already exist. Do not commit real production credentials.
KEY1 and KEY2 are used for security purposes. They should be changed to a random string, for example, by running either of the following command:
openssl rand -hex 32or
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"If you are using Docker, you can launch the database with the following command:
npm run db:startReset the local database, run migrations, and bootstrap required data:
npm run prisma:initRun only the idempotent bootstrap seed for required production-safe data:
npm run db:bootstrapInsert local dummy data explicitly when needed:
npm run seed:dummyVercel deploys run npm run build, which generates Prisma, applies migrations with prisma migrate deploy, and then runs the idempotent bootstrap seed.
cd backend
npm run testTests run in parallel using one PostgreSQL instance with one database per Vitest worker (databases are named aaasobo_test_<workerId> and are created/dropped automatically). Use Docker (Testcontainers), or set TEST_DATABASE_URL (or POSTGRES_PRISMA_URL/DATABASE_URL via backend/.env) to a reachable PostgreSQL instance; the configured DB user must be able to create/drop databases.
npm run devThe following message should be displayed:
$ npm run dev
> backend@1.0.0 dev
> nodemon --exec ts-node ./api/app.ts
[nodemon] 3.1.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: ts,json
[nodemon] starting `ts-node ./api/app.ts`
[Server]: http://localhost:4000cd frontend
npm installCreate a .env file in the frontend directory with the following content:
NEXTAUTH_SECRET="<generate_with_openssl_rand_hex_32>"
AUTH_SECRET="<generate_with_openssl_rand_hex_32>"
AUTH_SALT="next-auth.session-token"
AUTH_TRUST_HOST=true
NEXT_PUBLIC_FRONTEND_ORIGIN="http://localhost:3000"
# Optional. Default is http://localhost:4000
BACKEND_ORIGIN="http://localhost:4000"
# Optional. Default is http://localhost:4000
NEXT_PUBLIC_BACKEND_ORIGIN="http://localhost:4000"
CRON_SECRET="<same_value_as_backend_CRON_SECRET>"
BLOB_READ_WRITE_TOKEN="<development_vercel_blob_token>"
NEXTAUTH_SECRET and AUTH_SECRET should be randomly generated. See the backend section above. AUTH_SECRET, AUTH_SALT, and CRON_SECRET must match the backend values. BLOB_READ_WRITE_TOKEN is required for file uploads and must not be committed.
npm run devThe frontend should be available at http://localhost:3000.
This project is structured to separate concerns and make it easier to maintain and scale the application. Below is an overview of the key folders:
The components/ folder is organized into three main subfolders to promote code reusability and better organization.
Contains generic, low-level UI components that can be used across multiple features. These components are simple and don't contain any business logic. Examples include:
breadcrumb/โ A component for showing the page hierarchy.buttons/โ Reusable button components with different styles.loading/โ Components for showing loading states.modal/โ A reusable modal dialog component.
This folder contains components that belong to specific application features and are used across multiple pages. They are more complex and include business logic or interact with backend data. Examples include:
calendar/โ The main calendar view.classDetail/โ Displays detailed information about a class.classesTable/โ A table for displaying and managing classes.
This folder holds structural components that define the layout and navigation of the application. These include global elements used across the app, like side navigation bars. Examples:
sideNav/โ A sidebar navigation menu for the app.
components/
elements/
breadcrumb/
buttons/
loading/
modal/
features/
calendar/
classDetail/
classesTable/
layout/
sideNav/
The helper/ folder contains utility files and logic that assist with various aspects of the application, but aren't directly tied to the UI or core features. It's organized into three subfolders: api/, data/, and utils.
This folder contains functions that handle interactions with the backend controllers. These are typically service-like functions that facilitate communication between the frontend and the backend by calling specific controller actions.
adminsApi.tsโ Functions related to API calls for admin data, interacting with backend controllers.customersApi.tsโ Functions related to API calls for customer data, interacting with backend controllers.
Contains files with static or predefined data that might be used throughout the application. These files store non-dynamic data like navigation links or fixed configurations.
data.tsโ Contains any general or shared data used across the app.navLinks.tsโ Defines the navigation links structure for the app, used in the sidebar.
This folder holds general utility functions that perform tasks like data formatting or other common operations. These functions are reusable across different parts of the application.
authenticationUtils.tsโ Functions for authentication-related tasks like password validation, token verification, etc.dateUtils.tsโ Functions for working with dates, such as formatting, parsing, or manipulating date objects.
helper/
api/
adminsApi.ts
customersApi.ts
data/
data.ts
navLinks.ts
utils/
authenticationUtils.ts
dateUtils.ts