Customize Theme Code
The Soppiya storefront theme engine uses a modular, configuration-driven development architecture. It is designed to separate global layouts, page-specific templates, reusable components, and client-side APIs.
This guide serves as a comprehensive reference manual for developers and designers building custom, high-performance storefronts within the Soppiya SaaS ecosystem.
Concept: Theme Directory Architecture
Every Soppiya theme is composed of eight core folders, each managing a specific part of your storefront's layout, styling, or functionality.
[Theme Directory Root]
├── layout/ (Base structural outer frames)
├── templates/ (Page blueprints; JSON or Liquid files)
├── sections/ (Configurable, reusable layout modules)
├── blocks/ (Modular components nested inside sections)
├── snippets/ (Reusable helper code segments)
├── config/ (Customizer settings schemas & data)
├── locales/ (Translation & language files)
└── assets/ (Static media files: CSS, JS, images, SVGs)
Structural Layouts (/layout)
Layout files define the parent structural envelope (outer frame) of your pages. They render standard global HTML structures, global script/stylesheet calls, and your theme's header and footer section groups.
theme.liquid: The primary wrapper used across standard pages.password.liquid: A specialized wrapper displayed when your store is locked.- Key Mechanics: Inside a layout file, the engine uses the placeholder variable
{{ content_for_layout }}to tell the compiler where to inject your page-specific templates.
Page Blueprints (/templates)
Templates control the structural layout of specific pages. When a customer visits a page on your store, the routing system selects the template associated with that page type.
- JSON Templates (
.json): Configured as structured JSON maps, these files allow you to visually add, remove, and reorder page sections using the visual Theme Editor. - Liquid Templates (
.liquid): Static templates containing hardcoded HTML and Liquid markup. Note: Liquid templates do not allow you to dynamically rearrange sections in the Theme Editor.
Reusable Layout Modules (/sections)
Sections are self-contained layout blocks (such as Banners, Image with Text, or Product Carousels) that merchants can visually configure and place on pages.
- Color Scheme Overwrites: Sections feature built-in controls to bypass global styling and apply custom local background and text colors.
- Section Groups: JSON files (like
header-group.jsonorfooter-group.json) that bundle multiple sections (such as an announcement bar and header menu) into a static visual area. This lets merchants easily customize and reorder layout items in critical areas like headers and footers.
Component Elements (/blocks)
Blocks are the smaller, modular components nested inside sections (such as text headings, buttons, sliders, or image slides).
- Scope Isolation: Each block features its own independent settings schema (
{% schema %}). To prevent styling conflicts, block stylesheets are scoped using the unique block ID variable:block.id. - Infinite Reuse: Standard block files (like
button.liquidorvideo.liquid) can be loaded and reused across multiple different sections in your theme.
Helper Code Snippets (/snippets)
Snippets are small, reusable code snippets containing HTML, CSS, or Liquid logic. They are used to keep your theme code clean and organized.
- Invisible in the Customizer: Unlike sections and blocks, snippets are entirely invisible to merchants in the visual Theme Editor. They are called programmatically in code using the Liquid
{% render %}tag. - Isolated Scope: Snippets do not automatically inherit parent variables. If you want a snippet to use a specific variable (such as product details or currency data), you must explicitly pass that variable into the snippet.
Global Configuration Settings (/config)
Manages your global visual settings and saves your active layout customizations.
settings_schema.json: Controls the layout, input fields, and options shown in the Theme settings area of your visual editor.settings_data.json: Stores the actual values, colors, and options selected by the merchant in the editor.
Translation Files (/locales)
Locale files are JSON files that store translation files for text used throughout your storefront and theme editor. This lets merchants easily translate their storefront or edit repeated store phrases (like "Add to Cart") in a single place.
Static Asset Storage (/assets)
The assets folder stores the static files required for your theme's design and functionality. This includes CSS stylesheets, JS scripts, SVGs, images, and other media files.
Concept: Database Scoping & Variable Access
Soppiya data objects represent the dynamic variables used to render your store's database content on pages. To output an object's value, wrap its parameter in double-curly brace delimiters: {{ product.title }}.
┌────────────────────────────┐
│ Database Variable Access│
└─────────────┬──────────────┘
┌──────────────────────────┴──────────────────────────┐
▼ ▼
┌─────────────────────────────────┐ ┌─────────────────────────────────┐
│ Contextual Access │ │ Global Database Access │
├─────────────────────────────────┤ ├─────────────────────────────────┤
│ Available only within specific │ │ Query raw database records globally│
│ page routes (e.g., 'product' │ │ on any page using the underscore │
│ object on product.json) │ │ prefix (e.g., '_product') │
└─────────────────────────────────┘ └─────────────────────────────────┘
Contextual Variable Access
Certain objects are only initialized and accessible within their matching template routes. For example:
- The
productobject is only accessible on product pages. - The
collectionobject is only accessible on collection pages. - The
articleobject is only accessible on individual blog post pages.
Global Database Lookups (_ Prefix)
To bypass page routing limits, Soppiya supports direct, globally scoped database queries from any template, block, or snippet using an underscore prefix. For example:
_product[product_handle]: Fetches a product directly from the database by its handle._collection[collection_handle]: Fetches a collection directly from the database by its handle._blog[blog_handle]: Fetches a blog directly from the database by its handle._article[article_handle]: Fetches a blog article directly from the database by its handle.
This allows developers to build cross-sell modules, custom collection grids, or featured blog feeds globally on any page.
Concept: The Visual-to-Code Mapping Engine
Soppiya’s visual editing interface is powered by a structural bridge between your theme code and configuration files.
Customizer Schemas ({% schema %})
Every section and block file contains a {% schema %} tag block. This block defines the input types, sliders, and options shown in the Theme Editor sidebar for that module. Supported settings include:
- Checkboxes (
"type": "checkbox"): Creates an ON/OFF toggle in the customizer. - Select Menus (
"type": "select"): Creates a dropdown menu for preset choices. - Range Sliders (
"type": "range"): Creates a slider to adjust pixel-based margins, padding, or border-radius settings. - Conditional Display Logic (
"visible_if"): Dynamically hides or shows a setting based on another customizer option. For example, you can show a "Custom Height" slider only when the "Custom Height" option is selected in a height dropdown.
Settings Data Configuration
When a merchant modifies an option in the Theme Editor, their selection is instantly written to the config/settings_data.json file. The Soppiya compiler reads these saved values to render the active theme styles.
Concept: Dynamic Storefront Interactivity & AJAX APIs
To deliver fast, responsive shopping experiences, the storefront utilizes native browser APIs and lightweight client-side JavaScript.
Client-Side AJAX APIs
Soppiya exposes a clean JavaScript AJAX API. These endpoints are called securely from your storefront javascript using standard fetch requests:
- Get Cart (
GET /cart.js): Retrieves the current customer cart details as a JSON object. - Update Cart (
POST /cart/update): Updates line items, shipping addresses, selected shipping rates, payment configurations, and discount codes in a single request. - Create Order (
POST /order/create): Submits checkout address, contact information, and cart parameters to generate an active order in the database. - Pay Order (
POST /order/pay): Submits payment selections to generate a transaction gateway link.
Iframe-Free Dynamic Modals
To support product preview drawers or quick-view overlays without triggering full page reloads, Soppiya uses an iframe-alternative approach via the <object> HTML element:
┌──────────────────────────────┐
│ Trigger View-Options click │
└──────────────┬───────────────┘
│ modal('products/handle', event)
▼
┌──────────────────────────────┐
│ Create DOM Container │
└──────────────┬───────────────┘
│ document.createElement('section')
▼
┌──────────────────────────────┐
│ Inject <object> Element │
└──────────────┬───────────────┘
│ Points to relative product URL
▼
┌──────────────────────────────┐
│ onload Asset Filtering │
└──────────────┬───────────────┘
│ - Strips header, footer, menus
│ - Fades in focused details box
▼
┌──────────────────────────────┐
│ Slides Drawer Into View │
└──────────────────────────────┘
- Event Interception: Clicking the button triggers the global
modal("products/product-handle", event)function. The script runsevent.preventDefault()to stop the browser from navigating away. - DOM Container Creation: JavaScript dynamically creates the modal overlay (
id="product_quick_view") and card wrapper (id="product_quick_view_inner") elements. - Loading Content via
<object>: The script inserts an<object>tag pointing to the relative product URL. This loads the page in an isolated background container:const productDrawer = `<object id="modal" style="opacity: 0;" onload="handle_modal_onload()" data="${full_url.origin}/${url}" width="100%" height="100%"></object>`; - Isolating Content (
handle_modal_onload): Once the content loads, the script accesses the document inside the object container (modalElement.contentDocument), isolates the primary<main>wrapper, and strips away global layouts like the header, footer, and navigation menus to show only the product details box. - Inter-Frame Communication: When a customer interacts with the product details inside the quick-view modal, the script uses the
window.parentnamespace to communicate with the parent page, letting it know to trigger cart updates or display success overlays.
Concept: Custom Soppiya Filters & Logic Control
Liquid filters use the pipe separator symbol | to format and modify the output of variables and objects: {{ product.title | upcase }}.
Media & Asset Resolvers
asset_url: Returns the complete static server URL (e.g., hosted onstatic.soppiya.com) for a designated asset file.icon_url: Returns the hosted SVG asset path from the Soppiya icon library directory.img_url: Resolves standard image files from the theme assets directory.placeholder_url: Renders generic placeholder graphics (e.g.,hero-02.svg) for empty theme modules.full_url: Standardizes absolute paths by trimming whitespaces and securing valid URL structures.stylesheet_tag: Transforms an asset URL directly into a complete<link rel="stylesheet">element.script_tag: Transforms an asset URL directly into a complete<script>element.
Typography Compilers
font_import: Generates a CSS@importrule for Google Fonts based on theme font settings:{{ settings.body_font | font_import }}/* Outputs: @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400&display=swap'); */font_link: Generates an HTML<link>tag referencing specified font families.
Non-Destructive Array Mutators & Queries
Soppiya includes a robust set of array filters that return copies of modified arrays without mutating the parent dataset:
push: Appends an item to the end of an array.pop: Removes the last item from an array.shift: Removes the first item from an array.unshift: Prepends an item to the beginning of an array.concat: Joins multiple arrays together.reject: Excludes items matching specified parameter keys and values.where: Includes only array elements that match specific key-value queries.uniq: Strips duplicate values from an array.sum: Calculates the sum of all numerical values in an array.map: Extracts values from a specific property across an array of objects.find/find_index: Queries objects or resolves zero-based index positions within arrays.group_by/group_by_exp: Aggregates arrays into grouped properties or Liquid expression matches.has/has_exp: Checks for the existence of specific attributes or boolean expression criteria in arrays.