Built here · Live · Product · Design · Systems · Web

Fourword Thinking.

A daily game. Describe the prompt in exactly four words, then vote on the best ones.

Visit website
The live Fourword Thinking game. A masthead reading FOURWORD slash THINKING with a countdown to the next prompt, then prompt number three, Saturday 26 September, marked open now with four answered. The headline asks the player to describe Being the last one awake, with the word last in blue. Below it the four empty answer slots, numbered 01 to 04, the first outlined in coral with the cursor waiting in it, a Lock it in button, and the line zero of four words. A stat row along the bottom reads three prompts posted, four words always, sixteen winning words, zero accepted excuses.

About this build

What it is

One prompt a day. Answer it in exactly four words. Vote on yesterday’s answers, four votes to spend, never on your own. Only the top four are ever public, so the entire public surface of the site is sixteen words a day.

The constraint is the product. Four words is short enough that anyone will try it in the time it takes to read the prompt, and long enough that the good ones are actually good.

Why a brand practice built a word game

Three honest reasons, and the first one is the actual one.

It started because constraint is fun. Four words is a small enough box that the only way through it is to be interesting, which is the same thing that makes a good tagline hard. The name is the joke that made it worth building: Fourword Thinking, said out loud, is forward thinking. A practice that sells the idea that a tight constraint produces better work should probably enjoy proving it on itself.

The second is that the stack has to get proven somewhere. Every technical decision on this page is one I would otherwise be making for the first time on a client’s deadline. Cloudflare’s own documentation shows public config in a wrangler.toml variables block; on Pages that block is read at build time and is gone by the time a request arrives, so the value silently comes through as null. Here that meant a bot-protection widget that would have failed every single submission on day one. I found it on my own project on a Tuesday instead of on somebody’s launch day.

The third is that the four is structural, not decorative. A 2x2 input, four vertical rules, four stats, four winning answers each shown in its own four slots, four votes, four footer links. The number is the identity, and the test of whether an identity is real is whether it survives contact with a build rather than living in a PDF. If I am going to argue that to a client, the argument is cheaper to make when I can point at something.

What was hard

The empty room. Below about fifty people answering, a voting board is a dead room and the game looks abandoned on the day it launches. Under that threshold the site shows the best four answers it has ever produced, labeled as such, rather than an empty board. It is the single most important decision in the build and it is entirely a design problem rather than a technical one.

Knowing what a deploy actually did. Three separate times a change looked like it had failed to ship, and all three times the build was fine and the truth was somewhere else: build-time config never reaching the runtime, a stale browser copy, and a zone-level cache setting quietly overriding the file’s own headers. The diagnostic that would have saved all three is to fetch the same path through the domain and straight from the host and compare the two answers. That now lives in the notes for every project on this stack.

The pre-launch state nobody tests. Every test suite started a game before it checked anything, so the state that every first-time visitor actually sees was the one state with no coverage. It had a bug in it. There is a test for it now.

Where it stands

Open, on its own domain, with 44 prompts loaded and three test suites passing. A new prompt lands at midnight, yesterday’s answers go up for voting, and the day before that freezes into the archive. Starting it was one admin call, kept deliberately separate from deploying so that testing and sharing the link could never burn prompt number one.

The distribution loop closes it: midnight publishes the day’s prompt, seven in the morning a cron trigger captures it and posts it to the Nondescripts Instagram story. That was the last piece. A daily game nobody is reminded about is a daily game nobody plays, and the reminder had to be automatic or it would have lasted about a week.

What it demonstrates

No client, so the receipts have to be the work.

It runs on a real database, not a form that emails me
Ten tables in Cloudflare D1. Submissions, votes, daily rollover, winner freezing and an archive, all against live data. The day is derived from a single integer rather than stored per page, so there is one source of truth about what day it is and nothing to keep in sync.
Identity with no accounts and no signup
A signed anonymous token, one play per person per day, rewritable until midnight. Nobody registers, nobody hands over an email, and there is still a reliable answer to whether you already played. Bot protection is Cloudflare Turnstile rather than reCAPTCHA, which was chosen partly because reCAPTCHA obliges you to display its notice by contract.
Moderation that was tested rather than assumed
A wordlist filter at submit, swept against a 255,000 word dictionary and tightened twice. The first pass was blocking "niggling" and "snigger" on an unanchored pattern, and collapsing "con" into "coon". A filter nobody tests is a filter that quietly censors ordinary words.
It costs nothing to run, on purpose
The game itself has no cron job and no idle server. The first visitor of a new day creates the day, hands it the next prompt and closes voting on the one before. A day with no traffic costs nothing and still rolls over correctly the moment somebody arrives, which is what keeps it on the free tier rather than a monthly bill that arrives whether anyone played or not.
The daily post is automated end to end
Midnight, the site publishes the day's prompt. Seven in the morning, a Cloudflare cron trigger loads that day's page, captures the prompt as an image and posts it to the Nondescripts Instagram story over the API. Nobody screenshots anything, nobody remembers to post, and the thing being posted is the live page rather than a mockup of it, so the story cannot drift out of sync with the site. It runs on the same free tier as the rest of it. This is the problem most clients have with their own channels, solved on something I own first.

Up close

The parts worth looking at.

The four-slot answer input mid-answer, on the prompt Describe a grocery store at 11pm. The words fluorescent and hum are locked in with coral rules under them, the third slot is outlined in coral with nobod being typed, and the fourth is empty. Below it a Lock it in button and the counter three of four words.
Yesterday's voting board for the prompt Describe an empty parking lot. Four answers, each laid out in its own four slots, with a vote bar and vote button beside each: nothing happened here today at 47 votes, the lines outlive us at 41, seagulls own it now at 38, america resting between errands at 33.

Both detail shots are from a seeded local build, so the prompt numbers, answer counts and votes in them are test data. The screen at the top of this page is the real one.

The obvious question

Why does a brand practice build its own products?

Because the alternative is learning this on your deadline. Every decision on this page, and every trap written down in it, came out of a project where the only person exposed was me. Client work is where that gets applied, not where it gets discovered. It is also the honest answer to whether one person can carry something from the first sketch to a thing running in production, which is easier to show than to claim.

Also built here

Will You Bury Me.

Plain-language end-of-life logistics. Answer about forty questions, name one person, hand them a document they have agreed to hold.

See Will You Bury Me

Cookie preferences

Strictly necessary cookies keep the site working and cannot be switched off. Everything else is your call, and you can change it any time from the link in the footer.

  • Strictly necessary

    Remembers this choice and keeps forms secure. No tracking, no third parties. Set only on this domain.

    Always on