Play Skyjo Action with friends remotely. Built with Next.js, Supabase, and Web Push notifications.
- 🃏 Full Skyjo Action rules (action cards: -2 flip, -1 swap, 0 peek)
- 🔄 Real-time board updates via Supabase Realtime
- 🔔 Browser push notifications when it's your turn
- 🎮 2–6 players per game
- 📱 Works on desktop and mobile
- 🔗 Invite friends with a shareable link or 5-letter code
git clone <your-repo>
cd skyjo
npm install- Go to supabase.com and create a free project
- Run the SQL in
supabase/migrations/001_init.sqlin the SQL Editor - Copy your project URL and keys from Settings → API
npx web-push generate-vapid-keysCopy the output into your .env.local.
cp .env.local.example .env.localFill in:
NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...
NEXT_PUBLIC_VAPID_PUBLIC_KEY=BF...
VAPID_PRIVATE_KEY=xxx...
VAPID_EMAIL=you@example.com
npm run devVisit http://localhost:3000
npm i -g vercel
vercelAdd all the environment variables from .env.local to your Vercel project settings.
For push notifications to work in production, Vercel must be on HTTPS (it is by default).
- Host creates a game and shares the 5-letter code (or link)
- Friends join via the code at the home page or the invite link
- Once everyone is in, the host clicks Start Game
- Each player starts with a 3×4 grid of face-down cards
- On your turn:
- Draw from the deck or take the top discard
- Either place it on your grid (replacing one card) or discard it and flip one of your own face-down cards
- Action cards (placed):
- -2: Flip one opponent's face-up card face-down
- -1: Swap one of your cards with an opponent's
- 0: Peek at any face-down card privately
- Completing a column: Three identical face-up values in a column → that column is removed!
- End of round: When a player has all cards face-up, everyone else gets one more turn. If the triggering player doesn't have the lowest score, their score is doubled.
- Game ends when any player reaches 100 points. Lowest total wins!
app/
page.tsx # Home: create / join
lobby/[gameId]/page.tsx # Waiting room
join/[gameId]/page.tsx # Friend invite landing
game/[gameId]/
page.tsx # Main gameplay
results/page.tsx # Final scores
api/
game/
create/route.ts # POST: new game
join/route.ts # POST: join game
start/route.ts # POST: start (deal cards)
action/route.ts # POST: all turn actions
push/route.ts # Push subscription save
components/
GameCard.tsx # Card, DrawPile, DiscardPile
PlayerGrid.tsx # 3×4 grid for each player
Scoreboard.tsx # Running scores table
lib/
game-logic.ts # Pure game rules (deck, scoring, columns)
types.ts # TypeScript types
supabase.ts # Browser client
supabase-server.ts # Server client (service role)
push.ts # web-push wrapper
public/
sw.js # Service worker for push
supabase/
migrations/001_init.sql # DB schema