TABLE OF CONTENTS
- Introduction
- Prerequisites
- Environment Variables
- Znode Webstore Application
- Solution Structure
- Key Configuration Files
- Important Highlights
- Ways of Customization for Storefront Applications
- How to Customize
- Theme Customization Steps
- Use Case 1: Creating a New Component in the Existing Theme
- Use Case 2: Creating a New Component with the New Theme
- Use Case 3: Updating an Existing Base Component
- Use Case 4: Updating a Theme Widget
- Use Case 5: How to Design Predefined CMS Pages and Sections
- Use Case 6: How to Create and Manage Content Pages Using Page Builder
- Use Case 7: How to Update and Manage Existing Content Pages Using Page Builder
- Use Case 8: How to Customize Styling with Tailwind
- How to Build, Start, and Lint the Application
- Why Two Applications in the Project?
- Page Builder Configuration and Widget Guide
- TypeScript Project Configuration (tsconfig.json)
- Q&A
Introduction
The Znode Webstore front-end is a modern, scalable Ecommerce interface built for performance, usability, and responsiveness. It features a modular architecture with reusable components for core areas such as product listings, cart, and checkout. The application communicates with Znode’s back-end via RESTful APIs for real-time data, enabling dynamic content, user sessions, and secure transactions. Key optimizations include server-side rendering (SSR), code splitting, and Content Delivery Network (CDN) usage for fast loading and search engine optimization (SEO). The result is a secure, interactive, and user-friendly shopping experience aligned with modern web standards.
Prerequisites
The development setup includes command-line interface (CLI) installation, the Webstore Software Development Kit (SDK), environment variables, and other configurations. It is also essential to ensure the Webstore application is running correctly.
For detailed instructions on setting up the local development environment, refer to the Development Setup Guide.
Ensure the environment variables listed below are properly configured after completing the development setup.
Environment Variables
Set the following variables in the .env file located at the root of the project. These environment variables are essential for configuring authentication, APIs, caching, security, and third-party integrations.
Authentication Section
Variable | Description | Example |
NEXTAUTH_URL | Base URL for NextAuth authentication callbacks. | http://localhost:3000 |
NEXTAUTH_SECRET | Secret key for encrypting JWTs and securing cookies. This can be any value the customer prefers. | ABCDEF |
API Configuration Section
Variable | Description | Example |
API_URL | Base URL for the back-end API. | https://backend-api.com/api |
API_DOMAIN | Domain name from the API_URL. | api-domain-name |
API_V2_DOMAIN | Domain for accessing version two of the API. | api-v2-domain-name |
API_KEY | API key for authenticating requests. | ****** |
Payment Services Section
Variable | Description | Example |
NEXT_PUBLIC_PAYMENT_MANAGER_URL | URL for the Payment Manager service (client-exposed) | https://payment-service.com |
Location Services Section
Variable | Description | Example |
NEXT_PUBLIC_GEO_CODE_URL | URL for geocoding services (client-exposed). | https://geo-service.com |
NEXT_PUBLIC_GOOGLE_MAP_API_KEY | API key for Google Maps services (client-exposed). | ****** |
Logging and Caching Section
Variable | Description | Example |
LOGGING_METHOD | Method for logging application events (FILE or CONSOLE). | File |
CACHE_MEMORY | Cache storage type (MEMORY or FILE). | File |
ENABLE_CACHE | Flag to enable or disable caching. | true |
Application Settings Section
Variable | Description | Example |
WEBSTORE_DOMAIN_NAME | Domain name for the Webstore. | http://localhost:3000 |
DEFAULT_THEME | Sets the default theme for the Webstore. | base |
STORAGE | Storage type used by the application (file, redis, cdn). | file |
REDIS_CONNECTION_STRING | Connection string for Redis. | redis://localhost:6379 |
APP_NAME | Name of the application. | WEBSTORE |
IS_DEBUGGING | Enables or disables debugging mode. | false |
Security Policies
Variable | Description | Example |
CONTENT_SECURITY_POLICY | Defines allowed content sources for security. | default-src 'self' |
NODE_TLS_REJECT_UNAUTHORIZED | Disables SSL validation (use only for development). | 0 |
Znode Webstore Application
As part of the development setup, both the Webstore and Page Builder solutions are included. Once opened in the code editor, the application structure will appear as follows.
Solution Structure
The project uses a modular and scalable monorepo architecture powered by Nx. This structure simplifies managing and scaling multiple applications and shared libraries. Below is a description of each key directory and its purpose:
- .github/
Contains GitHub-related pipeline configuration used for automation and CI/CD.- workflows/: Defines GitHub Actions for tasks such as:
- Testing
- Linting
- Deploying on code push or merge
- workflows/: Defines GitHub Actions for tasks such as:
- .husky/
Manages Git hooks for enforcing quality checks.- pre-commit: Runs linters and formatters to maintain code quality
- pre-push: Runs tests to ensure application stability
- .nx/
Configuration for the Nx workspace to support:- Modular project structure
- Independent builds
- Targeted test execution
- .vscode/
Holds Visual Studio Code project-specific settings including:- Linting and formatting rules
- Debugger setup
- Recommended extensions
- apps/
Contains deployable applications:- webstore/: The complete Ecommerce application
- page-builder/: A content management interface with drag-and-drop and widget management features
- node_modules/
Auto-generated by the package manager.
Stores installed dependencies.
Should be excluded from version control. - packages/
Contains shared libraries and utilities, including:- agents/: API service wrappers using fetch or Axios
- base-components/: Shared UI elements
- clients/: Interfaces for third-party services such as payments and maps
- constants/: Static application-wide values
- custom-theme1-components/, custom-theme2-components/, theme1-components/: Theme-specific styling and layout components
- logger/: Structured logging utility
- page-builder/: Shared tools and components for the Page Builder
- types/: Shared TypeScript types and interfaces
- utils/: Utility functions (e.g., formatters, validators)
Key Configuration Files
- .eslintrc.json / .eslintignore
ESLint configuration for enforcing code style standards - .prettierrc / .prettierignore
Prettier configuration for consistent code formatting - tsconfig.base.json
Base TypeScript configuration shared across applications - package.json
Project metadata, scripts, and dependencies list
Important Highlights
What Is a Component?
A component is a reusable UI element used in the Webstore. Examples include buttons, headers, and grids.
To create a component, use the following files:
- Directory: packages/page-builder/src/configs/base-config/widgets/{widget-type}/
- ComponentConfig.tsx: Defines the configuration settings visible in the Page Builder
- ComponentRender.tsx: Handles the UI rendering based on settings
What Is a Widget?
A widget is a modular block used in the Page Builder that can be dragged and dropped to construct web pages.
Types of widgets:
- Znode Widgets: Integrated with the Znode CMS and Admin Console for dynamic content
- UI Widgets: Design-focused components aligned with the visual design system
- Page Widgets: Layout-defining components like sections or containers
Ways of Customization for Storefront Applications
Znode allows customization using both the Webstore and Page Builder with the following tools.
By Themes
- Existing Themes
- Webstore: Add new components within the existing base configuration
- Page Builder: Create new widgets in the existing configuration
- New Themes
- Webstore: Develop new components and define a new theme configuration
- Page Builder: Create widgets aligned with a new theme
In Pages Using Page Builder
- Existing Pages
- Update content using drag-and-drop
- Modify widget settings (text, images, colors, etc.)
- New Pages
- Create a layout using a blank canvas or predefined templates
- Define page settings and design using widgets
- Preview and publish
Tailwind Theme
Tailwind CSS is used for consistent, flexible, and scalable styling across themes.
How to Customize
Znode store front Webstore customizations are achieved through two types of applications:
- Webstore: Used for React-based UI components
- Page Builder: Used for CMS-driven drag-and-drop widgets
Customization is based on registering configuration types within the system for each type of applications: ie base configuration of type is used to build /modify components in web store and widgets in page builder applications. Same applicable for theme configurations types for new theme component vs theme widget. These type is used initially to create new base versions and later will be modified. Detailed used cases for each combination are explained in the upcoming sections.
Configuration Type (Configuration files) | Webstore | Page Builder |
Base Configuration | New Component | New Widget |
Theme Configuration (New) | New Theme Component | New Theme Widget |
Theme Customization Steps
As mentioned above, the use cases below described how to customize in store front applications with various combinations of theme and omponents and widgets
Creating a new custom theme
Please refer to Creating a Custom Theme.
Use Case 1: Creating a New Component in the Existing Theme
Follow the steps below to add a new component to the existing theme.
Step 1: Identify Widget Category
Choose the appropriate widget category based on requirements: widget categories are defined as Znode-Widgets, UI-Widgets or a Page-Widget widget.
- Znode Widgets: Integrated with the Znode CMS and Admin Console
- Examples: BannerSlider, ContentBlock, FeaturedProductList
- Features: Personalization, content targeting, dynamic rendering
- UI Widgets: Design-focused components
- Examples: Heading, Button, Image
- Features: Theme-agnostic, accessible, visually styled
- Page Widgets: Structural layout components
- Examples: PageWrapper, SectionLayout, SidebarLayout
- Features: Layout grouping, adaptive design support
Step 2: Create the Component
Navigate to:
packages/page-builder/src/configs/base-config/widgets/{widget-type}/
Create a folder with the component name (e.g., grid).
Step 3: Add Component Files
Create the following files:
- GridConfig.tsx: Defines configuration settings
- GridRender.tsx: Handles UI rendering
Step 4: Define GridConfig.tsx
export const GridConfig = { spacing: { type: 'number', label: 'Grid Spacing' }, columns: { type: 'number', label: 'Number of Columns' }, backgroundColor: { type: 'color', label: 'Background Color' }, };
Step 5: Define GridRender.tsx
export const GridRender = ({ spacing, columns, backgroundColor }) => { return ( <div style={{ display: 'grid', gap: spacing, backgroundColor }}> Render {columns} columns here </div> ); };
Step 6: Register the Component
In base-components-config.tsx, add:
import { GridConfig } from './widgets/ui-widgets/grid/GridConfig'; import { GridRender } from './widgets/ui-widgets/grid/GridRender'; export const baseComponentsConfig = { ..., grid: { config: GridConfig, render: GridRender }, };
Use Case 2: Creating a New Component with the New Theme
Step 1: Scaffold Theme Package
Use the following command to scaffold a new theme:
npx nx g @nx/next:lib packages/{themeName}
Step 2: Create Theme Folder Structure
Sample directory:
packages/page-builder/src/configs/bstore-config/ └── widgets/ ├── ui-widgets/ ├── page-widgets/ └── znode-widgets/
Step 3: Create root-config.ts
import { extendConfig } from '../base-config';
import { GridConfig } from './widgets/ui-widgets/grid/GridConfig';
import { GridRender } from './widgets/ui-widgets/grid/GridRender';
export const getRootConfig = () => {
return extendConfig({
uiWidgets: {
grid: { config: GridConfig, render: GridRender },
},
});
};
Step 4: Override or Add New Components
- Override: Copy and modify existing widgets in the new theme folder
- Add: Create new widgets inside the relevant widget category directory
Step 5: Map Theme in get-config.ts
In packages/page-builder/src/configs/root-configs/get-config.ts:
import { getRootConfig as getBstoreConfig } from './bstore-config/root-config';
export const getConfig = () => getBstoreConfig();
Use Case 3: Updating an Existing Base Component
To update any existing component in the base configuration:
- Modify settings in GridConfig.tsx
- Update the UI in GridRender.tsx
No additional registration is required if the component is already defined in base-components-config.tsx.
Use Case 4: Updating a Theme Widget
To update an existing component in a specific theme:
- Modify settings in GridConfig.tsx
- Update the UI in GridRender.tsx
No need to modify the base configuration. The theme component will automatically reflect the changes.
Use Case 5: How to Design Predefined CMS Pages and Sections
Page Builder allows customization of predefined commerce pages using the Admin Console.
Step 1: Access CMS Pages
- Log in to the Admin Console.
- Go to “CMS” > “Store Experience.”
- Find the appropriate store and click the “Page Builder” icon.
Step 2: Select a Commerce Page
Choose a predefined page such as:
- Product Detail Page
- Category Page
- Brand List Page
Step 3: Customize Components
Using the Page Builder interface:
- Rearrange widgets
- Add or remove widgets
- Adjust content (text, images, spacing)
Step 4: Preview and Save
- Click “Preview” to view changes
- Click “Save” to store updates
Step 5: Publish the Page
- Navigate to “Publishing Settings”
- Define visibility or schedule settings
- Confirm the publish action
Use Case 6: How to Create and Manage Content Pages Using Page Builder
Content pages can be created and managed using Page Builder’s predefined components.
Step 1: Log in to Admin Console
Use administrator credentials.
Step 2: Navigate to Content Pages
- Go to “CMS” > “Pages”
- Click “Add New” to create a new page
Step 3: Fill in Content Page Details
Complete required fields:
- Store
- Page Code
- Profile (if applicable)
- Page Name
- Is Active
- Locale(s)
SEO Configuration
- Page Title
- SEO Title
- SEO Keywords
- SEO Description
- Additional Meta Information
- SEO-Friendly URL
- Redirect setting
- Canonical URL
- Robot Tag
Activation Details
- Activation Date
- Expiration Date (optional)
Step 4: Save the Content Page
Click “Save” to store the page.
Step 5: Design the Page Using Page Builder
Click the “Page Builder” icon from the Actions column.
Customize with widgets using drag-and-drop.
Step 6: Preview and Publish
- Click “Preview”
- Click “Save”
Only published pages are rendered in the Webstore. Pages can be scheduled or updated at any time.
Key Notes
- Each saved page is versioned and stored in the database.
- Only published pages are available for rendering in the Webstore.
- Pages can be scheduled for publication or updated at any time.
- All widgets used in the page must be registered and available in the component registry.
Use Case 7: How to Update and Manage Existing Content Pages Using Page Builder
Existing content pages can be updated without writing code.
Step 1: Log in to Admin Console
Step 2: Navigate to Existing Content Pages
- Go to “CMS” > “Pages”
- Locate the desired page
Step 3: Open Page in Page Builder
Click the “Page Builder” icon from the Actions column.
Step 4: Customize Page Design
Use the drag-and-drop interface to:
- Rearrange or remove widgets
- Add components
- Modify styling or content
Step 5: Preview and Save Changes
- Click “Preview”
- Click “Save”
Changes will appear immediately on the Webstore.
Use Case 8: How to Customize Styling with Tailwind
Tailwind CSS enables scalable and consistent theming.
Step 1: Create tailwind.config.ts File
Place it inside each theme directory.
Example Structure:
bstore/
└── tailwind-config/
└── tailwind.config.ts
Step 2: Define the Theme Object
module.exports = { name: "bstore", selectors: ["[data-theme='bstore']"], extend: { colors: { primary: "#1D4ED8", secondary: "#9333EA", }, borderRadius: { lg: '1rem', } } };
Step 3: Configure Tailwind in Webstore or Page Builder
In the Tailwind configuration files:
const bstoreTailwindConfig = require('../bstore/tailwind-config/tailwind.config'); const safetyGearTailwindConfig = require('../safety-gear/tailwind-config/tailwind.config'); module.exports = { content: [ "./src/**/*.{js,ts,jsx,tsx}", "../bstore/**/*.{js,ts,jsx,tsx}", ], plugins: [ require("tailwindcss-themes")({ themes: [ bstoreTailwindConfig, safetyGearTailwindConfig, ] }) ] }
Key Notes
- Use data-theme attributes to scope styles
- Extend, rather than override, Tailwind defaults
- Ensure shared components adhere to theme selectors
How to Build, Start, and Lint the Application
Use the following commands to perform application tasks:
Task | Command |
Run Webstore | npx nx run webstore |
Build Webstore | npx nx run webstore:build |
Lint Webstore | npx nx run webstore:lint |
Run Page Builder | npx nx run page-builder |
Build Page Builder | npx nx run page-builder:build |
Lint Page Builder | npx nx run page-builder:lint |
Clear Nx Cache | npx nx reset |
Why Two Applications in the Project?
Webstore
The Webstore is the public-facing front-end application.
Key Features:
- Dynamic content rendering
- Responsive design for all devices
- Real-time updates from Page Builder
- Support for UI, Page, and Znode widgets
- Internationalization (i18n) support
Page Builder
The Page Builder is an internal content management tool for developers and content editors.
Key Features:
- Visual drag-and-drop interface
- Widget library with structured components
- Page publishing and scheduling
- Real-time preview functionality
Together, these applications deliver a decoupled headless content management experience.
Page Builder Configuration and Widget Guide
The Page Builder includes categorized widget types for streamlined design and layout.
Component Categories
UI Widgets
Reusable components used across different layouts:
- VerticalSpacing
- Column
- Flex
- Text
- Card
- Hero
- Logo
Znode Widgets
Widgets integrated with Znode Ecommerce and CMS systems:
- BannerSlider - Slideshow banner component.
- CategoriesCarousel - Rotating display of categories.
- OfferBanner - Promotional offer component.
- ProductsCarousel - Product listing in a slider.
- AdSpace - Custom ad slot area.
- HomePagePromo - Special homepage promo blocks.
- Image - Image rendering component.
- Video - Embedded video player.
Category Grouping in Configuration
Widgets are grouped by type in configuration files:
Layout Widgets
- Title: Layout Widgets
- Components: Flex, Column, VerticalSpacing
UI Widgets
- Title: UI Widgets
- Components: Text, Card, Logo, etc.
Znode Widgets
- Title: Znode Widgets
- Components: BannerSlider, ProductsCarousel, Image, etc.
These groupings enable organized display within collapsible categories in the Page Builder interface.
TypeScript Project Configuration (tsconfig.json)
The tsconfig.json file defines TypeScript compiler behaviors and module resolution settings.
Key Compiler Options
- target: Defines the JavaScript output version (e.g., es6)
- module: Specifies the module system (e.g., commonjs, esnext)
- strict: Enables strict type-checking for higher reliability
- esModuleInterop: Supports importing CommonJS modules
- skipLibCheck: Skips type checking for library files to improve build speed
- outDir: Defines the output directory for compiled JavaScript
- baseUrl: Sets the base path for imports
- paths: Enables aliasing for cleaner import paths
These options standardize project structure, enforce type safety, and enhance code maintainability.
Q&A
1. Why Use Node.js as the Runtime Environment?
Pros:
- Non-blocking, event-driven architecture for scalability
- Unified JavaScript usage across front-end and back-end
Cons:
- Single-threaded, which may limit performance for CPU-heavy tasks
Alternative: Java (Spring Boot), .NET
Pros: Mature ecosystems, multi-threading
Cons: Higher memory usage, slower startup
2. Why Use Next.js as the Web Application Framework?
Pros:
- Server-side rendering (SSR) and static site generation (SSG)
- Organized and scalable project structure
Cons:
- Learning curve, especially for new developers
Alternative: React with Create React App
Pros: Simpler setup
Cons: Lacks built-in SSR and SSG
3. Why Use HTML for Structuring Content?
Pros:
- Standardized, browser-compatible
- Semantic layout enhances accessibility
Cons:
- Limited interactivity
Alternative: Markdown (MDX)
Pros: Easy to write
Cons: Not ideal for complex layouts
4. Why Use CSS and Tailwind CSS for Styling?
Pros:
- Responsive design
- Utility-first approach for consistent styling
Cons:
- Steeper learning curve; verbosity
Alternative: SASS/Bootstrap
Pros: Prebuilt components
Cons: Less flexibility and heavier output
5. Why Use Redis for Caching?
Pros:
- High-performance, in-memory caching
- Quick data retrieval
Cons:
- Memory limitations for large datasets
- Persistence requires configuration
Alternative: Memcached
Pros: Simplicity
Cons: Limited data structure support
6. Why Use JavaScript and React for Interactivity?
Pros:
- Real-time UI interaction
- Component-based architecture
Cons:
- Heavier initial load
- Learning curve
Alternative: Vue.js
Pros: Simplicity, ease of integration
Cons: Smaller ecosystem