Testing, import and updates
Validate a package and release it while preserving customer data.
ZIP import in the admin panel
In the admin panel's templates section, choose ZIP import. This requires the templates.import permission. A valid package becomes a draft with the testing status; uploading does not publish the theme or change existing customer pages.
ZIP package structure
An admin import package contains archive.json, GS Loom sources in theme/, and additional files in assets/ when needed. Put these directly at the ZIP root or inside one enclosing folder:
noir-explorer/
├── archive.json
├── theme/
│ ├── loom.json
│ ├── layout/
│ ├── templates/
│ ├── sections/
│ ├── blocks/
│ ├── config/
│ └── locales/
└── assets/
└── blog.cssThe theme/ directory must contain a complete, valid theme, including loom.json. This tree illustrates the archive layout rather than every theme file. Do not add another enclosing folder or unrelated files such as .DS_Store and __MACOSX.
What archive.json contains
archive.json describes the archive format and GrowSite product configuration. Place it next to theme/. It does not replace theme/loom.json or section and block schema files.
Example for Noir Explorer:
{
"format": "gs-loom-archive",
"version": 1,
"configuration": {
"key": "noir-explorer",
"name": "Noir Explorer",
"version": "1.0.0",
"tier": "basic",
"supports_blog": true,
"price_cents": 0,
"default_settings": {},
"schema": {}
}
}| Field | Meaning and requirements |
|---|---|
format |
Required: gs-loom-archive. |
version |
Archive format version: 1. |
configuration.key |
Required; must match the key in theme/loom.json. Use 1–40 characters: a lowercase letter followed by lowercase letters, digits or hyphens. |
configuration.name |
Required product name, up to 200 characters. |
configuration.version |
Required product version, up to 30 characters. Keep it aligned with loom.json when preparing a release. |
configuration.tier |
Required: basic, plus or premium. |
configuration.supports_blog |
Required boolean, true or false, matching the theme's blog support. |
configuration.price_cents |
Required integer price in cents, from 0 to 10000000. Use 0 for a free theme. |
configuration.default_settings |
Required default product settings; use {} for no additional values. |
configuration.schema |
Optional product schema configuration; omit it or use {}. This does not replace the theme's .schema.json files. |
Preparing packages and troubleshooting
Start with the GrowSite Skeleton ZIP, which includes archive.json. The Launch Theme ZIP contains sources for local development: to import it through the panel, move the theme directory's contents into theme/ and add a valid archive.json beside it.
| Message | Action |
|---|---|
Unsupported archive path |
Check the directory layout and ensure there is exactly one archive.json at the package root. The importer uses this file to detect an enclosing folder. |
Configuration does not match the Loom manifest |
Make configuration.key match the key in theme/loom.json. |
GS Loom validation failed |
Fix the theme sources according to the compiler's error details. |
Duplicate archive entry |
Remove duplicate paths, including paths repeated with both / and Windows separators. |
The upload limit is 24 MiB. An archive may contain up to 5000 entries, up to 48,000,000 uncompressed bytes in total and up to 25,000,000 bytes per file. Symbolic links and . or .. path segments are rejected.
Import a new package
Run these commands from the repository root, using your real directory path:
npm run loom:import -- /absolute/path/launch-theme
npm run themes:build
npm run themes:check
npm run loom:test
npm run themes:test
npm run build:customer
npm run build:rendererThen synchronize products from the api directory:
php artisan themes:sync --activateImport refuses an existing key. themes:build updates both the Loom registry and catalog. themes:check detects stale generated data. Synchronization activates new products with --activate, preserves existing product prices/status and does not overwrite customer page content.
Source import from the terminal requires repository access. ZIP import in the panel is available to authorized administrators; it is not a public marketplace submission workflow.
Update a theme
Increase the manifest version, for example from 1.0.0 to 1.0.1:
npm run loom:update -- /absolute/path/launch-theme
npm run themes:build
npm run themes:check
npm run build:customer
npm run build:rendererThe update command requires a higher numeric version and refuses removed existing sections, blocks, page templates or settings, and incompatible setting type changes. This is a compatibility guard, not a visual regression guarantee. Changing markup, CSS, defaults or targeting may still alter a saved page.
Directly editing installed source and running themes:build bypasses the import/update compatibility gate. Use the update command for distributed package releases. Preserve a source revision and deployment artifact so a failed release can be rolled back together with its generated registries.
Validation checklist
| Area | Verify |
|---|---|
| Defaults | New instance controls match the template; opening does not save |
| Persistence | Empty string, zero and false survive save/reload |
| Blocks | Add, reorder, delete; static block remains fixed |
| Editor | Inline text, card styling and schema changes agree |
| Sources | Site/page values and fallback are correct |
| Languages | Storefront and schema dictionaries work independently |
| Rendering | Preview and public page match; no console errors |
| Responsive | Narrow mobile, desktop, long text, keyboard access |
| Migration | Existing customer documents still render correctly |
Additional renderer tests from the repository root:
node --test scripts/paylio-renderer.test.mjs scripts/theme-renderer.test.mjsAPI validation tests, from api:
php artisan test --compact --filter=loom_theme_settings
php artisan test --compact tests/Feature/LoomDocumentTest.phpDiagnose common failures
| Message or symptom | Action |
|---|---|
expected one schema |
Add exactly one valid schema to each section/block |
Unknown setting |
Correct the ID or declare it before storing a value |
Invalid range |
Check numeric default, min, max and positive step |
| Block missing in picker | Check targeting, private prefix and presets |
| Theme absent from catalog | Check catalog, home.json, build and API sync |
| Text shows a translation key | Check locale filename, nesting and default locale |
| Build says registry is stale | Run themes:build, review generated changes |
| Import says file unsupported | Remove nested folders, binaries or JavaScript |
Read the supported scope before extending a theme.