11 KiB

Portal Architecture

This document outlines the feature-driven architecture implemented for the customer portal.


Quick Reference

Aspect Location
Feature modules apps/portal/src/features/
Shared components apps/portal/src/components/ (atomic design)
API client apps/portal/src/core/api/index.ts
Query keys apps/portal/src/core/api/index.tsqueryKeys
Domain types import type { X } from "@customer-portal/domain/<module>"

Key patterns:

  • Pages are thin wrappers → import views from features
  • Features contain: api/, hooks/, stores/, components/, views/
  • Use React Query hooks from features (e.g., useInvoices from @/features/billing)

Folder Structure

apps/portal/src/
├── app/                              # Next.js App Router entry points (route groups only)
│   ├── (public)/                     # Marketing + auth routes, pages import feature views
│   ├── account/                      # Authenticated portal routes, thin wrappers around features
│   ├── api/                          # App Router API routes
│   ├── favicon.ico / globals.css     # Global assets
│   └── layout.tsx                    # Root layout/providers
├── components/                       # Shared UI components (design system)
│   ├── atoms/                        # Basic building blocks (Button, Input, Badge, etc.)
│   ├── molecules/                    # Combinations of atoms (DataTable, FormField, etc.)
│   ├── organisms/                    # Complex UI sections (AppShell, SiteFooter, etc.)
│   └── templates/                    # Page-level layouts (AuthLayout, PageLayout, etc.)
├── core/                             # App-wide infrastructure
│   ├── api/                          # HTTP client, query keys, error handling
│   ├── logger/                       # Application logging
│   └── providers/                    # React context providers (QueryProvider)
├── features/                         # Feature-specific modules composed by routes
│   ├── account/
│   ├── address/                      # Address management and Japan Post lookup
│   ├── auth/
│   ├── billing/
│   ├── checkout/
│   ├── dashboard/
│   ├── get-started/                  # Unified signup and eligibility flow
│   ├── landing-page/
│   ├── marketing/
│   ├── notifications/
│   ├── orders/
│   ├── realtime/
│   ├── services/                     # Service browsing and ordering (pre-purchase)
│   ├── subscriptions/                # Subscription management
│   ├── support/
│   └── verification/
├── shared/                           # Cross-feature helpers
│   ├── api/                          # Shared API services (currency, etc.)
│   ├── constants/                    # Data constants (countries, prefectures)
│   ├── hooks/                        # Generic React hooks
│   └── utils/                        # General utilities (cn, date, error-handling)
├── styles/                           # Global styles and design tokens
└── config/                           # Environment configuration

Design Principles

1. Feature-First Organization

Related functionality is grouped together in feature modules, making it easier to understand and maintain code.

2. Atomic Design

UI components follow atomic design principles:

  • Atoms: Basic building blocks (Button, Input, Badge, Spinner, etc.)
  • Molecules: Combinations of atoms (DataTable, FormField, AlertBanner, etc.)
  • Organisms: Complex UI sections (AppShell, SiteFooter, AgentforceWidget)
  • Templates: Page-level layouts (AuthLayout, PageLayout, PublicShell)

3. Separation of Concerns

Each feature module contains:

  • api/: Data fetching and API calls
  • stores/: State management (Zustand stores)
  • components/: UI components specific to the feature
  • hooks/: React hooks for state and operations
  • views/: Page-level view components
  • utils/: Utility functions
  • index.ts: Feature public API (barrel exports)

4. Centralized Shared Resources

  • core/: App-wide infrastructure (API client, logging, providers)
  • shared/: Cross-feature utilities, hooks, and constants
  • components/: Reusable UI components following atomic design

Feature Module Structure

Each feature follows a consistent internal structure:

features/[feature-name]/
├── api/                 # Data fetching layer
│   ├── [feature].api.ts
│   └── index.ts
├── stores/              # State management (if needed)
│   ├── [feature].store.ts
│   └── index.ts
├── components/          # Feature-specific components
│   ├── [Component].tsx
│   └── index.ts
├── hooks/               # Feature-specific hooks
│   ├── use[Feature].ts
│   └── index.ts
├── views/               # Page-level views
│   └── [Feature]View.tsx
├── utils/               # Feature utilities
└── index.ts             # Feature public API

