SafeSpace Educare is a full-stack web platform that connects students with mental health support in a safe, confidential environment. Students can chat anonymously with counselors, book one-on-one sessions, track their mood, access wellness resources, log victories, and share experiences with peers β all from a single dashboard.
Counselors manage their sessions, respond to anonymous chats, and view session notes. Administrators get a platform-wide analytics view to monitor engagement and counselor activity.
- Frontend: https://safespace.aimelive.com
- Backend API docs (Swagger): https://api-safespace.aimelive.com/api/docs#/
- Production
- Features
- Architecture
- User Roles
- Project Structure
- Quick Start
- Environment Variables
- API Overview
- Authentication Flow
- Database Schema
- Deployment
| Feature | Description |
|---|---|
| Anonymous Chat | Start a confidential chat session with a counselor. Identity is never revealed. |
| Session Booking | Browse counselors and book a one-on-one counseling session. |
| Mood Check-in | Log daily mood entries and track emotional trends over time. |
| Exercises | Access guided mental wellness exercises and activities. |
| Resources | Browse and save curated mental health articles and guides. |
| Victories | Record and celebrate personal achievements and milestones. |
| Testimonies | Share and read community stories of growth and resilience. |
| Feature | Description |
|---|---|
| Sessions Dashboard | View all booked sessions with student details, date, time, and topic. |
| Session Notes | Add private notes and update session status (scheduled / completed / cancelled). |
| Anonymous Chats | View and respond to student chat sessions β student identity stays hidden. |
| Analytics | See session statistics and common topic trends for their caseload. |
| Feature | Description |
|---|---|
| Platform Overview | Live counts of students, counselors, sessions, open chats, and resources. |
| Session Breakdown | Scheduled vs completed vs cancelled counts with visual breakdown. |
| Common Topics | Most frequent session topics across the whole platform. |
| Counselor Activity | Per-counselor session totals and completion rates. |
| Analytics Page | Dedicated full-detail analytics with charts and progress indicators. |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Browser β
β Next.js 16 (App Router, React 19) β
β Tailwind CSS Β· shadcn/ui Β· Lucide Icons β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β HTTP / REST (JSON)
β Bearer JWT
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NestJS 10 REST API (:5001) β
β Global prefix: /api Β· Swagger: /api/docs β
β β
β Auth Β· Sessions Β· Chat Β· Moods Β· Resources Β· Posts β
β Victories Β· Analytics Β· Health β
β β
β Guards: JwtAuthGuard Β· RolesGuard Β· ThrottlerGuard β
β Filters: HttpExceptionFilter β
β Cache: in-memory (or Redis) β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β pg driver / connection pool
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PostgreSQL β
β users Β· sessions Β· chat_sessions Β· chat_messages β
β moods Β· resources Β· saved_resources Β· posts Β· victoriesβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key design decisions:
- Stateless JWT authentication β no sessions stored server-side
- All SQL via parameterised queries (no ORM, using Kysely type definitions)
- Anonymous chat implemented via
is_anonymousflag β counselors see"Anonymous Student"only - Auto-migration runs on server start β no separate migration runner needed
- Rate limiting: 100 requests / 60 s per IP across all endpoints
- Analytics results cached (60 s) to reduce database load
student β full wellness dashboard, anonymous chat, session booking
counselor β sessions management, chat responses, analytics view
admin β platform-wide analytics, counselor activity overview
Each role has a dedicated sidebar navigation and role-appropriate dashboard. The JWT payload carries { id, email, role } β the backend enforces access with RolesGuard.
safespace-educare/
βββ frontend/ # Next.js application
β βββ app/
β β βββ auth/ # Login & register pages
β β βββ dashboard/ # Protected dashboard routes
β β βββ page.tsx # Role-aware home (student/counselor/admin)
β β βββ layout.tsx # Sidebar layout (all roles)
β β βββ chat/ # Anonymous chat page
β β βββ sessions/ # Counselor sessions page
β β βββ analytics/ # Admin analytics page
β β βββ book-session/
β β βββ mood/
β β βββ exercises/
β β βββ resources/
β β βββ victories/
β β βββ testimonies/
β βββ components/
β β βββ features/
β β β βββ anonymous-chat.tsx
β β βββ student-dashboard.tsx
β β βββ counselor-dashboard.tsx
β β βββ admin-dashboard.tsx
β β βββ ui/ # shadcn/ui components
β βββ lib/
β βββ api.ts # Centralised fetch wrapper
β βββ services/ # Per-feature API service modules
β
βββ backend/ # NestJS application
βββ src/
βββ main.ts # Bootstrap, Swagger, CORS, global pipes
βββ app.module.ts # Root module
βββ auth/ # Register, login, JWT strategy
βββ chat/ # Anonymous chat sessions & messages
βββ sessions/ # Counseling session booking & management
βββ moods/ # Mood check-in tracking
βββ resources/ # Resource library
βββ posts/ # Community posts
βββ victories/ # Personal victories
βββ analytics/ # Dashboard & admin analytics
βββ database/ # PostgreSQL pool, Kysely types, migrations
βββ cache/ # Cache module (memory or Redis)
βββ health/ # Health check endpoint
βββ common/ # Guards, decorators, filters, types
| Tool | Minimum version |
|---|---|
| Node.js | 18+ |
| npm | 9+ |
| PostgreSQL | 14+ |
You can use a hosted PostgreSQL service such as Neon or Supabase instead of a local instance.
git clone https://github.com/aimelive/safespace-educare.git
cd safespace-educarecd backend
cp .env.example .env # copy the template
# edit .env β fill in DATABASE_URL and JWT_SECRET at minimum
npm install
npm run start:dev # runs on http://localhost:5001The server auto-creates all required tables on first boot. No separate migration step.
cd frontend
cp .env.local.example .env.local # or create manually
# set NEXT_PUBLIC_API_URL=http://localhost:5001
npm install
npm run dev # runs on http://localhost:3000| URL | Description |
|---|---|
http://localhost:3000 |
Main application |
http://localhost:5001/api/docs |
Swagger / OpenAPI explorer |
http://localhost:5001/api/health |
API health check |
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
Yes | β | PostgreSQL connection string |
JWT_SECRET |
Yes | β | Secret key for signing JWTs β use a long random string in production |
JWT_EXPIRES_IN |
No | 24h |
Token lifetime (ms format: 24h, 7d) |
PORT |
No | 5001 |
Port the API server listens on |
NODE_ENV |
No | development |
development / production / test |
CORS_ORIGIN |
No | * |
Allowed frontend origin β set to your frontend URL in production |
CACHE_STORE |
No | memory |
memory or redis |
CACHE_REDIS_URL |
No | β | Redis URL (required when CACHE_STORE=redis) |
DB_POOL_MAX |
No | 20 |
Max PostgreSQL connection pool size |
| Variable | Required | Default | Description |
|---|---|---|---|
NEXT_PUBLIC_API_URL |
Yes | http://localhost:5001 |
Base URL of the backend API |
All API routes are prefixed with /api. Protected routes require an Authorization: Bearer <token> header.
| Module | Endpoint | Auth | Description |
|---|---|---|---|
| Auth | POST /api/auth/register |
Public | Create account |
POST /api/auth/login |
Public | Obtain JWT | |
GET /api/auth/me |
JWT | Current user profile | |
| Sessions | GET /api/sessions/counselors |
Public | List available counselors |
POST /api/sessions/book |
JWT | Book a session | |
GET /api/sessions/my-sessions |
JWT | Student's own sessions | |
GET /api/sessions/counselor-sessions |
JWT | Counselor's assigned sessions | |
PATCH /api/sessions/:id |
JWT | Update session status / notes | |
| Chat | POST /api/chat/start |
JWT | Start anonymous chat session |
POST /api/chat/message |
JWT | Send a message | |
GET /api/chat/sessions |
JWT | List sessions (role-aware) | |
GET /api/chat/:chatId |
JWT | Get messages for a session | |
| Moods | POST /api/moods |
JWT | Log mood entry |
GET /api/moods |
JWT | Mood history | |
| Resources | GET /api/resources |
JWT | Browse resources |
POST /api/resources/:id/save |
JWT | Save a resource | |
| Posts | GET /api/posts |
JWT | Community posts |
POST /api/posts |
JWT | Create a post | |
| Victories | GET /api/victories |
JWT | List victories |
POST /api/victories |
JWT | Log a victory | |
| Analytics | GET /api/analytics/dashboard |
Counselor/Admin | Counselor session stats |
GET /api/analytics/admin |
Admin | Platform-wide stats | |
| Health | GET /api/health |
Public | Server health check |
Full interactive documentation is available at /api/docs (Swagger UI).
1. User registers or logs in β backend returns { user, token }
2. Frontend stores token in localStorage
3. Every protected API call sends: Authorization: Bearer <token>
4. Backend validates the JWT and extracts { id, email, role }
5. RolesGuard checks role against the required @Roles() decorator
6. Token expires after JWT_EXPIRES_IN (default 24 hours)
Passwords are hashed with bcrypt (10 salt rounds) before storage. The plain-text password is never returned or logged.
All tables are auto-created on first server start. No manual SQL required.
users
id UUID PK Β· email Β· password (bcrypt) Β· name Β· age Β· role
school Β· specialization Β· available_hours Β· created_at
sessions
id UUID PK Β· student_id FK Β· counselor_id FK
scheduled_date Β· scheduled_time Β· topic Β· status Β· notes
created_at Β· updated_at
chat_sessions
id UUID PK Β· student_id FK Β· counselor_id FK (nullable)
is_anonymous BOOL Β· status Β· created_at
chat_messages
id UUID PK Β· chat_id FK Β· sender_id FK Β· message Β· created_at
moods
id Β· user_id FK Β· mood_score Β· note Β· created_at
resources
id UUID PK Β· title Β· description Β· url Β· category Β· is_active Β· created_at
saved_resources
user_id FK Β· resource_id FK Β· saved_at
posts
id Β· user_id FK Β· content Β· likes Β· created_at
victories
id Β· user_id FK Β· title Β· description Β· created_at
cd backend
npm run build # compiles TypeScript β dist/
npm run start:prod # runs node dist/mainSet NODE_ENV=production, a strong JWT_SECRET, and restrict CORS_ORIGIN to your frontend domain.
cd frontend
npm run build # Next.js production build
npm run start # serves the built appOr deploy to Vercel β import the frontend/ directory and set NEXT_PUBLIC_API_URL to your live backend URL.
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Commit your changes following conventional commit style
- Open a pull request with a clear description of the change