Develop and publish Sites

This guide is for external developers and agencies. You develop a website, shop, or portal in a local project directory and publish the Site in the Sites catalog. You do not need access to a customer Workspace, Git, or a CI environment.

Prerequisites

You need:

  • an invitation to the Publisher area,
  • a current nucli installation,
  • a local directory containing editable Sitegenerator sources.

A Site Package contains the complete sources, not build output. Build directories, node_modules, Git metadata, secrets, and local environment files are excluded.

Create the Publisher and Site

The operator invites you to the Publisher area and gives you its direct address, https://www.schukai.com/en/apps/workspace/sites/publisher. Open registration is disabled during the pilot, so the public catalog does not display a Publisher link. Redeem the invitation, sign in, and create a Publisher organization such as “Nordlicht Digital” on your first visit.

Create the Site next. Its entry contains the public name, category, optional public preview URL, and German and English summaries and descriptions. Both languages must be complete before you can submit a release for review. After saving, the Publisher area shows the Store Site ID used for CLI uploads.

Prepare the local project

Initialize the package metadata in the project directory:

bash
nucli sites package init . \
  --publisher nordlicht \
  --site commerce \
  --license MIT

nucli stores the stable package ID and coordinates in .nucli/site-package.json with restrictive permissions. This file is not included in the Site Package. Keep it with the project so later versions use the same package ID.

Validate the sources before building a version:

bash
nucli sites package validate .

Dependencies require exact entries in the lock file. Version ranges and latest are rejected. Hidden paths, symbolic links, colliding file names, and oversized files also fail validation.

Build the Site Package

Create a semantically versioned ZIP file:

bash
nucli sites package build . \
  --version 1.0.0 \
  --output nordlicht-commerce-1.0.0.zip

The command creates the manifest, calculates file digests, and validates the resulting archive. You can validate an existing ZIP again:

bash
nucli sites package validate nordlicht-commerce-1.0.0.zip

Upload the draft

Create a short-lived nucli upload token for the Site. Site Packages are always uploaded with nucli; Git and CI are not required. Pass the token only through standard input:

bash
nucli --host https://www.schukai.com/apps/workspace/sites \
  sites store upload nordlicht-commerce-1.0.0.zip \
  --site-id <store-site-id> \
  --token-stdin

Pipe the token into standard input and then close the input stream. Never put the token in the command line, project, ZIP file, or logs. The Store creates a private draft from the upload.

Submit the version

Confirm that the German and English metadata is complete. Then open the draft in the Publisher area and select Submit for review. The version remains private during moderation. After approval, it appears in the public catalog and can be installed into an empty Workspace.

A published version is immutable. Corrections require a new semantic version and a new Site Package.

Use Git and CI optionally

Git can support source history, collaboration, and reviews. A CI pipeline can automate the same build and upload workflow. Both are optional; the local nucli and browser workflow remains fully supported.

A public repository may contain Sitegenerator sources. Publisher tokens, Workspace sessions, local environment files, build output, and exported ZIP files must remain outside the repository.

Export from a Workspace

If you already develop inside a Workspace and have the site:packages:export permission, you can continue to export its Development sources on the server:

bash
nucli --tenant <tenant> sites package export <site-id> \
  --publisher nordlicht \
  --site commerce \
  --version 1.0.0 \
  --license MIT \
  --output nordlicht-commerce-1.0.0.zip

This convenience path is not required for external Publishers.

Export a complete shop theme

For Site Package V2, also select the required business templates and branding resources. The Sites tab and this command list the available components:

bash
nucli --tenant <tenant> sites package candidates <site-id>

The list returns 100 entries by default. Use --limit to request 1 to 200 entries per page. When the response includes nextCursor, pass it to the next request with --cursor <nextCursor>. The Sites tab provides a button to load more entries while preserving your selection.

Save the selection as a JSON array. Each entry contains a stable package-local key, its kind and the current resourceId. Branding components also declare a targetSlot that the importer maps to an existing destination profile.

json
[
  {"key": "invoice-de", "kind": "document", "resourceId": "<document-template-id>"},
  {"key": "order-mail-de", "kind": "mail", "resourceId": "<mail-template-id>"}
]

Add --components-file components.json to the export command. For the first V2 export, also supply --package-id <package-uuid>. This UUID is distinct from the Site ID and stays the same across package versions. An installed package's recorded identity can be reused.

Export reads current editable content, including subsequent changes. It supports snippets, document and mail templates, branding assets, fonts and themes. Language variants remain separate templates; Site translations remain under i18n. Static mail attachments retain filenames and media types. References to concrete operational documents or Storage objects block export instead of silently disappearing.

