A modern open-source platform for reading and writing novels, stories, and serialized fiction. Built with NestJS, SvelteKit, and PostgreSQL.
- About
- Features
- Tech Stack
- Architecture
- Getting Started
- Development
- Testing
- Deployment
- Project Structure
- API Documentation
- Contributing
- License
ReadNovls is a full-featured platform similar to Wattpad or Royal Road, where authors can publish their stories chapter by chapter, and readers can discover, read, and engage with content through likes, views, and comments.
-
User Management
- Email/password authentication
- Google OAuth integration
- JWT-based session management
- User profiles and account management
-
Story Management
- Create single stories or multi-part series
- Rich text editor with TipTap
- Draft and publish functionality
- Cover image uploads with Cloudinary
- Genre and tag categorization
- Mature content flagging
- Featured stories
-
Reader Engagement
- Like and view tracking with rate limiting
- Comment system
- Story discovery and search
- Responsive reading experience
-
Admin Features
- Content moderation
- User management
- Featured story curation
- Analytics dashboard
-
Infrastructure
- Background job processing with BullMQ
- Redis caching
- Email notifications
- Full-text search
- RESTful API with Swagger documentation
- Health checks and monitoring
- Framework: NestJS 11
- Database: PostgreSQL 16 with TypeORM
- Cache/Queue: Redis 7 with BullMQ
- Authentication: Passport.js with JWT
- Email: Resend / Nodemailer
- File Upload: Cloudinary
- Security: Helmet, CSRF protection, rate limiting
- Logging: Pino
- API Docs: Swagger/OpenAPI
- Framework: SvelteKit 2 with Svelte 5
- Styling: TailwindCSS 4
- UI Components: Bits UI
- Rich Text: TipTap
- Forms: Formsnap with Zod validation
- HTTP Client: Axios
- Testing: Vitest, Playwright
- Containerization: Docker with Docker Compose
- Package Manager: pnpm workspaces
- Language: TypeScript
This is a pnpm workspace monorepo with the following structure:
aaccraa/
βββ apps/
β βββ api/ # NestJS REST API
β βββ web/ # SvelteKit web application
β βββ admin/ # SvelteKit admin panel
βββ packages/ # Shared packages (future)
The API follows NestJS best practices with a modular architecture:
src/modules/- Feature modules (auth, users, stories, etc.)src/common/- Shared utilities, decorators, filters, interceptorssrc/core/- Core functionality (database, docs, mail, queue, redis, security)src/providers/- External service integrations (Cloudinary, AutoSend)
Path aliases are configured for clean imports:
@/modules/*βsrc/modules/*@/common/*βsrc/common/*@/core/*βsrc/core/*@/providers/*βsrc/providers/*
Both web and admin apps follow a similar structure:
src/lib/- Shared components, utilities, types, hookssrc/modules/- Feature-specific components and logicsrc/routes/- SvelteKit file-based routing with route groupssrc/services/- API service layersrc/styles/- Global styles
- Node.js >= 20.0.0
- pnpm >= 9.0.0
- Docker and Docker Compose (for database and Redis)
- PostgreSQL 16+ (if not using Docker)
- Redis 7+ (if not using Docker)
-
Clone the repository
git clone https://github.com/yourusername/aaccraa.git cd aaccraa -
Install dependencies
pnpm install
Copy the example environment file:
cp apps/api/.env.example apps/api/.envEdit apps/api/.env and configure:
Required:
# Server
PORT=3002
FRONTEND_URL=http://localhost:5173
# JWT Secrets (generate with: node -e "console.log(require('crypto').randomBytes(64).toString('hex'))")
JWT_SECRET=your-strong-secret-here
JWT_REFRESH_SECRET=your-different-strong-secret-here
CSRF_SECRET=your-csrf-secret-here
ANONYMOUS_VIEW_SECRET=your-view-secret-here
# Database
DB_HOST=localhost
DB_PORT=5433
DB_USER=aaccraa
DB_PASSWORD=your-secure-password
DB_NAME=aaccraa
# Redis
REDIS_HOST=localhost
REDIS_PORT=6380
REDIS_PASSWORD=your-secure-redis-password
# Email (AutoSend or other provider)
AUTOSEND_API_KEY=your-api-key
MAIL_FROM=noreply@yourdomain.comOptional:
# Google OAuth (for social login)
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_CALLBACK_URL=http://localhost:3002/api/v1/auth/google/callbackcp apps/web/.env.example apps/web/.envEdit apps/web/.env:
PUBLIC_API_URL=http://localhost:3002cp apps/admin/.env.example apps/admin/.envEdit apps/admin/.env:
PUBLIC_API_URL=http://localhost:3002Start PostgreSQL and Redis with Docker Compose:
cd apps/api
docker-compose up -dThis starts:
- PostgreSQL on port 5433
- Redis on port 6380
Install PostgreSQL 16+ and Redis 7+ locally and update the connection details in your .env file.
cd apps/api
pnpm build
pnpm migration:runpnpm seedFrom the root directory:
pnpm devThis starts:
- API: http://localhost:3002
- Web: http://localhost:5173
- Admin: http://localhost:5174
# API only
pnpm dev:api
# Web only
pnpm dev:web
# Admin only
pnpm dev:adminWhen the API is running, access Swagger documentation at:
http://localhost:3002/api/docs
http://localhost:3002/api/v1/health
pnpm testcd apps/api
pnpm test # Unit tests
pnpm test:watch # Watch mode
pnpm test:cov # Coverage report
pnpm test:e2e # E2E testscd apps/web
pnpm test:unit # Unit tests
pnpm test:e2e # Playwright E2E testscd apps/admin
pnpm test:unit # Unit tests
pnpm test:e2e # Playwright E2E testspnpm build-
Configure production environment
cp .env.production.example .env.production
-
Edit
.env.productionwith production values:- Generate strong secrets for JWT tokens
- Set strong database passwords
- Configure your domain for FRONTEND_URL
- Set up email service credentials
-
Build and deploy
docker-compose -f docker-compose.prod.yml up -d --build
This starts:
- PostgreSQL (internal only)
- Redis (internal only)
- API on port 3002
- Web on port 3000
docker exec -it readnovls-api-prod pnpm migration:run:prod# View all logs
docker-compose -f docker-compose.prod.yml logs -f
# View specific service logs
docker-compose -f docker-compose.prod.yml logs -f api
docker-compose -f docker-compose.prod.yml logs -f webaaccraa/
βββ apps/
β βββ api/ # NestJS Backend
β β βββ src/
β β β βββ common/ # Shared utilities
β β β β βββ decorators/ # Custom decorators
β β β β βββ entities/ # Base entities
β β β β βββ filters/ # Exception filters
β β β β βββ interceptors/
β β β β βββ middleware/
β β β β βββ utils/
β β β βββ core/ # Core functionality
β β β β βββ config/ # Configuration
β β β β βββ database/ # TypeORM & migrations
β β β β βββ docs/ # Swagger setup
β β β β βββ health/ # Health checks
β β β β βββ logger/ # Pino logger
β β β β βββ mail/ # Email service
β β β β βββ queue/ # BullMQ jobs
β β β β βββ redis/ # Redis client
β β β β βββ scheduler/ # Cron jobs
β β β β βββ security/ # Security config
β β β βββ modules/ # Feature modules
β β β β βββ accounts/ # Account management
β β β β βββ admin/ # Admin features
β β β β βββ auth/ # Authentication
β β β β βββ comments/ # Comment system
β β β β βββ profile/ # User profiles
β β β β βββ stories/ # Story management
β β β β β βββ dto/
β β β β β βββ entities/
β β β β β βββ services/
β β β β βββ upload/ # File uploads
β β β β βββ users/ # User management
β β β βββ providers/ # External services
β β β β βββ autosend/ # Email provider
β β β β βββ cloudinary/ # Image hosting
β β β βββ main.ts # Application entry
β β βββ test/ # E2E tests
β β βββ .env.example
β β βββ docker-compose.yml
β β βββ package.json
β β
β βββ web/ # SvelteKit Web App
β β βββ src/
β β β βββ lib/ # Shared code
β β β β βββ assets/ # Images, fonts, etc.
β β β β βββ axios/ # Axios config
β β β β βββ components/ # Reusable components
β β β β βββ hooks/ # Custom hooks
β β β β βββ types/ # TypeScript types
β β β β βββ utils/ # Utility functions
β β β βββ modules/ # Feature modules
β β β β βββ auth/ # Auth components
β β β β βββ comments/ # Comment components
β β β β βββ profile/ # Profile components
β β β β βββ stories/ # Story components
β β β βββ routes/ # SvelteKit routes
β β β β βββ (auth)/ # Auth route group
β β β β βββ (system)/ # Public routes
β β β β βββ sitemap.xml/
β β β βββ services/ # API services
β β β β βββ auth/
β β β β βββ comments/
β β β β βββ stories/
β β β β βββ upload/
β β β βββ styles/ # Global styles
β β βββ static/ # Static assets
β β βββ .env.example
β β βββ package.json
β β
β βββ admin/ # SvelteKit Admin Panel
β βββ src/
β β βββ lib/ # Shared code
β β β βββ assets/
β β β βββ axios/
β β β βββ components/
β β β βββ hooks/
β β β βββ types/
β β β βββ utils/
β β βββ modules/ # Feature modules
β β β βββ auth/
β β βββ routes/ # SvelteKit routes
β β β βββ (admin)/ # Admin route group
β β β βββ (auth)/ # Auth route group
β β βββ services/ # API services
β β β βββ analytics/
β β β βββ auth/
β β β βββ stories/
β β β βββ users/
β β βββ styles/ # Global styles
β βββ static/
β βββ .env.example
β βββ package.json
β
βββ packages/ # Shared packages (future)
βββ docker-compose.prod.yml # Production deployment
βββ .env.production.example
βββ pnpm-workspace.yaml
βββ package.json
βββ README.md
POST /api/v1/auth/register
POST /api/v1/auth/login
POST /api/v1/auth/refresh
POST /api/v1/auth/logout
GET /api/v1/auth/google
GET /api/v1/auth/google/callback
GET /api/v1/stories
GET /api/v1/stories/:id
POST /api/v1/stories
PUT /api/v1/stories/:id
DELETE /api/v1/stories/:id
POST /api/v1/stories/:id/publish
POST /api/v1/stories/:id/like
POST /api/v1/stories/:id/view
GET /api/v1/users/me
PUT /api/v1/users/me
GET /api/v1/users/:id
For complete API documentation, run the API and visit /api/docs.
pnpm dev # Run API and web in parallel
pnpm dev:api # Run API only
pnpm dev:web # Run web only
pnpm dev:admin # Run admin only
pnpm build # Build all packages
pnpm test # Run tests in all packages
pnpm lint # Lint all packages
pnpm format # Format code with Prettierpnpm build # Build the application
pnpm dev # Start in watch mode
pnpm start:prod # Start production build
pnpm test # Run unit tests
pnpm test:e2e # Run E2E tests
pnpm lint # Lint and fix
pnpm migration:generate # Generate new migration
pnpm migration:run # Run migrations
pnpm migration:revert # Revert last migration
pnpm seed # Seed databasepnpm dev # Start dev server
pnpm build # Build for production
pnpm preview # Preview production build
pnpm test:unit # Run unit tests
pnpm test:e2e # Run E2E tests
pnpm check # Type-check
pnpm lint # Lint code
pnpm format # Format codeAfter modifying entities:
cd apps/api
pnpm migration:generate src/core/database/migrations/YourMigrationNamepnpm migration:runpnpm migration:revertpnpm migration:showWe welcome contributions! Here's how you can help:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow the existing code style
- Write tests for new features
- Update documentation as needed
- Use conventional commits (feat, fix, docs, style, refactor, test, chore)
- Ensure all tests pass before submitting PR
- Keep PRs focused on a single feature or fix
- TypeScript: Use TypeScript for all new code
- ESLint & Prettier: Follow the configured linting and formatting rules
- Path Aliases: Use path aliases for imports in the API (
@/modules/*,@/common/*, etc.) - Naming Conventions: Use descriptive variable and function names
- Comments: Add JSDoc comments for public APIs and complex logic
- Use the GitHub issue tracker
- Check if the issue already exists
- Provide a clear description and steps to reproduce
- Include relevant logs or screenshots
- Specify your environment (OS, Node version, etc.)
- Create a new branch from
master - Make your changes
- Run tests locally:
pnpm test - Run linting:
pnpm lint - Format code:
pnpm format - Commit with conventional commit messages
- Push and create a PR
If you discover a security vulnerability, please email security@readnovls.com instead of using the issue tracker.
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with NestJS
- Frontend powered by SvelteKit
- UI components from Bits UI
- Rich text editing with TipTap
- Documentation: [Link to docs site]
- Discord: [Link to Discord]
- Email: support@readnovls.com
Made with β€οΈ by the ReadNovls community