Section pages are dynamic pages in the Fynd Commerce App that allow sellers to create custom templates by combining multiple reusable UI components called "sections". These pages are highly customizable and can be configured through the Theme Editor in the Fynd Platform Panel.
- What are Section Pages?
- How Section Pages Work
- Creating Section Pages on Platform
- What are Sections?
- Anatomy of a Section
- Creating Custom Sections
- Section Rendering System
- Navigation and Tracking
- Best Practices
Section pages are pages where you can add, edit, or remove sections. If you wish to create a custom template consisting of sections, you can create section pages. These pages are:
- Dynamic: Content is fetched based on the page value
- Customizable: Sections can be added, removed, or reordered
- Responsive: Sections adapt to different screen sizes and platforms
- Conditional: Sections can be shown/hidden based on user authentication, device type, and platform
- Theme-based: Content is fetched from the theme configuration
- Section-based: Built from reusable UI components
- Predicate-driven: Sections can be conditionally rendered
- Performance optimized: Lazy loading of section components
// src/pages/section-page/section-page.tsx
export default function SectionPage() {
const {fpi} = useFpi();
const page: any = useSelector(fpi.getters.PAGE);
return (
<Container keyBoardAvoid scrollEnable showHeader>
<SectionRenderer sections={page?.sections || []} />
</Container>
);
}- Navigation: User navigates to a section page
- URL Parsing: Navigation tracker extracts page value from URL
- Theme Fetching: Theme data is fetched based on page value
- Section Rendering: Sections are rendered with their configurations
- Predicate Evaluation: Sections are filtered based on conditions
Section pages follow specific URL patterns:
- Section Pages:
/sections/{pageValue}- Example:
/sections/productsβ pageValue = "products" - Example:
/sections/homeβ pageValue = "home"
- Example:
-
Access Theme Editor
- Go to the Theme Editor in the Fynd platform
- Navigate to the Platform Panel
-
Create New Section Page
- Click on the Pages dropdown menu on the top right corner
- Scroll down and click on the Add Section Page option
-
Configure Page
- Enter a name for your section page
- Select a Layout for your section page
- Configure page-specific settings
-
Add Sections
- Add sections to your section page
- Configure section properties
- Set up section predicates (conditions)
-
Save Changes
- Review your configuration
- Save your changes
- Publish the theme
{
"pageName": "Product Landing",
"pageValue": "products",
"layout": "default",
"sections": [
{
"id": "hero-1",
"name": "hero-image",
"props": {
"heading": {"value": "Welcome to Our Store"},
"description": {"value": "Discover amazing products"},
"button_text": {"value": "Shop Now"}
},
"predicate": {
"user": {
"anonymous": true,
"authenticated": true
},
"screen": {
"mobile": true,
"tablet": true
}
}
}
]
}Sections are reusable UI components that sellers can customize. Section files are present inside the sections folder of a theme. Each section is a self-contained React component with:
- Visual Interface: The component's UI
- Configuration Schema: Settings that define customizable properties
- Predicate Support: Conditional rendering based on various criteria
- Responsive Design: Adapts to different screen sizes
- Content Sections: Display text, images, and media
- Interactive Sections: Buttons, forms, and user interactions
- Layout Sections: Containers and structural elements
- Data Sections: Display dynamic content from APIs
Each section must have:
// Named export for the component
export function SectionName({props, blocks}: any) {
// Component implementation
return <View>{/* Section UI */}</View>;
}
// Named export for settings
export const settings = {
label: 'Section Display Name',
props: [
// Configuration schema
],
blocks: [
// Block configurations
],
};The settings export defines the configuration schema:
export const settings = {
label: 'Category Selector',
props: [
{
type: 'category',
id: 'category',
default: '',
label: 'Category Dropdown',
info: 'Search a category from the dropdown',
},
{
type: 'text',
id: 'heading',
default: 'Featured Categories',
label: 'Section Heading',
info: 'Enter the heading for this section',
},
],
blocks: [
{
type: 'hotspot_mobile',
label: 'Product Hotspot',
props: [
{
type: 'text',
id: 'hotspot_header',
label: 'Hotspot Title',
},
],
},
],
};Props are passed to the component and contain:
interface SectionProps {
// Configuration values
heading?: {value: string};
description?: {value: string};
button_text?: {value: string};
// Predicate information
predicate?: {
user?: {
anonymous?: boolean;
authenticated?: boolean;
};
screen?: {
mobile?: boolean;
tablet?: boolean;
};
platform?: {
ios?: boolean;
android?: boolean;
};
};
// Block data
blocks?: Array<{
type: string;
props: Record<string, any>;
}>;
}src/sections/
βββ my-custom-section/
β βββ index.ts
β βββ my-custom-section.tsx
β βββ styles.ts
β βββ README.md// src/sections/my-custom-section/my-custom-section.tsx
import React from 'react';
import {View} from 'react-native';
import {Text, Button} from '../../components/ui';
import {useThemedStyles} from '../../shared/hooks/use-themed-styles';
import getStyles from './styles';
export function MyCustomSection({props}: any) {
const {heading, description, button_text, button_link} = props;
const styles = useThemedStyles(getStyles);
return (
<View style={styles.container}>
{heading?.value && (
<Text variant="heading" style={styles.heading}>
{heading.value}
</Text>
)}
{description?.value && (
<Text variant="body" style={styles.description}>
{description.value}
</Text>
)}
{button_text?.value && (
<Button
title={button_text.value}
onPress={() => {
// Handle button press
}}
/>
)}
</View>
);
}
export const settings = {
label: 'My Custom Section',
props: [
{
type: 'text',
id: 'heading',
default: 'Welcome',
label: 'Section Heading',
info: 'Enter the main heading',
},
{
type: 'textarea',
id: 'description',
default: '',
label: 'Description',
info: 'Enter section description',
},
{
type: 'text',
id: 'button_text',
default: 'Learn More',
label: 'Button Text',
info: 'Enter button text',
},
{
type: 'url',
id: 'button_link',
default: '',
label: 'Button Link',
info: 'Enter button destination URL',
},
],
blocks: [],
};// src/sections/index.tsx
export const sectionMap: Record<
string,
React.LazyExoticComponent<React.ComponentType<any>>
> = {
'hero-image': React.lazy(() => import('./hero-image')),
'my-custom-section': React.lazy(() => import('./my-custom-section')),
// Add more sections here
};// src/sections/my-custom-section/index.ts
import {MyCustomSection} from './my-custom-section';
export default MyCustomSection;The SectionRenderer component handles:
- Lazy Loading: Sections are loaded on-demand
- Predicate Evaluation: Filters sections based on conditions
- Error Handling: Graceful fallbacks for missing sections
- Performance Optimization: Suspense boundaries for loading states
// src/components/common/section-renderer/section-renderer.tsx
export default function SectionsRenderer({sections}: {sections: any[]}) {
const {fpi} = useFpi();
const isLoggedIn = useSelector(fpi.getters.LOGGED_IN);
const isTablet = Dimensions.get('window').width >= 768;
return (
<View style={styles.container}>
{sections.map((item, _index) => {
// Evaluate predicates
const isUserPredicateValid = evaluateUserPredicate(item, isLoggedIn);
const isScreenPredicateValid = evaluateScreenPredicate(item, isTablet);
const isPlatformPredicateValid = evaluatePlatformPredicate(item);
// Render section if all predicates pass
if (
isUserPredicateValid &&
isScreenPredicateValid &&
isPlatformPredicateValid
) {
return <SectionRenderer key={item.id} section={item} />;
}
return null;
})}
</View>
);
}Sections support three types of predicates:
predicate: {
user: {
anonymous: true, // Show for non-logged-in users
authenticated: true // Show for logged-in users
}
}predicate: {
screen: {
mobile: true, // Show on mobile devices
tablet: true // Show on tablet devices
}
}predicate: {
platform: {
ios: true, // Show on iOS
android: true // Show on Android
}
}The navigation system automatically:
- Detects Route Changes: Monitors navigation state
- Extracts Page Values: Parses URLs for section pages
- Fetches Theme Data: Loads section configurations
- Tracks Performance: Measures navigation timing
// src/shared/hooks/use-navigation-tracker.tsx
const onRouteChange = useCallback(
async (route: NavigationRoute) => {
if (route.name === 'SectionPage' && route.params?.pageValue) {
const pageValueResult = getPageValueFromPath(route.params.pageValue);
// Fetch theme data for section page
await fpi.executeGQL(THEME_DATA, {
themeId: theme?.id,
pageValue: pageValueResult.pageValue,
});
}
},
[fpi, getPageValueFromPath, theme?.id],
);// Pattern: '/sections/products'
if (segments[0] === PATH_TYPES.SECTIONS) {
const sectionValue = segments[1] ?? DEFAULT_PAGES.SECTIONS;
return {pageValue: sectionValue};
}- Keep Sections Focused: Each section should have a single responsibility
- Use TypeScript: Define proper types for props and settings
- Implement Error Boundaries: Handle component errors gracefully
- Optimize Performance: Use lazy loading and memoization
- Follow Naming Conventions: Use kebab-case for section names
- Provide Defaults: Always set sensible default values
- Use Descriptive Labels: Make configuration user-friendly
- Add Help Text: Include info text for complex properties
- Validate Inputs: Implement proper validation for user inputs
- Group Related Props: Organize properties logically
- Mobile-First: Design for mobile devices first
- Use Flexbox: Implement flexible layouts
- Test on Multiple Devices: Ensure compatibility across devices
- Handle Orientation Changes: Support portrait and landscape modes
- Lazy Load Sections: Use React.lazy for code splitting
- Minimize Re-renders: Use React.memo and useMemo
- Optimize Images: Compress and resize images appropriately
- Cache Data: Implement caching for frequently accessed data
- Unit Tests: Test individual section components
- Integration Tests: Test section interactions
- Visual Regression Tests: Ensure UI consistency
- Accessibility Tests: Verify screen reader compatibility
See the complete implementation in src/sections/hero-image/ for a real-world example of a section with:
- Complex layout positioning
- Hotspot functionality
- Responsive design
- Multiple configuration options
- Predicate support
Use the template in src/sections/my-custom-section/ as a starting point for creating new sections.