Core vs Shared

Core (@/core/)

App-wide infrastructure that features depend on:

  • api/: HTTP client, query keys, response helpers, error handling
  • logger/: Application logging utilities
  • providers/: React context providers (QueryProvider)

Shared (@/shared/)

Cross-feature utilities that aren't infrastructure:

  • api/: Shared API services (currency)
  • constants/: Data constants (countries, prefectures)
  • hooks/: Generic React hooks (useLocalStorage, useDebounce, useMediaQuery)
  • utils/: General utilities (cn, date formatting, error handling)

Import Patterns

// Feature imports (prefer barrel exports)
import { LoginForm, useAuthStore } from "@/features/auth";
import { billingService, useInvoices } from "@/features/billing";

// Component imports (atomic design)
import { Button, Badge, Spinner } from "@/components/atoms";
import { DataTable, FormField } from "@/components/molecules";
import { AppShell } from "@/components/organisms";

// Core infrastructure
import { apiClient, queryKeys } from "@/core/api";
import { logger } from "@/core/logger";
import { QueryProvider } from "@/core/providers";

// Shared utilities
import { cn, formatIsoDate } from "@/shared/utils";
import { useDebounce, useMediaQuery } from "@/shared/hooks";
import { countries, japanPrefectures } from "@/shared/constants";

// Domain types (from shared package)
import type { Invoice } from "@customer-portal/domain/billing";

Path Mappings

  • @/* - Root src directory
  • @/components/* - Component library (atomic design)
  • @/core/* - App-wide infrastructure
  • @/features/* - Feature modules
  • @/shared/* - Cross-feature utilities
  • @/styles/* - Style files
  • @/config/* - Environment configuration

Pages vs Features

  • Route pages under src/app/** are thin shells and do not call APIs directly.
  • Data fetching and business logic live in src/features/**:
    • api/: Feature API services built on the shared apiClient
    • hooks/: React Query hooks that wrap API services
    • stores/: Zustand stores for complex state management
    • components/: Feature UI composed from shared atoms/molecules/organisms
    • views/: Page-level view components

This ensures pages remain declarative and the feature layer encapsulates logic.

Route Layering

  • (public): Marketing landing and authentication flows
  • account/: Authenticated portal experience (dashboard, billing, subscriptions, etc.)
  • api/: App Router API endpoints

Only layout.tsx, page.tsx, and loading.tsx files live inside the route groups.

Feature Module Inventory

Feature API Service Key Hooks Purpose
account accountService useProfileEdit, useAddressEdit Profile and address management
address addressService useAddressLookup Japan Post address lookup
auth (via store) useAuthStore, useAuthSession Authentication state
billing billingService useInvoices, usePaymentMethods, usePaymentRefresh Invoices and payments
checkout checkoutService useCheckoutStore Checkout flow
dashboard getMeStatus useMeStatus Dashboard data
get-started getStartedService useGetStartedFlow Unified signup flow
landing-page Marketing landing page
marketing Marketing components
notifications notificationService useNotifications User notifications
orders ordersService useOrdersList, useOrderDetail Order management
realtime useRealtimeEvents SSE/WebSocket events
services servicesService useInternetCatalog, useSimCatalog, useVpnCatalog Product catalog
subscriptions simActionsService, internetActionsService useSubscriptions Active service management
support supportService useCases, useCreateCase Support tickets
verification verificationService useResidenceCardVerification ID verification

Benefits

Developer Experience

  • Predictable code organization
  • Easy to find and modify code
  • Consistent patterns across features
  • Better IntelliSense and type safety

Maintainability

  • Clear separation of concerns
  • Reusable components and utilities
  • Centralized design system
  • Easier testing and debugging

Performance

  • Tree-shakeable exports
  • Code splitting by feature
  • Optimized bundle size
  • Better caching strategies

Scalability

  • Easy to add new features
  • Consistent architecture patterns
  • Modular and composable design
  • Clear boundaries between features