Template Developers: Template Structure
Locate the template's rendering, content, and integration responsibilities before editing it.
Template paths and editor controls depend on the separate template repository. Confirm them in your checkout; see what the product defines.
Files the deployer generates
Part of the structure is not a convention at all. The Web Builder deployer writes these files into the template clone before every Vercel deploy, and a template must be able to read them:
| Generated file | Contents |
|---|---|
data/configs.json | Site identity and theme: cpId, templateId, templateType, meta (title, description, logo, favicon, keywords, author, url), appearance (theme, fonts, colors), menus (main, footerMenu), and additional (copyright, social links, integrations) |
data/pages/<slug>.json | Per-page title, description, coverImage, and pageItems. The slug home (or /) is written as index.json |
next.config.ts | A generated config carrying the erxes env block (ERXES_API_URL, ERXES_APP_TOKEN, ERXES_CP_ID, ERXES_WEB_ID, TEMPLATE_TYPE, BUILD_MODE, and custom environmentVariables) |
app/favicon.ico | The site's favicon, downloaded from the erxes file endpoint |
See buildConfigs and buildPageConfigs and the file-writing block. The app/ path also tells you the deployed templates are Next.js App Router projects.
Common folder responsibilities
Earlier ecommerce template documentation used this layout as a reference. Inspect the selected repository rather than creating missing files just to match the tree.
app/
layout.tsx Shared page layout
page.tsx Home route
_components/
Header.tsx Navigation and branding
Footer.tsx Shared footer
sections/ Reusable page sections
... Content and application routes
components/ Template UI primitives and shared components
data/
configs.json Generated site config (and fixture stand-in)
pages/ Generated per-page content (and fixtures)
graphql/ Operations grouped by feature
lib/ Fetchers, adapters, contexts, rendering helpers
types/ Template and section types
public/ Static assets
Helpers named ApolloWrapper, ClientLayout, usePage, and renderSections may exist in these templates. Their names, locations, and behavior are template-specific. Keep server-only credential handling outside any browser import graph.
UI-only scope
Reading the structure is not a license to change it. For a UI-only assignment, treat graphql/ documents, lib/ fetchers, and the generated data/ shapes as fixed inputs. Change presentation components, not the data layer.
Content flow
A typical content page follows these steps:
- A fixture or server-side CMS request supplies page data. Live sites use
cpCmsPageDetail(or the generateddata/pages/*.json); thepageItemslist is the section input. - An adapter validates and converts the response into the template's expected shape.
- The page renderer maps each item's
typeto an existing component. - Each component renders validated
contentandconfigwith theme and layout values.
The product Page schema defines pageItems with _id, name, type, content, order, objectType, objectId, and JSON config. Web Builder pages use the same structure, except their items carry contentType/contentTypeId instead of objectType/objectId; see the WebPage schema. The schema does not define React component names or validate a template-specific Hero configuration. Those are template decisions.
Find the configuration
data/configs.json keys such as appearance, meta, and menus are product-written: the deployer generates them from the Web record's appearances, externalLinks, integrations, and kind: "main"/kind: "footer" menu items. Check the keys and the data-loading code your template uses before relying on them.
Keep public configuration and secret credentials separate. Static JSON and client components are visible to visitors. Use the CMS Setup for server-side authentication and CMS Queries for the response shapes.
Before changing a shared key
Find every consumer of a section identifier, configuration key, or page slug, including fixtures and editor previews. A presentation change should keep them intact. A planned change must update its producers, validators, renderers, and stored content together. Anything written by the deployer is fixed by the product, so a template cannot rename generated keys on its own.