# Authoring Conventions

This document defines the canonical record formats used across all files in `plugins/us-core/llms/`. The goal is a uniform shape that any LLM agent can parse predictably.

**Documentation set version**: tracks `us-core` plugin version (current: **8.45.2**).
Each generated file declares the source version in its front-matter.

---

## File header

Every `.md` file in `content/` begins with this block:

```markdown
---
title: <human-readable section title>
audience: content
source: us-core <version>
generated: <YYYY-MM-DD> by scripts/llms/build.php (or "manual")
---
```

`generated` says whether the file is auto-rendered, manually written, or hybrid (skeleton from script + manual overlay).

---

## Shortcode entry schema

Every shortcode is documented as a section with the following fields, in this order:

```markdown
### `us_btn` (config-id: `btn`)

**Category**: Basic
**Container**: no
**Public tag**: `[us_btn ...]`
**Source**: plugins/us-core/config/elements/btn.php

**Purpose**: <one sentence — when to use this shortcode>

**Parents**: <list of shortcodes this can be nested inside, or "any">
**Children**: <list of allowed child shortcodes, or "none" for leaf elements>

**Parameters**:

| Name | Type | Default | Group | Responsive | Show if | Notes |
|------|------|---------|-------|------------|---------|-------|
| `label` | text | `Click Me` | — | no | — | Button text. |
| `link` | link | `{"url":"#"}` | — | no | — | URL + target. |
| `style` | select | `1` | — | no | — | One of: `1`, `2`, `3`, `4`, `5`, `6`, `7`. |
| ... | | | | | | |

**Examples**:

```text
[us_btn label="Get started" link="url:%23pricing"]
```

**Notes** (optional):
- Anti-patterns, common pitfalls, version caveats.
```

Field meanings:

- **Category** — one of: `Containers`, `Basic`, `Interactive`, `Other`.
- **Container** — `yes` if the shortcode wraps children; `no` for leaf elements.
- **Public tag** — actual shortcode tag as used in `do_shortcode()`. Usually `us_` + config-id, except for `vc_*` tags (WPBakery-native) which keep their `vc_` prefix.
- **Source** — path to the config file in the repo (always relative from repo root).
- **Parents / Children** — derived from `as_child` / `as_parent` / `is_container` keys in the element config.
- **Parameters table** — flattened from the `params` array in the element config. Lists only element-specific parameters; the three shared parameter groups (Effects, Display Logic, Design) are documented in their own files (see below) and referenced via the "Common parameter groups included" line at the bottom of each shortcode record.
- **Context filter**: a param with a `context` allowlist (e.g. `'context' => array('header')` or `array('grid')`) that does not include `'shortcode'` is silently dropped — it is not editable via the shortcode tag. A param without `context` is considered shortcode-applicable by default. Example: `image` has 12+ params scoped to `'header'` for the Header Builder image element; none of them appear in this documentation set.
- **Excluded `type` values**: the following types are filtered out because they do not change shortcode behaviour:
  - `typography_options` — typography is configured globally via Theme Options, not per-shortcode
  - `heading` — visual separator in the builder UI, no value
  - `hidden` — internal helper field, not user-editable
  - `design_options` — CSS-emitting sub-controls (covered by the Design common group)
  - `wrapper_start` / `wrapper_end` — builder-UI wrapping markers, no shortcode attribute
  
  The same filter is applied to the four common-parameter group files: any rows of these types are dropped before the table is rendered, and the keys do not count toward the "≥ half present" inclusion threshold.
- **Type** reflects the `type` key (`text`, `select`, `color`, `link`, `icon`, `upload`, `switch`, `radio`, `slider`, `imgradio`, `autocomplete`, `group`).
- **Show if** documents conditional visibility from the `show_if` key. An array on the right-hand side (e.g. `conditions_operator != [always, never]`) means "any of these values".

---

## Common parameter groups

The element configs in `plugins/us-core/config/elements/*.php` end with three shared parameter packs that almost every shortcode mixes in verbatim. Documenting them inside every shortcode would balloon `shortcodes.md` by ~50 rows per entry, so each group is documented once in its own file:

| Group | File | Source config | Generation |
|-------|------|---------------|------------|
| Effects | [element-effects.md](content/element-effects.md) | `plugins/us-core/config/elements_effect_options.php` | auto (`common-params.php`) |
| Display Logic | [element-display-logic.md](content/element-display-logic.md) | `plugins/us-core/config/elements_conditional_options.php` | auto (`common-params.php`) |
| Design | [element-design.md](content/element-design.md) | `plugins/us-core/config/elements_design_options.php` | **manual** |

The Design file is hand-written because its central `css` parameter is a nested `design_options` config (~80 CSS sub-properties across 11 categories) that needs prose explanation of JSON encoding, breakpoint keys, the property whitelist, and anti-patterns — none of which collapse cleanly into a flat param table. Edit `content/element-design.md` directly; the build script does not touch it.

A fourth group (Hover Effect, `elements_hover_options.php`) exists in the us-core configs but is not exposed via shortcodes in the current build, so it has no dedicated documentation file.

A shortcode is considered to **include** a group when a clear majority (≥ half) of that group's parameter keys are present in its config. The generator detects this automatically and adds a `**Common parameter groups included**: [Effects], [Design], …` line at the bottom of the shortcode record.

---

