A Sudoku, a Nonogram and a Slitherlink puzzle can sit next to each other in the same catalogue while sharing surprisingly little internally. One is built around digits and constraints across rows, columns and boxes. Another turns numeric clues into runs of filled cells. A third asks for a single loop created from local relationships. If we tried to force all of those rule sets into one universal abstraction, we would eventually invent a language so generic that it became harder to understand than the individual games. The useful answer is not to make every puzzle secretly become the same puzzle. It is to decide carefully which responsibilities really are common.

That is the core architectural idea behind Blupoli Puzzles. Each puzzle owns an engine that understands its state, actions and completion rules. Around it sits a platform that handles recurring product needs: navigation, presentation, catalogue integration, common controls, themes, persistence where appropriate, accessibility, localisation and other shared capabilities. The separation began while the project was still called Blupoli Puzzles, as described in the story of the first Sudoku, but it matters even more now. A small catalogue can survive fuzzy boundaries; a growing one turns every fuzzy boundary into repeated work.

An engine is not a hidden miniature application

The easiest way to imagine a puzzle engine is as one side of a conversation. The platform says, “Here is the current state and the player has done this; what happens next?” The engine returns a new state or explains, through its contract, that the action has no effect. It can also expose whether the puzzle is complete, which information is meaningful and which restrictions apply. Just as important is what the engine does not need to know. It should not decide where the navigation sits, which font the site uses or how the header changes between light and dark themes.

That deliberate ignorance is a strength. The fewer unrelated responsibilities an engine knows about, the easier it is to test its logic without opening a browser and the easier it is to redesign presentation without touching rules. It also allows the same product shell to host games with radically different structures. A board can be a grid, a graph, a set of regions or something that is not naturally a board at all. The platform needs to know how to host and present it, but it should not pretend those structures all have the same internal meaning.

State is the contract between logic and experience

Separating engine and interface only works if the two sides agree on a clear contract. In practice, that contract is largely the state: a representation of what exists now and the information needed to display it. A Sudoku state may contain values, candidates and fixed cells. Another puzzle might need edges, markers, regions or positions. The interface reads that information; the engine transforms it when an action arrives. Instead of a click directly changing both visual elements and game rules, the action crosses an explicit boundary.

This produces a consequence players rarely think about until something breaks: it reduces impossible or contradictory states. If the UI could silently change a cell without the logic knowing, what the player sees and what the rules believe could diverge. When the engine is authoritative for game logic, the screen becomes a view of one source of truth. That does not eliminate bugs, but it makes many of them easier to reason about because there is a defined place where a transition should have been accepted, rejected or transformed.

A shared renderer does not have to mean one universal board

Puzzle platforms are naturally tempted by the idea of building the ultimate reusable “board component.” It works beautifully while the games look similar. Then one puzzle arrives with clues outside the grid, another uses triangular cells, another draws segments between nodes and another has no grid at all. If the shared renderer learns every special case, it becomes a forest of conditionals. Instead of reducing complexity, it centralises it, and every new addition risks disturbing all the older ones.

A healthier strategy is to share rendering patterns and behaviours rather than impose one compulsory geometry. Selection states, event handling, responsive rules, colour tokens, drawing helpers and interaction conventions can be common while each game remains free to compose the surface it needs. The platform defines how an experience joins the product; the puzzle defines how its reasoning is expressed. That small distinction determines whether unusual games can be first-class citizens or whether they have to be squeezed into the shape of whatever was built first.

Text-free diagram showing several distinct puzzle engines converging on a shared experience and catalogue layer
The engines do not need to resemble one another. What they share is the layer that turns them into coherent experiences within the same product.

Metadata is architecture too

A name, slug, summary, family or instruction text can look like editorial decoration, but on a platform those fields become structural. When data is scattered across pages and hard-coded fragments, every new capability has to rediscover it in a different way. When there is a consistent source of truth, catalogue listings can be built predictably, routes can be checked, editorial pages can link to real destinations and automated processes can verify that nothing has quietly become orphaned.

This matters more as the collection grows. The engine knows how to play; metadata knows how that game belongs to the product. Mixing the two would be as awkward as putting site navigation inside a solver. The separation lets a description or category change without touching logic, and lets the logic improve without rewriting how the catalogue presents it. Architecture is not only about organising code. It is also about organising responsibilities and deciding which information is canonical.

