Home Par Baked Entry

Sifter: Rendering Liquid Themes Offline

A look at Sifter, an offline Liquid theme renderer using cached mock.shop data, Horizon theme testing, Rust parsers, and careful agent workflows. It is working better than expected, which is always suspicious.

Posted:

Idea

Sifter has been quietly rumbling along for around nine months, mostly as a testing ground for model intelligence, agent workflows, and the kind of technical optimism that looks sensible until you are three parsers deep and questioning your life choices.

The idea is simple enough to explain and awkward enough to build: can we render a Shopify theme completely locally, using cached data from Shopify's authless mock.shop GraphQL API?

That means taking a real Shopify theme, reading its Liquid templates, resolving sections, snippets, settings, routes, and data, then producing something close enough to the real storefront that it can be tested locally without needing a live Shopify store for every change.

For small teams and developers, this is useful if you work with Shopify themes, want faster local feedback, or need a safer way to test storefront behaviour before real customers get involved.

Status

Sifter is surprisingly working well, which is both pleasing and mildly suspicious.

The renderer has gone through several rewrites. The earliest version was built in TypeScript, followed by two Rust attempts, and the current version started near the end of 2025. The latest Rust version has made the strongest progress so far, mainly because large parsing-heavy systems benefit from stricter types, clearer failure states, and fewer opportunities for everything to become a pile of optimistic strings.

The main test target is Shopify's Horizon theme. Most pages now render successfully, including enough real theme structure to make the project feel less like a toy and more like a useful development tool. The next big focus is performance: getting pages to render correctly is the first hurdle, but getting them to render quickly and predictably is what makes the tool worth using day to day.

There is still plenty to do. Sifter is not a polished product, it's a clean room implementation, not aiming to be 100% compatible and it is definitely not a replacement for Shopify's own tooling. It is a practical experiment in local Liquid theme rendering, offline storefront previews, and AI-assisted development on a codebase where vague intent is not enough.

Problems Faced

The first major problem was documentation. Theme behaviour is not one single neat thing. It is Liquid, JSON templates, theme settings, section schemas, storefront data, routing rules, filters, objects, and a long tail of details that only appear once you try to render a real theme.

That situation has improved a lot. Shopify's developer MCP, better public docs, coding-agent plugins, and model-specific skills have made it easier for agents to look up the right information instead of confidently inventing a small fictional shop platform in the corner.

The harder problem has been cost. A lot of early progress happened with GitHub Copilot while request-based billing made long sessions easier to justify. Once token-based billing became the norm, the economics changed. Agents can do impressive work, but complex parser projects burn context quickly. If every wrong turn costs money, planning stops being admin and starts being engineering.

That means Sifter has needed careful task shaping: smaller scopes, clear acceptance criteria, short feedback loops, and regular human steering. The agent can help build the wall, but someone still needs to point at the wall and say, "No, not through the plumbing."

Another recurring problem is testing against Horizon. The theme needs to be available so the renderer can be checked against something real, but the agent must not treat Horizon itself as the thing to fix. If the renderer fails on a valid theme, the answer is to improve the renderer, not quietly edit the theme until the test passes and everyone pretends that was science.

Techniques That Helped

The most useful technique has been continuous steering. AGENTS.md, README.md, focused prompts, and short implementation sessions have all helped keep the work grounded. Long-running sessions are rare, and full autopilot is rarer still.

Agents are very good at completing tasks as written. That is useful until the task is slightly wrong, too broad, or missing the bit that matters. Then they may still complete it, with the serene confidence of a contractor installing a door in the wrong wall.

For Sifter, the better pattern has been:

  • define a narrow rendering behaviour
  • point the agent at the relevant parser, object, or template path
  • ask for the smallest useful change
  • test against Horizon
  • inspect the failure before asking for the next fix

A full test suite is still needed. Rendering against a real theme has been more effective than expected, because it catches behaviour that isolated unit tests can miss, but it is not enough on its own. Parser projects need both: small tests for known rules and real-theme fixtures for the awkward cases.

SpecKit also helped with the first version of Sifter. Weeks of manual planning with a human at the wheel produced a clearer foundation than ad-hoc prompting would have managed. The problem came later, when changes started happening outside that process. SpecKit works best when it remains the source of truth. Once the spec becomes historical decoration, the project starts drifting.

Lessons Learned

The first lesson is that SpecKit is genuinely useful, but only if you keep using it for everything that changes the shape of the system. A spec-driven workflow does not survive well as a one-off planning ceremony. It needs to stay attached to the work.

The second lesson is that Rust has been a better fit than TypeScript for this project. TypeScript is excellent for many web projects, but Sifter is a parser-heavy system with lots of state, edge cases, and error handling. Rust makes more of that structure explicit. It also makes careless shortcuts more annoying, which is not always fun, but is often good.

The third lesson is that model choice matters. GPT has been better at following instructions across a large technical codebase, especially where the task requires restraint and consistency. Claude has often been useful for exploration, but in this project it was more likely to drift, improvise, or take a shortcut that looked helpful in the moment and created cleanup later. Mythos, during its short availability, surfaced a lot of useful improvement ideas, though at a very high token cost.

The fourth lesson is that cheaper agent plans can still produce serious work if the human steering them understands the system. The weak version of AI-assisted development is "let the agent vibe until something happens". The useful version is closer to technical direction: define the job, constrain the surface area, review the result, and keep the feedback loop tight.

Sifter is still unfinished, which makes it a perfect Par Baked project. It has working pages, unresolved performance work, a growing pile of parser knowledge, and enough sharp edges to keep everyone honest.

If you are building on Shopify, experimenting with AI-assisted development, or trying to turn a complicated technical idea into something usable, we can help you plan the work, avoid the expensive detours, and keep the project pointed at the right wall.