diff --git a/content/docs/storefront/themes/cdn-and-caching.mdx b/content/docs/storefront/themes/cdn-and-caching.mdx
index 659b875..51a3317 100644
--- a/content/docs/storefront/themes/cdn-and-caching.mdx
+++ b/content/docs/storefront/themes/cdn-and-caching.mdx
@@ -10,6 +10,8 @@ Storefront leverages CDNs and many caching strategies to ensure fast performant
Always use the store network domain `{store}.29next.store` when developing themes to bypass full page caching and preview your latest updates.
+
+The network domain bypasses the full-page cache. It does not, by itself, prove that a template lookup is fresh.
### Asset CDN
All merchant uploaded media assets and theme assets are loaded from our CDN for the fastest performance.
@@ -27,17 +29,32 @@ All pages on storefront are cached for 5 minutes to ensure popular pages are as
-To skip the cache, you can append a unique querystring such as `?skip_cache` to skip existing cache and see the latest.
+On the network domain or in an active preview session, append `?skip_cache=1` to bypass both the full-page and theme-template caches for that request. On a mapped production domain without a preview session, the parameter is ignored.
### Template Caching
Themes use many templates ie `layouts`, `partials`, and `assets` that when compiled together create amazing customer experiences. Templates are cached in memory to reduce database queries when compiling templates into the full html response.
-Updating a template through the dashboard or [Theme Kit](/docs/storefront/themes/theme-kit) should automatically purge the cache for you to see your latest changes on the network domain, see notes above.
+Each theme has a shared revision. Saving or deleting a template rotates that revision, so every application worker stops using its prior process-local or shared-cache entry. If a request must prove current database content, use the authorized `skip_cache=1` flow above.
+
+Network-domain responses include diagnostic headers:
+
+| Header | Meaning |
+| --- | --- |
+| `X-Theme-Id` | Active or previewed theme ID |
+| `X-Theme-Template` | Effective template selected after fallback |
+| `X-Theme-Template-Candidates` | Ordered custom and generic candidates |
+| `X-Theme-Template-Revision` | Version of the selected template |
+| `X-Theme-Revision` | Shared theme revision used for cache keys |
+| `X-Theme-Cache` | `local`, `shared`, `db`, or `bypass-db` source |
+
+These headers are intentionally omitted from mapped production domains. For a custom product page, verify that `X-Theme-Template` names the intended `product..html`; a product URL slug does not select the template.
+
+Theme assets use one canonical storage key per logical asset name. Replacing an asset updates that key and its versioned URL rather than accumulating suffixed filenames.
There are a few cases wherein a form on the frontend needs to use a `{% csrf_token %}` field to secure submission to the backend. The platform core JS will automatically replace `{% csrf_token %}` that are in cached versions of pages to ensure the forms still work.
**It is advisable to not implement custom templates that require `{% csrf_token %}`, we recommend the [Storefront GraphQL API](/docs/storefront/graphql) instead.**
-
\ No newline at end of file
+
diff --git a/content/docs/storefront/themes/guides/custom-product-templates.mdx b/content/docs/storefront/themes/guides/custom-product-templates.mdx
index f822e64..6afcf81 100644
--- a/content/docs/storefront/themes/guides/custom-product-templates.mdx
+++ b/content/docs/storefront/themes/guides/custom-product-templates.mdx
@@ -6,61 +6,59 @@ tags:
---
import { Callout } from 'fumadocs-ui/components/callout';
-Products can have very diverse design requirements that often require custom layouts. In this guide, we'll go over some of the best practices for creating and managing custom product templates.
+Products can have very different design requirements. Assign a named custom product template when a product needs a purpose-built layout.
-### Product Templates Location
+### Product Template Location
-In the `templates/catalogue` directory of a theme, theme developers can edit/manage the product page templates.
+Store product templates under `templates/catalogue`:
-```bash title="Product Templates Location"
-catalogue
- └── product.html (default)
- └── product..html
- └── product..html
+```text title="Product Templates Location"
+templates/catalogue/
+ product.html
+ product.subscription.html
+ product.bundle.html
```
-### Extend & Override
+The segment between `product.` and `.html` is the product's template key. A product URL slug does not select the template.
-**Create a Custom Product Template**
+### Build a Standalone Product Document
-Create a new product template in the **templates>catalogue** directory with the following naming convention:
+Create the exact file for the key you plan to assign:
-```bash title="Custom Product Template Naming"
-templates/catalogue/product..html
+```text title="Custom Product Template Naming"
+templates/catalogue/product..html
```
-Templates that follow this naming convention will be selectable on the product detail to use on the storefront.
-
-
-**Extend & Override Default Product Template**
-
-As a best practice, you should [extend](/docs/storefront/themes/templates/tags#extends--block) the default product template to override the necessary [template blocks](/docs/storefront/themes/templates/tags#extends--block) to achieve your customization with a limited amount of duplicate code.
+Do not extend `templates/catalogue/product.html` from a `product..html` file. Runtime template resolution already treats the generic template as a fallback; inheriting from it can hide selection mistakes and couples the custom design to a separate page implementation.
+A custom product template may be a complete document or extend the shared `layouts/base.html` shell. Keep independently replaceable global surfaces in named [template blocks](/docs/storefront/themes/templates/tags#extends--block).
```django title="Example Custom Product Template"
+{% extends "layouts/base.html" %}
-{% extends "templates/catalogue/product.html" %}
-
-{% block header %}
- // Custom Product Header Code
-{% endblock header %}
-
-{% block product_description %}
- // Custom Product Content Template Code
-{% endblock %}
-
+{% block title %}{{ product.title }}{% endblock title %}
+{% block content %}
+
+ {{ product.title }}
+ {# Render the complete custom product experience here. #}
+
+{% endblock content %}
```
-This strategy will simplify the creation and management of custom product templates so you can focus on the customized areas for the new custom product template.
+Validate and upload the exact file before assigning it:
+```bash
+ntk validate --server templates/catalogue/product.subscription.html
+ntk push templates/catalogue/product.subscription.html --json --no-progress
+```
-**Select Template for Product**
+### Assign and Verify the Template
-On your product of choice, select your newly created template as the Product Template to activate the template on your product in the storefront.
+On the product, set **Product Template** to the template key—for example, `subscription`. You can use the dashboard or the Admin API. Then open the product route in a preview session with `skip_cache=1`.
+On the network domain, confirm `X-Theme-Template: templates/catalogue/product.subscription.html`. If the header reports `templates/catalogue/product.html`, the platform fell back to the generic template; check the product's template field, filename, validation result, and upload outcome.
-
-You are not limited to overriding the existing template blocks in the default product template. You can create and add your own to the default template to overide in your custom template. For example, adding `{% block my_custom_block %}{% endblock %}` to product.html, around any area you wish to customize, will allow you to overide it in the custom template
-
\ No newline at end of file
+Preview selection is pinned in the `preview_theme` cookie. Use the storefront preview indicator's **Exit preview** action or `/?deactivate-theme=true` when you finish; opening a plain URL does not deactivate the preview.
+
diff --git a/content/docs/storefront/themes/guides/figma-to-theme.mdx b/content/docs/storefront/themes/guides/figma-to-theme.mdx
new file mode 100644
index 0000000..1fadf24
--- /dev/null
+++ b/content/docs/storefront/themes/guides/figma-to-theme.mdx
@@ -0,0 +1,46 @@
+---
+title: Figma-to-Theme Handoff
+sidebar_label: Figma-to-Theme Handoff
+tags:
+ - Guide
+---
+import { Callout } from 'fumadocs-ui/components/callout';
+
+Use the [`next-theme-figma`](/docs/skills) skill to turn a storefront design into a low-inference handoff, then use `next-theme-dev` to implement it in a Spark-derived theme.
+
+### Validate the Source Before Coding
+
+Capture the exact Figma file and node IDs, inventory desktop and mobile frames, identify reusable sections, and map design tokens and assets. A large metadata response with an empty child list is a truncation or tooling failure, not proof that the frame is empty.
+
+When a large file cannot be read reliably:
+
+1. Query the known frame or component node directly.
+2. Split a full page into smaller frame or section reads.
+3. Export assets by exact node ID in bounded batches.
+4. Retry selection synchronization no more than three times.
+5. If tool access still fails and the owner authorizes it, use an exported `.fig` source.
+
+Record unresolved gaps explicitly instead of inferring missing layout or asset details.
+
+### Require Visual Evidence
+
+Before declaring visual parity, keep both sides of the comparison:
+
+- A matching Figma frame image for each reviewed route and viewport.
+- A real storefront PNG for the same route and viewport.
+- Desktop and mobile coverage, including responsive behavior and touch states.
+
+Use Theme Kit for deterministic storefront capture:
+
+```bash
+ntk capture --url="/?preview_theme=&skip_cache=1" \
+ --output=qa-output --viewports=desktop,mobile --json --no-progress
+```
+
+
+DOM dimensions, text dumps, and screenshots of the wrong frame are diagnostics, not visual QA. If the matching Figma image cannot be obtained, stop the parity claim or record an accepted evidence gap with an owner.
+
+
+### Preserve Route Coverage
+
+Review every route in the handoff, not only the homepage. Product detail work must exercise the assigned custom product template, and every route must include a 1440px desktop and 390px mobile artifact before sign-off.
diff --git a/content/docs/storefront/themes/guides/meta.json b/content/docs/storefront/themes/guides/meta.json
index 6b56a04..8212ce3 100644
--- a/content/docs/storefront/themes/guides/meta.json
+++ b/content/docs/storefront/themes/guides/meta.json
@@ -1,4 +1,4 @@
{
"title": "Guides",
- "pages": ["custom-page-templates", "custom-product-templates", "product-variants"]
+ "pages": ["figma-to-theme", "custom-page-templates", "custom-product-templates", "product-variants"]
}
diff --git a/content/docs/storefront/themes/theme-kit.mdx b/content/docs/storefront/themes/theme-kit.mdx
index 2f18280..6bd908a 100644
--- a/content/docs/storefront/themes/theme-kit.mdx
+++ b/content/docs/storefront/themes/theme-kit.mdx
@@ -27,14 +27,19 @@ If you already have `python` and `pip`, install with the following command:
pip install next-theme-kit
```
+The core CLI installs without native Sass bindings on macOS (including Apple Silicon), Linux, and native Windows. Install optional features only when needed:
+
+```bash
+pip install 'next-theme-kit[sass]' # legacy libsass compilation
+pip install 'next-theme-kit[capture]' # screenshots; then run: playwright install chromium
+```
+
#### Mac OSX Requirements
See how to install `python` and `pip` with [HomeBrew](https://docs.brew.sh/Homebrew-and-Python#python-3x). Once you have completed this step you can install using the `pip` instructions above.
#### Windows Requirements
-* **Option 1 (Recommended)** - Windows 10 and above feature WSL (Windows Subsystem for Linux) which provides a native Linux environment, see how to [Install WSL with Ubuntu](https://docs.microsoft.com/en-us/windows/wsl/install). Once you have installed WSL, follow the [best practice guides to configure and use with VS Code](https://docs.microsoft.com/en-us/windows/wsl/setup/environment) and then follow the `pip` instructions above to install Theme Kit.
-
-* **Option 2** - Installing `python` in Windows natively can be done with through the [Windows App Store](https://apps.microsoft.com/store/detail/python-39/9P7QFQMJRFP7?hl=en-us&gl=us). Recommend using [Windows Powershell](https://apps.microsoft.com/store/detail/powershell/9MZ1SNWT0N5D?hl=en-us&gl=us). This route is a little more tricky and some knowledge on how to manage python in windows will be required.
+Theme Kit's core commands run in native Windows PowerShell as well as WSL. Install Python from [python.org](https://www.python.org/downloads/windows/) or the Windows App Store, create a virtual environment, then use the same `pip` command shown above.
**Use Python Virtual Environments** - For Mac, Windows, and Linux, it's a best practice to use a Python Virtual Environment to isolate python packages and dependencies to reduce potential conflicts or errors, [more on creating a Python Virtual Environment](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/).
@@ -54,6 +59,8 @@ Store authentication uses [OAuth 2.0](https://auth0.com/intro-to-iam/what-is-oau
#### 2. Configure Theme Kit
`ntk` reads its connection settings from two places: command flags (`--apikey`, `--store`, `--theme_id`) and the `config.yml` file in your theme directory. You do not need to create `config.yml` by hand — `ntk checkout` and `ntk init` write it for you, and after that commands run without flags:
+Store values are normalized to an absolute HTTPS origin. A bare hostname or `http://` value becomes `https://`; values containing a path, credentials, query string, fragment, or unsupported scheme fail immediately.
+
```yaml title="config.yml (written by ntk checkout / ntk init)"
development:
apikey:
@@ -96,6 +103,8 @@ With the package installed, you can now use the commands inside your theme direc
| `ntk push` | Push current theme state to store |
| `ntk watch` | Watch for local changes and automatically push changes to store |
| `ntk sass` | Process sass to css, see [Sass Processing](#sass-processing) |
+| `ntk validate` | Validate theme files locally or against the store |
+| `ntk capture` | Capture deterministic desktop and mobile PNGs |
#### Browse Store Themes
@@ -153,7 +162,7 @@ On success, `ntk init` logs the new theme ID and name, and persists the theme ID
To sync files between your local directory and the store, use `ntk push` to upload and `ntk pull` to download. Both upload or download the whole theme by default, and both accept file paths as positional arguments to limit the operation to specific files.
-File paths are relative to the theme root. `ntk push` only uploads files inside the theme directories (`assets`, `checkout`, `configs`, `layouts`, `locales`, `partials`, `sass`, `templates`) with valid theme file extensions — a path outside of them is skipped silently, not reported as an error.
+File paths are relative to the theme root. `ntk push` only uploads files inside the theme directories (`assets`, `checkout`, `configs`, `layouts`, `locales`, `partials`, `sass`, `templates`) with valid theme file extensions. Explicit unsupported or missing paths are reported as rejected and make the command fail.
@@ -196,6 +205,8 @@ ntk watch
On start, `ntk watch` logs the store, theme ID, a preview-theme URL, and the directory it is watching. Press `Ctrl + C` to stop.
+Opening a plain storefront URL does not leave a pinned preview session. Use the visible preview indicator's **Exit preview** link or open `/?deactivate-theme=true`.
+
Deletes sync too — deleting a local file while `ntk watch` is running deletes that file from the theme on the store.
@@ -204,6 +215,36 @@ Deletes sync too — deleting a local file while `ntk watch` is running deletes
`ntk watch` watches the current directory tree (subdirectories included) and only uploads files with valid theme extensions. It does not accept file arguments. To scope changes to specific files, run `ntk push` with file paths instead.
+#### Validate Before Upload
+
+Local validation checks supported paths, JSON syntax, template block balance, and unsafe custom-product inheritance. It does not claim to prove a complete runtime render.
+
+```bash
+ntk validate templates/catalogue/product.subscription.html configs/settings.json
+ntk validate --server templates/catalogue/product.subscription.html
+```
+
+`--server` submits locally valid text templates to the store validator without saving. It requires the store, API key, and theme ID from flags or `config.yml`.
+
+#### Capture Desktop and Mobile Evidence
+
+With the capture extra and Chromium installed, generate real rendered PNGs at the fixed 1440px desktop and 390px mobile widths:
+
+```bash
+ntk capture --url="/?preview_theme=&skip_cache=1" \
+ --output=qa-output --viewports=desktop,mobile --json --no-progress
+```
+
+Capture waits for network idle, web fonts, lazy content, and images. DOM measurements are useful diagnostics but are not a substitute for these visual artifacts.
+
+#### Automation Contract
+
+Finite commands accept `--json`, `--quiet`, and `--no-progress`. JSON mode writes exactly one schema-versioned result to stdout, keeps diagnostics on stderr, disables interactive progress, and reports file outcomes individually. Authentication, connection, validation, rejection, and partial-transfer failures return a non-zero exit status.
+
+```json
+{"schema_version":"1","command":"push","ok":true,"count":1,"results":[{"path":"templates/index.html","status":"uploaded"}]}
+```
+
#### Sass Processing
Theme kit includes support for Sass processing via [Python Libsass](https://sass.github.io/libsass-python/). Sass processing includes support for variables, imports, nesting, mixins, inheritance, custom functions, and more.