Child Template Setup

A child template inherits all layouts, module positions, and compiled CSS from the jcrafts parent template. It adds only customer-specific branding — colors, fonts, and optional component overrides — without duplicating any parent code.

  1. Overview
  2. Setup
  3. Design System Preview
  4. Component Overrides
  5. Custom Components

How Joomla Parent/Child Templates Work

The jcrafts template has <inheritable>1</inheritable> in its manifest. A child template declares:

<extension type="template" client="site">
  <name>jcrafts_customer</name>
  <parent>jcrafts</parent>
  ...
</extension>

Joomla then:

  • Serves all PHP files from the parent unless the child provides its own override.
  • Loads parent CSS and JS assets automatically.
  • Loads user.css from the child's media directory (via the template.user asset already defined in the parent's joomla.asset.json) — this is where customer branding is applied.

Two levels of customization

Level What you change Build step needed?
CSS override Write user.css directly with CSS custom property overrides No
Token rebuild Replace brand.tokens, run Terrazzo + Sass to regenerate user.css Yes (npm)

Step-by-Step Repository Setup

Use the Quick Start path below to bootstrap a new repo from the scaffold in under a minute. The Manual Setup section further down explains each file in detail.

Quick Start (scaffold)

  1. Create a new Forgejo repo named tmpl_jcrafts_<customer> and clone it.
  2. Create .npmrc in the repo root (required before npm install can reach the private registry):
# .npmrc
@simplysmart-it:registry=https://git.simplysmart-it.de/api/packages/JCrafts/npm/
//git.simplysmart-it.de/api/packages/JCrafts/npm/:_authToken=${NPM_TOKEN}

Set NPM_TOKEN as an environment variable or Forgejo secret. Never commit a real token.

How to create and set NPM_TOKEN

1. Create a Forgejo access token

In Forgejo: User Settings → Applications → Access Tokens → Generate Token. Enable the read:package permission (read-only is enough for npm install). Copy the generated value — it is shown only once.

2a. Local development

Add the token to your shell profile (~/.zshrc or ~/.bashrc). The project's .npmrc reads it via $ { NPM_TOKEN} at runtime — the actual token is never written into any .npmrc file in the repo:

# Add to ~/.zshrc or ~/.bashrc (not to .npmrc)
export NPM_TOKEN=your_token_here

After saving, reload your shell (source ~/.zshrc) or open a new terminal. Run npm install — it picks up the token automatically.

2b. Forgejo Actions (CI/CD)

In Forgejo: Repository → Settings → Actions → Secrets → Add Secret. Name: NPM_TOKEN, Value: the token from step 1. In your workflow YAML it is available as $ — the .npmrc reads it automatically via _authToken=$ { NPM_TOKEN}.

- name: Install dependencies
  run: npm install
  env:
    NPM_TOKEN: $
  1. Install the parent package and run the init script with your customer slug (lowercase letters and underscores only):
npm install @simplysmart-it/tmpl-jcrafts
npx jcrafts-init acme

