Skip to main content

Next API Schwab Application

The Next API Schwab application serves as the central API hub for Charles Schwab's web ecosystem, providing internal API services for data synchronization, content management, cache revalidation, and utility functions across multiple applications in the monorepo.

Overview

  • Application: apps/nextapi.schwab.com
  • Port: 3002
  • Version: 1.0.60
  • Framework: Next.js 15.3.2 with App Router
  • Purpose: Internal API services for non-public facing endpoints
  • Architecture: API-only Next.js application with serverless functions

Key Features

  • Content Management API: CMAP (Content Management API Portal) integration
  • Cache Revalidation: On-demand cache invalidation for content updates
  • Health Monitoring: Application health check endpoints
  • Environment Synchronization: Deployment webhook handling for environment sync
  • Utility Functions: URL building, path resolution, and data transformation
  • Drupal Integration: Content fetching from Drupal CMS systems
  • Edge Computing: Vercel Edge Config integration for dynamic configuration

Technical Architecture

Framework Stack

TechnologyVersionPurpose
Next.js15.3.2React framework with App Router
React19.1.0Component library (minimal usage)
TypeScript5.8.2Type safety and development experience
Vercel Edge Config1.4.0Dynamic configuration management
JSON52.2.3Enhanced JSON parsing

Core Dependencies

Key dependencies from package.json
{
"@schwab/fetch": "workspace:*",
"@schwab/ui": "workspace:*",
"@schwab/utilities": "workspace:*",
"@schwab/schema": "workspace:*",
"@vercel/edge-config": "^1.4.0",
"cross-env": "^7.0.3",
"json5": "^2.2.3"
}

Monorepo Integration

The application leverages several internal packages:

  • @schwab/fetch: HTTP client utilities and data fetching functions
  • @schwab/utilities: Common utility functions and logging
  • @schwab/schema: Data validation schemas and enums
  • @schwab/ui: Shared React components (limited usage)

Directory Structure

apps/nextapi.schwab.com/
├── src/
│ ├── app/ # App Router directory (Next.js 13+)
│ │ └── api/ # API route handlers
│ │ ├── cmap/ # Content Management API Portal
│ │ │ └── [...alias]/ # Dynamic CMAP content routes
│ │ ├── health-check/ # Application health monitoring
│ │ ├── sync-lower-environments/ # Deployment webhooks
│ │ └── utils/ # Utility API functions
│ │ ├── build-url-path.ts # URL construction utilities
│ │ └── revalidate-path-tag.ts # Cache revalidation logic
│ └── global/ # Global styles and utilities
│ ├── icons.scss # Icon definitions
│ ├── styles.scss # Global SCSS styles
│ └── windowDataLayer.tsx # Analytics data layer
├── public/ # Static assets
│ ├── fonts/ # Font files
│ ├── ira-poc/ # IRA proof-of-concept assets
│ └── test-img.png # Test images
├── .allowlists/ # Security allowlist configurations
├── next.config.js # Next.js configuration
├── postcss.config.js # PostCSS configuration
└── tsconfig.json # TypeScript configuration

API Endpoint Architecture

Health Check Endpoint

Route: /api/health-check
Method: GET
Purpose: Application health monitoring and version information

Health check implementation
export function GET() {
return new Response(JSON.stringify(getAppVersion(packageJSON.name)), {
status: 200,
});
}

Features:

  • Dynamic Response: Always fresh, never cached
  • Version Info: Returns application version and metadata
  • Monitoring Integration: Used by deployment and monitoring systems

Content Management API (CMAP)

Route: /api/cmap/[...alias]
Method: GET
Purpose: Drupal content fetching and transformation

CMAP route structure
export async function GET(request: NextRequest, props: { params: Promise<{ alias: string[] }> }) {
const params = await props.params;
const pageNodeId = Number(params.alias[3]);
const status = params.alias[1];
const lang = params.alias[2];

const story = await getStory(EDrupalSource.Education, '', pageNodeId, status, lang);
return Response.json(story?.data);
}

