There is a category of website that looks simple from the outside and is surprisingly interesting to build: the daily puzzle site.
Wordle is the obvious example. New York Times bought it for a reported seven figures. But the concept - one puzzle per day, resets at midnight, shareable result - is something any developer can build. I built DailyBrainHub - https://dailybrainhub.com - with six games running on this exact model and the technical decisions were more interesting than I expected.
The daily reset problem
The core mechanic of a daily puzzle site is that everyone gets the same puzzle on the same day. This sounds simple. It creates some interesting decisions.
Option 1: Server-generated puzzles. Your backend picks today's puzzle and serves it via API. Clean, controlled, easy to update. Requires a server.
Option 2: Deterministic client-side generation. You use today's date as a seed for a pseudo-random number generator. The same date always produces the same puzzle. No server needed.
function getDailyPuzzle(puzzleList) {
const today = new Date();
const seed = today.getFullYear() * 10000 +
(today.getMonth() + 1) * 100 +
today.getDate();
const index = seed % puzzleList.length;
return puzzleList[index];
}
This is elegant but has a limitation: once you have served all puzzles in your list, you cycle back to the beginning. You need a large enough puzzle pool that the cycle is not noticeable for at least a year.
Storing progress without accounts
Account systems are friction. Wordle had no accounts. DailyBrainHub has no accounts. But you still need to remember whether a player has completed today's puzzle.
localStorage is the answer for most cases:
function saveTodayProgress(gameId, result) {
const today = new Date().toISOString().split('T')[0];
const key = `${gameId}_${today}`;
localStorage.setItem(key, JSON.stringify(result));
}
function getTodayProgress(gameId) {
const today = new Date().toISOString().split('T')[0];
const key = `${gameId}_${today}`;
return JSON.parse(localStorage.getItem(key));
}
Using the date in the key means yesterday's data is automatically ignored without any cleanup logic. The player's progress resets naturally when the date changes.
The midnight reset
Players who are mid-puzzle at midnight need handling. The safest approach is to check the date when the page loads and when the player submits an answer. If the date has changed since the puzzle was loaded, show a message and refresh.
Shareable results without a backend
Wordle's viral mechanic was the emoji grid you could paste anywhere. No image, no link to a specific result, just text that conveyed the result visually.
function generateShareText(gameId, day, results) {
const emoji = results.map(r => r.correct ? 'checkmark' : 'cross').join('');
return `DailyBrainHub ${gameId} #${day}\n${emoji}\nhttps://dailybrainhub.com`;
}
This generates text that works in WhatsApp, Twitter, anywhere. The result does not need to link to anything specific - it just needs to be intriguing enough that someone asks "what is this?"
What I would do differently
If I were starting over, I would build the share mechanic first, before any other feature. Everything else - the puzzle logic, the design, the blog - is secondary to the sharing loop. That loop is how daily puzzle sites grow. I built the games first and the share button last, which was the wrong order.
Top comments (0)