## Per-site (dynamic) option values

Some shortcode and theme-option parameters expose **per-site option lists** that are configured in Theme Options and cannot be documented as a stable enumeration:

| Source                                | Helper                       | Affected parameters (examples)                                                                                       |
|---------------------------------------|------------------------------|----------------------------------------------------------------------------------------------------------------------|
| Theme Options → Buttons               | `us_get_btn_styles()`        | `btn.style`, `flipbox.btn_style`, `gallery.btn_style`, `cta.btn_style`, `popup.btn_style`, `pricing.btn_style`, also `back_to_top_style`, `cookie_btn_style`, `skip_to_content_btn_style`, etc. in Theme Options |
| Theme Options → Field Styles          | `us_get_field_styles()`      | `search.style`, `login.style`, `cform.field_style`, `wc_account_login.field_style`, etc.                              |
| Theme Options → Color Schemes         | `us_get_color_schemes(TRUE)` | `dark_theme` in Theme Options (and any future per-site scheme-pickers)                                               |

A parameter's `options` map is collapsed to a "per-site values" marker **only** when the complete output of one of these helpers (every `(key, value)` pair) appears in the map unchanged. Partial overlaps — e.g. `vc_row.columns` numerically reusing key `1` — do not trigger the collapse, because their labels differ. This avoids the common false-positive where button-style IDs (`'1'`, `'4'`, `'5'`) coincidentally match column-count IDs.

**Explicit overrides** (`$explicit_per_site_params` in `scripts/llms/generators/shortcodes.php`) cover params whose `options` are loaded only inside the live-builder edit context and therefore return an empty list at CLI build time. They are pinned by `<config-id>.<param-name>`:

| Pinned param                  | Source                                        |
|-------------------------------|-----------------------------------------------|
| `additional_menu.source`      | WP site menus (Appearance → Menus)            |

Add new pairs to that map as similar params are discovered.

```text
**Options for `style`:**

  - _per-site values from Theme Options → Buttons — not enumerated, configured on each install_
  - `` — None     (any static fallback options are still listed individually)
```

This keeps the documentation honest about what the agent can and cannot rely on for these enums.

---

## Section template entry schema

Section templates are pre-designed shortcode blocks fetched from the UpSolution help portal (`us.api`) — the same library the live builder exposes under the **Templates** tab. The snapshot is theme-specific (Impreza vs Zephyr) and license-gated: the generator must run on a site with an activated license (or `US_DEV_SECRET` / `US_THEMETEST_CODE` defined), otherwise the API returns no usable content.

Output layout:

- [`content/sections.md`](content/sections.md) — index page. Lists every category with its template count and a link to the per-category file.
- [`content/sections/<category-id>.md`](content/sections/) — one file per category. Each file documents every template in that category as a `### <template-id>` record with the full shortcode markup.

Per-template record shape:

```markdown
### `<template-id>`

**Category**: `<category-id>` — <Category name>
**Preview**: <category-url>#section-NN     <!-- anchored to the template's position on the category preview page -->
**Thumbnail**: <thumb-url> (W×H)            <!-- omitted if the API returned no thumbnail -->

```text
[vc_row ...]
  [vc_column ...]
    ...
  [/vc_column]
[/vc_row]
```
```

Notes on the schema:

- **`template-id`** is the key the API uses inside `templates_config.data.<category>.templates`. It is not always human-readable (e.g. `"01"`, `"hero_01"`) — the heading uses it verbatim so an agent can map back to the API response.
- **Preview** is the anchored URL on the category's public preview page. The anchor format (`#section-NN`, two-digit, 1-based) matches what the builder UI uses in `usof/templates/templates_list.php`.
- **Shortcode markup** is rendered verbatim from `templates_content.data.<template-id>`. The `use:placeholder` markers the live editor replaces with site-specific image placeholders are left in place — they document the intent of those slots without binding the snapshot to a specific install.
- Code fences use the `text` language tag, matching the rest of the documentation set.

### Cache and snapshot freshness

The raw API response is cached at `scripts/llms/cache/sections-<theme>.json` (gitignored). Re-running the generator reuses the cache; delete the file to force a fresh fetch. Each generated file declares its fetch date in `generated:` — when a new us-core or theme version is released and the section library changes, delete the cache and re-run.

---

## Source-link notation

Always use repo-relative paths with no leading slash:

```text
plugins/us-core/config/elements/btn.php
plugins/us-core/templates/elements/btn.php
plugins/us-core/templates/css-theme-options.php
```

For specific lines, append `:NN` (e.g. `plugins/us-core/config/elements/btn.php:26`).

---

## Versioning

Each generated file declares `source: us-core <version>` in its header. When `us-core` is upgraded:

1. Run `scripts/llms/build.php` to regenerate.
2. Diff the result — review changed parameters and added/removed shortcodes.
3. Update manual overlays in `scripts/llms/manual/` if any user-facing meaning changed.

The build script writes the current `US_CORE_VERSION` into every output file automatically.

---

## Conventions for manual files

Manual files (anti-patterns, "when to use") follow Markdown best practice:

- One H1 per file (the `title` from front-matter is the document title).
- H2 for sections, H3 for sub-sections.
- Code blocks for shortcode examples must use the `text` language tag (not `html` or `php`), so agents recognize them as raw shortcode markup, not interpreted code.