Parameters:

  • alias[1]: Content status (published, draft, etc.)
  • alias[2]: Language code (en, es, zh-CN, etc.)
  • alias[3]: Drupal node ID for content retrieval

Environment Synchronization

Route: /api/sync-lower-environments
Method: POST
Purpose: Webhook handler for deployment synchronization

Webhook verification
async function verifySignature(req, payload) {
const signature = crypto
.createHmac('sha1', process.env.WEBHOOK_SECRET)
.update(payload)
.digest('hex');
return signature === req.headers['x-vercel-signature'];
}

Features:

  • Webhook Security: HMAC signature verification
  • Deployment Tracking: Monitors deployment status across environments
  • Team Integration: Vercel team and user identification

Cache Revalidation Utilities

Module: /api/utils/revalidate-path-tag.ts
Purpose: On-demand cache invalidation for content updates

Cache revalidation logic
export function revalidateCache(request: NextRequest) {
const path = request.nextUrl.searchParams.get('path');
const revalByPath = isBooleanTrue(request.nextUrl.searchParams.get('revalidatebypath'));
const revalByTag = request.nextUrl.searchParams.get('revalidatebytag');

// Revalidation logic implementation
}

Cache Tags:

  • MegaNav Menu Cache: Navigation component cache invalidation
  • Utility Nav Cache: Utility navigation updates
  • Card Cache: Content card component updates

Development Workflow

Local Development

Development commands
# Install dependencies
pnpm install

# Start development server on port 3002
pnpm dev

# Build for production
pnpm build

# Start production server
pnpm start

# Type checking
pnpm type-check

# Conformance checking
pnpm conformance

The development server automatically runs on port 3002 with process management to prevent port conflicts.

API Testing

API endpoint testing
# Health check
curl http://localhost:3002/api/health-check

# CMAP content retrieval
curl http://localhost:3002/api/cmap/education/published/en/12345

# Cache revalidation
curl "http://localhost:3002/api/utils/revalidate?path=/example&revalidatebypath=true"

Configuration Management

Next.js Configuration

The application uses several key configurations:

Key Next.js configuration
const nextConfig = {
experimental: {
useCache: true,
},
reactStrictMode: true,
trailingSlash: true,
transpilePackages: [
'@adobe/react-spectrum',
// Additional React Spectrum packages...
],
};

Features:

  • Experimental Caching: Enhanced performance with Next.js caching
  • React Strict Mode: Development safety and debugging
  • Trailing Slash: Consistent URL formatting
  • Package Transpilation: Adobe React Spectrum compatibility

Environment Variables

Required environment variables
# Webhook security
WEBHOOK_SECRET=your_webhook_secret

# Vercel integration
VERCEL_TOKEN=your_vercel_token

# Additional API configurations
DRUPAL_API_BASE_URL=your_drupal_url

Content Management Integration

Drupal Source Integration

The application integrates with multiple Drupal sources:

Content Flow Architecture

  1. Content Request: Frontend applications request content via CMAP API
  2. Drupal Fetching: API fetches content from appropriate Drupal source
  3. Data Transformation: Content processed and formatted for consumption
  4. Cache Management: Responses cached with appropriate tags
  5. Revalidation: Cache invalidated when content updates occur

Security and Performance

Security Measures

  • Webhook Verification: HMAC signature validation for webhooks
  • Environment Isolation: Secure handling of environment-specific data
  • Allowlist Configuration: Defined security boundaries
  • Non-Public API: Internal-only endpoints not exposed to public internet

Performance Optimizations

  • Next.js 15 Features: Latest performance improvements and caching
  • Dynamic Routes: Efficient routing for parameterized endpoints
  • Edge Computing: Vercel Edge Config for low-latency configuration
  • Cache Strategy: Intelligent caching with tag-based invalidation

API Reference

Health Check API

GET /api/health-check
Content-Type: application/json