Use the placeholders and branding resolution provided by each renderer. URLs and IDs written directly into HTML or Lua remain unchanged; export does not rewrite arbitrary source code for another workspace.

In a local project, the component catalog lives at theme-components/components.json. The shared package validator checks referenced files and dependencies. V2 requires the sitepackage.components.v2 server capability. Existing V1 packages containing only Sitegenerator sources remain supported.

New invoice bundles require static HTML so their PDFs remain identical during recovery. Before PDF generation, the renderer rejects scripts, inline event handlers, JavaScript URLs, embedded active documents, and automatic navigation. Use absolute URLs or internal fragment references for navigation links. Relative image and font paths remain supported under the existing asset contract. Check the rendered invoice before distributing the theme; package validation does not replace this check.

V3 profile bindings and footers

Packages containing legacy BrandLogo resources, custom HTML footers, or multiple profile bindings use V3 and require sitepackage.theme-components.v3. The catalog contains components, profileSlots, and bindings. These capabilities cannot be exported losslessly as V2.

Preview current bindings in the Sites tab or with nucli sites package profile-graph <site-id> --components-file components.json. The CLI returns an API envelope containing meta and data. Save only the graph object in data, for example by piping the result through jq '.data' > bindings.json. Review that object and pass it to export with --bindings-file bindings.json. Its fingerprint binds export to the reviewed state; changed bindings require a new preview. Profile names and operational settings are not copied into portable profiles.

For import, profileTargets and footerTargets map declared slots to existing destination resources. decisions contains the component and binding decisions shown in the plan. Use --theme-options-file options.json instead of --components-file for larger V3 options. Existing selection files remain limited to 64 KiB; new graph and options files are limited to 512 KiB. Only regular files are accepted; symlinks, FIFOs, and devices are rejected.

Footer components reference HTML sources for document or mail. Each channel requires a neutral variant with an empty locale. Resolution selects the exact locale, base language, then neutral variant. Sources are limited to 64 KiB and rendered footers to 1 MiB.

All footer sources together are limited to 100 MiB. Every reference counts, including language variants sharing one file. Component and profile metadata are also limited to 100 MiB per validation step.

For example, field "Sender.LegalName" emits the resolved legal name, label supplies its label, and has checks whether a field has a value. Tables, columns, and conditions allow custom arrangements within the permitted HTML/CSS subset. Field names must be known literals. Loops, recursive partials, scripts, and external includes are rejected. Required fields must appear as visible output. Presentation is stored under FooterDefinition.TemplatePolicy.presentation; content and compliance policies are preserved.

Custom document templates place the footer through {{.Branding.Footer.HTML}}. Full-layout mail templates use {{.footerHTML}} in HTML and {{.footerText}} in plain text. The renderer supplies these values; caller-provided mail data cannot replace them. Plain text retains the standard content. A later footer presentation failure falls back to the complete standard footer.

Inside .Pages, document templates access the footer through {{$.Branding.Footer.HTML}}. Multi-page templates use the existing data-layout-role, data-layout-page-number, and data-layout-page-total attributes; measurement templates use data-layout-measurement and data-layout-measure-prototype. Each page or supported measurement prototype may contain the fragment at most once. The visible document must contain at least one footer. Indirect access to reserved footer fields through aliases, index, or pipelines is rejected.

Preflight detects direct hiding and invisible HTML containers, but does not compute the general CSS cascade. Use document or mail previews to check how the footer interacts with the surrounding template's stylesheets.

Import preflight also checks existing profiles sharing the footer. It processes at most 500 footer definitions, 500 profiles and 500 effective active templates per channel, and 2,000 combinations of profile, language, and document type overall. Template sources are limited to 100 MiB per channel. Exceeding a limit blocks the import.

The technical cleanup receipt is limited to 4 MiB. Long package paths and many existing empty directories can reach this limit even when individual files are small. Import checks this budget before preparation and before switching sources.

Static attachments are limited to 32 entries and 25 MiB of decoded content per mail. All mail components together may contain at most 100 MiB of decoded attachments; each file remains limited to 10 MiB. Every reference counts, including repeated references to the same package file.

Verify the result

The publication is prepared when:

  • nucli sites package validate finishes successfully,
  • the upload appears as a private draft in the Publisher area,
  • the draft coordinate and version match the local project.

After moderation, the public catalog displays the Site and its approved version.

First-version limits

The pilot supports free public Sites. Sales, billing, payouts, automatic updates for installed Sites, open Publisher registration, and installation into non-empty Sites are outside this contract.