Timo Knuth eb932ebdaa Publish milestones per channel and add Instagram
Consent is bound to the channel it was given for: approving a post on X says
nothing about Instagram. Publishing state moves from the SocialMilestone row
into SocialMilestonePost, one row per channel, where a missing row means no
consent. The dialog asks per channel, shows the text each one will publish and
keeps a separate handle for each; Instagram captions end in hashtags because a
link there is not clickable.

Also fixes three problems in the existing X path:

- A QR code already past several thresholds produced one prompt per threshold,
  and since the post quotes the current scan count, every one of them would
  have published the same number. Only the highest threshold is announced now.
- Detection ran after every unique scan and re-read the QR code's full scan
  history just to hit skipDuplicates. Known milestones are filtered first.
- A failed post stayed failed forever because the consent dialog only opens
  once. The queue now retries three times on its own, spaces first attempts by
  SOCIAL_MILESTONE_MIN_GAP_HOURS, and Settings lists every milestone per
  channel with restart and revoke.

The worker no longer renders the card itself; it downloads the image the app
renders at /s/m/<token>/og, which also serves the new square and portrait
formats. Instagram publishing stays off until SOCIAL_MILESTONE_CHANNELS and
SOCIAL_WORKER_CHANNELS both name it.

Schema changes are manual SQL, see sql/2026-08-16_*.sql. Run both before
deploying this version.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 13:46:13 +02:00
2026-07-06 21:53:53 +02:00
2026-08-11 21:50:42 +02:00
Fix
2026-07-07 00:10:29 +02:00
2026-07-06 21:53:53 +02:00
2026-07-13 18:51:52 +02:00
2026-07-06 21:53:53 +02:00
2026-03-23 19:01:52 -05:00
2026-07-15 18:08:51 +02:00
2026-08-05 19:32:52 +02:00
2026-07-15 18:08:51 +02:00
2026-01-16 12:44:13 +01:00
2026-08-13 06:10:01 -05:00
2026-07-06 21:53:53 +02:00
2026-07-06 21:53:53 +02:00
2026-07-06 21:53:53 +02:00
2026-07-29 15:13:18 +02:00
2026-07-28 13:29:35 +02:00
2026-07-06 21:53:53 +02:00
2026-03-23 19:01:52 -05:00
2026-03-23 19:01:52 -05:00
2026-01-27 12:29:44 +01:00
2026-04-29 20:34:09 +02:00
2026-07-06 21:53:53 +02:00
2026-03-23 19:01:52 -05:00
2026-03-23 19:01:52 -05:00
2026-03-23 19:01:52 -05:00
add
2026-04-21 12:37:18 +02:00
2026-07-06 21:53:53 +02:00
2026-07-06 21:53:53 +02:00
2026-07-15 18:08:51 +02:00
2026-03-23 19:01:52 -05:00
2026-08-05 19:32:52 +02:00
2026-07-06 21:53:53 +02:00
2026-03-23 19:01:52 -05:00
2026-03-23 19:01:52 -05:00
2026-08-14 13:02:59 +02:00
2026-01-22 20:09:54 +01:00
2026-07-06 21:53:53 +02:00
2026-01-14 14:02:48 +01:00
2026-03-06 16:15:39 +01:00
2026-01-13 12:08:34 +01:00
2026-07-06 21:53:53 +02:00
2026-07-08 19:03:40 +02:00
2026-04-14 11:21:17 +02:00
2026-03-31 18:46:01 +02:00
sql
2026-07-06 00:38:26 +02:00
2026-03-06 16:15:39 +01:00
2026-04-14 10:35:29 +02:00
2026-08-05 22:28:34 +02:00
2026-07-15 18:08:51 +02:00
2026-07-06 21:53:53 +02:00
2026-07-06 21:53:53 +02:00
2026-04-29 20:34:09 +02:00
2026-03-23 19:01:52 -05:00
2026-08-05 19:32:52 +02:00
2026-07-06 21:53:53 +02:00
2026-07-06 21:53:53 +02:00
2026-08-05 19:32:52 +02:00
2026-01-22 20:09:54 +01:00
2026-07-06 21:53:53 +02:00
2026-07-06 21:53:53 +02:00
2026-04-02 11:37:58 +02:00
2026-04-23 14:52:13 +02:00
2026-04-29 20:34:09 +02:00
2026-07-08 19:03:40 +02:00
2026-04-02 11:37:58 +02:00

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

Run database in Docker, app on host machine:

  1. Clone the repository:
git clone https://github.com/yourusername/qr-master.git
cd qr-master
  1. Install dependencies:
npm install
  1. Copy and configure environment:
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
  1. Start database services:
npm run docker:dev
  1. Run database migrations and seed:
npx prisma migrate dev
npm run db:seed

Note

: If you get migration errors, you can reset the database:

npx prisma migrate reset

This will drop the database, recreate it, run all migrations, and seed data.

  1. Start development server:
npm run dev
  1. Access the application:

Option 2: Full Docker (Production)

Run everything in Docker:

  1. Clone and setup:
git clone https://github.com/yourusername/qr-master.git
cd qr-master
cp env.example .env
# Edit .env with your configuration
  1. Build and start:
npm run docker:prod
  1. Run migrations:
docker-compose exec web npx prisma migrate deploy
  1. Access at http://localhost:3050

📚 For detailed Docker setup, see DOCKER_SETUP.md

Demo Account

After running npm run db:seed, use these credentials to test the application:

The seed script also creates sample QR codes for testing.

Development

Available Scripts

# 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:
npm install
  1. Set up PostgreSQL and Redis locally

  2. Configure .env with local database URL:

DATABASE_URL=postgresql://postgres:postgres@localhost:5435/qrmaster?schema=public
  1. Run migrations and seed:
npx prisma migrate dev
npm run db:seed
  1. Start dev server:
npm run dev

Resetting the Database

If you need to reset your database (drop all tables, recreate, and reseed):

# 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 -
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

# 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

The application includes production-ready Docker configuration with PostgreSQL and Redis:

# 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.

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

# Solution: Reset the database
npx prisma migrate reset

Problem: "Error: P1001: Can't reach database server"

# 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

# Regenerate Prisma Client
npx prisma generate

Problem: Need to start completely fresh

# 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:

# 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

# Windows: Run PowerShell as Administrator
# Linux/Mac: Use sudo for docker commands

Problem: Out of disk space

# 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 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

Führe diese im Terminal aus:

IndexNow (Bing/Yandex + Partner): npm run submit:indexnow Google Indexing API: npm run trigger:indexing

Description
No description provided
Readme MIT 184 MiB
Languages
TypeScript 77.5%
HTML 20.1%
JavaScript 1.6%
PLpgSQL 0.3%
Shell 0.2%