Response:
{
"name": "app_nextapi.schwab.com",
"version": "1.0.60",
"timestamp": "2025-01-01T00:00:00Z"
}

CMAP Content API

GET /api/cmap/{source}/{status}/{lang}/{nodeId}
Content-Type: application/json

Parameters:
- source: Content source (education, prospect, etc.)
- status: published | draft | archived
- lang: en | es | zh-CN | zh-TW
- nodeId: Drupal node identifier

Response:
{
"data": {
"title": "Content Title",
"body": "Content body...",
"metadata": { ... }
}
}

Cache Revalidation API

POST /api/utils/revalidate
Content-Type: application/json

Query Parameters:
- path: Content path to revalidate
- revalidatebypath: boolean flag for path-based revalidation
- revalidatebytag: cache tag for tag-based revalidation

Response:
{
"success": true,
"revalidated": ["path1", "path2"],
"timestamp": "2025-01-01T00:00:00Z"
}

Error Handling and Logging

Structured Logging

Error handling pattern
try {
const story = await getStory(source, '', nodeId, status, lang);
return Response.json(story?.data);
} catch (e: unknown) {
SchLogger.error(e);
return new Response(`Failed to generate response: ${(e as Error).message}`, {
status: 400,
});
}

Features:

  • Centralized Logging: SchLogger for consistent log formatting
  • Error Context: Detailed error messages with request context
  • HTTP Status Codes: Appropriate status codes for different error types
  • Request Tracking: Request correlation for debugging

Integration Patterns

Monorepo API Consumption

API integration pattern
// Frontend application consuming Next API
import { fetchContent } from '@schwab/fetch';

const contentData = await fetchContent('/api/cmap/education/published/en/12345');

Cache Invalidation Workflow

Deployment and Operations

Build Process

  1. Dependency Resolution: pnpm workspace dependency installation
  2. TypeScript Compilation: Type checking and JavaScript generation
  3. Next.js Build: API route compilation and optimization
  4. Asset Processing: Static asset optimization
  5. Serverless Functions: Individual API route deployment

Monitoring and Health Checks

  • Health Endpoint: /api/health-check for application status
  • Error Tracking: Centralized error logging and monitoring
  • Performance Metrics: API response time and throughput monitoring
  • Cache Hit Rates: Cache efficiency tracking

Common Use Cases

Content Synchronization

Content sync implementation
// Sync content from Drupal to applications
const syncContent = async (nodeId: number, lang: string) => {
const response = await fetch(`/api/cmap/education/published/${lang}/${nodeId}`);
const content = await response.json();
return content;
};

Cache Management

Cache revalidation usage
// Revalidate specific content path
const revalidateContent = async (path: string) => {
const response = await fetch(`/api/utils/revalidate?path=${path}&revalidatebypath=true`, {
method: 'POST'
});
return response.json();
};

Troubleshooting

Common Issues

IssueCauseSolution
Port 3002 in usePrevious API process runningUse kill script in dev command
CMAP 404 errorsInvalid node ID or sourceVerify Drupal node exists and is published
Webhook verification failsIncorrect WEBHOOK_SECRETCheck environment variable configuration
Cache not invalidatingMissing cache tagsVerify revalidation tag configuration
TypeScript errorsSchema mismatchesRun pnpm type-check and update schemas

Development Tips

Performance

Use the health check endpoint to verify API availability before running integration tests.

Security

Never expose internal API endpoints to public internet. Use proper authentication and rate limiting for any external access.

Future Enhancements

  • GraphQL Integration: Enhanced query capabilities for complex data requirements
  • Rate Limiting: API rate limiting and throttling implementation
  • Authentication Layer: JWT-based authentication for secure API access
  • Metrics Dashboard: Real-time API performance and usage metrics
  • Content Preview: Draft content preview capabilities
  • Multi-Environment: Enhanced environment-specific configuration management

This Next API application serves as the backbone for Charles Schwab's content management and data synchronization needs, providing reliable, performant, and secure API services across the entire monorepo ecosystem.