The script copies all scaffold files, substitutes jcrafts_acme / Acme\Template\JCrafts / tmpl-jcrafts-acme throughout, and renames the dotfile templates.

  1. Edit tokens/brand.tokens — swap the color hue references (e.g. { base.color.blue.*} → your customer's palette) and update font families.
  2. Build:
npm run build

This generates media/css/user.css. Install both the parent and child templates in Joomla, activate the child, and the site uses the customer brand colors.


Manual Setup (reference)

Follow these steps if you want to set up each file by hand or understand what the scaffold contains.

1. Create a new repository

Name it tmpl_jcrafts_<customer> and initialise it in Forgejo.

2. Configure the npm registry

Create .npmrc in the repo root. The _authToken line intentionally omits https::

# .npmrc
@simplysmart-it:registry=https://git.simplysmart-it.de/api/packages/SimplySmart-IT/npm/
//git.simplysmart-it.de/api/packages/SimplySmart-IT/npm/:_authToken=${NPM_TOKEN}

Set NPM_TOKEN as an environment variable or Forgejo secret — see the Quick Start section above for step-by-step instructions. Never commit a real token.

3. Install the parent package

npm install @simplysmart-it/tmpl-jcrafts

4. Copy the brand token starter

mkdir -p tokens
cp node_modules/@simplysmart-it/tmpl-jcrafts/scaffold/tokens/brand.tokens tokens/brand.tokens

Edit tokens/brand.tokens — change the color references (e.g. { base.color.blue.*} → a different hue) and font family values to match the customer brand.

5. Create the source directory structure

mkdir -p src/templates/jcrafts_customer
mkdir -p src/media/templates/site/jcrafts_customer/scss
mkdir -p src/media/templates/site/jcrafts_customer/css
mkdir -p src/media/templates/site/jcrafts_customer/fonts

6. Create user.scss

This file imports the parent's compiled token CSS and adds any additional overrides:

// src/media/templates/site/jcrafts_customer/scss/user.scss
// Import parent token CSS custom properties (compiled by tokens:build step)
@use 'node_modules/@simplysmart-it/tmpl-jcrafts/src/media/templates/site/jcrafts/scss/tokens/abstracts/ds-tokens' as *;

// Custom fonts — run `npm run grab-fonts` first, then uncomment and adapt:
// @use '@simplysmart-it/tmpl-jcrafts/src/media/templates/site/jcrafts/scss/abstracts/fontface' as fontface;
// @layer base {
//   @include fontface.font("public-sans", "Public Sans", "normal-400-latin", 400, normal);
// }

// Any additional component overrides go here

7. Add build scripts and config to package.json

The config block drives all script paths — only the slug in the config needs to change per customer:

{
  "config": {
    "build": {
      "extension": "build/tmp",
      "media": "build/tmp/media",
      "zipname": "jcrafts_customer"
    },
    "dev": {
      "extension": "src/templates/jcrafts_customer",
      "media": "src/media/templates/site/jcrafts_customer"
    }
  },
  "scripts": {
    "tokens:build": "BRAND_TOKENS_PATH=./tokens/brand.tokens npx tz build --config node_modules/@simplysmart-it/tmpl-jcrafts/design-system/terrazzo.config.mjs",
    "sass:compile": "sass --no-source-map --style=expanded --update --load-path=node_modules ./$npm_package_config_dev_media/scss:./$npm_package_config_build_media/css",
    "css:prefix": "postcss --use autoprefixer -b 'defaults' --no-map --replace ./$npm_package_config_build_media/css/*.css",
    "css:minify": "cleancss --output ./$npm_package_config_build_media/css/ --batch --batch-suffix \".min\" \"./$npm_package_config_build_media/css/*.css\"",
    "compile": "npm run tokens:build && npm run sass:compile && npm run css:prefix && npm run css:minify",
    "build:prod": "npm run compile && node build/SetupExtPackage.mjs && cd build/tmp && npm pack"
  }
}

7a. Download custom fonts (optional)

If the customer uses Google Fonts other than the parent template's defaults, configure and download them:

  1. Create fonts.json at the repo root listing the desired families:
[
  { "family": "Roboto", "weights": [400, 700] }
]
  1. Run the download script (requires the parent package to be installed):
npm run grab-fonts

Fonts are downloaded to src/media/templates/site/jcrafts_customer/fonts/ and the script prints the exact @include fontface.font(…) lines to add to user.scss.

8. Create templateDetails.xml

Place this file at src/templates/jcrafts_customer/templateDetails.xml:

<?xml version="1.0" encoding="utf-8"?>
<extension type="template" client="site">
  <name>jcrafts_customer</name>
  <version>1.0.0</version>
  <parent>jcrafts</parent>
  <namespace path="src">Customer\Template\JCrafts</namespace>
  <files folder="templates/jcrafts_customer">
    <!-- PHP override files go here; leave empty if using no overrides -->
  </files>
  <media destination="templates/site/jcrafts_customer" folder="media">
    <folder>css</folder>
    <folder>fonts</folder>
  </media>
</extension>

9. Run the build

npm run build:prod

This generates src/media/templates/site/jcrafts_customer/css/user.css and packages everything into build/jcrafts_customer-1.0.0.zip. Install both the parent template and this child template in Joomla, activate the child, and the site will use the customer brand colors.

Previewing Your Brand in the Design System

The parent package includes the full 11ty design system. You can run it locally with your brand tokens applied so you see every component in the customer's colors before touching a Joomla instance.

1. Install the design system dependencies

cd node_modules/@simplysmart-it/tmpl-jcrafts/design-system
npm install
cd -

2. Build tokens with your brand override

BRAND_TOKENS_PATH=$(pwd)/tokens/brand.tokens \
  npx --prefix node_modules/@simplysmart-it/tmpl-jcrafts/design-system \
  tz build \
  --config node_modules/@simplysmart-it/tmpl-jcrafts/design-system/terrazzo.config.mjs

3. Start the design system dev server

npm --prefix node_modules/@simplysmart-it/tmpl-jcrafts/design-system run start

Open localhost:8080 — you'll see the full component library rendered with your customer's primary, secondary, and accent colors.

Tip: Add a convenience script to your child template's package.json:

{
  "scripts": {
    "design-system": "BRAND_TOKENS_PATH=$(pwd)/tokens/brand.tokens npm --prefix node_modules/@simplysmart-it/tmpl-jcrafts/design-system run start"
  }
}

Then simply run npm run design-system from the child template root.

Overriding Individual Components

For structural changes beyond colors and fonts — different button shapes, altered card layout, custom navigation — copy the relevant SCSS file from the parent package and override it in the child template.

SCSS component override

  1. Find the component SCSS in node_modules/@simplysmart-it/tmpl-jcrafts/src/media/templates/site/jcrafts/scss/components/
  2. Copy it to src/media/scss/components/ in your child repo
  3. Import it in user.scss after the parent's token import so your rules take precedence
// user.scss
@use 'node_modules/@simplysmart-it/tmpl-jcrafts/src/media/templates/site/jcrafts/scss/tokens/abstracts/ds-tokens' as *;

// Component override: custom button shape
@use 'components/button' as *;

PHP / module template override

To override a Joomla module or component layout, mirror the path from the parent's html/ folder in the child template. For example, to override the menu output:

# In the child Joomla template directory:
mkdir -p html/mod_menu
cp /path/to/jcrafts/html/mod_menu/default.php html/mod_menu/default.php
# Edit html/mod_menu/default.php as needed

Joomla's template override system automatically uses the child's file when it exists.

Injecting Custom Components into the Design System

Child templates can add their own components to the design system explorer alongside the parent components. No changes to the parent package are needed — the design system discovers child components at runtime via a symlink.

How it works

Two environment variables control the injection:

Variable Required Default Purpose
CHILD_COMPONENTS_PATH Yes Path to the child template's component directory
CHILD_COMPONENTS_LABEL No _child Group name shown in the sidebar; also used as the symlink directory name

Before each build, the design system creates a symlink src/_includes/components/<label> pointing to your component directory. The existing component discovery globs follow symlinks, so no other config changes are needed.

1. Component file structure

Each component needs at minimum a .config.js (for the explorer) and a .njk (for the preview). A .webc file is optional but required if the component is used as a WebC element.

src/components/
└── MyWidget/
    ├── my-widget.config.js   # required — name, label, variants
    ├── my-widget.njk         # required — preview template
    └── my-widget.webc        # optional — WebC component definition

2. Minimal .config.js

module.exports = {
  name: 'my-widget',
  label: 'My Widget',
  variants: [
    { name: 'default', label: 'Default' }
  ]
};

3. Add the script to your child's package.json

Extend the design-system script with the two new variables:

{
  "scripts": {
    "design-system": "BRAND_TOKENS_PATH=$(pwd)/tokens/brand.tokens CHILD_COMPONENTS_PATH=$(pwd)/src/components CHILD_COMPONENTS_LABEL=Acme npm --prefix node_modules/@simplysmart-it/tmpl-jcrafts/design-system run start"
  }
}

Then run npm run design-system — your components appear in the sidebar under the label you chose, alongside all parent components, rendered in your brand colors.

Notes

  • The symlink is created fresh before each build and is not cleaned up on exit (it is listed in the parent's .gitignore so it won't be committed accidentally).
  • If you use a custom CHILD_COMPONENTS_LABEL other than _child, add it to your child repo's .gitignore under the design-system path: node_modules/@simplysmart-it/tmpl-jcrafts/design-system/src/_includes/components/Acme
  • File changes inside CHILD_COMPONENTS_PATH trigger live reload during npm run start.