A mobile-responsive web application for providers to manage worksheets for clients. Built with Nuxt.js and TypeScript, featuring OTP-based authentication for admins and clients, with standard email/password authentication for providers.
- Admin Dashboard: OTP-based authentication with system oversight capabilities
- Provider Management: Email/password authentication with client and worksheet management
- Client Portal: OTP-based authentication for worksheet completion
- Worksheet System: Template creation, assignment, and review workflow
- Mobile-First Design: Responsive interface optimized for all devices
- Frontend: Nuxt.js with TypeScript
- Database: PostgreSQL with Neon (serverless)
- ORM: Drizzle ORM with drizzle-kit for migrations
- Authentication: Custom OTP system (SMS/Email) + traditional auth
- SMS: Twilio for OTP delivery
- Email: Resend for OTP delivery and notifications
- Deployment: Vercel
npm installCreate a .env file with the following variables:
# Database
DATABASE_URL="postgresql://username:password@localhost:5432/emerald_silver_dev"
# Authentication
NEXTAUTH_SECRET="your-secret-key-change-in-production"
NEXTAUTH_URL="http://localhost:3000"
# SMS (Twilio)
TWILIO_ACCOUNT_SID="your-twilio-account-sid"
TWILIO_AUTH_TOKEN="your-twilio-auth-token"
TWILIO_PHONE_NUMBER="+1234567890"
# Email (Resend)
RESEND_API_KEY="your-resend-api-key"
FROM_EMAIL="noreply@yourdomain.com"
# Application
NODE_ENV="development"- Go to supabase.com and sign up for a free account
- Click "New Project"
- Choose your organization
- Enter project details:
- Name:
emerald-silver - Database Password: Create a strong password (save this!)
- Region: Choose closest to you
- Name:
- Click "Create new project" (takes ~2 minutes)
- In your Supabase dashboard, go to Settings → Database
- Scroll down to Connection string section
- Select URI tab
- Copy the connection string (looks like
postgresql://postgres:[YOUR-PASSWORD]@...) - Replace
[YOUR-PASSWORD]with the password you created
Update your .env file with the Supabase connection string:
DATABASE_URL="postgresql://postgres:YOUR_PASSWORD@db.xxx.supabase.co:5432/postgres"# Push schema directly to Supabase (recommended for development)
npm run db:push✅ Success! You should see output like:
Your database is now in sync with your schema
You can view your tables in Supabase:
- Go to Table Editor in your Supabase dashboard
- You should see 3 tables:
users,clients,otp_codes - Or use Drizzle Studio:
npm run db:studio
Local PostgreSQL with Docker:
# Start local PostgreSQL with Docker
docker-compose up -d
# Then: npm run db:pushTraditional Migration Approach:
npm run db:generate # Generate migrations
npm run db:migrate # Apply migrationsOnce your database is set up and schema is pushed, create an admin user:
# Create admin user automatically
npm run create-adminOr manually add to your database:
INSERT INTO users (email, phone, role, name, is_active)
VALUES ('admin@example.com', '+1234567890', 'admin', 'System Administrator', true);You can customize the admin user by setting environment variables:
ADMIN_EMAIL="your-admin@example.com" npm run create-adminnpm run devVisit http://localhost:3000 and navigate to Admin Login to test the OTP authentication flow.
- Start the server:
npm run devand go tohttp://localhost:3000 - Navigate to Admin Login: Click "Admin Login" or go to
/admin/login - Enter Admin Credentials: Use
admin@example.comor+1234567890(from the created admin user) - Receive OTP: Check your email/SMS for the 6-digit verification code
- Verify Code: Enter the code on the verification page
- Access Dashboard: Successfully authenticated admins will be redirected to
/admin/dashboard
Note: Make sure your Twilio and Resend API keys are configured in .env to receive OTP codes.
npm run db:generate # Generate new migration from schema changes
npm run db:migrate # Apply pending migrations
npm run db:push # Push schema directly (development)
npm run db:studio # Open Drizzle Studio (database GUI)npm run dev # Start development server
npm run build # Build for production
npm run preview # Preview production build
npm run typecheck # Run TypeScript checks/
├── components/ # Vue components
│ ├── admin/ # Admin-specific components
│ ├── provider/ # Provider-specific components
│ ├── client/ # Client-specific components
│ └── shared/ # Shared components
├── pages/ # Nuxt.js pages/routes
│ ├── admin/ # Admin login and dashboard
│ └── index.vue # Home page
├── server/ # Server-side code
│ └── api/ # API routes
│ └── auth/ # Authentication endpoints
├── lib/ # Shared utilities and configurations
│ ├── db/ # Database schema and utilities
│ └── auth/ # Authentication utilities
├── middleware/ # Route protection middleware
└── assets/ # Static assets and styles
- Admin enters email or phone number
- System generates 6-digit OTP code (5-minute expiration)
- Code sent via Resend (email) or Twilio (SMS)
- Admin enters code for verification
- JWT session token created and stored in HTTP-only cookie
- Sessions last 24 hours
- HTTP-only cookies for security
- Automatic session verification via middleware
- Protected routes redirect to login if session invalid
- users: Admins and providers with role-based access
- clients: Client records managed by providers
- otp_codes: Time-limited verification codes
- worksheet_templates: Form definitions (future)
- worksheet_instances: Completed worksheets (future)
- Input Validation: Server-side validation for all inputs
- Session Management: Secure JWT tokens with HTTP-only cookies
- OTP Security: Time-limited codes with single-use enforcement
- Role-based Access: Middleware protection for admin/provider routes
- CSRF Protection: SameSite cookie configuration
This application is designed for deployment on Vercel with Neon PostgreSQL:
- Database: Set up Neon PostgreSQL database
- Environment Variables: Configure all required env vars in Vercel
- Build Command:
npm run build - Output Directory:
.output
For detailed deployment instructions, see the Nuxt deployment documentation.