476 lines
14 KiB
Markdown
476 lines
14 KiB
Markdown
# QR Master - Create Custom QR Codes in Seconds
|
|
|
|
A production-ready SaaS application for creating and managing QR codes with advanced tracking, analytics, and Stripe payment integration.
|
|
|
|
## Features
|
|
|
|
- 🎨 **Custom QR Codes** - Create static and dynamic QR codes with full customization
|
|
- 📊 **Advanced Analytics** - Track scans, locations, devices, and user behavior
|
|
- 🔄 **Dynamic Content** - Edit QR code destinations anytime without reprinting
|
|
- 📦 **Bulk Operations** - Import CSV/Excel files to create up to 1,000 QR codes at once
|
|
- 💳 **Stripe Integration** - FREE, PRO, and BUSINESS subscription plans with secure billing
|
|
- 🎨 **Custom Branding** - Logo upload, custom colors (PRO+ plans)
|
|
- 🌍 **SEO Optimized** - Schema.org structured data, meta tags, breadcrumbs
|
|
- 🔒 **Privacy-First** - GDPR-compliant, hashed IPs, DNT headers respected
|
|
- 📱 **Responsive Design** - Works perfectly on all devices
|
|
|
|
## Tech Stack
|
|
|
|
- **Frontend**: Next.js 14 (App Router), TypeScript, Tailwind CSS
|
|
- **Backend**: Next.js API Routes, Prisma ORM
|
|
- **Database**: PostgreSQL (with Prisma migrations)
|
|
- **Cache**: Redis (optional)
|
|
- **Auth**: NextAuth.js (Credentials + Google OAuth)
|
|
- **Payments**: Stripe (Subscriptions & Webhooks)
|
|
- **QR Generation**: qrcode library
|
|
- **Bulk Processing**: Papa Parse (CSV), XLSX, JSZip
|
|
- **Analytics**: PostHog (optional)
|
|
- **SEO**: next-sitemap, Schema.org structured data
|
|
|
|
## Quick Start
|
|
|
|
### Prerequisites
|
|
|
|
- Node.js 18+
|
|
- Docker and Docker Compose V2
|
|
- Git
|
|
|
|
### Installation
|
|
|
|
#### Option 1: Development Mode (Recommended)
|
|
|
|
Run database in Docker, app on host machine:
|
|
|
|
1. Clone the repository:
|
|
|
|
```bash
|
|
git clone https://github.com/yourusername/qr-master.git
|
|
cd qr-master
|
|
```
|
|
|
|
2. Install dependencies:
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
3. Copy and configure environment:
|
|
|
|
```bash
|
|
cp env.example .env
|
|
```
|
|
|
|
Edit `.env` and set:
|
|
|
|
- `NEXTAUTH_SECRET` (generate: `openssl rand -base64 32`)
|
|
- `IP_SALT` (generate: `openssl rand -base64 32`)
|
|
- (Optional) Google OAuth credentials
|
|
|
|
4. Start database services:
|
|
|
|
```bash
|
|
npm run docker:dev
|
|
```
|
|
|
|
5. Run database migrations and seed:
|
|
|
|
```bash
|
|
npx prisma migrate dev
|
|
npm run db:seed
|
|
```
|
|
|
|
> **Note**: If you get migration errors, you can reset the database:
|
|
>
|
|
> ```bash
|
|
> npx prisma migrate reset
|
|
> ```
|
|
>
|
|
> This will drop the database, recreate it, run all migrations, and seed data.
|
|
|
|
6. Start development server:
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
7. Access the application:
|
|
- **App**: http://localhost:3050
|
|
- **Database UI**: http://localhost:8080 (Adminer - username: `root`, password: `root`)
|
|
- **Database**: localhost:5435 (username: `postgres`, password: `postgres`)
|
|
- **Redis**: localhost:6379
|
|
|
|
#### Option 2: Full Docker (Production)
|
|
|
|
Run everything in Docker:
|
|
|
|
1. Clone and setup:
|
|
|
|
```bash
|
|
git clone https://github.com/yourusername/qr-master.git
|
|
cd qr-master
|
|
cp env.example .env
|
|
# Edit .env with your configuration
|
|
```
|
|
|
|
2. Build and start:
|
|
|
|
```bash
|
|
npm run docker:prod
|
|
```
|
|
|
|
3. Run migrations:
|
|
|
|
```bash
|
|
docker-compose exec web npx prisma migrate deploy
|
|
```
|
|
|
|
4. Access at http://localhost:3050
|
|
|
|
📚 **For detailed Docker setup, see [DOCKER_SETUP.md](DOCKER_SETUP.md)**
|
|
|
|
## Demo Account
|
|
|
|
After running `npm run db:seed`, use these credentials to test the application:
|
|
|
|
- **Email**: demo@qrmaster.com
|
|
- **Password**: demo123
|
|
- **Plan**: FREE (3 QR codes limit)
|
|
|
|
The seed script also creates sample QR codes for testing.
|
|
|
|
## Development
|
|
|
|
### Available Scripts
|
|
|
|
```bash
|
|
# Development
|
|
npm run dev # Start Next.js dev server (port 3050)
|
|
npm run build # Build for production
|
|
npm run start # Start production server
|
|
|
|
# Database
|
|
npm run db:generate # Generate Prisma Client
|
|
npm run db:migrate # Run migrations (dev mode)
|
|
npm run db:deploy # Deploy migrations (production)
|
|
npm run db:seed # Seed database with demo data
|
|
npm run db:studio # Open Prisma Studio UI
|
|
npx prisma migrate reset # Reset database (drop, recreate, migrate, seed)
|
|
|
|
# Docker
|
|
npm run docker:dev # Start DB & Redis only
|
|
npm run docker:dev:stop # Stop dev services
|
|
npm run docker:dev:clean # Stop and clean containers
|
|
npm run docker:prod # Start full stack (production)
|
|
npm run docker:stop # Stop all services
|
|
npm run docker:logs # View container logs
|
|
npm run docker:db # PostgreSQL CLI
|
|
npm run docker:redis # Redis CLI
|
|
npm run docker:backup # Backup database to SQL file
|
|
```
|
|
|
|
### Local Development (without Docker)
|
|
|
|
1. Install dependencies:
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
2. Set up PostgreSQL and Redis locally
|
|
|
|
3. Configure `.env` with local database URL:
|
|
|
|
```env
|
|
DATABASE_URL=postgresql://postgres:postgres@localhost:5435/qrmaster?schema=public
|
|
```
|
|
|
|
4. Run migrations and seed:
|
|
|
|
```bash
|
|
npx prisma migrate dev
|
|
npm run db:seed
|
|
```
|
|
|
|
5. Start dev server:
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
### Resetting the Database
|
|
|
|
If you need to reset your database (drop all tables, recreate, and reseed):
|
|
|
|
```bash
|
|
# Full reset (drops database, reruns migrations, seeds data)
|
|
npx prisma migrate reset
|
|
|
|
# Or manually:
|
|
npx prisma migrate reset --skip-seed # Reset without seeding
|
|
npm run db:seed # Then seed manually
|
|
```
|
|
|
|
This is useful when:
|
|
|
|
- Schema has changed significantly
|
|
- You have migration conflicts
|
|
- You want to start fresh with clean data
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
qr-master/
|
|
├── src/
|
|
│ ├── app/ # Next.js app router pages
|
|
│ ├── components/ # React components
|
|
│ ├── lib/ # Utility functions and configurations
|
|
│ ├── hooks/ # Custom React hooks
|
|
│ ├── styles/ # Global styles
|
|
│ └── i18n/ # Translation files
|
|
├── prisma/ # Database schema and migrations
|
|
├── docker/ # Docker initialization scripts
|
|
│ ├── init-db.sh # PostgreSQL initialization
|
|
│ └── README.md # Docker documentation
|
|
├── public/ # Static assets
|
|
├── docker-compose.yml # Production Docker setup
|
|
├── docker-compose.dev.yml # Development Docker setup
|
|
├── Dockerfile # Container definition
|
|
├── DOCKER_SETUP.md # Complete Docker guide
|
|
└── env.example # Environment template
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### Authentication
|
|
|
|
- `POST /api/auth/signin` - Sign in with credentials
|
|
- `POST /api/auth/signout` - Sign out
|
|
- `GET /api/auth/session` - Get current session
|
|
|
|
### QR Codes
|
|
|
|
- `GET /api/qrs` - List all QR codes
|
|
- `POST /api/qrs` - Create a new QR code (dynamic or static)
|
|
- `POST /api/qrs/static` - Create a static QR code
|
|
- `GET /api/qrs/[id]` - Get QR code details
|
|
- `PATCH /api/qrs/[id]` - Update QR code
|
|
- `DELETE /api/qrs/[id]` - Delete QR code
|
|
- `DELETE /api/qrs/delete-all` - Delete all user's QR codes
|
|
|
|
### Analytics
|
|
|
|
- `GET /api/analytics/summary` - Get analytics summary for a QR code
|
|
|
|
### User & Settings
|
|
|
|
- `GET /api/user/plan` - Get current user plan
|
|
- `GET /api/user/stats` - Get user statistics
|
|
- `POST /api/user/password` - Update password
|
|
- `POST /api/user/profile` - Update profile
|
|
- `DELETE /api/user/delete` - Delete account
|
|
|
|
### Stripe Payments
|
|
|
|
- `POST /api/stripe/checkout` - Create checkout session
|
|
- `POST /api/stripe/portal` - Create customer portal session
|
|
- `POST /api/stripe/webhook` - Handle Stripe webhooks
|
|
- `POST /api/stripe/cancel-subscription` - Cancel subscription
|
|
|
|
### Public Redirect
|
|
|
|
- `GET /r/[slug]` - Redirect and track QR code scan
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Description | Required | Default |
|
|
| ------------------------------------ | ----------------------------- | -------- | ---------------------------------------------------------------------- |
|
|
| `DATABASE_URL` | PostgreSQL connection string | Yes | `postgresql://postgres:postgres@localhost:5435/qrmaster?schema=public` |
|
|
| `NEXTAUTH_URL` | Application URL | Yes | `http://localhost:3050` |
|
|
| `NEXTAUTH_SECRET` | Secret for JWT encryption | Yes | Generate with `openssl rand -base64 32` |
|
|
| `IP_SALT` | Salt for IP hashing (privacy) | Yes | Generate with `openssl rand -base64 32` |
|
|
| `GOOGLE_CLIENT_ID` | Google OAuth client ID | No | - |
|
|
| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | No | - |
|
|
| `STRIPE_SECRET_KEY` | Stripe secret key | No | - |
|
|
| `STRIPE_WEBHOOK_SECRET` | Stripe webhook signing secret | No | - |
|
|
| `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY` | Stripe public key | No | - |
|
|
| `NEXT_PUBLIC_INDEXABLE` | Allow search engine indexing | No | `false` (set to `true` in production) |
|
|
| `REDIS_URL` | Redis connection string | No | `redis://redis:6379` |
|
|
| `NEXT_PUBLIC_POSTHOG_KEY` | PostHog analytics key | No | - |
|
|
| `NEXT_PUBLIC_POSTHOG_HOST` | PostHog host URL | No | - |
|
|
|
|
**Note**: Copy `env.example` to `.env` and update the values before starting.
|
|
|
|
### Generating Secrets
|
|
|
|
```bash
|
|
# Generate NEXTAUTH_SECRET
|
|
openssl rand -base64 32
|
|
|
|
# Generate IP_SALT
|
|
openssl rand -base64 32
|
|
```
|
|
|
|
## Security & Privacy
|
|
|
|
- **IP Hashing**: IP addresses are hashed with salt before storage (GDPR-compliant)
|
|
- **DNT Respect**: Honors Do Not Track browser headers
|
|
- **Rate Limiting**: API endpoints protected against abuse
|
|
- **CSRF Protection**: Token-based CSRF validation on mutations
|
|
- **Secure Sessions**: NextAuth.js with encrypted JWT tokens
|
|
- **Stripe Security**: PCI-compliant payment processing
|
|
- **SQL Injection Prevention**: Prisma ORM parameterized queries
|
|
|
|
## Database Schema
|
|
|
|
The application uses PostgreSQL with Prisma ORM. Key models:
|
|
|
|
- **User**: User accounts with Stripe subscription data
|
|
- **QRCode**: QR code records (static/dynamic, multiple content types)
|
|
- **QRScan**: Scan analytics data (hashed IP, device, location, UTM params)
|
|
- **Integration**: Third-party integrations (Zapier, etc.)
|
|
- **Account/Session**: NextAuth authentication data
|
|
|
|
### Supported QR Code Types
|
|
|
|
- **URL**: Website links
|
|
- **VCARD**: Contact cards (name, email, phone, company)
|
|
- **GEO**: GPS locations
|
|
- **PHONE**: Phone numbers (tel: links)
|
|
- **TEXT**: Plain text
|
|
- **SMS**: SMS messages
|
|
- **WHATSAPP**: WhatsApp messages
|
|
|
|
### Plans
|
|
|
|
- **FREE**: 3 dynamic QR codes, unlimited static
|
|
- **PRO**: 50 codes, custom branding, advanced analytics
|
|
- **BUSINESS**: 500 codes, bulk upload, API access, priority support
|
|
|
|
## Deployment
|
|
|
|
### Docker (Recommended for Self-Hosting)
|
|
|
|
The application includes production-ready Docker configuration with PostgreSQL and Redis:
|
|
|
|
```bash
|
|
# Build and start all services
|
|
docker-compose up -d --build
|
|
|
|
# Run migrations
|
|
docker-compose exec web npx prisma migrate deploy
|
|
|
|
# View logs
|
|
docker-compose logs -f
|
|
```
|
|
|
|
For detailed deployment instructions, see [DOCKER_SETUP.md](DOCKER_SETUP.md).
|
|
|
|
### Vercel
|
|
|
|
1. Push your code to GitHub
|
|
2. Import the project in Vercel
|
|
3. Add a PostgreSQL database (Vercel Postgres, Supabase, or other)
|
|
4. Add environment variables in Vercel dashboard
|
|
5. Deploy
|
|
|
|
**Note**: For Vercel deployment, you'll need to set up a PostgreSQL database separately.
|
|
|
|
## Troubleshooting
|
|
|
|
### Database Issues
|
|
|
|
**Problem**: Migration errors or schema conflicts
|
|
|
|
```bash
|
|
# Solution: Reset the database
|
|
npx prisma migrate reset
|
|
```
|
|
|
|
**Problem**: "Error: P1001: Can't reach database server"
|
|
|
|
```bash
|
|
# Check if Docker containers are running
|
|
docker ps
|
|
|
|
# Restart database
|
|
npm run docker:dev:stop
|
|
npm run docker:dev
|
|
```
|
|
|
|
**Problem**: Prisma Client out of sync
|
|
|
|
```bash
|
|
# Regenerate Prisma Client
|
|
npx prisma generate
|
|
```
|
|
|
|
**Problem**: Need to start completely fresh
|
|
|
|
```bash
|
|
# Stop all Docker containers
|
|
npm run docker:dev:stop
|
|
|
|
# Remove volumes (⚠️ deletes all data)
|
|
docker volume prune
|
|
|
|
# Restart everything
|
|
npm run docker:dev
|
|
npx prisma migrate dev
|
|
npm run db:seed
|
|
```
|
|
|
|
### Port Already in Use
|
|
|
|
If port 3050 is already in use:
|
|
|
|
```bash
|
|
# Find and kill the process (Windows)
|
|
netstat -ano | findstr :3050
|
|
taskkill /PID <PID> /F
|
|
|
|
# Or change the port in package.json
|
|
"dev": "next dev -p 3051"
|
|
```
|
|
|
|
### Docker Issues
|
|
|
|
**Problem**: Permission denied errors
|
|
|
|
```bash
|
|
# Windows: Run PowerShell as Administrator
|
|
# Linux/Mac: Use sudo for docker commands
|
|
```
|
|
|
|
**Problem**: Out of disk space
|
|
|
|
```bash
|
|
# Clean up Docker
|
|
docker system prune -a
|
|
```
|
|
|
|
## Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
5. Open a Pull Request
|
|
|
|
## License
|
|
|
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
|
|
## Support
|
|
|
|
For support, email support@qrmaster.net or open an issue on GitHub.
|
|
|
|
## Acknowledgments
|
|
|
|
- Next.js team for the amazing framework
|
|
- Vercel for hosting and deployment
|
|
- All open-source contributors
|
|
|
|
---
|
|
|
|
Built with ❤️ by QR Master Team
|