Skip to content

evn88/psy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

260 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Deploy Status Next.js TypeScript License: PolyForm Noncommercial 1.0.0

Documentation languages: English | Русский

🧠 Vershkov.com

Professional psychology platform β€” a modern web application for psychologist Anna Vershkova, built with Next.js 16, featuring client management, survey system, and secure multi-provider authentication.

πŸ”— Live: vershkov.com


✨ Features

πŸ” Authentication & Security

  • Multi-provider auth β€” Email/Password, Google OAuth, and WebAuthn (Passkeys) via NextAuth v5
  • Email verification β€” New users must confirm their email before accessing the platform
  • Welcome notifications β€” Automated welcome emails for Google sign-up (not on repeat login)
  • Rate limiting β€” Login attempt throttling (3 attempts per hour)
  • Role-based access β€” ADMIN, USER, and GUEST roles with granular route protection

πŸ“‹ Survey System

  • Admin-created surveys with multiple question types (single choice, multi choice, free text, scale)
  • User assignment and completion tracking
  • Results viewer with comment discussions between admin and users
  • Draft auto-save for survey responses

πŸ“§ Email System

  • Resend integration for transactional emails
  • Batch sending from admin panel (up to 100 per batch)
  • Real-time delivery status tracking with polling
  • Multilingual email templates β€” emails are sent in the user's preferred language
  • Beautiful React Email templates (verification, welcome, admin messages)

🌍 Internationalization

  • Full English and Russian support via next-intl
  • Cookie-based locale detection (no URL prefixes)
  • User language preference saved to profile
  • Extensible β€” add new languages by creating a translation file

🎨 UI & Design

  • Dark/Light/System theme support via next-themes
  • Responsive layout with mobile-first design
  • Component library built on Radix UI primitives
  • Toast notifications via Sonner
  • Inter font with Latin & Cyrillic subsets

πŸ‘€ User Dashboard

  • Personal dashboard with stats
  • Survey management (pending/completed)
  • Profile management (name, Google account linking)
  • Passkey management (create/delete)
  • Appearance & language settings

πŸ›  Admin Panel

  • User management (CRUD, role assignment)
  • Survey builder & assignment
  • Email broadcast tool
  • Real-time online status tracking (heartbeat)

πŸ— Tech Stack

Layer Technology
Framework Next.js 16 (App Router, Turbopack)
Language TypeScript (strict mode)
Database PostgreSQL + Prisma ORM
Auth NextAuth v5 (Google, Credentials, WebAuthn)
Email Resend + React Email
i18n next-intl
UI Radix UI, Tailwind CSS, Lucide Icons
State React Hook Form, Sonner
Charts amCharts 5
DnD @dnd-kit
Deploy Vercel (standalone output)
Analytics Vercel Analytics + Speed Insights

πŸš€ Getting Started

Prerequisites

  • Node.js 18+
  • PostgreSQL database
  • Resend API key
  • Google OAuth credentials (optional)

Installation

# Clone the repository
git clone https://github.com/evn88/psy.git
cd psy

# Install dependencies
npm install

# Set up environment variables
cp .env.example .env.local

# Generate Prisma client
npx prisma generate

# Run database migrations
npx prisma migrate deploy

# Start development server
npm run dev

Environment Variables

Authentication & Database

Variable Description
AUTH_SECRET NextAuth secret key for session signing (generate: openssl rand -base64 32)
AUTH_GOOGLE_ID Google OAuth client ID (formerly GOOGLE_CLIENT_ID)
AUTH_GOOGLE_SECRET Google OAuth client secret (formerly GOOGLE_CLIENT_SECRET)
DATABASE_URL PostgreSQL connection string (full URL with credentials)
POSTGRES_URL Alternative Postgres connection string (used by Vercel Postgres)
PRISMA_DATABASE_URL Explicit Prisma database URL (overrides DATABASE_URL if set)
ADMIN_EMAIL Email address to grant admin access on first login (e.g., your@email.com)

Email & Notifications

Variable Description
RESEND_API_KEY Resend API key for transactional emails
VAPID_PRIVATE_KEY VAPID private key for push notifications (keep secret)
NEXT_PUBLIC_VAPID_PUBLIC_KEY VAPID public key for push notifications (safe to expose)
VAPID_SUBJECT VAPID subject URI (e.g., mailto:your@email.com) for push notification identification
CRON_SECRET Secret token for securing daily Vercel Cron endpoint /api/cron/session-reminders
WORKFLOW_MONTHLY_STEP_LIMIT Optional monthly workflow steps budget for admin alerts (default: 50000)
WORKFLOW_ALERT_THRESHOLD_PERCENT Optional warning threshold in percent (default: 80)
WORKFLOW_ESTIMATED_STEPS_PER_REMINDER Optional estimated steps per one reminder workflow run (default: 3)

