A production-ready Wordle-style daily word game built as a Farcaster Mini-App. Guess the 5-letter word in 6 tries, track your streak, and share your results!
✅ Farcaster Mini-App Integration
- Seamless authentication with Farcaster FID
- Share results directly to Farcaster
- Device-independent progress tracking
✅ Daily Word Puzzle
- New 5-letter word every day at midnight Istanbul time (UTC+3)
- Deterministic word selection using salted hash
- Server-side validation to prevent cheating
✅ Streak Tracking
- Maintain your daily streak
- Track your maximum streak
- Consecutive day logic with Istanbul timezone
✅ Beautiful UI
- Mobile-first responsive design
- Smooth flip animations on tile reveal
- On-screen keyboard with letter states
- Color-blind mode with patterns
- Dark mode support
✅ Robust Backend
- SQLite database for persistence
- In-memory active game tracking
- 6-attempt limit per day per user
- Rate limiting and validation
- React + TypeScript + Vite
- TailwindCSS for styling
- @farcaster/miniapp-sdk for Farcaster integration
- Luxon for timezone handling
- Shadcn/ui components
- Node.js + Express
- better-sqlite3 for database
- Salted hash word selection
- Europe/Istanbul timezone
- Node.js 20+ (Replit provides this)
- Replit account
- Farcaster account for testing
-
Environment Variables
- Add
WORD_SALTto Replit Secrets (any random string, e.g., "my-secret-salt-2025") SESSION_SECRETis already configured
- Add
-
Run the Application
npm run dev
The app will start on port 5000 with hot module replacement.
-
Build for Production
npm run build npm start
The project uses a single Express process that:
- Serves API endpoints under
/api/* - Hosts the React frontend
- Handles Vite HMR in development
- Serves static files in production
SQLite database is automatically created at ./data/app.db on first API call.
Tables:
profiles- Farcaster user profilesdaily_results- Completed game resultsstreaks- User streak data
GET /api/me- Get user stats (streak, remaining attempts)POST /api/guess- Submit a guessGET /api/board- Get anonymized daily statsGET /version.json- App version for cache-busting
-
Enable Developer Mode in Farcaster
- Go to Settings → Developer Tools
- Toggle on "Developer Mode"
-
Add Your Mini-App
- Navigate to the developer section
- Add your Replit URL as a Mini-App
- Test within the Farcaster client
-
Local Testing
- Development mode uses a mock FID (12345)
- Test game logic without Farcaster client
- API endpoints accessible directly
- Guess the 5-letter word in 6 tries
- Each guess must be a valid English word
- After each guess, tiles change color:
- 🟩 Green - Correct letter in correct position
- 🟨 Yellow - Correct letter in wrong position
- ⬜ Gray - Letter not in the word
- New word available daily at midnight Istanbul time
- Keep your streak going!
/
├── client/ # React frontend
│ ├── src/
│ │ ├── components/ # UI components
│ │ ├── lib/ # Utilities (date, words, api, fc)
│ │ └── pages/ # Game page
│ └── index.html
├── server/ # Express backend
│ ├── lib/ # Server utilities
│ ├── db.ts # Database setup
│ ├── routes.ts # API endpoints
│ └── index.ts # Server entry
├── shared/ # Shared types
│ └── schema.ts
├── public/ # Static assets
│ └── version.json
└── data/ # SQLite database (auto-created)
└── app.db
All date operations use Europe/Istanbul (UTC+3) timezone:
- Daily word changes at midnight Istanbul time
- Streak calculations respect Istanbul date boundaries
- Both frontend and backend use Luxon for consistent timezone handling
Daily word is selected deterministically:
hash(WORD_SALT + YYYYMMDD_ISTANBUL) % WORD_LIST_LENGTHThis ensures:
- Same word for all players on a given day
- Unpredictable word sequence
- No way to predict future words
- Playing consecutive days increments streak
- Missing a day resets to 0
- Max streak is tracked separately
- Losing doesn't break streak (only missing days)
- Games in progress stored in memory (Map)
- Only completed games persisted to database
- Prevents duplicate results per day
- Enforces 6-attempt limit
- Server-side word validation
- Salted hash prevents word prediction
- FID-based authentication via headers
- Rate limiting via database checks
- No mock data in production paths
Database is created on first API call. If issues persist:
rm -rf data/
# Restart the app- Ensure you're testing in Farcaster client
- Check Developer Mode is enabled
- Verify your Mini-App URL is correct
- Check
WORD_SALTis set in Secrets - Verify server is running on port 5000
- Check logs with
refresh_all_logstool
This app is designed for Replit hosting:
- All dependencies are pre-configured
- Database persists in
/datadirectory - Port 5000 is automatically exposed
- Environment variables via Replit Secrets
- Single process handles everything
Built with ❤️ for the Farcaster ecosystem. Inspired by the original Wordle game.
MIT