Webstore Customization Guide

TABLE OF CONTENTS


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

VariableDescriptionExample
NEXTAUTH_URLBase URL for NextAuth authentication callbacks.http://localhost:3000
NEXTAUTH_SECRETSecret key for encrypting JWTs and securing cookies. This can be any value the customer prefers.ABCDEF

API Configuration Section

VariableDescriptionExample
API_URLBase URL for the back-end API.https://backend-api.com/api
API_DOMAINDomain name from the API_URL.api-domain-name
API_V2_DOMAINDomain for accessing version two of the API.api-v2-domain-name
API_KEYAPI key for authenticating requests.******

Payment Services Section

VariableDescriptionExample
NEXT_PUBLIC_PAYMENT_MANAGER_URLURL for the Payment Manager service (client-exposed)https://payment-service.com

Location Services Section

VariableDescriptionExample
NEXT_PUBLIC_GEO_CODE_URLURL for geocoding services (client-exposed).https://geo-service.com
NEXT_PUBLIC_GOOGLE_MAP_API_KEYAPI key for Google Maps services (client-exposed).******

Logging and Caching Section

VariableDescriptionExample
LOGGING_METHODMethod for logging application events (FILE or CONSOLE).File
CACHE_MEMORYCache storage type (MEMORY or FILE).File
ENABLE_CACHEFlag to enable or disable caching.true

Application Settings Section

VariableDescriptionExample
WEBSTORE_DOMAIN_NAMEDomain name for the Webstore.http://localhost:3000
DEFAULT_THEMESets the default theme for the Webstore.base
STORAGEStorage type used by the application (file, redis, cdn).file
REDIS_CONNECTION_STRINGConnection string for Redis.redis://localhost:6379
APP_NAMEName of the application.WEBSTORE
IS_DEBUGGINGEnables or disables debugging mode.false

Security Policies

VariableDescriptionExample
CONTENT_SECURITY_POLICYDefines allowed content sources for security.default-src 'self'
NODE_TLS_REJECT_UNAUTHORIZEDDisables 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
  • .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)
WebstorePage Builder
Base ConfigurationNew ComponentNew Widget
Theme Configuration (New)New Theme ComponentNew 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:

TaskCommand
Run Webstorenpx nx run webstore
Build Webstorenpx nx run webstore:build
Lint Webstorenpx nx run webstore:lint
Run Page Buildernpx nx run page-builder
Build Page Buildernpx nx run page-builder:build
Lint Page Buildernpx nx run page-builder:lint
Clear Nx Cachenpx 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

Did you find it helpful? Yes No

Send feedback
Sorry we couldn't be helpful. Help us improve this article with your feedback.