Readory is a TypeScript npm-workspace monorepo for a serialized reading platform. It includes a Next.js frontend, a NestJS API server, and a shared package consumed by both applications.
readory-banner.mp4
Readory lets readers discover, buy access to, organize, and read books and chapters while giving administrators tools to operate the catalog and platform.
Current platform capabilities include:
- Public discovery pages for home content, books, genres, dynamic book types, contributors, public profiles, collections, and live search.
- Reader flows for image, text, and PDF-derived chapter content with reading context and progress persistence.
- Account flows for registration, OTP verification, login, Google sign-in/linking, password reset, logout, session refresh, device/session management, and profile retrieval.
- Wallet flows for balances, transaction history, deposits, payment initialization, payment callbacks, and payment result pages.
- User dashboard pages for library, reading history/export, progress, favorites, collections, settings, connected devices, and notifications.
- Admin pages for books, chapters, chapter content, scheduled publications, collections, contributors, genres, book types, media, users, staff, transactions, notifications, audit logs, settings, and overview dashboards.
- PostgreSQL persistence through Prisma migrations and a seed script.
- Redis-backed infrastructure for caching, throttling-related services, queues, scheduled publishing, notifications, PDF/text processing, and session-related data.
- S3-compatible object storage for media and chapter content.
- Meilisearch-backed search.
- Email delivery through SMTP/Nodemailer templates.
- English and Persian frontend localization.
.
├── frontend/ # Next.js App Router application
├── server/ # NestJS API, Prisma schema/migrations, backend tests
├── shared/ # Internal @readory/shared TypeScript package
├── assets/ # README screenshots
├── package.json # Root workspace scripts and dependencies
└── package-lock.json
| Area | Technologies |
|---|---|
| Monorepo | npm workspaces, TypeScript, Prettier |
| Frontend | Next.js 16, React 19, TypeScript, App Router, next-intl, SWR, React Hook Form, Zod |
| Frontend UI | Tailwind CSS 4, Radix UI, shadcn-style local components, lucide-react, next-themes, Recharts, dnd-kit, Framer Motion |
| Backend | NestJS 11, Passport, JWT, class-validator, class-transformer, Helmet, throttling |
| Data | PostgreSQL, Prisma Client, Prisma migrations, pg, @prisma/adapter-pg |
| Auth | Cookie-backed access/refresh tokens, argon2 password hashing, Google OAuth ID-token verification, role/permission guards |
| Storage/media | AWS SDK S3 client, S3 presigned URLs, Multer, Sharp, PDF tooling |
| Infrastructure | Redis, BullMQ, Nest schedule, Meilisearch, Nodemailer |
| Testing | Jest, ts-jest, Supertest, Nest testing utilities, frontend linting |
Install or provision the following before running the full application:
- Node.js and npm compatible with the versions used by Next.js 16 and NestJS 11.
- PostgreSQL.
- Redis.
- S3-compatible object storage.
- Meilisearch.
- SMTP credentials for email-dependent flows.
- A Google OAuth client ID if Google sign-in/linking should be enabled.
Install dependencies from the repository root:
npm installBuild the shared workspace before running either app:
npm run build:sharedDuring shared-package development, run:
npm run dev:sharedCreate local environment files from the examples:
cp server/.env.example server/.env
cp frontend/.env.local.example frontend/.env.localThe server example includes runtime, database, JWT/session, admin-session, Google, Redis, rate-limit, S3, mail, collection, scheduled-publishing, notification, PDF-processing, and Meilisearch keys. The frontend example includes the public API URL, public media base URL, and public Google client ID.
At minimum for local development, set:
| File | Key | Purpose |
|---|---|---|
server/.env |
DATABASE_URL |
PostgreSQL connection string. |
server/.env |
JWT_SECRET |
Secret for signing/verifying JWTs. |
server/.env |
CORS_ORIGIN |
Frontend origin allowed to send credentialed browser requests. |
server/.env |
FRONTEND_URL |
Frontend URL used by redirects and email links. |
server/.env |
REDIS_HOST, REDIS_PORT |
Redis connection for cache and queue-backed services. |
server/.env |
S3_* |
S3-compatible storage configuration. |
server/.env |
MEILISEARCH_HOST, MEILISEARCH_API_KEY |
Search service configuration. |
frontend/.env.local |
NEXT_PUBLIC_API_BASE |
Base URL for the NestJS API. |
frontend/.env.local |
NEXT_PUBLIC_S3_PUBLIC_BASE_URL |
Public URL for media/chapter assets. |
Never commit real secrets.
Run Prisma commands from server/:
cd server
npx prisma generate
npx prisma migrate dev
npx prisma db seedThe seed script requires SEED_ADMIN_PASSWORD in server/.env.
Run the backend and frontend in separate terminals after dependencies, shared build, and env files are ready:
npm --workspace server run start:dev
npm --workspace frontend run devBy default, the server listens on PORT from server/.env, and the frontend uses the backend URL from NEXT_PUBLIC_API_BASE.
| Command | Description |
|---|---|
npm run build |
Runs build in all workspaces. |
npm run build:shared |
Builds @readory/shared. |
npm run dev:shared |
Builds @readory/shared in watch mode. |
npm run format |
Formats the repository with Prettier. |
npm run format:check |
Checks formatting without writing. |
Use these from the repository root with npm --workspace <workspace> run <script> or from inside each workspace.
| Command | Description |
|---|---|
npm run dev |
Starts the Next.js development server. |
npm run build |
Creates a production Next.js build. |
npm run start |
Starts the built Next.js app. |
npm run lint |
Runs ESLint. |
| Command | Description |
|---|---|
npm run start |
Starts NestJS. |
npm run start:dev |
Starts NestJS in watch mode. |
npm run start:debug |
Starts NestJS in debug watch mode. |
npm run build |
Compiles the server into server/dist/. |
npm run start:prod |
Runs node dist/main. |
npm run lint |
Runs ESLint with automatic fixes. |
npm run format |
Formats server source and test files. |
npm run test |
Runs unit tests. |
npm run test:watch |
Runs unit tests in watch mode. |
npm run test:cov |
Runs tests with coverage. |
npm run test:debug |
Runs Jest under the Node inspector. |
npm run test:e2e |
Runs e2e tests with test/jest-e2e.json. |
A typical deployment should:
- Install dependencies with
npm install. - Configure all required server and frontend environment variables.
- Build the shared package with
npm run build:shared. - Apply Prisma migrations against the target database.
- Build the server and frontend with
npm --workspace server run buildandnpm --workspace frontend run build. - Start the server with
npm --workspace server run start:prod. - Start the frontend with
npm --workspace frontend run start. - Confirm
CORS_ORIGINincludes the frontend origin andNEXT_PUBLIC_API_BASEpoints to the deployed backend.
Build outputs:
- Frontend:
frontend/.next/. - Server:
server/dist/. - Shared package:
shared/dist/.
- Backend setup and API details:
server/README.md. - Frontend setup, routes, and UI details:
frontend/README.md.
| Text | Image |
|---|---|
![]() |
![]() |
| Admin | User |
|---|---|
![]() |
![]() |
Readory includes a Docker setup for the full stack: Next.js frontend, NestJS backend, PostgreSQL, Redis, MinIO, and Meilisearch.
Development keeps source files bind-mounted so frontend and backend changes do not require image rebuilds. Dependencies stay inside named Docker volumes so host node_modules do not overwrite container dependencies.
cp .env.development.example .envStart only shared infrastructure when you want to run the apps with their normal local commands on the host:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up postgres redis minio meilisearch
npm install
npm run build:shared
npm --workspace server run start:dev
npm --workspace frontend run dev -- --port 3001Or run the app containers with hot reload enabled:
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile app up --buildUseful local endpoints:
- Frontend: http://localhost:3001
- Backend API: http://localhost:3000
- MinIO API: http://localhost:9000
- MinIO console: http://localhost:9001
- Meilisearch: http://localhost:7700
Create a production .env from .env.example, replace every secret, and point public URLs at the deployed hostnames:
cp .env.example .env
# edit .envBuild reproducible production images and start the full stack:
docker compose up --build -dRun database migrations explicitly if needed:
docker compose run --rm migrateStop the stack while preserving data volumes:
docker compose downStop the stack and delete local data volumes:
docker compose down -v- Production images use a single multi-stage
Dockerfilewith separateserverandfrontendtargets. - Development uses
docker-compose.dev.ymloverrides, bind mounts, and namednode_modulesvolumes for fast hot reload without rebuild loops. - Containers communicate through Compose service names such as
postgres,redis,minio, andmeilisearch. - Secrets and deployment-specific values live in
.env; committed files only provide examples. - Healthchecks gate backend startup on infrastructure readiness and frontend startup on backend readiness.





