A real-time multiplayer drawing and guessing game powered by modern web technologies and AI.
PictionAI combines the timeless fun of Pictionary with real-time multiplayer gameplay. Players take turns drawing while others race to guess the hidden word within the time limit. Built with cutting-edge technologies, the game features AI-powered card generation and real-time synchronization across all players.
- Real-time Multiplayer: Instant synchronization of drawings, guesses, and scores across all players
- AI-Powered Cards: Intelligent card generation using Groq AI with fallback card library
- Live Scoring: Atomic score updates with dual scoring (guesser time bonus + drawer 25% points)
- Drawing Tools: Full-featured canvas with brush, eraser, color picker, and undo functionality
- Game History: Track your games with statistics and category filters
- Dark Mode: Theme support with system preference detection
- Multiple Languages: Built with internationalization support (Italian/English)
- Node.js 18+ and pnpm (or npm/yarn/bun)
- A Convex account (free tier available at convex.dev)
# Clone the repository
git clone https://github.com/violabg/pictionary-game.git
cd pictionary-game
# Install dependencies
pnpm install
# Set up environment variables
cp .env.example .env.local# Terminal 1: Start the Convex backend
npx convex dev
# Terminal 2: Start the Next.js frontend
pnpm devOpen http://localhost:3000 in your browser. The Convex dashboard URL will be displayed in Terminal 1.
pnpm build
pnpm start- Framework: Next.js 16.0+ (App Router)
- React: 19.2+ with TypeScript
- Styling: Tailwind CSS 4.1+ with dark mode support
- UI Components: Base UI with custom primitives
- Forms: react-hook-form + Zod validation
- Animations: Tailwind animations and react-confetti
- Database & Real-time: Convex (replaces traditional databases)
- Authentication: @convex-dev/auth (built-in Convex authentication)
- File Storage: Convex native storage for drawings
- API Calls: Convex actions (server-side Node.js operations)
- Card Generation: @ai-sdk/groq with Vercel AI SDK
- Fallback: Hardcoded card library per category
The backend uses Convex's type-safe function system:
- Queries (
convex/queries/): Read-only operations with real-time subscriptions - Mutations (
convex/mutations/): Atomic write operations (game logic, scoring) - Actions (
convex/actions/): External API calls (AI, file uploads) - Schema (
convex/schema.ts): Database tables and indexes
Key tables: users, games, players, cards, turns, guesses, drawings
- App Router (
app/): Pages for home, auth, game, history, profile - Game Board (
components/game/): Real-time drawing canvas, guess input, score tracking - Auth Components (
components/auth/): Login, signup, password recovery - UI Library (
components/ui/): Reusable Base UI components - Custom Hooks (
hooks/): Convex subscriptions, auth state, timer management
Player joins → Game created in "waiting" state
↓
Game starts → Players assigned, first drawer selected
↓
Drawer begins turn → Canvas opens, 60-120s timer starts
↓
Other players guess → Submitted via mutations with atomic validation
↓
Correct guess? → Points awarded immediately (time bonus + drawer bonus)
↓
Drawing uploaded → Screenshot stored in Convex storage
↓
Next turn → Automatic round-robin drawer rotation
The game ensures consistency through Convex mutations:
- Turn Creation: Drawer calls
startNewTurn(creates turn in "drawing" state) - Guess Submission: Atomic mutation validates guess and awards points
- Turn Completion: Three scenarios handled atomically:
- Correct guess → Both players earn points, turn → "completing"
- Manual winner → Host selects winner, points awarded
- Time up → No points, timer expires, advance to next turn
- Score Persistence: All scores and turn metadata persisted in single transaction
See TURN_MANAGEMENT_ANALYSIS.md for detailed turn flow documentation.
- Functional components with TypeScript
"use client"directive for interactive components- Arrow function syntax
- Server components by default in Next.js App Router
- Tailwind CSS utilities for layout and responsive design
- OKLCH color format in CSS files
- Dark mode with
dark:prefix - Avoid inline styles
- Type-safe Convex function references:
api.mutations.game.startNewTurn - Validator schemas for all Convex functions (
argsandreturns) - Built-in Convex authentication with user profiles
- User data stored in extended
userstable
- Zod schemas for validation
- react-hook-form with
@hookform/resolvers/zod - Field validation on submit
- Guesser:
timeLeftseconds (full time bonus) - Drawer:
max(10, floor(timeLeft / 4))(25% of time bonus, minimum 10 points) - Time up: No points awarded
- All scores updated atomically in database
-
Backend:
- Add table to
convex/schema.tsif needed - Create queries in
convex/queries/ - Create mutations in
convex/mutations/ - Always include
argsandreturnsvalidators
- Add table to
-
Frontend:
- Create component in
components/directory - Use
useQueryfor real-time subscriptions - Use
useMutationfor writes - Add
"use client"for hooks
- Create component in
-
Types:
- Import from
convex/_generated/dataModelforDoc,Id - Extend types as needed in feature files
- Import from
Get current user:
import { useAuthenticatedUser } from "@/hooks/useAuth";
const { profile } = useAuthenticatedUser();Query real-time data:
import { useQuery } from "convex/react";
const game = useQuery(api.queries.games.getGame, { game_id });Update database:
import { useMutation } from "convex/react";
const submitGuess = useMutation(api.mutations.game.submitGuess);
await submitGuess({ game_id, guess_text });Follow the TESTING_GUIDE.md for comprehensive test scenarios covering:
- Authentication flows
- Game creation and joining
- Lobby state management
- Drawing and guess submission
- Turn rotation and scoring
- Edge cases and concurrency
# Deploy to Convex Cloud
npx convex deployDeploy to any Next.js-compatible platform (Vercel, AWS Amplify, Netlify, etc.):
pnpm build
# Upload build artifacts to your hosting platform- Ensure
npx convex devis running in a separate terminal - Check that
.env.localcontains valid Convex deployment URL - Clear browser cache and reload
- Some browsers require HTTPS for canvas operations
- Check browser console for canvas permission errors
- Ensure drawing tools component is mounted with
"use client"
- Verify Groq API key in Convex environment variables
- Check Convex action logs for quota exceeded errors
- Fallback card library will be used automatically
- Real-time: Automatic subscriptions without polling
- Type Safety: Generate types from schema automatically
- Atomic Operations: All-or-nothing mutations prevent inconsistencies
- File Storage: Built-in storage for drawings
- Developer Experience: Zero-config authentication, live reload
This project uses Convex exclusively (not Supabase). Convex provides better real-time support, simpler authentication, and atomic operations better suited for multiplayer games.
- Real-time subscriptions scoped to specific game instance
- Avoid re-rendering entire game board on each draw stroke
- Use Convex indexes for efficient queries
- Lazy load game history and profile pages
We welcome contributions! Please read CONTRIBUTING.md for guidelines.
This project is licensed under the MIT License - see LICENSE file for details.
For issues, questions, or suggestions, please open an issue on GitHub.
Built with ❤️ by the PictionAI team