<!--
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>

This file is part of a Moko Consulting project.

SPDX-License-Identifier: GPL-3.0-or-later

# FILE INFORMATION
DEFGROUP: MokoOnyx.GitHub
INGROUP: MokoOnyx
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
PATH: /.github/CLAUDE.md
VERSION: 01.00.05
BRIEF: Claude Code custom instructions for MokoOnyx template
-->

# MokoOnyx — Claude Code Instructions

## What This Repo Is

This is a **Moko Consulting MokoWaaS** (Joomla) repository governed by [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards). All coding standards, workflows, and policies are defined there and enforced here via bulk sync.

Repository URL: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
Extension name: **MokoOnyx**
Extension type: **template** (`mokoonyx`)
Platform: **Joomla 5.x / 6.x / MokoWaaS**
Successor to: **MokoCassiopeia** (renamed in v01.00.00)

---

## Primary Language

**PHP** (≥ 8.1) is the primary language for this Joomla template. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`.

---

## File Header — Always Required on New Files

Every new file needs a copyright header as its first content.

**PHP:**
```php
<?php
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
 *
 * This file is part of a Moko Consulting project.
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * FILE INFORMATION
 * DEFGROUP: MokoOnyx.Template
 * INGROUP: MokoOnyx
 * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
 * PATH: /path/to/file.php
 * VERSION: XX.YY.ZZ
 * BRIEF: One-line description of purpose
 */

defined('_JEXEC') or die;
```

**Markdown:**
```markdown
<!--
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>

This file is part of a Moko Consulting project.

SPDX-License-Identifier: GPL-3.0-or-later

# FILE INFORMATION
DEFGROUP: MokoOnyx.Documentation
INGROUP: MokoOnyx
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
PATH: /docs/file.md
VERSION: XX.YY.ZZ
BRIEF: One-line description
-->
```

**YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. JSON files are exempt.

---

## Version Management

**`README.md` is the single source of truth for the repository version.**

- **Patch version is auto-bumped by the release workflow** — `release.yml` reads the current version from `README.md`, increments the patch (`XX.YY.ZZ` → `XX.YY.(ZZ+1)`), updates `README.md`, `templateDetails.xml`, and the matching channel in `updates.xml`, commits, pushes, then builds the ZIP. Manual bumping is no longer required.
- The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references.
- Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.00.05`).
- Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only.

### Joomla Version Alignment

The version in `README.md` **must always match** the `<version>` tag in `templateDetails.xml` and the matching channel entry in `updates.xml`. The release workflow updates all three automatically.

### Multi-Channel updates.xml

`updates.xml` contains separate `<update>` blocks per stability channel (development, alpha, beta, rc, stable). Each release workflow only modifies its own channel using targeted Python regex replacement — other channels are preserved untouched. Joomla filters by the user's "Minimum Stability" setting.

```xml
<updates>
  <!-- 1. DEVELOPMENT --> <update>...<tag>development</tag>...</update>
  <!-- 2. ALPHA -->       <update>...<tag>alpha</tag>...</update>
  <!-- 3. BETA -->        <update>...<tag>beta</tag>...</update>
  <!-- 4. RC -->          <update>...<tag>rc</tag>...</update>
  <!-- 5. STABLE -->      <update>...<tag>stable</tag>...</update>
</updates>
```

**Key rules:**
- SHA-256 must be raw hex (no `sha256:` prefix)
- Version format must be `XX.YY.ZZ`, not tag names like `v01`
- Download URLs must point to Gitea (not GitHub) for all pre-release channels
- **Always push updates.xml to main** — Joomla sites read from main, not dev

---

## MokoCassiopeia Migration (v01.x only)

MokoOnyx v01.x includes a migration system for MokoCassiopeia users:

- **`helper/migrate.php`** — runs on first page load via `index.php` bootstrap
- Creates `.migrated` marker file so it only runs once
- Copies template style params from MokoCassiopeia → MokoOnyx
- Creates matching styles, copies user files, redirects update server
- **Joomla 6 does NOT call `<scriptfile>` for templates** — that's why migration runs from `index.php` instead of `script.php`
- The migration script will be **removed in v02.00.00** (see ROADMAP.md)

---

## Template Structure

```
MokoOnyx/
├── src/
│   ├── templateDetails.xml    # Joomla installer manifest
│   ├── script.php             # Install/update script (limited in Joomla 6 for templates)
│   ├── index.php              # Main template file (includes migration bootstrap)
│   ├── helper/
│   │   ├── migrate.php        # MokoCassiopeia → MokoOnyx migration (v01.x)
│   │   ├── favicon.php        # Favicon generator
│   │   └── minify.php         # Asset minification
│   ├── language/              # Language INI files (en-GB, en-US)
│   ├── media/                 # CSS, JS, images, vendor assets
│   └── templates/             # Custom CSS palette starters, theme test
├── updates.xml                # Update server manifest (root — required)
├── .gitea/workflows/          # Gitea Actions workflows
├── docs/                      # Documentation
├── README.md                  # Version source of truth
├── CHANGELOG.md
└── LICENSE
```

---

## Gitea Actions — Token Usage

Every workflow must use **`secrets.GA_TOKEN`** (the org-level Personal Access Token).

```yaml
# ✅ Correct
- uses: actions/checkout@v4
  with:
    token: ${{ secrets.GA_TOKEN }}
```

```yaml
# ❌ Wrong
token: ${{ github.token }}
token: ${{ secrets.GITHUB_TOKEN }}
```

Note: Workflows are in `.gitea/workflows/` (not `.github/workflows/`).

---

## Naming Conventions

| Context | Convention | Example |
|---------|-----------|---------|
| PHP class | `PascalCase` | `MyController` |
| PHP method / function | `camelCase` | `getItems()` |
| PHP variable | `$snake_case` | `$item_id` |
| PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` |
| PHP class file | `PascalCase.php` | `ItemModel.php` |
| YAML workflow | `kebab-case.yml` | `release.yml` |
| Markdown doc | `kebab-case.md` | `installation-guide.md` |

---

## Commit Messages

Format: `<type>(<scope>): <subject>` — imperative, lower-case subject, no trailing period.

Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build`

---

## Branch Naming

Format: `<prefix>/<MAJOR.MINOR.PATCH>[/description]`

Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/`

---

## Keeping Documentation Current

| Change type | Documentation to update |
|-------------|------------------------|
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
| New or changed templateDetails.xml | Release workflow auto-bumps version across README.md, templateDetails.xml, and updates.xml |
| New release | Trigger `release.yml` — auto-bumps patch, builds ZIP, updates matching channel in `updates.xml` |
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
| **Every release** | **Patch auto-bumped** by `release.yml` — no manual version bump needed |

---

## Key Constraints

- Never commit directly to `main` — all changes go via PR, squash-merged
- Never skip the FILE INFORMATION block on a new file
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
- Never hardcode version numbers in body text — update `README.md` and let automation propagate
- Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows — always use `secrets.GA_TOKEN`
- Never let `templateDetails.xml` version, `updates.xml` version, and `README.md` version go out of sync
- Always push `updates.xml` to main after updating on dev (Joomla reads from main)
- Always update documentation when changing MokoStandards-API or MokoStandards repos