The host stops every game from reinventing the application

Between a game engine and a complete page there is a useful coordinating layer we can call the host: the place where a game enters the application. The host can create or load a session, connect global controls, present product information, coordinate restart behaviour and solve the recurring details that would otherwise appear in every engine. Its value comes from understanding enough of both sides without taking ownership of puzzle-specific rules.

When this layer works well, adding a game feels less like building a small standalone app and more like registering a new participant in a known system. The engine contributes its capabilities. Metadata says what the game is. The host provides the environment. A game-specific view draws whatever the puzzle needs. That composition means a global improvement—such as a new help pattern or navigation change—does not require opening dozens of independent implementations and repeating the same edit by hand.

Consistency saves attention before the thinking even begins

The benefit of a shared experience is not merely visual. Attention is part of the puzzle. If every game moves its controls, changes restart behaviour and invents incompatible selection conventions, players spend working memory learning the application instead of solving the challenge. A coherent platform can teach its basic grammar once and reserve the interesting difference for the puzzle rules themselves.

This does not mean suppressing every unique interaction. A game may need its own buttons, symbols or manipulation model. Useful consistency belongs to the things people reasonably expect to come from the product: returning to the catalogue, starting over, understanding status, recognising what can be interacted with, using keyboard or touch and receiving feedback. Stabilise those layers and each engine can be more adventurous without increasing onboarding friction in equal measure.

Accessibility improves when solutions can propagate

Shared architecture offers another less visible advantage: it makes transversal improvements affordable. If every game owns an unrelated focus system, labels, touch sizes and keyboard navigation, fixing an accessibility problem means solving it repeatedly. When common elements live in central components or conventions, one improvement can reach many experiences at once. The platform becomes a multiplier for quality, not just a multiplier for quantity.

There are clear limits. A Nonogram needs accessible information a Sudoku does not, and a connection puzzle may require an entirely different strategy. The common layer cannot replace specific work. What it can do is remove repetitive work so that effort can be spent on the unique accessibility problem each puzzle presents. It is the same principle used for engines: share where a real common responsibility exists, specialise where rules or interaction genuinely differ.

Bugs can reveal that a responsibility lives in the wrong layer

When one bug requires touching five engines to fix identical behaviour, the responsibility may have been placed too low. When a shared component grows exceptions for ten unrelated games, it may have been placed too high. Failures reveal more than incorrect code; they reveal incorrect boundaries. An architecture that is allowed to evolve pays attention to those patterns and moves responsibilities when evidence contradicts the original organisation.

For that reason, the engine-host-interface split is not treated as doctrine. It is a model that earns its place by staying useful. Some capabilities look specific at first and later prove common. Some abstractions begin centrally and eventually need to split because they hide important differences. The goal is not to preserve a beautiful diagram. The goal is to keep the cost of understanding and changing the system low. A boundary is good while it reduces coupling without hiding behaviour we still need to reason about.

Generating, solving and validating are related jobs, not the same job

Another place where responsibility matters is puzzle creation. A solver asks, “Does a solution exist, and how can it be reached?” A generator asks, “How can I construct an instance?” A quality verifier may need additional questions: is the solution unique, does the puzzle avoid degenerate patterns, and is the challenge appropriate for the intended level? Combining all three roles in one piece of code can feel convenient at first, but it makes each job harder to test and reason about independently.

Separation lets those tools share knowledge without confusing their goals. A solver can help validate a generator, but it does not magically turn every generated board into a good puzzle. We explore that distinction in depth in the article on generation and solving. From an architecture perspective, the important lesson is that two algorithms can depend on the same rules while still deserving different contracts because they answer different questions.

A platform does not need to know the future in order to be ready for it

Thinking about scalability can easily become over-engineering. If we imagine every possible puzzle type before implementing the second, we end up building extension points for problems that may never arrive. A more pragmatic approach has worked better: keep boundaries small, notice repeated patterns and generalise when there are enough examples to show what is actually common. Extensibility comes more from clear responsibilities than from predicting an infinite list of options.

This also lowers the cost of being wrong. A narrow interface between engine and host can be revised. A generic framework packed with hypothetical concepts becomes infrastructure nobody wants to touch. Being prepared for growth does not mean predicting every future game. It means preventing the first game from capturing decisions that really belong to the product as a whole. The rest can evolve as evidence arrives.

