Skip to main content

Templates

Two stacks ship as templates: shop-next and shop-vue. Each is a runnable shop, not a starter — the full Propeller surface (login, register, cart, checkout, catalog, account routes, CMS catch-all) is included.

Layout per template

templates/
shop-next/
template.json # manifest: stack, version, propellerCompat
shared/... # files copied for every mode
b2b-routes/... # account routes copied only for b2b + hybrid
shop-vue/
template.json
shared/...
b2b-routes/...

Templates are not workspaces — they're static content the CLI copies verbatim. Files matching *.template.* are run through Handlebars and emitted with the .template suffix stripped; everything else is copied as-is.

shop-next surface

AreaWhat's in shared/
app/All universal routes — login, register, cart, checkout, product/[slug], cluster/[slug], category/[id]/[slug], search, (cms)/[...slug], blog/, account/{orders,addresses,favorites,invoices}
app/api/auth, graphql, revalidate route handlers
components/Shop-level components (Layout, Header, Footer) + auth/RequireUserMode.tsx
context/AuthContext, CartContext, CompanyContext, GlobalContext, LanguageContext, PriceContext
data/config.ts (templated), countries.ts, defaults.ts, companyViewerAttributes.ts
hooks/, lib/, utils/Domain helpers, SDK seam wiring, SEO helpers
public/Static assets
next.config.template.tsTemplated — transpilePackages and remotePatterns derived from prompts
app/layout.template.tsxTemplated — <html lang>, title, description from prompts
data/config.template.tsTemplated — shopMode, portal.mode, channelId, anonymousId, taxZone, currency
package.template.jsonTemplated — name + pinned UI packages
README.template.mdTemplated — mode-conditional installation notes
lib/routeGuards.tsDeclarative route → allowed userModes map

In b2b-routes/: the five B2B account routes (app/account/{quotes,quote-requests,authorization-requests,authorization-settings,price-requests}/), each gated with <RequireUserMode allow={['b2b']}>.

shop-vue surface

Mirror of the Next template but for Vue 3 + Vite SSR.

AreaWhat's in shared/
Rootindex.html, server.js (SSR), vite.config.ts, three tsconfigs, .env.example, .gitignore
src/App.vue, client/server entry points, assets/, components/, composables/, lib/, stores/
src/views/Catalog views, login/register, cart, checkout, account universal views
src/router/index.template.tsTemplated — SHOP_MODE baked in; B2B route entries wrapped in {{#unless isB2C}}…{{/unless}}

In b2b-routes/: the six B2B account views (QuotesView.vue, QuoteDetailView.vue, QuoteRequestsView.vue, AuthorizationRequestsView.vue, AuthorizationSettingsView.vue, PriceRequestsView.vue).

Templated files (Handlebars)

FileWhat it parameterises
data/config.template.ts (Next) / src/lib/config.template.ts (Vue)shopMode, portal.mode, channelId, anonymousId, taxZone, currency
package.template.jsonname, pinned package URLs
next.config.template.ts (Next)transpilePackages, remotePatterns
app/layout.template.tsx (Next)<html lang>, title, description
src/router/index.template.ts (Vue)SHOP_MODE, B2B route registrations
README.template.mdMode-conditional install notes

Substitution variables documented in propeller.json schema.

Choosing a template

Two questions:

  1. Existing team skills. Pick the stack your team already knows. Both templates ship the same Propeller surface — there's no feature gap.
  2. SSR posture. Next 16 ships Server Components; Vue 3 + Vite ships SSR-with-hydration. The Next template uses Server Components for the catalog shells; the Vue template uses SSR with client islands.

Neither stack will lock you in — the consumer-owned lib/api.ts / lib/services.ts seam means you can shell out to your own backend microservices through the same composables either way.

Template manifest

Each template ships a template.json declaring:

  • stack: 'next' | 'vue'
  • version: semver matching the CLI version at release time
  • propellerCompat: semver range of the Propeller UI packages this template is compatible with

The CLI reads template.json at scaffold time to fail fast if the template was authored against an incompatible UI package version.