Skip to main content
This guide explains how the page editor is wired in the Members Portal and how mock data is injected so you can design and test components without a live API.

Key concepts

  • Editor configuration lives in src/views/admin/editor/components/useEditorConfiguration.tsx and uses Puck (@measured/puck) to declare components, fields, categories and render functions.
  • Components that need data typically accept a mockData prop and delegate fetching to a use*Data hook which supports an optional mockData override.
  • Mock payloads are colocated in src/views/admin/editor/mockData/mocks/*.ts and are lazy-loaded via a small helper hook.

How mock data works

  1. Opt-in at the editor field level
    • Most components include a withMockData field and default it to true in the editor only.
    • useEditorConfiguration provides withMockDataFields which you can spread into a component’s fields.
  2. Load the data
    • Editor render functions call useMockedData(Name, inEditor && props.withMockData) and pass the result to the presentational component as mockData.
    • The hook is defined in src/views/admin/editor/mockData/mockedData.ts.
  3. Provide a mock module
    • Place a file named exactly like the editor component key in src/views/admin/editor/mockData/mocks/.
    • Export getMockData(business?: any) which returns the mocked payload. business is provided by the current route context and helps match currency, branding, etc.

The useMockedData hook

Source: src/views/admin/editor/mockData/mockedData.ts
  • Uses import.meta.glob('./mocks/*.ts') to lazily import {Name}.ts.
  • Calls getMockData(business) if present and returns its result.
  • When loadData is false, returns undefined so live fetching occurs.

The data hooks contract

Data hooks (for example useFaqData, useBlogData, useProductsData, usePredictiveBookingsData) call useData/useTypedData from src/api/fetchData.ts.
  • They accept an optional mockData parameter.
  • useData short-circuits and returns { resource: mockData, isLoading: false } if mockData is provided, otherwise it performs the real HTTP call.
  • Hooks also declare response shapes via createShape(...) to limit fields and enable server-side shaping.

Adding a new editor component

  1. Create the UI component
    • Add a presentational component under src/views/admin/editor/components/editorComponents/v1/YourComponentEC.tsx.
    • The component should accept an optional mockData prop (typed to the shape your data hook expects) and pass it to the relevant use*Data hook, or consume it directly if it doesn’t fetch.
  2. Add mock data (optional but recommended)
    • Create src/views/admin/editor/mockData/mocks/YourComponent.ts exporting getMockData(business?: any).
    • Return a payload that matches what your UI expects. You can import and reuse other mocks to keep parity across variants.
  3. Register the component in the editor
    • Open src/views/admin/editor/components/useEditorConfiguration.tsx.
    • Add a lazy import for your YourComponentEC.
    • Extend the Components type with a YourComponent: {} entry.
    • Add a config entry under components with:
      • label
      • fields (include ...withMockDataFields if you support it)
      • defaultProps (often { withMockData: true })
      • render: (props) => { const mockData = useMockedData('YourComponent', props.editMode && props.withMockData); return <YourComponentEC {...props} mockData={mockData} /> }
    • Optionally, add it to a categories group so it appears in the editor palette.
  4. Wire a data hook (if needed)
    • In your YourComponentEC, call the relevant use*Data(mockData) hook and pass its return to the presentational child.
    • Example pattern:
      import { useXData } from '@/views/x/useXData'
      export default function YourComponentEC(props: { mockData?: typeof shape.type } & any) {
        const data = useXData(props.mockData)
        return <YourComponent data={data} {...props} />
      }
      

Naming rules and gotchas

  • File naming must match the editor key exactly. If your key is UpcomingEventsDashboardSection, the mock file must be UpcomingEventsDashboardSection.ts.
  • getMockData can accept the business object to tailor outputs (currency, business name, web address).
  • When outside the editor (live runtime), withMockData has no effect—mock hook returns undefined and real requests run.
  • Keep mock payloads small and representative. Prefer a handful of items and realistic field names so the UI matches production.

Example: FAQ section

  • Editor config:
    • In useEditorConfiguration, the FaqPageSection entry sets defaultProps: { withMockData: true } and passes mockData to <FaqPageSectionEC/>.
  • Mock file:
    • src/views/admin/editor/mockData/mocks/FaqPageSection.ts exports several FAQ articles.
  • Data hook:
    • src/views/faq/useFaqData.tsx accepts mockData and passes it into useTypedData(..., { mockData }).

Troubleshooting

  • “No mock module found” error: ensure the mock filename matches the editor component name and lives under mockData/mocks/.
  • Mock renders but shape mismatch: align the mock payload with the shape your data hook requests.
  • Not seeing mock vs live toggle: make sure the component spreads ...withMockDataFields and uses props.editMode to guard loading.

Checklists

When adding a component:
  • UI component under editorComponents/v1
  • Mock under mockData/mocks with getMockData
  • Editor registration in useEditorConfiguration
  • Category placement
  • Optional data hook integration that respects mockData