<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Infrastructure on Worlds of the Next Realm - Dev Blog</title><link>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/categories/infrastructure/</link><description>Recent content in Infrastructure on Worlds of the Next Realm - Dev Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Tue, 17 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/categories/infrastructure/index.xml" rel="self" type="application/rss+xml"/><item><title>The Development Journey, Part 1: Nine Days from Zero</title><link>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-development-journey-part-1-nine-days-from-zero/</link><pubDate>Tue, 17 Feb 2026 00:00:00 +0000</pubDate><guid>https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-development-journey-part-1-nine-days-from-zero/</guid><description>&lt;p&gt;This is the first of a three-part series covering the development journey of Worlds of the Next Realm so far. In this post, we cover the foundation: standing up infrastructure, building the first services, and getting something on screen.&lt;/p&gt;
&lt;p&gt;The timeline is aggressive. The first commit landed on February 8th, 2026. Nine days later, we had 11 repositories, a live beta environment, a working authentication system, a Flutter web client with isometric tile maps, and a backend serving real game data from DynamoDB.&lt;/p&gt;
&lt;h2 id="day-1-2-the-foundation-sprint-feb-8-10"&gt;&lt;a href="#day-1-2-the-foundation-sprint-feb-8-10" class="header-anchor"&gt;&lt;/a&gt;Day 1-2: The Foundation Sprint (Feb 8-10)
&lt;/h2&gt;&lt;p&gt;Everything started with the Flutter client and the AWS infrastructure.&lt;/p&gt;
&lt;p&gt;The FrontEndClient repo received 12 PRs in the first two days. We scaffolded the entire application structure — domain models, theming, navigation, mock backend layer, and all the core UI screens: troops, leaders, research, guild, inventory, expeditions, barter, events, settings, chat, shop, and AI companion. Most of these screens were populated with mock data, but the architecture was real — Riverpod state management, GoRouter navigation, Dio HTTP client with interceptors.&lt;/p&gt;
&lt;p&gt;The most significant piece was the isometric 2.5D tile map renderer built on the Flame game engine. This would become the city view and world map — the visual heart of the game.&lt;/p&gt;
&lt;p&gt;Simultaneously, the Infra repo went up with CDK stacks for the VPC, DynamoDB tables, Application Load Balancer, and CloudFront distribution. We deployed the BackendApi on Lambda behind API Gateway, and the NotificationService and WorldSimulation on Fargate.&lt;/p&gt;
&lt;p&gt;All three backend services had working CDK deployments by the end of day 2. The CI/CD pipelines were live — every push to main deployed to beta automatically.&lt;/p&gt;
&lt;h2 id="day-3-4-the-data-layer-feb-11-12"&gt;&lt;a href="#day-3-4-the-data-layer-feb-11-12" class="header-anchor"&gt;&lt;/a&gt;Day 3-4: The Data Layer (Feb 11-12)
&lt;/h2&gt;&lt;p&gt;This is where BackendCommon became the backbone of the project.&lt;/p&gt;
&lt;p&gt;We built a generalized DynamoDB data store abstraction — a single-table design where every game entity (players, cities, buildings, resources, troops, worlds) lives in one table with partition key patterns and GSIs for alternate access patterns. The data store handles serialization, optimistic concurrency via version IDs, and batch operations.&lt;/p&gt;
&lt;p&gt;The DynamoDB schema went through several iterations during these two days:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Started with a partition key + sort key design&lt;/li&gt;
&lt;li&gt;Removed the sort key&lt;/li&gt;
&lt;li&gt;Added GSI1&lt;/li&gt;
&lt;li&gt;Added GSI2&lt;/li&gt;
&lt;li&gt;Restored the sort key and added GSI1&lt;/li&gt;
&lt;li&gt;Recreated the table as PK-only with GSI1&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&amp;rsquo;s 6 PRs in the Infra repo just iterating on the table schema. Each change required coordinating across BackendCommon (data models), Infra (CDK table definition), and the services that read the data. This is one of the costs of a multi-repo architecture — schema changes ripple across repositories.&lt;/p&gt;
&lt;p&gt;The OperationalTools CLI also came to life during this phase: &lt;code&gt;create-user&lt;/code&gt;, &lt;code&gt;load-game-data&lt;/code&gt;, &lt;code&gt;generate-map&lt;/code&gt;, and &lt;code&gt;bootstrap-world&lt;/code&gt; commands. These tools are essential for populating the game world with data — definition files for buildings, troops, resources, and research loaded from JSON into DynamoDB.&lt;/p&gt;
&lt;h2 id="day-5-authentication-and-api-wiring-feb-13"&gt;&lt;a href="#day-5-authentication-and-api-wiring-feb-13" class="header-anchor"&gt;&lt;/a&gt;Day 5: Authentication and API Wiring (Feb 13)
&lt;/h2&gt;&lt;p&gt;February 13th was one of the busiest days of the project. Across all repos, we merged PRs covering:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Authentication service&lt;/strong&gt;: Full username/password auth with RS256 JWT tokens, Argon2id password hashing, family-based refresh token rotation, and JWKS endpoint for public key distribution. The master encryption key went through its own evolution — first as a CDK context value, then moved to AWS Secrets Manager for proper secret management.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JWT middleware in BackendApi&lt;/strong&gt;: All API endpoints now verified authentication tokens. We added request/response models for all 22 planned endpoints and created stub handlers for each one.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Frontend auth integration&lt;/strong&gt;: The Flutter client was hooked up to the real authentication service. The mock login button was removed. Real JWT tokens flowed from login through to API calls.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Structured logging&lt;/strong&gt;: Every service got consistent JSON logging — critical for debugging in a distributed system where you need to correlate requests across Lambda, Fargate, and CloudWatch.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Security hardening&lt;/strong&gt;: CloudFront origin verify headers and WAF rules on the ALB to prevent direct access bypassing the CDN.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was also the day of the &amp;ldquo;README wave&amp;rdquo; — every repo got a README, documentation links, and design doc references. Housekeeping, but important for a multi-repo project where anyone (human or AI) needs to find their way around.&lt;/p&gt;
&lt;h2 id="the-first-render"&gt;&lt;a href="#the-first-render" class="header-anchor"&gt;&lt;/a&gt;The First Render
&lt;/h2&gt;&lt;p&gt;Getting the isometric city to render with real data in the browser was the first real milestone. The early versions had&amp;hellip; issues.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-development-journey-part-1-nine-days-from-zero/missing-icons.png"
	width="3016"
	height="1556"
	loading="lazy"
	
		alt="Early city view with missing navigation icons"
	
 
 title="The first render of the city view. Buildings are placed, the isometric grid works, but the bottom navigation bar icons are all missing — a Flutter web asset deployment issue."
 data-title-escaped="The first render of the city view. Buildings are placed, the isometric grid works, but the bottom navigation bar icons are all missing — a Flutter web asset deployment issue."
 
	
		class="gallery-image" 
		data-flex-grow="193"
		data-flex-basis="465px"
	
