frontend architecture
Modernizing 200+ production templates
Backward-compatible system evolution across a live, multi-team AEM environment — without a single production regression.
- Role
- Frontend Architect
- Platform
- Fortune 200 Banking Platform
- Timeline
- 2021–2022
- Team
- 5 engineers · 3 business units · Multi-team coordination
200+
backward-compatible
Templates modernized
0
across all rollouts
Regressions
None
incremental rollout
Delivery freeze
Problem
Three years of organic growth across three business units had produced a frontend system that resisted change: unpredictable CSS cascade behavior, a ClientLib dependency graph nobody could fully reason about, and component patterns that had diverged beyond reconciliation.
Approach
Categorized 200+ templates into Extend / Refactor / Replace / Deprecate. Adopted the delegation pattern for backward-compatible modernization. Reorganized ClientLib categories around architectural role rather than business unit. Incremental rollout per business unit with explicit sign-off.
Outcome
200+ templates modernized without a single production regression. ClientLib dependency graph documented and deterministic. New component development time measurably reduced. Cross-BU governance process established and still in use.
The problem
Three years of organic growth across three business units had produced a frontend system that resisted change. An unpredictable CSS cascade. A ClientLib dependency graph nobody could fully reason about. Component patterns that had diverged beyond reconciliation.
The directive: modernize without breaking what's live. No production freeze. No big-bang rewrite. Backward compatible at the content layer, the rendering layer, and the dependency layer simultaneously.
"The risk wasn't in the components we were replacing. It was in the components we didn't know were depending on them."
Big-bang rewrite approach
Replace all 200+ templates in a single multi-month effort. Requires freezing delivery. One high-risk launch. Any post-launch issue affects everything simultaneously.
Incremental modernization
Categorize by risk profile. Low-risk changes ship alongside active delivery. Replace and Deprecate batches ship with isolated validation. Zero delivery freeze. Risk isolated per batch.
System architecture
Before categorizing anything as 'modernize,' the work was scoped into four buckets: Extend (sound architecture, needs new capabilities), Refactor (correct function, problematic implementation), Replace (architecture not recoverable), and Deprecate (duplicate solutions for the same need).
Component governance lifecycle — multi-team approval model
Component request
Author need identified
Architecture review
Reuse vs build decision
Policy definition
Governance constraints authored
a11y validation
NVDA · VoiceOver · axe-core
Staging sign-off
BU lead + QA approval
Production deploy
Zero-regression release
The most consequential decision: the delegation pattern as the standard modernization approach. New components wrap existing ones rather than replacing them. Authored content continues resolving correctly through the delegation chain. Authors experience no disruption. QA validates new behavior against existing content without migration.
Key decisions
Challenge → Decision → Outcome
Challenge
Decision
Outcome
200+ live templates that couldn't be frozen or migrated
Delegation pattern — new components wrap existing, content resolves through chain
Backward-compatible rollout
zero content migration required
ClientLib categories organized by business unit, producing non-deterministic loading
Reorganize by architectural role — base, components, page-type overrides
Deterministic CSS loading order independent of business unit
Three teams with independent delivery cadences and sign-off requirements
Cross-BU governance process — component review, staging validation, BU sign-off
Standard process for all shared component changes
onboarding reduced from weeks to days
Legacy and modernized components co-existing on same pages
Strict category scoping — each component version in isolated ClientLib category
No cascade collisions between component generations
Decision
Delegation pattern as the default modernization approach
Existing content authored against original component properties continues resolving correctly through the delegation chain. Authors experience no disruption. QA validates new behavior against existing authored content without requiring content migration at scale.
Alternative: Full replacement with content migration. Rejected due to scale (200+ templates), live-system risk, and multi-team coordination complexity.
Tradeoff: Delegation chains add rendering complexity and a longer dependency graph to reason about. Worth it for the backward compatibility guarantee.
Outcomes
New component development became faster because the delegation pattern and reorganized ClientLib structure gave engineers a clear, consistent scaffold.
200+
Templates modernized
0
Production regressions
None
Delivery freeze required
Days
New engineer onboarding time
The cross-BU governance process established during this project became the standard process for all subsequent shared component changes. The incremental approach created a repeatable pattern — not a one-time migration.
Reflection
Instrument before optimizing. We had no usage telemetry before beginning. Knowing which components were actively used, and in which template configurations, would have let us sequence the work by actual risk rather than estimated risk — a meaningful difference when you're committing to zero regressions.
Start ClientLib reorganization earlier. Running it in parallel with component modernization created unnecessary uncertainty. The CSS loading instability introduced ambiguity into component QA — you couldn't always tell if a visual regression was a component issue or a cascade issue. Resolving the dependency graph first would have made every subsequent validation step faster and cleaner.