All posts
3 min readBy Anggaproduct / architecture / Expo / mobile

One idea, four apps

The product and architecture bet behind shipping a family of four themed crossword games from a single shared codebase.

The plan was never "build a crossword app". It was "build one crossword engine and ship it four times".

The bet

Indonesian crossword puzzles ("teka teki silang") are a huge, evergreen casual genre. Rather than make one general app and fight for attention, I split the audience into four themed products:

  • TTS 90an - nostalgia for the 1990s.
  • TTS 60-80an - the 60s through 80s era.
  • TTS Gen Z - slang and culture for younger players.
  • TTS Gen Alpha - bright and current.

Four store listings means four chances to rank, four sets of keywords, four audiences who feel like the app was made for them. The cost is maintaining four apps. The trick is making that cost almost zero.

What is actually different per app

When you strip it down, only a handful of things change between the four:

  • Theme colors (one palette file).
  • Strings (the app name, a few era-specific labels).
  • Achievements (the same tiers, different flavor titles).
  • The 100 levels (entirely different clues and answers).
  • Branding assets (icon, splash, store graphics).

Everything else is identical: the crossword grid, the input flow, the hint system, the streak calendar, the achievements engine, the store screen, the purchase logic, crash reporting, analytics. That is roughly 95% of the code.

Why this matters for velocity

Because the shared surface is so large, almost every feature was built once and copied to the other three apps. Add a streak calendar, copy it three times. Fix a keyboard bug, copy it three times. Tune the hint economy, copy it three times.

For a long time that copy-paste was fine, even fast. It only became a problem late, when subtle drift crept in (a stray whitespace difference in one file caused an automated patch to silently skip one app). That is the subject of the final post in this series, where the four repos finally became a monorepo.

The content pipeline

The one genuinely per-app thing that needed real work was the levels. Each app needs 100 interlocking crosswords on its theme. I wrote a generator: a small word list per app feeds a deterministic placement algorithm that interlocks answers into a grid and emits level JSON. Seeded randomness keeps it reproducible, so regenerating never reshuffles a player's existing levels.

All 100 levels ship inside the app. No server, no downloads, no network dependency for gameplay. A player on a plane with no signal can finish the whole game. That decision simplified everything downstream, and it is the reason the apps work fully offline, which later became a deliberate part of the hint economy.

The lesson

A "family of apps" is a product strategy disguised as an engineering decision. The engineering only pays off if the shared core is genuinely shared and the per-app surface is genuinely small. Keep that boundary clean and you get four products for not much more than the price of one. Let it blur and you get four maintenance burdens.

Next: the crossword engine itself, and why tap handling is harder than it looks.