A modern, mobile-first PWA for marketing lotteries that allows businesses to promote their products through interactive games with live participant counters and integrated advertising systems.
- Real-time Lottery Games: Create and manage marketing lotteries with live participant counters
- Interactive Participation: Users can join games with secure payment processing
- Automatic Drawing System: Fair and transparent winner selection when quotas are reached
- Business Promotion: Companies can showcase products and boost visibility
- Firebase Realtime Database: Live participant counters and game status updates
- Firestore: Complex data management for users, games, products, and payments
- Real-time Notifications: Instant updates for game progress and results
- Stripe: Credit card processing for international users
- Mobile Money: Orange Money and MTN Mobile Money for African markets
- Secure Transactions: End-to-end encrypted payment processing
- Mobile-First Design: Optimized for mobile devices with responsive layouts
- PWA Capabilities: Installable app with offline functionality
- Real-time Counters: Live participant numbers visible during games
- Beautiful UI: Modern lottery theme with dark backgrounds and orange accents
- Frontend: Next.js 14 + TypeScript + Tailwind CSS
- Backend: Firebase (Firestore + Realtime Database)
- Authentication: Firebase Auth
- Payments: Stripe + Mobile Money APIs
- Storage: Firebase Storage + Cloudinary
- PWA: @ducanh2912/next-pwa
- Deployment: Vercel
Firestore Collections:
├── users (profiles, roles)
├── categories (game categories)
├── products (company products)
├── games (lottery games)
├── tickets (participations)
├── payments (transactions)
└── enterprises (company profiles)
Realtime Database:
└── gameCounters/{gameId}
├── participants (current count)
├── status (game state)
├── maxParticipants
└── lastUpdate (timestamp)
- Node.js 18+ and Yarn
- Firebase project with Firestore and Realtime Database enabled
- Stripe account (optional, for payment processing)
git clone <repository-url>
cd lottery-app
yarn install-
Create a new Firebase project at Firebase Console
-
Enable the following services:
- Authentication (Email/Password)
- Firestore Database
- Realtime Database
- Storage
- Functions (optional)
-
Create a
.env.localfile with your Firebase configuration:
# Firebase Configuration
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key_here
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=123456789
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
NEXT_PUBLIC_FIREBASE_DATABASE_URL=https://your_project-default-rtdb.firebaseio.comThe app is already configured with PWA support using @ducanh2912/next-pwa. The configuration includes:
- Service Worker: Automatic registration and caching
- Web App Manifest: App metadata and icons
- Offline Support: Basic caching strategies
- Install Prompt: "Add to Home Screen" functionality
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Users collection
match /users/{userId} {
allow read: if request.auth != null && (request.auth.uid == userId || resource.data.role == 'ADMIN');
allow create: if request.auth != null && request.auth.uid == userId;
allow update: if request.auth != null && request.auth.uid == userId;
allow delete: if false; // Users cannot be deleted, only deactivated
}
// Games collection
match /games/{gameId} {
allow read: if true; // Public read access
allow create: if request.auth != null &&
(get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role in ['ADMIN', 'VENDOR']);
allow update: if request.auth != null &&
(resource.data.createdBy == request.auth.uid ||
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'ADMIN');
allow delete: if request.auth != null &&
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'ADMIN';
}
// Tickets collection
match /tickets/{ticketId} {
allow read: if request.auth != null &&
(resource.data.userId == request.auth.uid ||
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'ADMIN');
allow create: if request.auth != null && request.auth.uid == resource.data.userId;
allow update: if false; // Tickets cannot be modified after creation
allow delete: if false; // Tickets cannot be deleted
}
}
}{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid || root.child('users').child(auth.uid).child('role').val() === 'ADMIN'",
".write": "$uid === auth.uid",
".validate": "newData.hasChildren(['email', 'firstName', 'lastName', 'role'])"
}
},
"gameCounters": {
"$gameId": {
".read": "auth != null",
".write": "auth != null && (root.child('users').child(auth.uid).child('role').val() in ['ADMIN', 'VENDOR'] || root.child('games').child($gameId).child('createdBy').val() === auth.uid)"
}
}
}
}Firestore Rules:
firebase deploy --only firestore:rulesRealtime Database Rules:
firebase deploy --only databaseyarn devOpen http://localhost:3000 to view the application.
- Mobile-First Approach: All components designed for mobile devices first
- Responsive Grid System: Adapts seamlessly to tablet and desktop
- Touch-Friendly Interface: Optimized for mobile interactions
- Progressive Enhancement: Enhanced features on larger screens
- Primary Background: Dark charcoal (
#1a1a1a) - Secondary Background: Dark gray (
#0f0f0f) - Primary Accent: Vibrant orange (
#FF5722) - Secondary Accent: Warm orange (
#FF9800) - Text Colors: White, light gray, and orange accents
- Mobile: < 768px (default)
- Tablet: 768px - 1024px
- Desktop: > 1024px
- Web App Manifest: Complete app metadata
- Install Prompt: Native app-like installation
- App Icons: Multiple sizes for different devices
- Splash Screen: Custom loading experience
- Service Worker: Caches essential resources
- Offline First: Works without internet connection
- Background Sync: Syncs data when connection returns
- Push Notifications: Real-time updates (future feature)
- Lazy Loading: Components load on demand
- Image Optimization: Next.js automatic optimization
- Code Splitting: Automatic bundle optimization
- Caching Strategy: Intelligent resource caching
- Register/Login: Create an account or sign in
- Browse Games: View available lottery games
- Participate: Purchase tickets for games you're interested in
- Track Progress: Monitor real-time participant counters
- Receive Results: Get notified when games are drawn
- Create Products: Add your products to the platform
- Launch Games: Create lottery games with your products
- Monitor Engagement: Track real-time participation and views
- Boost Visibility: Use advertising features to promote games
- Manage Results: Handle drawing and winner notifications
src/
├── app/ # Next.js app router pages
│ ├── [locale]/ # Internationalized routes
│ │ ├── en/ # English locale pages
│ │ ├── fr/ # French locale pages
│ │ ├── admin/ # Admin panel pages
│ │ ├── auth/ # Authentication pages
│ │ ├── dashboard/ # User dashboard
│ │ ├── games/ # Games listing
│ │ ├── layout.tsx # Locale-specific layout
│ │ └── page.tsx # Home page with locale
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout
│ └── page.tsx # Root redirect
├── components/ # Reusable components
│ ├── ui/ # shadcn/ui components
│ ├── providers/ # Context providers
│ └── home/ # Home page components
├── lib/ # Utility libraries
│ ├── firebase/ # Firebase configuration and services
│ ├── i18n/ # Internationalization
│ ├── themes/ # Theme management
│ ├── constants/ # Project constants
│ └── utils/ # Helper functions
├── types/ # TypeScript type definitions
└── hooks/ # Custom React hooks
lottery-app/
├── firestore.rules # Firestore security rules
├── database.rules.json # Realtime Database rules
├── next.config.js # Next.js configuration
├── tailwind.config.ts # Tailwind CSS configuration
├── package.json # Dependencies and scripts
├── .github/ # GitHub Actions workflows
├── .husky/ # Git hooks configuration
├── .eslintrc.json # ESLint configuration
├── .prettierrc # Prettier configuration
└── public/ # Static assets
├── icons/ # PWA icons
├── images/ # App images
└── manifest.json # PWA manifest
import { useGameCounter } from '@/lib/hooks/useGameCounter';
function GameCounter({ gameId }: { gameId: string }) {
const { counter, loading, error } = useGameCounter(gameId);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div className="text-2xl font-bold">
{counter?.participants || 0} / {counter?.maxParticipants || 0} Participants
</div>
);
}import { firestoreService, realtimeService } from '@/lib/firebase/services';
// Create a new game
const gameId = await firestoreService.createGame({
title: 'Win an iPhone!',
ticketPrice: 1000,
maxParticipants: 100,
// ... other fields
});
// Initialize real-time counter
await realtimeService.updateGameCounter(gameId, {
participants: 0,
status: 'ACTIVE',
maxParticipants: 100,
});- Connect your GitHub repository to Vercel
- Set environment variables in Vercel dashboard
- Deploy automatically on push to main branch
- HTTPS Required: PWA features only work over HTTPS
- Service Worker: Automatically registered on production
- Manifest: Automatically served with proper headers
- Icons: Ensure all icon sizes are available
Ensure all Firebase configuration variables are set in your production environment.
- Authentication: Firebase Auth with email/password
- Authorization: Role-based access control (USER, ADMIN, ENTERPRISE)
- Data Validation: Server-side validation for all inputs
- Payment Security: PCI-compliant payment processing
- Rate Limiting: API rate limiting to prevent abuse
- Real-time Updates: < 100ms response time for live counters
- Optimized Queries: Efficient Firestore queries with proper indexing
- CDN Integration: Static assets served via CDN
- PWA Features: Service workers for offline capabilities
- Mobile Optimization: Touch-friendly, responsive design
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Setup, architecture, and troubleshooting are in the docs/ folder.
- Documentation index – Overview and links to all docs
- Setup guide – Local setup and Firebase
- General troubleshooting – Common issues
- i18n troubleshooting – i18n issues
- Documentation: See docs/ for guides
- Issues: Report bugs via GitHub Issues
- Discussions: Join community discussions on GitHub
- Basic authentication system
- Real-time game counters
- Game creation and management
- User participation system
- Mobile-first responsive design
- PWA implementation
- Payment integration (Stripe + Mobile Money)
- Automatic drawing system
- Winner notifications
- Business profiles
- Push notifications
- Advanced analytics dashboard
- Advertising system
- Mobile app (React Native)
- Multi-language support
- Advanced PWA features
Built by Avom Brice Check my portfolio at https://maebrieporfolio.vercel.app
Mobile-first, PWA-ready, and fully responsive
