Architecture: How to structure the provideBrandSeo() API for minimal integ...

Documentation for Sessions

🏗️ Architecture: How to structure the provideBrandSeo() API for minimal integ...

Date: 2026-02-27
Time: 23:49:45 UTC
Session: gspace1-151.5
Agent: architecture
Confidence: 95%
Status: ✅ Documented


📋 Decision Context

Question:

How to structure the provideBrandSeo() API for minimal integration friction across 6 apps?

Task: Session 151: provideBrandSeo() API design


🎯 Decision Made

Chosen:

Single function provideBrandSeo(brand: AppBrand) returning Provider[]. Only provides APP_BRAND token + TitleStrategy override. All 4 services (Seo, SeoContext, Favicon, JsonLd) use providedIn: 'root' — zero registration needed. Each app adds one spread: ...provideBrandSeo(BRAND_PRESET)

Options Considered:

  1. Provider[] with spread syntax (provideApiConfig pattern)
  2. makeEnvironmentProviders()
  3. NgModule with forRoot()
  4. Each service provided separately

💭 Reasoning

ROOT CAUSE of zero SEO adoption: No infrastructure existed, and adding SEO required too many manual steps per app (Meta service, Title service, canonical management, OG tags, etc.). DESIGN PRINCIPLE: The lowest-friction integration wins adoption. Following provideApiConfig pattern exactly (Provider[] return type, spread syntax). ALTERNATIVES REJECTED: (1) makeEnvironmentProviders() — incompatible with spread syntax used in all 6 app configs. (2) Registering all services explicitly — unnecessary since providedIn: 'root' handles tree-shaking. (3) Module-based approach — forbidden by CLAUDE.md (standalone only). WOULD BE WRONG IF: A service needs app-specific configuration beyond the AppBrand (then it would need explicit provider config). EARLY WARNING: If NullInjectorError for APP_BRAND appears in tests, test modules need { provide: APP_BRAND, useValue: GOGRAB_SPACE_BRAND }.


📁 Files Involved


🔗 Related


Auto-generated by MCP Smart Consolidation