A production-ready Node.js/Express backend for the PopVia application with MongoDB integration, comprehensive JWT authentication, OAuth support, user management, file upload capabilities, sharing features, time tracking, collaboration tools, shared content management, company verification, invoice processing, payment integration, job board, proposal templates, and team management.
Target Market: SaaS productivity platform serving SMBs, freelancers, and agencies Revenue Potential: $20M+ ARR by 2050 through scalable subscription model Value Delivered: 10x ROI through time savings, team collaboration, business management, and client acquisition Key Features: Complete business management API with authentication, collaboration, job board, proposal templates, invoicing, and analytics
- RESTful API for task, project, user, company, client, invoice, job, proposal template, and team management
- Comprehensive Authentication with JWT, refresh tokens, OAuth (Google), email verification, and account locking
- User Management with registration, login, password reset, profile management, and user tiers (Basic, Pro, Admin)
- MongoDB Integration with Mongoose ODM and optimized queries
- File Upload System with GridFS storage (10MB limit) and image processing
- Task & Project Sharing with permission-based access control and public links
- Shared Content System for viewing tasks and projects shared with users
- Time Tracking with start/stop timer, session history, and detailed statistics
- User Limits with Basic (10 tasks/5 projects) and Pro (unlimited) tiers
- Collaboration Features with username-based sharing and public links
- Shared Project Task Creation allowing users to add tasks to shared projects
- Company Management with verification system, public profiles, logo uploads, and analytics
- Client Management with contact tracking, project relationships, and engagement analytics
- Invoice System with line items, calculations, status tracking, and payment processing
- Payment Integration with Stripe for subscriptions and invoice payments
- Job Board System with job posting, public job board, application management, and analytics
- Proposal Templates with variable system, categories, public sharing, and usage analytics
- Team Management with role-based permissions, member invitations, and team analytics
- Email System with Resend for verification, notifications, invoice delivery, and pro welcome emails
- OAuth Integration with Google OAuth for seamless login
- CORS Configuration for cross-origin requests
- Security Headers with Helmet.js
- Rate Limiting on authentication and payment endpoints
- Health Monitoring with detailed status endpoints
- Production Logging with Morgan
- Input Validation with express-validator
- Environment Configuration for flexible deployment
- Feedback System for user suggestions and bug reports
- Analytics & Statistics for comprehensive business insights
- Node.js 18+
- MongoDB (local or Atlas)
- npm or yarn
Copy the example environment file and configure it:
cp env.example .env# Server Configuration
PORT=3001
NODE_ENV=production
# Database
MONGODB_URI=mongodb://localhost:27017/taskmanager
# CORS
ALLOWED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
FRONTEND_URL=https://yourdomain.com
# File Upload
MAX_FILE_SIZE=10485760
# Authentication
JWT_SECRET=your-super-secret-jwt-key-change-in-production
# OAuth Configuration (OPTIONAL)
GOOGLE_CLIENT_ID=your-google-client-id-here
GOOGLE_CLIENT_SECRET=your-google-client-secret-here
# Email Configuration (for verification and password reset)
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_USER=your-email@gmail.com
EMAIL_PASS=your-app-password
EMAIL_FROM=PopVia <noreply@popvia.me>
# Email Configuration
RESEND_API_KEY=your-resend-api-key-here
RESEND_FROM=noreply@popvia.me
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key_here
STRIPE_PUBLISHABLE_KEY=pk_test_your_stripe_publishable_key_here
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here# Security
SESSION_SECRET=your-session-secret-here
# Logging
LOG_LEVEL=info# Install dependencies
npm install
# Start development server with nodemon
npm run dev
# Start production server
npm start# Install production dependencies only
npm ci --only=production
# Start with PM2
pm2 start server.js --name "popvia-backend"
# Or start directly
npm start# Build the image
docker build -t popvia-backend .
# Run with environment file
docker run -d \
--name popvia-backend \
-p 3001:3001 \
--env-file .env \
popvia-backend# Start all services
docker-compose up -d
# View logs
docker-compose logs -f backend
# Stop services
docker-compose downGET /api/health- Server and database status
POST /api/auth/register- User registration with email verificationPOST /api/auth/login- User login with JWT tokensPOST /api/auth/logout- User logoutPOST /api/auth/refresh- Refresh JWT tokenPOST /api/auth/verify-email- Email verificationPOST /api/auth/forgot-password- Password reset requestPOST /api/auth/reset-password- Password resetGET /api/auth/me- Get current user profilePUT /api/auth/profile- Update user profilePUT /api/auth/change-password- Change passwordGET /api/auth/profile/:username- Get public user profile by usernamePUT /api/auth/profile-picture- Update profile pictureGET /api/auth/google- Initiate Google OAuth loginGET /api/auth/google/callback- Google OAuth callbackPOST /api/auth/oauth/token- Exchange OAuth tokens for JWT
GET /api/tasks- Get all tasks (with filtering)GET /api/tasks/:id- Get task by IDPOST /api/tasks- Create new taskPUT /api/tasks/:id- Update taskDELETE /api/tasks/:id- Delete taskPATCH /api/tasks/:id/toggle- Toggle completionPOST /api/tasks/:id/share- Share task with userPOST /api/tasks/:id/share/add-user- Add user to shared taskDELETE /api/tasks/:id/share/remove-user- Remove user from shared taskGET /api/tasks/shared- Get shared tasksPOST /api/tasks/:id/start-timer- Start time trackingPOST /api/tasks/:id/stop-timer- Stop time trackingGET /api/tasks/:id/time-summary- Get time tracking summaryGET /api/tasks/limits- Get task limits for user
GET /api/projects- Get all projectsGET /api/projects/:id- Get project by IDPOST /api/projects- Create new projectPUT /api/projects/:id- Update projectDELETE /api/projects/:id- Delete projectPOST /api/projects/:id/share- Share project with userGET /api/projects/shared- Get shared projectsGET /api/projects/limits- Get project limits for user
GET /api/companies- Get all companiesGET /api/companies/:id- Get company by IDPOST /api/companies- Create new companyPUT /api/companies/:id- Update companyDELETE /api/companies/:id- Delete companyGET /api/companies/verified- Get verified companies (public)GET /api/companies/verify/:token- Verify company by tokenPOST /api/companies/:id/request-verification- Request company verificationPOST /api/companies/:id/generate-public-link- Generate public company linkGET /api/companies/public/:slug/:token- Get public company detailsGET /api/companies/stats- Get company statistics
GET /api/clients- Get all clientsGET /api/clients/:id- Get client by IDPOST /api/clients- Create new clientPUT /api/clients/:id- Update clientDELETE /api/clients/:id- Delete client
GET /api/invoices- Get all invoicesGET /api/invoices/:id- Get invoice by IDPOST /api/invoices- Create new invoicePUT /api/invoices/:id- Update invoiceDELETE /api/invoices/:id- Delete invoicePOST /api/invoices/:id/payment-link- Generate payment linkPOST /api/invoices/:id/send-email- Send invoice email
GET /api/jobs- Get all jobs (user's jobs)GET /api/jobs/:id- Get job by IDPOST /api/jobs- Create new jobPUT /api/jobs/:id- Update jobDELETE /api/jobs/:id- Delete jobGET /api/jobs/public- Get public job boardPOST /api/jobs/:id/publish- Publish jobPOST /api/jobs/:id/apply- Apply for jobGET /api/jobs/:id/applications- Get job applicationsGET /api/jobs/:slug- Get job by slug (public)
GET /api/proposal-templates- Get all templatesGET /api/proposal-templates/:id- Get template by IDPOST /api/proposal-templates- Create new templatePUT /api/proposal-templates/:id- Update templateDELETE /api/proposal-templates/:id- Delete templateGET /api/proposal-templates/public- Get public templatesPOST /api/proposal-templates/:id/duplicate- Duplicate templatePOST /api/proposal-templates/:id/generate- Generate proposal from templateGET /api/proposal-templates/categories- Get template categories
GET /api/teams- Get all teamsGET /api/teams/:id- Get team by IDPOST /api/teams- Create new teamPUT /api/teams/:id- Update teamDELETE /api/teams/:id- Delete teamPOST /api/teams/:id/members- Add team memberDELETE /api/teams/:id/members/:userId- Remove team memberPUT /api/teams/:id/members/:userId/role- Update member roleGET /api/teams/limits- Get team limits for user
POST /api/payments/create-link- Create Stripe payment linkPOST /api/payments/webhook- Handle Stripe webhooksGET /api/payments/verify-session/:sessionId- Verify payment session
POST /api/uploads/task/:taskId- Upload file to taskDELETE /api/uploads/task/:taskId/file/:filename- Delete fileGET /api/uploads/files/:filename- Download file
GET /api/tasks/shared/:token- Get shared task by tokenGET /api/projects/shared/:token- Get shared project by tokenPUT /api/tasks/shared/:token- Update shared taskPUT /api/projects/shared/:token- Update shared project
GET /api/dashboard- Get dashboard statistics and dataGET /api/dashboard/stats- Get comprehensive analytics
POST /api/feedback- Send feedback email
?project=marketing- Filter by project?tag=analytics- Filter by tag?completed=true- Filter by completion status?search=keyword- Search in title and description
?category=engineering- Filter by job category?type=full-time- Filter by job type?locationType=remote- Filter by location type?search=keyword- Search in job title and description
{
email: String (required, unique),
username: String (required, unique),
password: String (hashed with bcrypt),
firstName: String (required),
lastName: String (required),
displayName: String (required),
biography: String,
profilePicture: String,
userType: String (enum: ['basic', 'pro', 'admin'], default: 'basic'),
isEmailVerified: Boolean (default: false),
emailVerificationToken: String,
passwordResetToken: String,
passwordResetExpires: Date,
isLocked: Boolean (default: false),
failedLoginAttempts: Number (default: 0),
lockUntil: Date,
role: String (enum: ['user', 'admin'], default: 'user'),
oauthProvider: String,
oauthId: String,
lastLogin: Date,
createdAt: Date,
updatedAt: Date
}{
title: String (required),
description: String,
dueDate: Date,
project: String,
tags: [String] (max 3),
completed: Boolean (default: false),
priority: String (enum: ['low', 'medium', 'high'], default: 'medium'),
userId: ObjectId (ref: 'User'),
// Sharing fields
shareToken: String (unique),
sharePermission: String (enum: ['readonly', 'editable']),
isShared: Boolean (default: false),
sharedUsernames: [String],
shareViewCount: Number (default: 0),
shareCreatedAt: Date,
shareExpiresAt: Date,
// Time tracking fields
timeTracking: {
isRunning: Boolean (default: false),
startTime: Date,
totalTime: Number (default: 0),
sessions: [{
startTime: Date,
endTime: Date,
duration: Number
}]
},
estimatedTime: Number (default: 0),
// File attachments
fileAttachments: [{
filename: String,
originalName: String,
mimetype: String,
size: Number,
data: Buffer,
hash: String,
uploadedAt: Date
}],
createdAt: Date,
updatedAt: Date
}{
name: String (required),
description: String,
color: String (default: '#3182ce'),
active: Boolean (default: true),
userId: ObjectId (ref: 'User'),
// Sharing fields
shareToken: String (unique),
sharePermission: String (enum: ['readonly', 'editable']),
isShared: Boolean (default: false),
sharedUsernames: [String],
shareViewCount: Number (default: 0),
shareCreatedAt: Date,
shareExpiresAt: Date,
createdAt: Date,
updatedAt: Date
}{
name: String (required),
description: String,
industry: String,
size: String (enum: ['startup', 'small', 'medium', 'large']),
website: String,
logo: String,
location: {
city: String,
state: String,
country: String
},
isVerified: Boolean (default: false),
verificationToken: String,
isActive: Boolean (default: true),
shareToken: String (unique),
slug: String (unique),
createdBy: ObjectId (ref: 'User'),
createdAt: Date,
updatedAt: Date
}{
title: String (required),
description: String,
requirements: String,
responsibilities: String,
category: String (enum: ['engineering', 'design', 'marketing', 'sales', 'product', 'operations', 'finance', 'hr', 'legal', 'customer-support', 'data-science', 'devops', 'qa', 'content', 'other']),
type: String (enum: ['full-time', 'part-time', 'contract', 'internship', 'freelance']),
level: String (enum: ['entry', 'junior', 'mid', 'senior', 'lead', 'executive']),
location: {
type: String (enum: ['remote', 'onsite', 'hybrid']),
city: String,
state: String,
country: String
},
salary: {
min: Number,
max: Number,
currency: String (default: 'USD'),
period: String (enum: ['hourly', 'daily', 'weekly', 'monthly', 'yearly'])
},
skills: [String],
status: String (enum: ['draft', 'published', 'paused', 'closed', 'archived']),
isActive: Boolean (default: true),
publishedAt: Date,
expiresAt: Date,
slug: String (unique),
shareToken: String (unique),
viewCount: Number (default: 0),
applicationCount: Number (default: 0),
applications: [{
name: String,
email: String,
phone: String,
coverLetter: String,
portfolio: String,
appliedAt: Date
}],
companyId: ObjectId (ref: 'Company'),
createdBy: ObjectId (ref: 'User'),
createdAt: Date,
updatedAt: Date
}{
title: String (required),
description: String,
category: String (enum: ['web-development', 'mobile-development', 'design', 'consulting', 'marketing', 'maintenance', 'other']),
content: String (required),
variables: [{
name: String,
description: String,
defaultValue: String,
required: Boolean
}],
isPublic: Boolean (default: false),
isActive: Boolean (default: true),
usageCount: Number (default: 0),
lastUsedAt: Date,
tags: [String],
estimatedValue: Number (default: 0),
estimatedHours: Number (default: 0),
userId: ObjectId (ref: 'User'),
createdAt: Date,
updatedAt: Date
}{
name: String (required),
description: String,
owner: ObjectId (ref: 'User', required),
members: [{
user: ObjectId (ref: 'User', required),
role: String (enum: ['admin', 'member', 'viewer'], default: 'member'),
joinedAt: Date (default: Date.now)
}],
projects: [ObjectId (ref: 'Project')],
isActive: Boolean (default: true),
settings: {
allowMemberInvites: Boolean (default: true),
requireApproval: Boolean (default: false),
defaultRole: String (enum: ['member', 'viewer'], default: 'member')
},
createdAt: Date,
updatedAt: Date
}- JWT Authentication - Secure token-based authentication with 15-minute expiration
- Refresh Tokens - 7-day refresh tokens for seamless user experience
- OAuth Integration - Google OAuth with automatic account creation
- Password Hashing - bcryptjs with 12 salt rounds
- Email Verification - Required email verification for new accounts
- Password Reset - Secure password reset via email with 1-hour token expiration
- Account Locking - Automatic account locking after 5 failed login attempts (2-hour lock)
- Rate Limiting - Protection against brute force attacks
- Helmet.js - Security headers
- CORS - Cross-origin resource sharing
- Input Validation - Request sanitization with express-validator
- File Upload Limits - Size and type restrictions (10MB max)
- Error Handling - No sensitive data exposure
- Password Requirements - Minimum 12 characters with uppercase, lowercase, and special character
- User Limits - Basic users limited to 10 tasks and 5 projects
- Access Control - Proper validation for shared content access
- Pro Features - Role-based access control for premium features
- Use HTTPS in production
- Configure CORS origins
- Use environment variables
- Implement security headers
- Add input validation
- Secure file uploads
- Add rate limiting
- Implement authentication
- Add OAuth integration
- Add email verification
- Add password reset functionality
- Add account locking
- Add password strength requirements
- Add user limits and access control
- Add role-based permissions
- Add request logging
- Add API documentation
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage- Unit tests for models
- Integration tests for routes
- Authentication tests (including OAuth)
- File upload tests
- Sharing functionality tests
- Time tracking tests
- User limits tests
- Shared content tests
- Job board tests
- Proposal template tests
- Team management tests
- Database connection status
- Server uptime
- Memory usage
- Response times
- API endpoint availability
- HTTP request logging with Morgan
- Error logging to console
- OAuth authentication logging
- Payment processing logs
- File upload logs
- Production: Configure external logging service
npm start # Start production server
npm run dev # Start development server with nodemon
npm test # Run tests
npm run test:watch # Run tests in watch mode
npm run test:coverage # Run tests with coverage
npm run lint # Run ESLint
npm run lint:fix # Fix ESLint issues
npm run format # Format code with Prettier
npm run seed # Seed database with test data
npm run seed:admin # Create admin user
npm run health # Check server health# Seed database with test data
npm run seed
# Create admin user
npm run seed:admin
# Create shared content for testing
node scripts/create-shared-content.js# Backup database
npm run backup
# Restore database
npm run restore- Set
NODE_ENV=production - Configure MongoDB connection string
- Set CORS origins
- Configure JWT secrets
- Set up OAuth credentials (Google)
- Set up email service credentials (Resend recommended)
- Configure Stripe API keys
- Render.com: Web Service deployment
- Vercel: Serverless deployment
- Railway: Container deployment
- Heroku: Container deployment
See the main DEPLOYMENT.md for detailed instructions.
- User registers with email/password or uses OAuth
- Verification email sent automatically (for email registration)
- User verifies email (if required)
- User can login and receive JWT tokens
- Refresh tokens used for session management
- Account locked after 5 failed attempts
- User clicks OAuth login button
- Redirected to OAuth provider (Google)
- User authorizes application
- Callback processes user data
- User account created/updated automatically
- JWT tokens generated and returned
- User starts timer on a task
- Session begins and is tracked
- User can stop timer to end session
- Total time accumulated across all sessions
- Statistics available for progress tracking
- User shares task/project with username
- Shared content appears in recipient's shared panel
- Recipient can view and optionally edit (based on permissions)
- Public share links available for external access
- Pro users create job postings
- Jobs can be published to public board
- Candidates apply through public interface
- Applications tracked and managed
- Analytics available for job performance
- Users create reusable templates with variables
- Templates can be shared publicly
- Users generate client-specific proposals
- Template usage tracked for analytics
- Templates organized by category and tags
All endpoints return consistent error responses:
{
error: "Error Type",
message: "User-friendly error message",
details: [] // Optional validation details
}{
message: "Success message",
data: {}, // Response data
token: "jwt-token", // For auth endpoints
refreshToken: "refresh-token" // For auth endpoints
}- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
Built with β€οΈ for productive business management
PopVia Backend - Powering productivity since 2025
The application sends several types of emails using Resend:
- Email Verification: Sent when users register
- Password Reset: Sent when users request password reset
- Shared Access: Sent when users share tasks/projects
- Feedback: Sent when users submit feedback
- Pro Welcome: Sent when users upgrade to pro membership
- Company Verification: Sent when companies request verification
- Job Applications: Sent when candidates apply for jobs
When a user upgrades to PopVia Pro, they automatically receive a welcome email that includes:
- Congratulations message
- Overview of pro features (unlimited tasks, team collaboration, priority support)
- Link to start using unlimited features
- Contact information for support
The email is triggered automatically in the following scenarios:
- Successful Stripe payment completion
- Subscription creation
- Subscription status updates to active
- Manual session verification
# Test with a sample user
node scripts/test-pro-welcome-email.js
# Upgrade a specific user to pro and send welcome email
node scripts/upgrade-user-to-pro.js user@example.comPOST /api/payments/create-link- Create Stripe payment linkPOST /api/payments/webhook- Handle Stripe webhooksGET /api/payments/verify-session/:sessionId- Verify payment session
GET /api/tasks- Get user's tasksPOST /api/tasks- Create new taskPUT /api/tasks/:id- Update taskDELETE /api/tasks/:id- Delete taskGET /api/projects- Get user's projectsPOST /api/projects- Create new projectPUT /api/projects/:id- Update projectDELETE /api/projects/:id- Delete project
POST /api/tasks/:id/share- Share task with userPOST /api/projects/:id/share- Share project with userGET /api/shared-content- Get shared content
GET /api/companies- Get user's companiesPOST /api/companies- Create new companyGET /api/clients- Get user's clientsPOST /api/clients- Create new client
GET /api/jobs- Get user's jobsPOST /api/jobs- Create new jobGET /api/jobs/public- Get public job boardGET /api/proposal-templates- Get user's templatesPOST /api/proposal-templates- Create new templateGET /api/proposal-templates/public- Get public templates
GET /api/teams- Get user's teamsPOST /api/teams- Create new teamPUT /api/teams/:id/members- Add team member