Proof of Concept: Validating Seeded Randomization and Content Families in Shipping API Dojo v2

Before migrating the entire curriculum to the content-family model, I needed to validate that the approach actually works.
Issue #8 was that proof of concept. A narrow slice—minimum viable randomization for MCQ answers, lesson drills, and arena scenarios—implemented to prove the data model and rendering approach before committing to the full migration.
This is the work I did, what I validated, and the results.
The PoC scope: narrow and representative
The proof of concept kept the slice intentionally small:
- Implement minimum viable randomization for MCQ answer order
- Implement minimum viable randomization for lesson drill order
- Implement minimum viable randomization for arena scenario order
- Convert one REST lesson to the content-family direction
- Convert one SOAP lesson to the content-family direction
- Convert one scenario into a deeper scenario-family ladder exemplar
- Validate stable progress mapping and SSR-safe behavior under TanStack Start
The goal wasn't to ship features. The goal was to validate the architecture. If the content-family model, seeded randomization, and compatibility adapters work for one lesson, they'll work for twenty.
Seeded randomization in practice
The core of the PoC was seeded randomization. Not chaotic randomization—deterministic, reproducible randomization.
The implementation:
- MCQ answer order: shuffle answer options based on a seed, track which position is correct
- Lesson drill order: shuffle drills within a lesson based on a seed
- Arena scenario order: shuffle scenarios based on a seed
The critical property is determinism. Same seed, same order. Different seed, different order.
That's what makes progress tracking possible. If I complete lesson-abc with seed-12345 and see drills in order [3, 1, 2], and you complete the same lesson with the same seed and see the same order, our progress maps to the same family IDs. If we use different seeds, we see different orders but our progress still maps to the same family IDs.
The shuffle helpers were heavily tested with automated coverage. Deterministic behavior, different-seed behavior, edge cases—all validated before the PoC was considered complete.
Content-family conversion
The PoC converted two lessons to the content-family model: one REST lesson and one SOAP lesson.
The conversion meant:
- Extracting drills into a drill-family structure with a stable ID
- Creating run variants for the drills
- Mapping lesson content to the new family-based references
- Adding compatibility adapters so old and new content can coexist
The compatibility adapters were crucial. During the PoC, and during the full migration, I need migrated and unmigrated content to coexist. The adapters handle the translation layer—old lesson references get mapped to new family IDs, new content uses the family model directly.
The scenario conversion was similar: one scenario converted to a scenario-family ladder exemplar. The ladder concept is important—scenarios can have depth and progression, not just flat sequencing.
SSR-safe behavior validation
One of the constraints from technical scoping was SSR preservation. Lessons must remain crawlable and SSR-visible. Randomization can't break that.
The PoC validated:
- Primary lesson content stays SSR-visible
- Only the parts that truly need runtime seeds randomize
- TanStack Start SSR HTML renders correctly for the exemplar lesson routes
- Real-route behavior works with browser control validation
The validation used browser control testing for route-level behavior. Unit tests covered the shuffle helpers and seed derivation. The combination proved that the randomization approach doesn't break SSR while still delivering the randomized experience.
Stable progress mapping
Progress tracking was the other critical validation. The PoC needed to prove that:
- Progress maps to family IDs, not specific runs
- Same-seed behavior produces the same experience
- Different-seed behavior produces different experiences but same progress mapping
- The progress model works under TanStack Start's server-authoritative approach
The auth foundation from issue #11 provided the server-authoritative progress tracking. The PoC validated that the content-family model integrates correctly with that progress model.
Compatibility adapters
The compatibility adapters are what make incremental migration possible.
During the PoC, and throughout the full migration in issue #9, old and new content coexist. The adapters handle:
- Old lesson references → new family ID mappings
- Old drill references → new drill-family mappings
- Old scenario references → new scenario-family mappings
- Graceful degradation when content is partially migrated
This means I don't have to do a big-bang migration. I can migrate wave by wave, lesson by lesson, with the site remaining functional throughout.
What the PoC proved
The PoC proved several critical things:
- The content-family data model works in practice, not just in theory
- Seeded randomization delivers deterministic, reproducible behavior
- Compatibility adapters enable incremental migration
- SSR-safe behavior is achievable with careful randomization boundaries
- Progress mapping to family IDs is stable across different seeds
- The TanStack Start stack supports the required server-authoritative patterns
These were the risks that could have blocked the full migration. By validating them in a narrow slice, I reduced the risk profile for the entire content-family migration.
Security considerations
The PoC validated the technical architecture, but it revealed a security vulnerability that needs to be addressed in the full implementation: seed exposure in URLs.
If the URL exposes the seed value, users can share exact drill URLs to give others the same randomized experience. This defeats the purpose of randomized practice and undermines certificate validity, since multiple users could claim the same "unique" randomized path.
The seeds should not be visible in URLs. Instead, seeds need to be:
- Generated server-side on first access
- Stored in user session or database tied to the user's progress record
- Never exposed to the client or URL
This is a known issue tracked separately in the shipping-api-dojo repository. The PoC focused on validating the randomization mechanics and data model, but the production implementation must address seed security before certificates are issued.
What the PoC didn't do
The PoC intentionally avoided:
- Full content migration (that's issue #9)
- Billing, email, or domain infrastructure expansion (those were issue #11)
- Higher-value randomization features (that's issue #10)
- Full curriculum expansion to 20/20/20 (that's issue #9)
- Production-grade seed security implementation
The PoC was focused on validation, not completion. Once the architecture was proven, the full migration could proceed with confidence.
What this enabled
With the PoC complete, the full content migration in issue #9 could proceed. The content-family model was proven. The seeded randomization approach was validated. The compatibility adapter pattern was established.
The browser smoke suite in issue #17 would later validate that all of this works together at the route level. But the PoC was the foundation that made the full migration possible.
Sometimes the most important work is the work that proves the work is possible.
Related Posts

Shipping API Dojo v2: A Foundation for Randomized Learning at Scale
The massive v2 rebuild of Shipping API Dojo introduces content families, seeded randomization, and a full auth/billing foundation. Here's the architecture and vision behind the 20/20/20 curriculum expansion.

Auth Foundation: Building Better Auth, Creem Billing, and Email Infrastructure for Shipping API Dojo v2
Issue #11 completed the auth, entitlements, billing, email, and domain foundation for Shipping API Dojo v2. Better Auth, Creem, Resend, and the shipping.apidojo.app domain came together.

Technical Scoping: How Shipping API Dojo v2 Designed Its Content-Family Foundation
Before building Shipping API Dojo v2, I needed a complete technical blueprint. I scoped content families, seeded randomization, auth/billing/email/domain strategy, and the decisions that shaped the architecture.