This is the Sitecore Content SDK - a comprehensive TypeScript/JavaScript SDK for building modern web applications with Sitecore XM Cloud. The project provides core functionality, React components, Next.js integration, and CLI tools for scaffolding applications.
- Language: TypeScript (Node LTS)
- Runtime: Node LTS
- Build:
tsc->dist/, templates bundled viascripts/build-templates.ts - Testing: Mocha + Sinon + Chai, coverage via
nyc - Lint/format: ESLint + Prettier
- Package Manager: Yarn 3.1.0
@sitecore-content-sdk/core- Core SDK functionality@sitecore-content-sdk/react- React-specific SDK@sitecore-content-sdk/nextjs- Next.js integration and middleware@sitecore-content-sdk/cli- CLI tools and scaffoldingcreate-content-sdk-app- Scaffolding CLI & templates
content-sdk/
├── packages/
│ ├── create-content-sdk-app/ # Scaffolding CLI & templates
│ ├── core/ # Core SDK functionality
│ ├── nextjs/ # Next.js-specific SDK
│ ├── react/ # React-specific SDK
│ └── cli/ # Additional CLI tools
└── samples/ # Example applications
- Sources:
src/** - Never edit:
dist/**(compiled output) - Templates: Copied to generated apps, self-contained, use
.env.*.examplefor env values - Initializers: Each exposes
init(args), reuse common processes/utilities
Core Philosophy:
- Write clean, modular, and idiomatic code
- Prefer declarative over imperative patterns
- Make code readable and self-documenting
- TypeScript-first development approach
Code Organization:
- Use Node LTS
- Export public types at module boundaries
- Prefer pure functions and thin wrappers
- No top-level side effects (except CLI entry)
- Modular architecture with clear separation of concerns
TypeScript Usage:
- Enable strict mode in all projects
- Prefer explicit types over
any - Use discriminated unions for complex state
- Export types at module boundaries for reusability
Functional Programming:
- Prefer pure functions where possible
- Use immutable data patterns
- Avoid side effects in business logic
- Compose small, focused functions
Readability:
- Use descriptive variable and function names
- Keep functions small and focused (single responsibility)
- Add comments for complex business logic only
- Prefer self-documenting code over extensive comments
Error Strategy:
- Fail fast with clear, actionable messages
- Propagate child-process errors with context
- Use custom error classes for domain-specific errors
- Handle edge cases explicitly with guard clauses
Security:
- Sanitize user inputs
- Validate data at boundaries
- Never log sensitive information
- Use environment variables for configuration
Logging:
- Clear phases and results
- Support silent flag if available
- Use appropriate log levels (debug, info, warn, error)
- Include context in error messages
Imports:
- Relative for local modules
- Never import from
dist/ - Group imports logically (external, internal, relative)
- Use barrel exports (index.ts) for clean APIs
Lint and Format:
- Keep ESLint + Prettier passing at all times
- Follow configured style rules consistently
- Use automated formatting on save
- Address linting warnings promptly
Variables and Functions:
- Use camelCase:
getUserData(),isLoading,currentUser - Boolean variables: prefix with
is,has,can,should - Event handlers: prefix with
handleoron:handleClick,onSubmit
Components (React):
- Use PascalCase:
SitecoreComponent,PageLayout,ContentBlock - File names match component names:
SitecoreComponent.tsx
Constants:
- Use UPPER_SNAKE_CASE:
API_ENDPOINT,DEFAULT_TIMEOUT,MAX_RETRIES - Export at module level when shared
Directories:
- Use kebab-case:
src/components,src/api-clients,src/sitecore-utils - Organize by feature when appropriate:
src/content-management/
Types and Interfaces:
- Use PascalCase with descriptive names:
ContentItem,LayoutProps,SitecoreConfig - Prefix interfaces with
Ionly when needed for disambiguation
Directory Structure:
src/
components/ # UI components (React)
utils/ # Helper functions and utilities
api/ # Sitecore integrations and API clients
lib/ # Third-party library configurations
types/ # TypeScript type definitions
hooks/ # Custom React hooks
styles/ # Styling files
File Organization:
- Group related functionality in feature directories
- Keep components co-located with their styles and tests
- Export public APIs through index.ts files
API Calls:
- Always wrap in try/catch blocks
- Throw custom errors with context:
SitecoreFetchError,ConfigurationError - Handle edge cases with guard clauses
Input Validation:
- Sanitize user inputs before processing
- Validate data at application boundaries
- Use type guards for runtime type checking
- Escape content when rendering to prevent XSS
Optimization Patterns:
- Memoize components with React.memo when appropriate
- Lazy-load non-critical modules:
const Component = lazy(() => import('./Component')) - Use useCallback and useMemo for expensive operations
TypeScript:
- Enable strict mode in tsconfig.json
- Prefer type assertions over any:
value as ContentItem - Use discriminated unions for complex state management
JSDoc Comments:
- All new functions, interfaces, classes must have JSDoc style comments
- Include @param tags for all parameters with types and descriptions
- Include @returns tag for return values with type and description
- Use descriptive comments that explain the purpose and behavior
- Follow existing Content SDK JSDoc patterns
Configuration:
- Always use environment variables for API endpoints and keys
- Never hardcode API keys in source code
- Use
.env.examplefiles to document required environment variables - Prefer
sitecore.config.tsfor centralized configuration
// sitecore.config.ts
import { defineConfig } from '@sitecore-content-sdk/nextjs/config';
export default defineConfig({
api: {
edge: {
contextId: process.env.SITECORE_EDGE_CONTEXT_ID || '',
clientContextId: process.env.NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID,
edgeUrl:
process.env.NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME ||
process.env.SITECORE_EDGE_PLATFORM_HOSTNAME ||
'https://edge-platform.sitecorecloud.io',
},
local: {
apiKey: process.env.SITECORE_API_KEY || '',
apiHost: process.env.SITECORE_API_HOST || '',
},
},
defaultSite: process.env.NEXT_PUBLIC_DEFAULT_SITE_NAME || 'default',
defaultLanguage: process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE || 'en',
editingSecret: process.env.SITECORE_EDITING_SECRET,
});API Client Usage:
- Use HTTPS for all XM Cloud endpoints
- Implement proper retry logic with exponential backoff
- Cache responses appropriately (consider content freshness)
- Handle GraphQL errors gracefully
Sitecore Component Naming:
- Use descriptive, feature-based names:
HeroWithContent,ProductListing,ContentBlockGrid - Follow PascalCase convention
- Include component type in name when helpful:
LayoutContainer,ContentRenderer
Component Registration:
- Register components in the component map
- Use consistent component names across registration and files
- Include TypeScript types for all component props
// Component props interface
interface ContentBlockProps {
fields: {
title: Field;
content: Field;
image: Field;
};
}Field Handling:
- Always validate field existence before rendering
- Use helper functions for common field operations
- Handle empty/null fields gracefully
- Prefer Sitecore field components over manual rendering
// Good: Using Sitecore field components
<Text field={fields?.title} tag="h1" />
<RichText field={fields?.content} />
// Avoid: Manual field value extraction unless necessaryContent SDK Client Methods:
- Prefer using
scClient.getPage()for page data and layout fetching - Use
scClient.getDictionary()for localized content - Leverage
scClient.getErrorPage()for error page handling - Use
scClient.getPreview()for preview mode content - Implement proper error boundaries for layout rendering
- Handle missing placeholder content gracefully
- Cache layout data when appropriate
Content Fetching:
- Implement caching strategy for content (React Query recommended)
- Use GraphQL queries efficiently (avoid over-fetching)
- Implement proper loading states and error handling
- Consider content preview vs. published content scenarios
Security Best Practices:
- Sanitize user inputs before processing
- Validate content from Sitecore before rendering
- Use Content Security Policy (CSP) headers
- Never expose sensitive configuration in client-side code
// Content validation example
function validateContentItem(item: unknown): ContentItem {
if (!item || typeof item !== 'object') {
throw new Error('Invalid content item');
}
// Additional validation logic
return item as ContentItem;
}Error Handling:
- Create custom error classes:
SitecoreFetchError,ComponentRenderError - Log errors appropriately for debugging
- Provide fallback content when components fail to render
- Use error boundaries in React applications
Placeholder Management:
- Use strongly-typed placeholder names
- Handle dynamic placeholders appropriately
- Implement fallback rendering for missing placeholders
- Follow Sitecore's placeholder naming conventions
Testing:
- Mock Sitecore services in unit tests
- Test component rendering with various field configurations
- Include tests for error scenarios (missing fields, API failures)
- Use Sitecore's test data helpers when available
- Drive init via
Initializer.init(args) - Clear prompts and defaults
- Install dependencies after scaffolding
- Print next steps
- No deployments or CI flows
- No global user state changes
- Avoid breaking arg names
- Additive changes with defaults
- Never edit
dist/**- These are compiled artifacts - Do not commit secrets -
.envignored, use.env.example - Template edits must build/run with
npm install && npm run build - Reuse common processes - Don't duplicate functionality
DRY Principle:
- Don't Repeat Yourself - extract common functionality
- Create reusable utilities and helper functions
- Use composition over inheritance
- Share types and interfaces across modules
SOLID Principles:
- Single Responsibility: each function/class has one purpose
- Open/Closed: extend functionality through composition
- Dependency Inversion: depend on abstractions, not implementations
Code Clarity:
- Write self-documenting code with clear intent
- Use meaningful names that express business concepts
- Prefer explicit over implicit behavior
- Make dependencies and requirements obvious
Modular Design:
- Organize code into focused, cohesive modules
- Minimize coupling between modules
- Use clear interfaces between layers
- Follow established patterns consistently
Data Flow:
- Prefer unidirectional data flow
- Validate inputs at system boundaries
- Transform data at appropriate layers
- Handle errors close to their source
Testing:
- Write testable code with minimal dependencies
- Use dependency injection for better testability
- Mock external services and side effects
- Test behavior, not implementation details
Version Control:
- Write descriptive commit messages
- Keep commits focused and atomic
- Use branching strategies appropriate to team size
- Review code before merging
Documentation:
- Document public APIs and interfaces
- Include usage examples for complex functionality
- Keep documentation close to code
- Update documentation with code changes
Performance:
- Optimize for readability first, performance second
- Profile before optimizing
- Cache expensive operations appropriately
- Consider memory usage and cleanup
Code Review:
- Review for logic, readability, and maintainability
- Check error handling and edge cases
- Verify tests cover new functionality
- Ensure documentation is updated
Continuous Integration:
- All tests must pass before merging
- Linting and formatting checks must pass
- Build process must complete successfully
- No breaking changes without proper migration