&gt;&lt;/p&gt;
&lt;p&gt;The bottom navigation bar icons were missing because of how Flutter web packages and deploys JSON-declared assets. It took a dedicated fix to properly deploy subdirectory JSON assets to S3.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://ipjohnson-org.github.io/WorldsOfTheNextRealm.Blog/p/the-development-journey-part-1-nine-days-from-zero/clouds.png"
	width="3020"
	height="1566"
	loading="lazy"
	
		alt="Cloud rendering dominating the viewport"
	
 
 title="An early attempt at the city exterior. The cloud/fog-of-war effect was supposed to mark unexplored territory, but it completely dominates the view, obscuring everything underneath."
 data-title-escaped="An early attempt at the city exterior. The cloud/fog-of-war effect was supposed to mark unexplored territory, but it completely dominates the view, obscuring everything underneath."
 
	
		class="gallery-image" 
		data-flex-grow="192"
		data-flex-basis="462px"
	
&gt;&lt;/p&gt;
&lt;p&gt;The cloud overlay — intended to obscure the city exterior — was rendering far too aggressively. The terrain and buildings underneath were completely invisible. This would take several more days and multiple PRs to get right.&lt;/p&gt;
&lt;h2 id="what-we-learned"&gt;&lt;a href="#what-we-learned" class="header-anchor"&gt;&lt;/a&gt;What We Learned
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Multi-repo coordination is expensive.&lt;/strong&gt; A schema change in DynamoDB touches Infra (CDK), BackendCommon (models), BackendApi (endpoints), OperationalTools (data loading), and sometimes the FrontEndClient (API contracts). The NuGet package pipeline adds latency — you merge a BackendCommon PR, wait for CI to publish the package, then update dependent repos. We ended up with explicit rules: create the BackendCommon PR first, wait for CI, then create dependent PRs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mock-first works.&lt;/strong&gt; Building the entire Flutter client with mock backends first meant we could iterate on UI and navigation without waiting for the real APIs. When the APIs were ready, we swapped in real repositories one at a time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CDK schema iteration is painful.&lt;/strong&gt; Six PRs to get the DynamoDB table right. Each one required a CDK deploy, which means CloudFormation stack updates, which means waiting for DynamoDB table operations to complete. Some of these were destructive — dropping and recreating the table. In a production environment, this would require careful migration planning.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="stats-days-1-5-feb-8-13"&gt;&lt;a href="#stats-days-1-5-feb-8-13" class="header-anchor"&gt;&lt;/a&gt;Stats: Days 1-5 (Feb 8-13)
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Repositories created&lt;/td&gt;
 &lt;td&gt;11&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;PRs merged&lt;/td&gt;
 &lt;td&gt;143&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Commits&lt;/td&gt;
 &lt;td&gt;~310&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Services deployed&lt;/td&gt;
 &lt;td&gt;5 (BackendApi, AuthService, NotificationService, WorldSimulation, FrontEndClient)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CDK stacks&lt;/td&gt;
 &lt;td&gt;5 (VPC, DataStore, Web/ALB, CloudFront, PipelineOIDC)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;DynamoDB schema iterations&lt;/td&gt;
 &lt;td&gt;6&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Backend endpoints stubbed&lt;/td&gt;
 &lt;td&gt;22&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Flutter screens built&lt;/td&gt;
 &lt;td&gt;17&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;NuGet packages published&lt;/td&gt;
 &lt;td&gt;3 (BackendCommon, BackendCommon.Cdk, BackendCommon.Testing)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CI/CD pipelines&lt;/td&gt;
 &lt;td&gt;8 (one per deployable repo)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="code-written-as-of-feb-13"&gt;&lt;a href="#code-written-as-of-feb-13" class="header-anchor"&gt;&lt;/a&gt;Code Written (as of Feb 13)
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Language&lt;/th&gt;
 &lt;th&gt;Lines&lt;/th&gt;
 &lt;th&gt;Purpose&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Dart&lt;/td&gt;
 &lt;td&gt;~14,000&lt;/td&gt;
 &lt;td&gt;Flutter client&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;C#&lt;/td&gt;
 &lt;td&gt;~6,500&lt;/td&gt;
 &lt;td&gt;Backend services + shared libraries&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;TypeScript&lt;/td&gt;
 &lt;td&gt;~520&lt;/td&gt;
 &lt;td&gt;CDK infrastructure&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Markdown&lt;/td&gt;
 &lt;td&gt;~30,000&lt;/td&gt;
 &lt;td&gt;Design docs, game data, READMEs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;JSON&lt;/td&gt;
 &lt;td&gt;~18,000&lt;/td&gt;
 &lt;td&gt;Game definitions, config&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item></channel></rss>