Default layout templates
Perastage can preload layout templates from library/default_layouts/.
Folder
Place template files in:
library/default_layouts/
The directory is resolved through ProjectUtils::GetDefaultLibraryPath("default_layouts"),
so packaged defaults can be copied to the user library fallback when needed.
File format
Preferred default layouts use the portable .pslayout package format. A
.pslayout file is a ZIP archive with this versioned structure:
manifest.jsonlayout.jsonresources/layout_images/<content-addressed image files>
manifest.json declares format: "perastage-layout-package",
packageVersion: 1, the layout schema version, and the layout entry point.
layout.json contains exactly one layout template document using the existing
layout schema.
Legacy .json layout template files remain readable for compatibility, but new
exports no longer create standalone JSON templates. Default template files are
processed in deterministic alphabetical order. Invalid files are ignored;
Perastage continues with the remaining files.
If no valid templates are found, Perastage keeps the existing behavior and starts with the built-in empty layout.
Image portability
Portable .pslayout files must be self-contained. Export rewrites image element
metadata so both path and projectResource reference the packaged
resources/layout_images/ entry, and originalPath is omitted to avoid leaking
local source paths. Image payloads are content-addressed and deduplicated inside
the package. Layout package and project archive resource names are canonical
UTF-8 ZIP paths: they are relative, use / separators on every platform, and
reject backslashes, drive-qualified paths, absolute paths, and traversal. ZIP
directory entries are metadata and never count as packaged image payloads.
Validation first inspects raw local-header and central-directory names and
requires them to match byte-for-byte before wxWidgets can normalize them. It
then applies the existing canonical logical-path, duplicate, ambiguity, entry
count, and payload-size checks to the names exposed by the ZIP reader. Both
layers must succeed.
When a package is imported, Perastage materializes image files into owned runtime
storage, updates the runtime imagePath, preserves projectResourcePath, and
registers the bytes so later .pstg project saves can package the same images.
Legacy JSON image paths
Legacy imageViews[].path values still support:
- Absolute paths when the file exists on the current machine.
- Relative paths to the template file directory.
- Relative paths to app resources:
resources/<file>(for exampleresources/Perastage_logo.png).
Legacy JSON templates are not self-contained. Prefer recreating bundled defaults
as .pslayout packages when image portability is required.
Security restrictions
Portable package readers reject unsafe archive paths, including absolute paths,
empty entry names, backslash-separated names, . or .. traversal components,
duplicate critical entries, missing manifests, missing entry points, unsupported
package versions, invalid JSON, and image references outside
resources/layout_images/. Conservative entry count and payload size limits are
applied to avoid pathological packages.
Scope
Template loading is applied when:
- The user uses New Project.
- The active config has no stored
layouts_collectionyet (for example first launch with an empty config). - The stored
layouts_collectionvalue exists but is empty/invalid.
If a project already has stored layouts, template files are ignored.