Skip to main content
ADR-018accepted

Monolithic Page Components over Micro-Component Architecture

Context

The portfolio's component architecture faces a fundamental trade-off: should pages be built from small, reusable atomic components (buttons, cards, badges, labels) composed into molecules and organisms (design system pattern), or should each page be a self-contained unit with its own styled components defined in the same file? The design system approach offers reuse and consistency across pages — a StatusBadge component defined once is used identically everywhere. The monolithic approach offers locality and independence — each page's visual logic is entirely contained in its file, with no shared component dependencies that create coupling. The portfolio has 15+ distinct pages, each with unique layout requirements, but several share visual patterns (card layouts, status badges, metadata rows, breadcrumbs).

Decision

Adopt a monolithic page component architecture where each page file defines its own styled components alongside the page logic. Shared styled components are limited to a minimal set: BasicStyle.js (BreadCrums, BasicButtom, and base layout primitives) and the MainLayout wrapper. All page-specific styles — cards, grids, badges, typography — are defined as styled components in the same file as the page that uses them. STATUS_COLORS is defined independently in both decisions.js and decisions/[id].js rather than extracted to a shared constant. Each page owns its complete visual specification with zero imports from a shared component library beyond the minimal base.

Consequences

Positive: Opening any page file shows the complete visual implementation — no hunting through component directories, no implicit style inheritance, no 'where is this styled?' debugging. New pages are created by copying an existing page file and modifying it, rather than composing from a library of components that may have implicit coupling. Deleting a page removes 100% of its styles — no orphaned shared components. The styled-components co-location pattern means each component's styles are adjacent to its render logic, making the relationship between structure and presentation immediately visible. Refactoring one page's layout never creates regressions in other pages. Negative: Visual patterns are duplicated across pages. The StatusBadge pattern exists in at least 3 files with slightly different implementations. Card layouts are defined independently in each page, leading to subtle inconsistencies in padding, border-radius, and spacing (24px vs 28px padding, 6px vs 8px border-radius). Updating a shared pattern (e.g., changing the accepted status color from green to blue) requires finding and modifying every instance. The total CSS output is larger than it would be with shared components because each page generates its own styled-components independently. For a portfolio with 15+ pages, the duplication is manageable; for a product application with 100+ pages, this approach would be untenable.

Calibrated Uncertainty

Predictions at Decision Time

Expected the monolithic approach to maximize development speed for a single-developer project. Predicted the duplication would be manageable at the current scale (15-20 pages). Assumed visual inconsistencies from duplicated patterns would be minor and acceptable. Predicted no scenario where the design system approach would become necessary.

Measured Outcomes

Development speed is indeed high — creating the entire ADR section (list page + detail page + 12 data entries) took a single session, with styles copied from existing patterns and modified. Duplication is manageable at 15+ pages with ~8 duplicated patterns. Visual inconsistencies exist but are subtle: padding varies 24-28px across card components, border-radius varies 6-8px. These inconsistencies are not visible to users but are technically present. The prediction about never needing a design system holds — the portfolio's page count is stable and each page has sufficiently unique layout requirements that extracting shared components would add abstraction overhead without meaningful reuse value.

Unknowns at Decision Time

Did not know at decision time whether the portfolio would expand significantly in page count. If it grew to 50+ pages, the duplication burden would become untenable. Also unknown: whether a future developer (or AI agent) would need to make systematic changes across all pages — the monolithic architecture makes bulk style changes difficult because each instance must be found and modified independently. The calibration fields added to ADRs demonstrated this: the new UI sections were added only to the detail page, but if similar sections needed to appear on the list page, the styles would be duplicated rather than shared.

Reversibility Classification

Two-Way Door

Extracting shared components from the monolithic pages is a progressive refactor: identify duplicated patterns, extract them to a shared components directory, import them in existing pages. This can happen incrementally — one pattern at a time, one page at a time. The monolithic pages continue to work during the migration. Estimated effort for full extraction: 15-20 hours across all pages. The reverse direction (inlining shared components back into pages) is equally possible and simpler.

Strongest Counter-Argument

A design system with 15-20 shared components (Badge, Card, MetricValue, SectionTitle, etc.) would eliminate all duplication, enforce visual consistency, and reduce total CSS output. Changes to shared patterns would propagate automatically to all pages. Tools like Storybook could provide a visual component catalog for reference. The design system approach is industry standard for a reason — it scales better and reduces visual bugs. The counter-counter: the portfolio is not a product application. The page count is stable, the developer count is 1, and each page has unique enough requirements that forced consistency through abstraction would produce either over-generic components or a proliferation of component variants. At this scale, the abstraction overhead exceeds the duplication cost.

Technical Context

Stack
styled-componentsReactNext.js Pages Router
Shared Components
3
Page Specific Styled Components
120+
Avg Styled Components Per Page
15
Duplicated Patterns
~8 across pages
Constraints
  • No shared component library beyond BasicStyle.js
  • Each page owns its styles
  • Duplication preferred over abstraction

Related Decisions