Component Architecture - Three-Tier System
Date: October 11, 2025
Status: β
Implemented
Branch: feat/tailwind-integration
Overview
Section titled βOverviewβThis monorepo uses a three-tier component architecture to organize UI code by reusability and scope:
1. MONOREPO-WIDE (packages/ui/) β Everyone uses2. DIVISION-SPECIFIC (packages/ui-{division}/) β Division apps use3. APP-SPECIFIC (apps/{division}/{brand}/src/components/) β Single app usesπ Directory Structure
Section titled βπ Directory Structureβmonorepo/βββ packages/ # REUSABLE LIBRARIESβ ββ βββ ui/ # Tier 1: Monorepo-wideβ β βββ src/β β βββ components/β β βββ Button/ # Generic buttonβ β βββ Input/ # Generic inputβ β βββ Modal/ # Generic modalβ β βββ Slider/ # Generic sliderβ β βββ navigation/ # Base navigation primitivesβ ββ βββ ui-stay-match/ # Tier 2: Stay Match divisionβ β βββ src/β β βββ components/β β βββ Hero/ # Stay Match hero patternβ β βββ Navigation/ # Stay Match navigationβ ββ βββ ui-guestroom/ # Tier 2: Guestroom division (future)β β βββ src/β β βββ components/β ββ βββ ui-homestay/ # Tier 2: Homestay division (future)β βββ src/β βββ components/ββββ apps/ # APPLICATIONS βββ stay_match/ βββ pinkguest/ βββ web/ β βββ src/ β βββ components/ # Tier 3: Pinkguest web only β βββ mobile/ β βββ src/ β βββ components/ # Tier 3: Pinkguest mobile only β βββ shared/ # Brand assets (not components!) βββ assets/images/ # Images βββ constants/ # Content/copyπ― When to Use Each Tier
Section titled βπ― When to Use Each TierβTier 1: Monorepo-Wide (packages/ui/)
Section titled βTier 1: Monorepo-Wide (packages/ui/)βUse when:
- Component is used across ALL divisions (Stay Match, Guestroom, Homestay, etc.)
- Zero business logic
- Pure presentation
- Generic and universal
Examples:
Button- Every app needs buttonsInput- Every app has inputsModal- Every app shows modalsTooltip- Every app has tooltipsSlider- Generic slider component- Base navigation primitives (
BottomNavigation,HorizontalTabs)
Package name: @cloudalt-frontend/ui
Import:
import { Button, Input, Modal } from '@cloudalt-frontend/ui';Tier 2: Division-Specific (packages/ui-{division}/)
Section titled βTier 2: Division-Specific (packages/ui-{division}/)βUse when:
- Component is used across multiple apps in one division
- Implements division-specific UI patterns
- Shared within division, not across divisions
Examples for Stay Match:
Hero- Landing page hero (shared pattern across pinkguest, orangeguest, roomlgbt)StayMatchNavigation- Navigation specific to Stay Match appsSearchBar- Stay Match-specific search patternsListingCard- How Stay Match shows listings
Examples for Guestroom (future):
GuestroomHero- Different hero pattern than Stay MatchGuestroomSearch- Different search UX
Package names:
@cloudalt-frontend/ui-stay-match@cloudalt-frontend/ui-guestroom@cloudalt-frontend/ui-homestay
Import:
import { Hero, StayMatchNavigation } from '@cloudalt-frontend/ui-stay-match';Tier 3: App-Specific (apps/{division}/{brand}/{platform}/src/components/)
Section titled βTier 3: App-Specific (apps/{division}/{brand}/{platform}/src/components/)βUse when:
- Component is used ONLY in this specific app
- Has business logic specific to this app/platform
- Too unique to share
Examples for pinkguest web:
PinkguestCheckoutFlow- Pinkguest-specific checkoutPinkguestProfileSettings- Unique settings pagePinkguestDashboard- Brand-specific dashboard
Examples for pinkguest mobile:
MobileOnboarding- Mobile-specific onboarding flowCameraIntegration- Mobile camera features
Location:
apps/stay_match/pinkguest/web/src/components/apps/stay_match/pinkguest/mobile/src/components/
Import:
// Direct relative import within the appimport { CheckoutFlow } from '../components/CheckoutFlow';π³ Decision Tree
Section titled βπ³ Decision TreeβQuestion: Where should this component live?
Is it used in multiple apps?βββ NO βββ apps/{division}/{brand}/{platform}/src/components/β (App-specific, keep it there)βββ YES β ββ Is it used across divisions? β ββ YES βββ packages/ui/ β (Everyone needs it, make it generic) β ββ NO βββ Multiple apps in same division? β ββ YES βββ packages/ui-{division}/ (Division-specific pattern)π Examples by Tier
Section titled βπ Examples by Tierβ| Component | Tier | Package | Used By |
|---|---|---|---|
| Button | 1 | packages/ui/ | All apps everywhere |
| Input | 1 | packages/ui/ | All apps everywhere |
| Modal | 1 | packages/ui/ | All apps everywhere |
| Hero | 2 | packages/ui-stay-match/ | All Stay Match apps |
| StayMatchNavigation | 2 | packages/ui-stay-match/ | All Stay Match apps |
| GuestroomHero | 2 | packages/ui-guestroom/ | All Guestroom apps |
| CheckoutFlow | 3 | apps/stay_match/pinkguest/web/ | Pinkguest web only |
| ProfileSettings | 3 | apps/stay_match/pinkguest/mobile/ | Pinkguest mobile only |
π Best Practices
Section titled βπ Best Practicesβ1. Start Specific, Extract When Needed
Section titled β1. Start Specific, Extract When Neededββ DONβT:
Build Hero in packages/ui/ "because we might need it later"β DO:
1. Build Hero in apps/stay_match/pinkguest/web/src/components/2. Orangeguest needs it? β Extract to packages/ui-stay-match/3. Guestroom needs similar? β They build their own in packages/ui-guestroom/4. Everyone needs the pattern? β Extract common parts to packages/ui/2. Donβt Prematurely Abstract
Section titled β2. Donβt Prematurely AbstractβOnly move components to packages when you have real duplication, not anticipated future use.
3. Division Boundaries are Real
Section titled β3. Division Boundaries are RealβStay Match and Guestroom can have different implementations of similar components. Donβt force them to share unless truly generic.
4. Brand Assets β Components
Section titled β4. Brand Assets β ComponentsβBrand-specific images and content go in apps/{division}/{brand}/shared/, not in packages.
π Migration Path
Section titled βπ Migration PathβWhen extracting a component from app to package:
- Copy component to new package location
- Update imports in the package
- Update consuming apps to import from package
- Test that everything still works
- Delete original app-specific component
- Update documentation
π Current Status
Section titled βπ Current StatusβImplemented:
Section titled βImplemented:β- β
packages/ui/- Monorepo-wide components - β
packages/ui-stay-match/- Stay Match division package - β
StayMatchNavigationmigrated toui-stay-match - β
Hero component placeholder in
ui-stay-match - β
Brand assets structure:
apps/stay_match/pinkguest/shared/
Future:
Section titled βFuture:β- β³
packages/ui-guestroom/- When Guestroom apps need shared components - β³
packages/ui-homestay/- When Homestay apps need shared components - β³ Extract more components to
ui-stay-matchas duplication emerges
Brand Assets (Special Case)
Section titled βBrand Assets (Special Case)βIcons and images that differ per brand belong in:
β FAQs
Section titled ββ FAQsβQ: Should generic components go in ui or ui-stay-match?
A: If ALL divisions will use it β packages/ui/. If only Stay Match β packages/ui-stay-match/.
Q: Can I import from ui-guestroom in a Stay Match app?
A: Technically yes, but donβt. Each division should be independent.
Q: What if pinkguest and orangeguest have slight variations of a component?
A: Put the shared pattern in ui-stay-match, pass brand-specific props or use design tokens for styling differences.
Q: Should I create ui-{division} packages for all divisions now?
A: No! Only create them when you have real components to share. Start with app-specific components first.
π Related Documentation
Section titled βπ Related Documentationβ- Design Token System - How to use design tokens for styling
- Asset Management - Where to put images, icons, and fonts
- Tailwind Integration Guide - Using Tailwind with components
- Onboarding Guide - Getting started
Last Updated: October 11, 2025
Maintained By: Engineering Team