An online book-reading and digital library platform β read EPUB/PDF books in the browser, read together in collaborative rooms, get AI-powered recommendations, and moderate it all from a dedicated admin panel.
Verso 2.0 is a full-stack web application for reading and managing digital books. Readers open EPUB and PDF titles directly in the browser, build a personal library, highlight and annotate passages, listen with a built-in text-to-speech narrator, rate and review books, and track their progress on a stats dashboard. A social layer adds a real-time community chat, friendships and direct messages, and collaborative reading rooms where a group reads the same book together with shared highlights, threaded discussion, and live presence. Google Gemini powers book/people recommendations, an in-context reading assistant, and automatic spoiler detection in chat.
Built as an academic / university project, Verso 2.0 is composed of three independent applications that share a single database:
| App | Folder | Role |
|---|---|---|
| Frontend | FRONTEND/verso |
React single-page app β the reader UI |
| Backend API | BACKEND/verso-api-system |
Laravel REST API + Reverb websockets + queued jobs |
| Admin | Admin |
Laravel + Filament moderation panel |
- In-browser readers for EPUB and PDF, powered by epub.js and pdf.js.
- Personal uploads β upload your own EPUB/PDF files and read them in the same reader.
- Highlights & annotations β select text to highlight in colors and attach notes.
- Narrator (text-to-speech) β have the book read aloud with selectable voice and playback speed controls.
- Reader preferences β adjustable font scale, light/dark theme, and ambient ASMR audio.
- Library tools β favorites, bookmarks, and reading history with per-book progress.
- Reviews & ratings β leave star ratings and written reviews on any title.
- Charts and statistics on your reading activity (pages, sessions, streaks) rendered with Recharts.
- Community chat β a global, real-time chat with emoji reactions.
- Friendships β send, accept, and decline friend requests.
- Direct messages β private friend-to-friend messages with read receipts.
- Reading rooms scoped to a single book, so a group can read together.
- Room chat, shared highlights, and threaded comments on each highlight.
- Live presence β see who's online and which page each member is on.
- Persistent room invitations β invite anyone (not just friends) with clickable in-app notifications that survive across sessions.
- Recommendations β personalised book and people suggestions.
- Reading assistant β ask questions about a highlighted passage and get answers in context.
- Spoiler detection β community and room messages are automatically scanned and flagged for spoilers via a queued background job.
- Author dashboard β authors publish books and manage their own titles.
- Book approval workflow β submitted books move through pending β approved / rejected (with a rejection reason) before appearing publicly.
- User ban system β ban/unban users with a reason; the
CheckBannedmiddleware blocks banned users from the API and from logging in. - Filament admin panel β manage users, books, reviews, community messages, reading rooms, and room messages from one dashboard.
- Quizzes & lessons, an events calendar, personal todos, and a user points system.
- Token-based authentication (Laravel Sanctum) with role-based access:
reader,author, andadmin.
| Layer | Technologies |
|---|---|
| Frontend | React 19, Vite 8, TypeScript + JSX, Tailwind CSS 4, React Router 7, Recharts, epub.js, pdf.js, Laravel Echo + Pusher JS |
| Backend API | Laravel 13 (PHP 8.3), Laravel Sanctum (auth), Eloquent ORM, queued Jobs, smalot/pdfparser (PDF text extraction) |
| Admin | Laravel 13 + Filament 4 |
| Realtime | Laravel Reverb (WebSocket server) + Laravel Echo / Pusher JS on the client |
| AI | Google Gemini API (gemini-2.5-flash) for recommendations, the reading assistant, and spoiler detection |
| Database | MySQL 8 / MariaDB (SQLite supported for a quick start) |
The three apps are deployed separately but talk to one shared database. The React SPA calls the REST API over HTTP and subscribes to Reverb for realtime events; the Admin panel reads and writes the same database the API uses.
βββββββββββββββββββββββββββ
Browser (reader) ββββΆβ React SPA (Vite :5173) β
βββββββββββββ¬ββββββββββββββ
HTTP /api β WebSocket
βΌ
ββββββββββββββββββββββββββββββββββββββββββββ
β Laravel Backend (verso-api-system) β
β β’ REST API β http://localhost:8000
β β’ Reverb (realtime) β ws://localhost:8080
β β’ Queue worker (AI spoiler jobs) β
βββββββββββββββββββββ¬βββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββ
β MySQL database β (shared)
ββββββββββ²ββββββββββ
β
βββββββββββββββββββββ΄βββββββββββββββββββββββ
β Laravel + Filament Admin (:8001 /admin) β
ββββββββββββββββββββββββββββββββββββββββββββ
The Admin app has no schema migrations of its own β it operates directly on the backend's database. Point both apps'
.envat the same database.
Verso2.0/
βββ FRONTEND/
β βββ verso/ # React + Vite single-page app
β βββ src/
β βββ api/ # API client modules (auth, books, rooms, chat, β¦)
β βββ pages/ # Route pages (Home, ReadingPage, Community, ReadingRooms, β¦)
β βββ components/ # UI: reader/, reader/narrator/, room/, community/, dashboard/
β βββ context/ # React context providers (auth, user)
β βββ hooks/ # Custom React hooks
β βββ lib/ # Shared helpers (e.g. Echo client)
β
βββ BACKEND/
β βββ verso-api-system/ # Laravel REST API + Reverb
β βββ app/
β β βββ Http/Controllers/ # API controllers (Room, Community, Recommendation, β¦)
β β βββ Http/Middleware/ # CheckBanned, β¦
β β βββ Models/ # Eloquent models
β β βββ Events/ # Broadcast events (realtime, spoiler flags)
β β βββ Jobs/ # Queued jobs (DetectSpoilerJob, RoomDetectSpoilerJob)
β β βββ Services/ # GeminiService, RecommendationService, BookParser
β βββ routes/ # api.php, channels.php, web.php
β βββ database/ # Migrations & seeders
β
βββ Admin/ # Laravel + Filament admin panel (path: /admin)
βββ app/
βββ Filament/Resources/ # Users, Books, Reviews, CommunityMessages,
β # ReadingRooms, RoomMessages
βββ Providers/Filament/ # AdminPanelProvider.php (brand "Verso Admin")
Each app also has its own README in its folder.
The frontend, backend, and admin panel run as three separate apps. Follow the steps in order β the backend (and its database) comes first because the other two depend on it.
- PHP 8.3+
- Composer 2
- Node.js 20+ (the repo is verified on Node 24) and npm
- MySQL 8 / MariaDB (or SQLite for a quick start)
Works on Linux, macOS, and Windows (WSL2 recommended on Windows).
git clone git@github.com:TheRealNightmare/Verso2.0.git
cd Verso2.0cd BACKEND/verso-api-system
# Install PHP dependencies
composer install
# Create your environment file and app key
cp .env.example .env
php artisan key:generateConfigure the database (MySQL β primary path). Create a database, then edit .env:
CREATE DATABASE verso CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=verso
DB_USERNAME=your_mysql_user
DB_PASSWORD=your_mysql_passwordSQLite alternative (quick start): keep
DB_CONNECTION=sqlitein.envand runtouch database/database.sqliteβ no database server needed. (Remember the Admin app must then point at this same SQLite file.)
Run migrations and link storage (the storage link serves uploaded book files):
php artisan migrate # add --seed if you want seed data
php artisan storage:linkConfigure Reverb (realtime WebSockets). Make sure broadcasting points at Reverb:
BROADCAST_CONNECTION=reverb
REVERB_APP_ID=your_app_id
REVERB_APP_KEY=your_app_key
REVERB_APP_SECRET=your_app_secret
REVERB_HOST=localhost
REVERB_PORT=8080
REVERB_SCHEME=httpRemember the
REVERB_APP_KEYvalue β the frontend must use the same key.
Configure Gemini AI (optional, but enables AI features). Get a free key from
Google AI Studio, then set in .env:
GEMINI_API_KEY=your_gemini_key
GEMINI_MODEL=gemini-2.5-flashLeave
GEMINI_API_KEYblank to disable AI recommendations, the reading assistant, and spoiler detection β those features degrade gracefully and the rest of the app works normally.
Start the backend. It needs three processes; open three terminals (all from
BACKEND/verso-api-system):
php artisan serve # REST API β http://localhost:8000
php artisan reverb:start # WebSockets β ws://localhost:8080 (realtime chat & presence)
php artisan queue:listen # processes queued jobs, incl. AI spoiler detectionTip:
composer devruns the server, queue, log tailer, and Vite concurrently in a single terminal (note: it starts Vite, not Reverb β you still runreverb:startseparately for realtime).
The admin panel shares the backend's database, so its .env must use the same DB
credentials you set above. It does not have its own data migrations to run.
cd ../../Admin # from BACKEND/verso-api-system
composer install
cp .env.example .env
php artisan key:generateEdit the Admin .env so the DB_* values match the backend (same MySQL database, or the
same SQLite file). Then run it on a different port (8000 is the API):
php artisan serve --port=8001 # admin panel β http://localhost:8001/adminFilament ships compiled assets, so this is enough. To customise the admin theme, run
npm install && npm run buildinAdmin/as well.
The Filament panel only lets in users whose role is admin. Create a normal account
first β register through the app once the frontend is running (step 4), or create one
directly with php artisan make:filament-user from Admin/ β then promote it to admin.
From either the Admin or BACKEND/verso-api-system folder (they share the database):
php artisan tinker --execute="App\Models\User::where('email','you@example.com')->update(['role'=>'admin']);"Now log in at http://localhost:8001/admin with that account.
cd ../FRONTEND/verso # from Admin
# Install JS dependencies
npm installCreate (or confirm) FRONTEND/verso/.env:
VITE_API_URL=http://localhost:8000/api
VITE_REVERB_APP_KEY=your_app_key # must match backend REVERB_APP_KEY
VITE_REVERB_HOST=localhost
VITE_REVERB_PORT=8080
VITE_REVERB_SCHEME=httpStart the dev server:
npm run dev # app β http://localhost:5173Visit http://localhost:5173, register an account, and start reading. Moderators manage the platform at http://localhost:8001/admin.
- Chat / presence is silent: the frontend
VITE_REVERB_APP_KEYmust match the backendREVERB_APP_KEY, andphp artisan reverb:startmust be running. - Spoilers never get flagged: make sure
php artisan queue:listenis running and a validGEMINI_API_KEYis set. - No AI recommendations / assistant: confirm
GEMINI_API_KEYis set (these features are disabled when it's blank). - API requests fail / CORS errors: check
VITE_API_URLpoints at the running API (http://localhost:8000/api). - Can't log into
/admin: the account needsrole = 'admin'(and must not be banned), and the Admin app's.envmust point at the same database as the backend.
Backend (BACKEND/verso-api-system):
| Command | Description |
|---|---|
composer dev |
Run API server, queue worker, log tailer, and Vite together |
composer test |
Clear config and run the test suite |
php artisan serve |
Start the REST API on port 8000 |
php artisan reverb:start |
Start the Reverb WebSocket server on port 8080 |
php artisan queue:listen |
Process queued jobs (e.g. spoiler detection) |
Admin (Admin):
| Command | Description |
|---|---|
php artisan serve --port=8001 |
Start the Filament admin panel at /admin |
php artisan make:filament-user |
Create a panel user (then promote to role = admin) |
npm run build |
Build the custom admin theme assets (optional) |
Frontend (FRONTEND/verso):
| Command | Description |
|---|---|
npm run dev |
Start the Vite dev server on port 5173 |
npm run build |
Type-check and build for production |
npm run preview |
Preview the production build |
npm run lint |
Run ESLint |
npm run test |
Run the Vitest suite |
See each app's own README for more detail: FRONTEND/verso Β· BACKEND/verso-api-system Β· Admin