AI & Storage

Variable Description
AI_GATEWAY_API_KEY Vercel AI Gateway API key (optional if using OIDC)
BLOB_READ_WRITE_TOKEN Vercel Blob storage token for file uploads
VERCEL_OIDC_TOKEN Auto-provisioned OIDC token for Vercel services (set by Vercel on deploy)

Application URLs

Variable Description
NEXT_PUBLIC_APP_URL Public base URL of the application (e.g., http://localhost:3000)
PROD_DOMAIN Production domain with protocol (e.g., https://example.com) - required for production emails

Admin Setup

  1. Register β€” Sign up with your email or Google OAuth
  2. Set ADMIN_EMAIL β€” Add your email to .env.local:
    ADMIN_EMAIL=your@email.com
  3. Login Again β€” Sign in again and your account will automatically be elevated to ADMIN role
  4. Access Admin Panel β€” Navigate to /admin (accessible only to ADMIN users)

πŸ“ Project Structure

src/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ (main)/          # Main layout group
β”‚   β”‚   β”œβ”€β”€ admin/       # Admin panel pages
β”‚   β”‚   β”œβ”€β”€ auth/        # Authentication page
β”‚   β”‚   └── my/          # User dashboard pages
β”‚   └── api/             # API routes
β”‚       β”œβ”€β”€ auth/        # Register, verify-email
β”‚       β”œβ”€β”€ profile/     # Profile updates, passkeys
β”‚       β”œβ”€β”€ send/        # Email sending
β”‚       └── settings/    # User preferences
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ admin/           # Admin-specific components
β”‚   β”œβ”€β”€ email-templates/ # React Email templates
β”‚   β”œβ”€β”€ my/              # User dashboard components
β”‚   └── ui/              # Radix UI primitives
β”œβ”€β”€ i18n/                # Internationalization config
β”œβ”€β”€ shared/lib/          # Shared utilities (Prisma, email)
└── middleware.ts         # Auth & locale middleware
messages/
β”œβ”€β”€ en.json              # English UI translations
β”œβ”€β”€ ru.json              # Russian UI translations
β”œβ”€β”€ email-en.json        # English email translations
└── email-ru.json        # Russian email translations

πŸ“œ Scripts

Command Description
npm run dev Start dev server with Turbopack
npm run build Production build (Prisma generate + Next.js)
npm start Start production server
npm run lint Run ESLint
npm run type-check TypeScript type checking

πŸ“± PWA: Offline Mode

The application works offline thanks to the Service Worker (public/sw.js).

Offline-Available Pages

Page Path
Home /
User Dashboard /my
Sessions Schedule /my/sessions
Surveys /my/surveys

Adding a New Page to Offline Cache

  1. Open public/sw.js
  2. Find the PRE_CACHED_URLS array
  3. Add the required path:
const PRE_CACHED_URLS = [
    '/',
    '/my',
    '/my/sessions',
    '/my/surveys',
    '/my/your-page',  // ← add here
];
  1. Deploy. After updating the Service Worker, new pages will appear in the cache automatically.

To clear the old cache for all users (for example after a major update) β€” change the constant:

const CACHE_VERSION = 'v2'; // was v1

Caching Strategies

Request Type Strategy
/api/** Network Only β€” never cache
/_next/static/** Cache First β€” immutable JS/CSS bundles
PNG/SVG/ICO Cache First β€” static icons
HTML pages Network First β†’ fallback to cache

πŸ”” Push Notifications

Initial Setup (one-time)

  1. Generate VAPID keys:

    npx web-push generate-vapid-keys
  2. Add to .env.local and on the server:

    NEXT_PUBLIC_VAPID_PUBLIC_KEY=<public_key>
    VAPID_PRIVATE_KEY=<private_key>
    VAPID_SUBJECT=mailto:admin@vershkov.com

How It Works

  • On the first visit, users are shown a banner requesting permission
  • Subscriptions are stored in the PushSubscription table in the database
  • Management: /my/settings β†’ "Push Notifications"
  • If blocked by user β€” instructions for unblocking are displayed

Platform Support

Platform Status
Android Chrome/Firefox βœ… Full
iOS Safari 16.4+ (PWA installed) βœ… Works
iOS Safari (browser) ❌ Apple does not support
Desktop Chrome/Firefox/Edge βœ… Full

Sending from Admin Panel

  1. /admin/send-email β†’ select recipients β†’ write message (up to 178 characters)
  2. Click "Send Push" β†’ confirm

πŸ“„ License

This project is licensed under the PolyForm Noncommercial License 1.0.0. Commercial use is strictly prohibited.

About

Website for a psychologist (vershkov.com)

Resources

License

Stars

Watchers

Forks

Contributors