Tests become more useful when layers have clear purposes

A separated engine can be exercised with states and actions without depending on pixels. The interface can be reviewed against known states without generating a complicated puzzle first. Catalogue processes can validate routes and metadata without solving anything. This division means each check can fail for a more specific reason. Integrated testing still matters, but it does not have to be the only way to discover that a simple rule has broken.

For a large library, that property becomes essential. Shared changes have a wide blast radius. We need enough confidence to improve them without assuming every global edit may have broken a game nobody happened to open manually. Automated checks do not replace real experience review, but they provide the safety net that makes maintaining many pieces practical. Architecture and quality reinforce one another: systems are easier to verify when their parts expose clear, observable contracts.

AI works better when the repository explains the boundaries

AI-assisted development makes explicit architecture even more valuable. An agent can produce code quickly, but it needs to know which file is canonical, what belongs in the engine, where a game is registered and which checks define a complete integration. In a repository full of implicit conventions, generation speed simply produces inconsistency faster. In a repository with clear contracts, AI can repeat established patterns without inventing a fresh architecture for every task.

That does not make system design automatic. If anything, it shifts value toward the decisions an agent cannot responsibly make from syntax alone: whether two games truly share a pattern, whether an abstraction improves the player experience, whether one exception deserves to become a platform capability, or whether a shortcut today makes tomorrow materially worse. In how we use AI during development, we look more closely at that relationship between speed and judgement.

Catalogue growth became a stress test

Small architectures can look elegant simply because they have not yet met a case that contradicts them. Every new puzzle acts as a stress test. One introduces input that is not cell-based. Another needs multiple phases. Another uses an irregular board. Another places essential information outside the grid. If the platform accepts only what it already knows, every new addition becomes a fight. If it accepts anything with no contract at all, it stops providing meaningful value.

The balance comes from watching where problems repeat. When several experiences need the same capability, the platform can consider owning it. When a requirement only makes sense for one game, the engine or its specialised view can keep it. This strategy explains the journey from one puzzle to a broader platform better than any catalogue number. Growth was a continuing exercise in finding the right boundary between variety and coherence.

Architecture also decides how expensive it is to improve old work

New features tend to attract more attention than refinements, but a sustainable system must make both reasonably cheap. If improving one interaction pattern requires editing every game separately, the platform creates debt that punishes quality work. If the shared behaviour lives in the right layer, one improvement can lift the whole catalogue. The same principle applies to styling, navigation, localisation, accessibility policy and other cross-cutting concerns.

This is why we do not judge the architecture only by how quickly it can add games. It also matters how quickly the standard can be raised. A good common layer lets a lesson learned late benefit work created earlier. That is especially valuable in an evolving product because it prevents the older catalogue from being frozen at the quality level of the moment each game was originally implemented.

The best architecture should be almost invisible while you play

A player does not need to know whether a transition was handled by an engine, a host or a shared component. They need the puzzle to respond, the controls to make sense and the move from one game to another not to require relearning the entire application. The architecture exists to create that feeling of naturalness and to make it maintainable. When a technical layer becomes conspicuous in the player experience, some internal complexity may have leaked through.

That is why this subject belongs on the Blog even though it is about software. The interesting story is not a list of classes or an API reference. It is the relationship between an internal decision and something anyone can notice: variety without chaos, consistency without uniformity, growth without turning the catalogue into a museum of unrelated pages. Architecture matters when it lets the product become simpler to use while becoming more capable internally.

A shared home for games that do not look alike

Blupoli Puzzles can bring together very different experiences precisely because it does not require all of them to be variations of one template. The engine protects the puzzle’s logical identity. The specialised view protects its interaction. The host and common layers protect product coherence. Metadata protects discovery and organisation. Verification protects the confidence to keep changing things. None of those pieces is particularly interesting in isolation; together they turn a collection into a platform.

If you want to see the result rather than the diagram, the best test is to open Blupoli Puzzles and move between games that ask you to think in different ways. The architecture is doing its job when that transition feels natural. If you want the next part of the story, continue with “From one puzzle to a platform”. Code will continue to change; the principle remains the same: share the common parts so the differences have room to matter.