Directory Structure
A complete EverShop theme follows this structure:
themes/my-theme/
├── src/ # Source files (development)
│ ├── components/ # Reusable components
│ │ ├── common/ # Shared components
│ │ └── frontStore/ # Store-specific components
│ └── pages/ # Page-specific components
│ ├── all/ # Components for all pages
│ ├── homepage/ # Homepage components
│ ├── productDetail/ # Product page components
│ └── categoryView/ # Category page components
├── dist/ # Compiled files (production)
│ ├── components/
│ ├── pages/
│ └── tailwind.config.js # Optional custom Tailwind config
├── package.json # Theme package configuration
└── tsconfig.json # TypeScript configuration
Required Files
package.json
Every theme must have a package.json file:
{
"name": "my-theme",
"version": "1.0.0",
"type": "module",
"private": true,
"scripts": {
"build": "tsc"
}
}
The type: "module" field is required for ESM support.
tsconfig.json
TypeScript configuration for your theme:
{
"compilerOptions": {
"module": "NodeNext",
"target": "ES2018",
"lib": ["dom", "dom.iterable", "esnext"],
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"declaration": true,
"sourceMap": true,
"allowJs": true,
"checkJs": false,
"jsx": "react",
"outDir": "./dist",
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"allowArbitraryExtensions": true,
"strictNullChecks": true,
"baseUrl": ".",
"rootDir": "src",
"paths": {
"@components/*": [
"./src/components/*",
"../../node_modules/@evershop/evershop/src/components/*"
]
}
},
"include": ["src"]
}
Key configurations:
- outDir: Compiled files go to
./dist
- rootDir: Source files are in
src
- paths: Alias for importing EverShop components
Directory Breakdown
src/ Directory
The src/ directory contains your theme’s source code during development.
src/pages/
Page-specific components organized by route:
| Directory | Purpose | When Components Load |
|---|
pages/all/ | Components that appear on every page | All routes |
pages/homepage/ | Homepage-only components | / route |
pages/productDetail/ | Product page components | /product/:slug route |
pages/categoryView/ | Category page components | /category/:slug route |
pages/cart/ | Shopping cart components | /cart route |
pages/checkout/ | Checkout page components | /checkout route |
Example: A component in pages/all/
// themes/my-theme/src/pages/all/EveryWhere.tsx
import React from 'react';
export default function EveryWhere() {
return (
<div className="container mx-auto px-4 py-8">
<p>This component appears on every page!</p>
</div>
);
}
export const layout = {
areaId: 'content',
sortOrder: 20
};
src/components/
Reusable components that can be imported by page components:
src/components/
├── common/ # Shared across admin and storefront
│ ├── Button.tsx
│ └── Modal.tsx
└── frontStore/ # Store-specific components
├── Header.tsx
└── Footer.tsx
Example: Reusable component
// themes/my-theme/src/components/common/Button.tsx
import React from 'react';
interface ButtonProps {
children: React.ReactNode;
onClick?: () => void;
variant?: 'primary' | 'secondary';
}
export default function Button({ children, onClick, variant = 'primary' }: ButtonProps) {
const baseClasses = 'px-4 py-2 rounded font-medium';
const variantClasses = variant === 'primary'
? 'bg-blue-600 text-white hover:bg-blue-700'
: 'bg-gray-200 text-gray-800 hover:bg-gray-300';
return (
<button className={`${baseClasses} ${variantClasses}`} onClick={onClick}>
{children}
</button>
);
}
dist/ Directory
The dist/ directory contains compiled JavaScript files generated by TypeScript:
dist/
├── components/
│ ├── common/
│ │ ├── Button.js
│ │ ├── Button.d.ts
│ │ └── Button.js.map
│ └── frontStore/
└── pages/
├── all/
│ ├── EveryWhere.js
│ ├── EveryWhere.d.ts
│ └── EveryWhere.js.map
└── homepage/
Never edit files in dist/ directly. Always edit source files in src/ and rebuild.
Component File Naming
EverShop has specific naming requirements:
Valid component names (PascalCase):
MyComponent.tsx
ProductCard.tsx
HeaderNav.tsx
Invalid component names:
myComponent.tsx (starts with lowercase)
my-component.tsx (kebab-case)
my_component.tsx (snake_case)
Components must:
- Start with an uppercase letter
- Use PascalCase naming
- Have a
.tsx or .jsx extension
- Be located in a page-specific directory
Layout Configuration
Every page component must export a layout object:
export const layout = {
areaId: 'content', // Required: where to render
sortOrder: 10 // Required: rendering order
};
Available Area IDs
Common area IDs in the storefront:
| Area ID | Location | Typical Use |
|---|
header | Top of page | Navigation, logo, cart icon |
content | Main content area | Page-specific content |
footer | Bottom of page | Footer links, copyright |
left | Left sidebar | Filters, categories |
right | Right sidebar | Related products, ads |
Sort Order
Components with lower sortOrder values render first:
// This renders first
export const layout = { areaId: 'content', sortOrder: 5 };
// This renders second
export const layout = { areaId: 'content', sortOrder: 10 };
// This renders third
export const layout = { areaId: 'content', sortOrder: 20 };
Advanced Page Targeting
You can target multiple pages using special naming conventions:
Page Combinations
Use + to target multiple specific pages:
pages/
├── homepage+productDetail/ # Appears on homepage AND product pages
│ └── PromoBar.tsx
└── categoryView+productDetail/ # Appears on category AND product pages
└── Breadcrumb.tsx
Sample Theme Example
Here’s a real example from the EverShop sample theme:
// themes/sample/src/pages/homepage/OnlyHomePage.tsx
import React from 'react';
export default function OnlyHomePage() {
return (
<div className="container mx-auto px-4 py-8 bg-gray-100 rounded-lg shadow-md mt-10">
<h1 className="font-bold text-center mb-6">Home Page Only</h1>
<p className="text-gray-700 text-center">
This component is only rendered on the home page.
</p>
<p className="text-gray-700 text-center">
You can modify this component at{' '}
<code>themes/sample/src/pages/homepage/OnlyHomePage.tsx</code>
</p>
</div>
);
}
export const layout = {
areaId: 'content',
sortOrder: 10
};
Building Your Theme
To compile your theme from src/ to dist/:
This runs TypeScript compilation and prepares your theme for production.
Next Steps
Customize Your Theme
Learn how to style components and override core functionality
Create a Theme
Start building your custom theme