[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GKKBJ2P7CYR5218W59HT0D":3,"skill-same:01M6GKKBJ2P7CYR5218W59HT0D":85},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":47,"repositoryHtmlUrl":48,"repositoryHomepageUrl":49,"ownerHtmlUrl":50,"ownerBlogUrl":51,"ownerDescription":6,"updatedAt":52,"install":53,"resources":66},"01M6GKKBJ2P7CYR5218W59HT0D","acorn-stack",null,"Use when changing how Acorn boots or is wired on a Sage theme, Acorn mu-plugin or Radicle root - Application::configure(), withProviders(), withRouting(), ACORN_BASEPATH, base_path(), provider register() vs boot(), where providers are registered (functions.php, config\u002Fapp.php, composer.json extra.acorn.providers), config publishing, optimize:clear, \"'acorn' is not a registered wp command\". For generating providers, blocks or composers use acorn-scaffolding; for hook timing use wp-hooks-lifecycle; for unexplained breakage use roots-debugging.","hekivo\u002Fkivo-wise","hekivo","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F278159278?v=4","01M6GKH8S3Z4CAJ9RRR607G1WJ","Hekivo","01M6GKH8XNM7HTVF4DC86MA8RG",14,"MIT","https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fplugins\u002Fkivo-wise\u002Fskills\u002Facorn-stack\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"acorn stack","stack","provider","hook","composer","timing","theme","register","app","scaffolding","optimize","config","hooks","command","extra","configure","how","lifecycle","Providers","debugging","2026-11-10 10:12:30",false,"---\nname: acorn-stack\ndescription: Use when changing how Acorn boots or is wired on a Sage theme, Acorn mu-plugin or Radicle root - Application::configure(), withProviders(), withRouting(), ACORN_BASEPATH, base_path(), provider register() vs boot(), where providers are registered (functions.php, config\u002Fapp.php, composer.json extra.acorn.providers), config publishing, optimize:clear, \"'acorn' is not a registered wp command\". For generating providers, blocks or composers use acorn-scaffolding; for hook timing use wp-hooks-lifecycle; for unexplained breakage use roots-debugging.\n---\n\n# Acorn stack (theme, mu-plugin, project root)\n\nAcorn is the same library in all three profiles. What changes is **where it boots, which directory it treats as `base_path()`, and where providers are listed**. Read the profile, namespace and Acorn base path from the session context before touching anything.\n\nRunner placeholders come from the session context: `{{runner.wp}}` (WP-CLI), `{{runner.acorn}}` (WP-CLI `acorn` subcommand), `{{runner.composer}}`, `{{runner.node}}`, `{{runner.test}}`, `{{runner.cache}}` (the project's cache-clear wrapper, if any). On a Lando project the defaults are `lando wp`, `lando wp acorn`, `lando composer`, a Node tooling command such as `lando npm` or `lando yarn`, and whatever cache tooling `.lando.yml` defines. Never run WP-CLI, Composer, PHP or Node on the host for project work.\n\n## When to use\n\n- Adding or changing a service provider, binding, View Composer, Blade component or config file.\n- Deciding where a piece of logic lives (provider, composer, component, bootstrap file, service class).\n- Acorn does not boot, boots with the wrong base path, or `{{runner.acorn}}` is missing.\n- A change is not picked up and you suspect an Acorn cache (config, routes, views, packages, ACF Composer manifest).\n\nNot for: scaffolding new artifacts (`acorn-scaffolding`), hook placement and timing (`wp-hooks-lifecycle`), Livewire (`acorn-livewire`), routes and middleware (`acorn-routes-api`), triage of errors (`roots-debugging`).\n\n## Inputs required\n\n1. Profile (`sage-theme`, `acorn-mu-plugin`, `radicle-app`), the Acorn base path and the PSR-4 namespace mapped to `app\u002F` (session context; confirm with the command in step 0).\n2. The Composer project that requires `roots\u002Facorn` (theme folder, plugin folder, or project root). Its `composer.json` decides the namespace and which packages are discovered.\n3. What is being added or changed, and whether it needs the container (DI, config) or is a plain WordPress hook.\n\n### Profiles at a glance\n\n| Concern | `sage-theme` | `acorn-mu-plugin` | `radicle-app` |\n|---|---|---|---|\n| Base path | Theme folder, inferred from the theme's `composer.json` | Plugin folder: the plugin must define `ACORN_BASEPATH` or pass a path to `Application::configure($path)` | Project root: `ACORN_BASEPATH` defined in `bedrock\u002Fapplication.php` |\n| Boot call | `functions.php` calls `Application::configure()->withProviders([...])->boot()` while the theme loads (after `setup_theme`, before `after_setup_theme`) | Main plugin file defers the boot to `after_setup_theme`, often through a small configurator class | A committed mu-plugin boots on `after_setup_theme` |\n| Provider list | `withProviders([...])` in `functions.php` (Sage ships `App\\Providers\\ThemeServiceProvider`) | `withProviders([...])` in the boot code or configurator class | `composer.json` → `extra.acorn.providers` |\n| Namespace | `App\\` | Project namespace from the plugin's `composer.json` | `App\\` |\n| Blade templates for WordPress pages | `SageServiceProvider` filters the template hierarchy | No Sage filters: the plugin hooks `template_include` \u002F `*_template_hierarchy` itself, or only renders views from blocks, shortcodes and routes | Root `resources\u002Fviews`; the theme folder holds only `index.php` and `style.css` |\n| `{{runner.acorn}}` available | Only while the theme is active | Always (mu-plugins cannot be deactivated) | Always |\n| Usually installed | ACF Composer, Poet only if required | ACF Composer, Poet, Livewire are common | No ACF, no Poet, no Livewire by default |\n\nDeep dive: [references\u002Fboot-and-paths.md](references\u002Fboot-and-paths.md).\n\n## Procedure\n\nCommands: write every command with the runner value from the session context filled in (for example `lando wp acorn optimize:clear`), never a bare `wp`\u002F`composer`\u002F`php`\u002F`npm`, never the placeholder, never \"prefix with lando if you use it\". Commands that run in CI or a deploy script go in a separate block labelled with where they run.\n\n### 0) Confirm the runtime facts, do not assume them\n\n```bash\n{{runner.wp}} eval 'echo base_path(), PHP_EOL, app()->getNamespace(), PHP_EOL, storage_path(), PHP_EOL;'\n{{runner.acorn}} about\n```\n\nIf `base_path()` points at the theme on an `acorn-mu-plugin` project, the plugin is missing `ACORN_BASEPATH` (see Failure modes). If `{{runner.acorn}}` prints `'acorn' is not a registered wp command`, the theme or plugin that boots Acorn is not active or crashed before booting.\n\n### 1) Decide where the code goes\n\n| Logic | Location | Native mechanism |\n|---|---|---|\n| Plain `add_action` \u002F `add_filter`, no dependencies | Bootstrap files: Sage `app\u002Fsetup.php`, `app\u002Ffilters.php`; mu-plugin bootstrap files required by the main file; Radicle theme config or a provider | WordPress Plugin API |\n| Hooks that need services or config | A provider's `boot()` | `Illuminate\\Support\\ServiceProvider` |\n| Container bindings | A provider's `register()` | `singleton`, `bind`, `instance` |\n| Business logic, API clients | `app\u002FServices\u002F` (or a domain folder), bound in a provider when it needs config | Container auto-resolution of type-hinted constructors |\n| Data for an existing template | View Composer in `app\u002FView\u002FComposers\u002F` | Auto-discovered by Acorn's `ViewServiceProvider` |\n| Reusable markup with props | Blade component (`app\u002FView\u002FComponents\u002F` + `resources\u002Fviews\u002Fcomponents\u002F`, or anonymous view only) | Blade `\u003Cx-…>` convention |\n| Editor-placed section | Block (see `acorn-scaffolding`) | ACF Composer or `register_block_type` |\n| Settings that differ per environment | `config\u002F\u003Cfile>.php` reading `env()` | Acorn config repository |\n\nHook placement details per profile live in `wp-hooks-lifecycle`. Search `app\u002F`, the bootstrap files and the existing providers before adding a class.\n\n### 2) Providers\n\n1. Generate with `{{runner.acorn}} make:provider ExampleServiceProvider` (or follow `acorn-scaffolding`).\n2. `register()`: bindings only. `boot()`: hooks, view composers, anything that resolves services. Never `add_action` in `register()` or in the constructor.\n3. Register it where this profile reads providers (table above). The generator only appends to a bootstrap providers file (`\u003Cbootstrap path>\u002Fproviders.php`, by default inside `storage\u002Fframework\u002F`) when one already exists, which is rare, so assume it did not.\n4. Base class: `Illuminate\\Support\\ServiceProvider` for feature providers. Only a Sage theme's main provider extends `Roots\\Acorn\\Sage\\SageServiceProvider` (it adds the template-hierarchy filters). Do not extend it in an mu-plugin or Radicle project.\n5. A provider that throws during `register()`\u002F`boot()` is **skipped**, the exception is reported to the log, and it is re-thrown after boot only in `local`\u002F`development`\u002F`testing` web requests. On production the feature silently disappears: check the log.\n\nFull rules, discovery and examples: [references\u002Fproviders-and-container.md](references\u002Fproviders-and-container.md).\n\n### 3) Views, composers, components\n\n- Views resolve from `config('view.paths')`, by default `resources\u002Fviews` under the base path.\n- View Composers: extend `Roots\\Acorn\\View\\Composer`, live anywhere under `app\u002FView\u002FComposers\u002F`, set `protected static $views = [...]`. Acorn discovers them; no manual wiring. Data from `with()` does **not** overwrite data already passed to the view; `override()` does.\n- Blade components: class components in `app\u002FView\u002FComponents\u002F` resolve by name (`\u003Cx-product-card>`); anonymous components are files in `resources\u002Fviews\u002Fcomponents\u002F`. `config\u002Fview.php` → `components` is only for aliases.\n- Escape once: `{{ $value }}` already escapes; never wrap `esc_*()` inside it (`wp-security-escaping`).\n\nDetails: [references\u002Fviews-composers-components.md](references\u002Fviews-composers-components.md).\n\n### 4) Config, storage, publishing\n\n- Every file in the base path's `config\u002F` is loaded; Acorn ships defaults for `app`, `cache`, `database`, `logging`, `view` and others, so publish only what you change: `{{runner.acorn}} vendor:publish --tag=\u003Ctag>` or `{{runner.acorn}} acorn:init storage`.\n- `storage_path()` is `\u003Cbase>\u002Fstorage` when that folder exists, otherwise `wp-content\u002Fcache\u002Facorn` (created on demand). Compiled views, caches and logs live there.\n- An mu-plugin with no `config\u002F`, `resources\u002F` or `storage\u002F` folder of its own falls back to the **active theme's** folder of that name before the default. Create the folders in the plugin.\n\n### 5) Caches: know which layer you are clearing\n\n| Layer | Files | Rebuild | Clear |\n|---|---|---|---|\n| Config, routes | `\u003Cstorage>\u002Fframework\u002Fcache\u002F{config,routes-v7}.php` | `{{runner.acorn}} optimize` | `{{runner.acorn}} optimize:clear` |\n| Provider and package manifests | `\u003Cstorage>\u002Fframework\u002Fcache\u002F{services,packages}.php` | `{{runner.acorn}} package:discover` | delete the files |\n| Compiled Blade | `\u003Cstorage>\u002Fframework\u002Fviews\u002F` | `{{runner.acorn}} view:cache` | `{{runner.acorn}} view:clear` |\n| ACF Composer manifest + generated `block.json` | `\u003Cstorage>\u002Fframework\u002Fcache\u002Facf-composer\u002F` | `{{runner.acorn}} acf:cache` (also run by `optimize`) | `{{runner.acorn}} acf:clear` (also run by `optimize:clear`) |\n| Laravel cache store | per `config\u002Fcache.php` (file, Redis…) | n\u002Fa | `{{runner.acorn}} cache:clear` (also run by `optimize:clear`) |\n| WordPress object cache | Redis\u002FMemcached drop-in | n\u002Fa | `{{runner.wp}} cache flush` |\n\nRules:\n\n- Treat `optimize:clear` and `optimize` as a pair. `optimize:clear` alone also deletes the ACF Composer manifest and flushes the Laravel cache store; at least one production mu-plugin returned 500 on every request until the manifest was rebuilt.\n- While a cache exists, edits to what it holds are **ignored**: cached config ignores `config\u002F*.php` and `.env` edits; a cached ACF Composer manifest ignores edits to `fields()` and to block properties.\n- Prefer `{{runner.cache}}` when the project defines one; it usually chains the steps in the right order.\n\nDetails: [references\u002Fcaches-and-config.md](references\u002Fcaches-and-config.md).\n\n## Verification\n\n```bash\n{{runner.wp}} eval 'echo base_path(), PHP_EOL, app()->getNamespace(), PHP_EOL;'\n{{runner.wp}} eval 'var_dump(app()->getProvider(App\\Providers\\ExampleServiceProvider::class) !== null);'   # use your namespace\n{{runner.acorn}} list            # your commands and generators are present\n{{runner.acorn}} route:list      # when routes changed\n{{runner.cache}}                 # or: {{runner.acorn}} optimize:clear && {{runner.acorn}} optimize\n{{runner.test}}\n```\n\nThen load the affected page and read `storage\u002Flogs\u002F` (or `wp-content\u002Fcache\u002Facorn\u002Flogs\u002F`) for `Skipping provider` lines. Report what you ran and what you saw.\n\n## Failure modes\n\n| Symptom | Cause | Fix |\n|---|---|---|\n| `'acorn' is not a registered wp command` | The theme or plugin that boots Acorn is inactive, or it fatals before `boot()` | Activate the theme (`sage-theme`); check the PHP error log; confirm `vendor\u002Fautoload.php` exists in the Composer project that owns Acorn |\n| `base_path()` is the theme on an mu-plugin project | No `ACORN_BASEPATH` and no path passed to `configure()`; inference falls through to the theme's `composer.json` or `app\u002F` | Define `ACORN_BASEPATH` in the main plugin file before booting, or call `Application::configure($pluginPath)` |\n| Provider never runs | Not listed where this profile reads providers, or skipped after an exception | Add it to `withProviders()` \u002F `extra.acorn.providers` \u002F `config\u002Fapp.php`; search the log for `Skipping provider` |\n| Package provider not found after `composer require` | Stale package manifest, or the package lives in a Composer project Acorn does not scan | `{{runner.acorn}} package:discover`; mu-plugin packages are found only because the base path points at the plugin |\n| Composer data missing in the view | Class outside `app\u002FView\u002FComposers\u002F`, does not extend `Roots\\Acorn\\View\\Composer`, or `$views` does not match the view name | Fix the class; `{{runner.acorn}} view:clear` |\n| Config or `.env` edit ignored | Config cache from `optimize` | `{{runner.acorn}} config:clear` then `optimize` |\n| ACF field or block property edit ignored | ACF Composer manifest still holds the old definition | `{{runner.acorn}} acf:cache` (or `optimize`) |\n| 500 on every request right after `optimize:clear` | Project depends on the ACF Composer manifest or a cached config | `{{runner.acorn}} optimize`; afterwards always run the pair |\n| Hook registered in `register()` behaves oddly | Container not booted; other providers not registered yet | Move it to `boot()` |\n| Sage template filters missing in an mu-plugin | `SageServiceProvider` belongs to the theme profile | Hook `template_include` in the plugin's own provider |\n\n## Escalation\n\nStop and ask when: the base path or namespace in the session context disagrees with step 0; a provider must be ordered relative to others and you cannot tell why; the change needs `optimize` behaviour on a remote environment; a fix would edit `wp-config.php`, `.env`, `bedrock\u002F*.php` or files under `vendor\u002F`; or the profile is none of the three.\n\n\u003C!-- verified:\nvendor\u002Froots\u002Facorn\u002Fsrc\u002FRoots\u002FAcorn\u002FConfiguration\u002FConcerns\u002FPaths.php:16-27 — inferBasePath order APP_BASE_PATH, ACORN_BASEPATH, theme composer.json, theme app\u002F, closest composer.json, fallback;\nPaths.php:85-101 — findPath tries app path, basePath(type), get_theme_file_path(type); :115-129 storage fallback wp-content\u002Fcache\u002Facorn;\nApplication.php:69-84 (acorn 6.2.0) — configure() builds withPaths\u002FwithKernels\u002FwithEvents\u002FwithCommands\u002FwithProviders\u002FwithMiddleware\u002FwithExceptions;\nApplicationBuilder.php:140-150,167-170 — withProviders merges into bootstrap providers path; boot() calls bootAcorn immediately (no hook);\nApplication\u002FConcerns\u002FBootable.php:41-57,79-110 — WP-CLI registers the `acorn` command only when Acorn booted;\nApplication.php:247-275 — package discovery scans base path, content root, template, stylesheet and active_plugins dirs;\nPackageManifest.php:62-97 — reads extra.acorn \u002F extra.laravel providers including the root composer.json;\nApplication.php:320-339 — config app.providers + package providers registered; :307-313,367-391 — failing providers skipped and reported;\nView\u002FViewServiceProvider.php:169-197 — composers auto-discovered in app\u002FView\u002FComposers; View\u002FComposer.php:61-90 — with() does not overwrite view data, override() does;\nIlluminate\u002FFoundation\u002FConsole\u002FOptimizeClearCommand.php:59-70 — clear runs config, cache, compiled, events, routes, views + package tasks;\nlog1x\u002Facf-composer 3.4.6 src\u002FProviders\u002FAcfComposerServiceProvider.php:67-73 — optimizes acf:cache \u002F acf:clear; src\u002FComposer.php:109-117 — fields read from manifest when cached;\nrefs\u002Froots-sage\u002Ffunctions.php:35-39 — Sage boots at include time with withProviders; refs\u002Froots-docs\u002Facorn\u002Finstallation.md:126-128 — inactive booter error;\nwp\u002Fwp-settings.php:705,741-757 — setup_theme, theme functions.php, after_setup_theme order (WP 7.1.3)\n-->\n","# Acorn stack (theme, mu-plugin, project root)\n\nAcorn is the same library in all three profiles. What changes is **where it boots, which directory it treats as `base_path()`, and where providers are listed**. Read the profile, namespace and Acorn base path from the session context before touching anything.\n\nRunner placeholders come from the session context: `{{runner.wp}}` (WP-CLI), `{{runner.acorn}}` (WP-CLI `acorn` subcommand), `{{runner.composer}}`, `{{runner.node}}`, `{{runner.test}}`, `{{runner.cache}}` (the project's cache-clear wrapper, if any). On a Lando project the defaults are `lando wp`, `lando wp acorn`, `lando composer`, a Node tooling command such as `lando npm` or `lando yarn`, and whatever cache tooling `.lando.yml` defines. Never run WP-CLI, Composer, PHP or Node on the host for project work.\n\n## When to use\n\n- Adding or changing a service provider, binding, View Composer, Blade component or config file.\n- Deciding where a piece of logic lives (provider, composer, component, bootstrap file, service class).\n- Acorn does not boot, boots with the wrong base path, or `{{runner.acorn}}` is missing.\n- A change is not picked up and you suspect an Acorn cache (config, routes, views, packages, ACF Composer manifest).\n\nNot for: scaffolding new artifacts (`acorn-scaffolding`), hook placement and timing (`wp-hooks-lifecycle`), Livewire (`acorn-livewire`), routes and middleware (`acorn-routes-api`), triage of errors (`roots-debugging`).\n\n## Inputs required\n\n1. Profile (`sage-theme`, `acorn-mu-plugin`, `radicle-app`), the Acorn base path and the PSR-4 namespace mapped to `app\u002F` (session context; confirm with the command in step 0).\n2. The Composer project that requires `roots\u002Facorn` (theme folder, plugin folder, or project root). Its `composer.json` decides the namespace and which packages are discovered.\n3. What is being added or changed, and whether it needs the container (DI, config) or is a plain WordPress hook.\n\n### Profiles at a glance\n\n| Concern | `sage-theme` | `acorn-mu-plugin` | `radicle-app` |\n|---|---|---|---|\n| Base path | Theme folder, inferred from the theme's `composer.json` | Plugin folder: the plugin must define `ACORN_BASEPATH` or pass a path to `Application::configure($path)` | Project root: `ACORN_BASEPATH` defined in `bedrock\u002Fapplication.php` |\n| Boot call | `functions.php` calls `Application::configure()->withProviders([...])->boot()` while the theme loads (after `setup_theme`, before `after_setup_theme`) | Main plugin file defers the boot to `after_setup_theme`, often through a small configurator class | A committed mu-plugin boots on `after_setup_theme` |\n| Provider list | `withProviders([...])` in `functions.php` (Sage ships `App\\Providers\\ThemeServiceProvider`) | `withProviders([...])` in the boot code or configurator class | `composer.json` → `extra.acorn.providers` |\n| Namespace | `App\\` | Project namespace from the plugin's `composer.json` | `App\\` |\n| Blade templates for WordPress pages | `SageServiceProvider` filters the template hierarchy | No Sage filters: the plugin hooks `template_include` \u002F `*_template_hierarchy` itself, or only renders views from blocks, shortcodes and routes | Root `resources\u002Fviews`; the theme folder holds only `index.php` and `style.css` |\n| `{{runner.acorn}}` available | Only while the theme is active | Always (mu-plugins cannot be deactivated) | Always |\n| Usually installed | ACF Composer, Poet only if required | ACF Composer, Poet, Livewire are common | No ACF, no Poet, no Livewire by default |\n\nDeep dive: [references\u002Fboot-and-paths.md](references\u002Fboot-and-paths.md).\n\n## Procedure\n\nCommands: write every command with the runner value from the session context filled in (for example `lando wp acorn optimize:clear`), never a bare `wp`\u002F`composer`\u002F`php`\u002F`npm`, never the placeholder, never \"prefix with lando if you use it\". Commands that run in CI or a deploy script go in a separate block labelled with where they run.\n\n### 0) Confirm the runtime facts, do not assume them\n\n```bash\n{{runner.wp}} eval 'echo base_path(), PHP_EOL, app()->getNamespace(), PHP_EOL, storage_path(), PHP_EOL;'\n{{runner.acorn}} about\n```\n\nIf `base_path()` points at the theme on an `acorn-mu-plugin` project, the plugin is missing `ACORN_BASEPATH` (see Failure modes). If `{{runner.acorn}}` prints `'acorn' is not a registered wp command`, the theme or plugin that boots Acorn is not active or crashed before booting.\n\n### 1) Decide where the code goes\n\n| Logic | Location | Native mechanism |\n|---|---|---|\n| Plain `add_action` \u002F `add_filter`, no dependencies | Bootstrap files: Sage `app\u002Fsetup.php`, `app\u002Ffilters.php`; mu-plugin bootstrap files required by the main file; Radicle theme config or a provider | WordPress Plugin API |\n| Hooks that need services or config | A provider's `boot()` | `Illuminate\\Support\\ServiceProvider` |\n| Container bindings | A provider's `register()` | `singleton`, `bind`, `instance` |\n| Business logic, API clients | `app\u002FServices\u002F` (or a domain folder), bound in a provider when it needs config | Container auto-resolution of type-hinted constructors |\n| Data for an existing template | View Composer in `app\u002FView\u002FComposers\u002F` | Auto-discovered by Acorn's `ViewServiceProvider` |\n| Reusable markup with props | Blade component (`app\u002FView\u002FComponents\u002F` + `resources\u002Fviews\u002Fcomponents\u002F`, or anonymous view only) | Blade `\u003Cx-…>` convention |\n| Editor-placed section | Block (see `acorn-scaffolding`) | ACF Composer or `register_block_type` |\n| Settings that differ per environment | `config\u002F\u003Cfile>.php` reading `env()` | Acorn config repository |\n\nHook placement details per profile live in `wp-hooks-lifecycle`. Search `app\u002F`, the bootstrap files and the existing providers before adding a class.\n\n### 2) Providers\n\n1. Generate with `{{runner.acorn}} make:provider ExampleServiceProvider` (or follow `acorn-scaffolding`).\n2. `register()`: bindings only. `boot()`: hooks, view composers, anything that resolves services. Never `add_action` in `register()` or in the constructor.\n3. Register it where this profile reads providers (table above). The generator only appends to a bootstrap providers file (`\u003Cbootstrap path>\u002Fproviders.php`, by default inside `storage\u002Fframework\u002F`) when one already exists, which is rare, so assume it did not.\n4. Base class: `Illuminate\\Support\\ServiceProvider` for feature providers. Only a Sage theme's main provider extends `Roots\\Acorn\\Sage\\SageServiceProvider` (it adds the template-hierarchy filters). Do not extend it in an mu-plugin or Radicle project.\n5. A provider that throws during `register()`\u002F`boot()` is **skipped**, the exception is reported to the log, and it is re-thrown after boot only in `local`\u002F`development`\u002F`testing` web requests. On production the feature silently disappears: check the log.\n\nFull rules, discovery and examples: [references\u002Fproviders-and-container.md](references\u002Fproviders-and-container.md).\n\n### 3) Views, composers, components\n\n- Views resolve from `config('view.paths')`, by default `resources\u002Fviews` under the base path.\n- View Composers: extend `Roots\\Acorn\\View\\Composer`, live anywhere under `app\u002FView\u002FComposers\u002F`, set `protected static $views = [...]`. Acorn discovers them; no manual wiring. Data from `with()` does **not** overwrite data already passed to the view; `override()` does.\n- Blade components: class components in `app\u002FView\u002FComponents\u002F` resolve by name (`\u003Cx-product-card>`); anonymous components are files in `resources\u002Fviews\u002Fcomponents\u002F`. `config\u002Fview.php` → `components` is only for aliases.\n- Escape once: `{{ $value }}` already escapes; never wrap `esc_*()` inside it (`wp-security-escaping`).\n\nDetails: [references\u002Fviews-composers-components.md](references\u002Fviews-composers-components.md).\n\n### 4) Config, storage, publishing\n\n- Every file in the base path's `config\u002F` is loaded; Acorn ships defaults for `app`, `cache`, `database`, `logging`, `view` and others, so publish only what you change: `{{runner.acorn}} vendor:publish --tag=\u003Ctag>` or `{{runner.acorn}} acorn:init storage`.\n- `storage_path()` is `\u003Cbase>\u002Fstorage` when that folder exists, otherwise `wp-content\u002Fcache\u002Facorn` (created on demand). Compiled views, caches and logs live there.\n- An mu-plugin with no `config\u002F`, `resources\u002F` or `storage\u002F` folder of its own falls back to the **active theme's** folder of that name before the default. Create the folders in the plugin.\n\n### 5) Caches: know which layer you are clearing\n\n| Layer | Files | Rebuild | Clear |\n|---|---|---|---|\n| Config, routes | `\u003Cstorage>\u002Fframework\u002Fcache\u002F{config,routes-v7}.php` | `{{runner.acorn}} optimize` | `{{runner.acorn}} optimize:clear` |\n| Provider and package manifests | `\u003Cstorage>\u002Fframework\u002Fcache\u002F{services,packages}.php` | `{{runner.acorn}} package:discover` | delete the files |\n| Compiled Blade | `\u003Cstorage>\u002Fframework\u002Fviews\u002F` | `{{runner.acorn}} view:cache` | `{{runner.acorn}} view:clear` |\n| ACF Composer manifest + generated `block.json` | `\u003Cstorage>\u002Fframework\u002Fcache\u002Facf-composer\u002F` | `{{runner.acorn}} acf:cache` (also run by `optimize`) | `{{runner.acorn}} acf:clear` (also run by `optimize:clear`) |\n| Laravel cache store | per `config\u002Fcache.php` (file, Redis…) | n\u002Fa | `{{runner.acorn}} cache:clear` (also run by `optimize:clear`) |\n| WordPress object cache | Redis\u002FMemcached drop-in | n\u002Fa | `{{runner.wp}} cache flush` |\n\nRules:\n\n- Treat `optimize:clear` and `optimize` as a pair. `optimize:clear` alone also deletes the ACF Composer manifest and flushes the Laravel cache store; at least one production mu-plugin returned 500 on every request until the manifest was rebuilt.\n- While a cache exists, edits to what it holds are **ignored**: cached config ignores `config\u002F*.php` and `.env` edits; a cached ACF Composer manifest ignores edits to `fields()` and to block properties.\n- Prefer `{{runner.cache}}` when the project defines one; it usually chains the steps in the right order.\n\nDetails: [references\u002Fcaches-and-config.md](references\u002Fcaches-and-config.md).\n\n## Verification\n\n```bash\n{{runner.wp}} eval 'echo base_path(), PHP_EOL, app()->getNamespace(), PHP_EOL;'\n{{runner.wp}} eval 'var_dump(app()->getProvider(App\\Providers\\ExampleServiceProvider::class) !== null);'   # use your namespace\n{{runner.acorn}} list            # your commands and generators are present\n{{runner.acorn}} route:list      # when routes changed\n{{runner.cache}}                 # or: {{runner.acorn}} optimize:clear && {{runner.acorn}} optimize\n{{runner.test}}\n```\n\nThen load the affected page and read `storage\u002Flogs\u002F` (or `wp-content\u002Fcache\u002Facorn\u002Flogs\u002F`) for `Skipping provider` lines. Report what you ran and what you saw.\n\n## Failure modes\n\n| Symptom | Cause | Fix |\n|---|---|---|\n| `'acorn' is not a registered wp command` | The theme or plugin that boots Acorn is inactive, or it fatals before `boot()` | Activate the theme (`sage-theme`); check the PHP error log; confirm `vendor\u002Fautoload.php` exists in the Composer project that owns Acorn |\n| `base_path()` is the theme on an mu-plugin project | No `ACORN_BASEPATH` and no path passed to `configure()`; inference falls through to the theme's `composer.json` or `app\u002F` | Define `ACORN_BASEPATH` in the main plugin file before booting, or call `Application::configure($pluginPath)` |\n| Provider never runs | Not listed where this profile reads providers, or skipped after an exception | Add it to `withProviders()` \u002F `extra.acorn.providers` \u002F `config\u002Fapp.php`; search the log for `Skipping provider` |\n| Package provider not found after `composer require` | Stale package manifest, or the package lives in a Composer project Acorn does not scan | `{{runner.acorn}} package:discover`; mu-plugin packages are found only because the base path points at the plugin |\n| Composer data missing in the view | Class outside `app\u002FView\u002FComposers\u002F`, does not extend `Roots\\Acorn\\View\\Composer`, or `$views` does not match the view name | Fix the class; `{{runner.acorn}} view:clear` |\n| Config or `.env` edit ignored | Config cache from `optimize` | `{{runner.acorn}} config:clear` then `optimize` |\n| ACF field or block property edit ignored | ACF Composer manifest still holds the old definition | `{{runner.acorn}} acf:cache` (or `optimize`) |\n| 500 on every request right after `optimize:clear` | Project depends on the ACF Composer manifest or a cached config | `{{runner.acorn}} optimize`; afterwards always run the pair |\n| Hook registered in `register()` behaves oddly | Container not booted; other providers not registered yet | Move it to `boot()` |\n| Sage template filters missing in an mu-plugin | `SageServiceProvider` belongs to the theme profile | Hook `template_include` in the plugin's own provider |\n\n## Escalation\n\nStop and ask when: the base path or namespace in the session context disagrees with step 0; a provider must be ordered relative to others and you cannot tell why; the change needs `optimize` behaviour on a remote environment; a fix would edit `wp-config.php`, `.env`, `bedrock\u002F*.php` or files under `vendor\u002F`; or the profile is none of the three.\n\n\u003C!-- verified:\nvendor\u002Froots\u002Facorn\u002Fsrc\u002FRoots\u002FAcorn\u002FConfiguration\u002FConcerns\u002FPaths.php:16-27 — inferBasePath order APP_BASE_PATH, ACORN_BASEPATH, theme composer.json, theme app\u002F, closest composer.json, fallback;\nPaths.php:85-101 — findPath tries app path, basePath(type), get_theme_file_path(type); :115-129 storage fallback wp-content\u002Fcache\u002Facorn;\nApplication.php:69-84 (acorn 6.2.0) — configure() builds withPaths\u002FwithKernels\u002FwithEvents\u002FwithCommands\u002FwithProviders\u002FwithMiddleware\u002FwithExceptions;\nApplicationBuilder.php:140-150,167-170 — withProviders merges into bootstrap providers path; boot() calls bootAcorn immediately (no hook);\nApplication\u002FConcerns\u002FBootable.php:41-57,79-110 — WP-CLI registers the `acorn` command only when Acorn booted;\nApplication.php:247-275 — package discovery scans base path, content root, template, stylesheet and active_plugins dirs;\nPackageManifest.php:62-97 — reads extra.acorn \u002F extra.laravel providers including the root composer.json;\nApplication.php:320-339 — config app.providers + package providers registered; :307-313,367-391 — failing providers skipped and reported;\nView\u002FViewServiceProvider.php:169-197 — composers auto-discovered in app\u002FView\u002FComposers; View\u002FComposer.php:61-90 — with() does not overwrite view data, override() does;\nIlluminate\u002FFoundation\u002FConsole\u002FOptimizeClearCommand.php:59-70 — clear runs config, cache, compiled, events, routes, views + package tasks;\nlog1x\u002Facf-composer 3.4.6 src\u002FProviders\u002FAcfComposerServiceProvider.php:67-73 — optimizes acf:cache \u002F acf:clear; src\u002FComposer.php:109-117 — fields read from manifest when cached;\nrefs\u002Froots-sage\u002Ffunctions.php:35-39 — Sage boots at include time with withProviders; refs\u002Froots-docs\u002Facorn\u002Finstallation.md:126-128 — inactive booter error;\nwp\u002Fwp-settings.php:705,741-757 — setup_theme, theme functions.php, after_setup_theme order (WP 7.1.3)\n-->\n",{"name":5,"description":7},"main","4045a2f672c1d4c1b4a5a5712b468c5d73ca6724","plugins\u002Fkivo-wise\u002Fskills\u002Facorn-stack",0,"https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise","https:\u002F\u002Fhekivo.github.io\u002Fkivo-wise\u002F","https:\u002F\u002Fgithub.com\u002Fhekivo","https:\u002F\u002Fhekivo.dev","2026-11-08 06:10:39",{"source":8,"skillName":5,"commands":54,"prompt":64,"zipAvailable":65},[55,58,61],{"tool":56,"command":57},"npx","npx skills add hekivo\u002Fkivo-wise --skill acorn-stack",{"tool":59,"command":60},"bunx","bunx skills add hekivo\u002Fkivo-wise --skill acorn-stack",{"tool":62,"command":63},"pnpm","pnpm dlx skills add hekivo\u002Fkivo-wise --skill acorn-stack","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fplugins\u002Fkivo-wise\u002Fskills\u002Facorn-stack\u002FSKILL.md",true,[67,73,77,81],{"path":68,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":71,"sourceHtmlUrl":72},"references\u002Fboot-and-paths.md","REFERENCE","参考文档",6683,"https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fplugins\u002Fkivo-wise\u002Fskills\u002Facorn-stack\u002Freferences\u002Fboot-and-paths.md",{"path":74,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":75,"sourceHtmlUrl":76},"references\u002Fcaches-and-config.md",5105,"https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fplugins\u002Fkivo-wise\u002Fskills\u002Facorn-stack\u002Freferences\u002Fcaches-and-config.md",{"path":78,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":79,"sourceHtmlUrl":80},"references\u002Fproviders-and-container.md",5701,"https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fplugins\u002Fkivo-wise\u002Fskills\u002Facorn-stack\u002Freferences\u002Fproviders-and-container.md",{"path":82,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":83,"sourceHtmlUrl":84},"references\u002Fviews-composers-components.md",4779,"https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fplugins\u002Fkivo-wise\u002Fskills\u002Facorn-stack\u002Freferences\u002Fviews-composers-components.md",[86,121,139,162,180,203],{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":102,"publishedAt":39},"01M6GKWJDFKQM27HTFXX20QVTP","wp-rest-api","Use when building, extending, or debugging WordPress REST API endpoints\u002Froutes: register_rest_route, WP_REST_Controller\u002Fcontroller classes, schema\u002Fargument validation, permission_callback\u002Fauthentication, response shaping, register_rest_field\u002Fregister_meta, or exposing CPTs\u002Ftaxonomies via show_in_rest.","https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fthird-party\u002Fwp-rest-api\u002FSKILL.md",[92,97],{"categoryNo":93,"categoryName":94,"taxonomyType":95,"taxonomyTypeDesc":96},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":98,"categoryName":99,"taxonomyType":100,"taxonomyTypeDesc":101},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[103,104,105,106,107,108,38,109,110,111,112,113,114,115,116,117,118,26,119,120],"REST","api","wp rest api","rest api","wordpress","workflows","authentication","Meta","controller","Bash","shaping","filesystem","use","schema","show","route","with","wp-cli",{"skillNo":122,"name":123,"nameZh":6,"description":124,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":125,"categories":126,"keywords":129,"publishedAt":39},"01M6GKWEA5BMJZ2RPPEEJTCC3N","wp-abilities-api","Use when working with the WordPress Abilities API (wp_register_ability, wp_register_ability_category, \u002Fwp-json\u002Fwp-abilities\u002Fv1\u002F*, @wordpress\u002Fabilities) including defining abilities, categories, meta, REST exposure, and permissions checks for clients.","https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fthird-party\u002Fwp-abilities-api\u002FSKILL.md",[127,128],{"categoryNo":93,"categoryName":94,"taxonomyType":95,"taxonomyTypeDesc":96},{"categoryNo":98,"categoryName":99,"taxonomyType":100,"taxonomyTypeDesc":101},[104,130,131,107,108,132,110,103,112,133,134,114,135,115,26,136,137,119,138,120],"wp abilities api","cli","permissions","php","json","node","targets","clients","categories",{"skillNo":140,"name":141,"nameZh":6,"description":142,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":143,"categories":144,"keywords":145,"publishedAt":39},"01M6GKWA4GG2BZRFXCR9E73VR7","wp-security-escaping","Use when writing or reviewing code that outputs data, handles input or checks permissions in a WordPress + Acorn project - Blade {{ }} vs {!! !!}, esc_html, esc_attr, esc_url, wp_kses_post, \"&#038; in the URL\", double escaping, sanitize_text_field, nonces, current_user_can, map_meta_cap, permission_callback, $wpdb->prepare, whereRaw, file uploads, escaping ACF values, secrets in .env. For route middleware use acorn-routes-api; for ACF validation use acf-native; for Livewire actions use acorn-livewire.","https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fskills\u002Fwp-security-escaping\u002FSKILL.md",[],[146,147,148,149,150,132,151,110,104,152,153,154,155,118,156,157,158,159,160,161],"security","wp security","wp security escaping","writing","code","actions","secrets","livewire","text","cap","map","project","middleware","native","URL","routes-api",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":168,"publishedAt":39},"01M6GKW6VVY73BMZ3JNDMR4CWZ","wp-phpstan","Use when configuring, running or fixing PHPStan in a WordPress project that uses Acorn - phpstan.neon, baseline, szepeviktor\u002Fphpstan-wordpress stubs, larastan, level raising, \"Cannot access property on mixed\", get_field() types, paths for app\u002F. For Pint or Mago formatting use testing-wp; for runtime errors use roots-debugging.","https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fskills\u002Fwp-phpstan\u002FSKILL.md",[],[169,170,107,38,171,172,115,157,173,174,175,176,27,177,178,179],"wp phpstan","testing","baseline","access","get","neon","runtime","formatting","paths","types","errors",{"skillNo":181,"name":182,"nameZh":6,"description":183,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":184,"categories":185,"keywords":186,"publishedAt":39},"01M6GKW3JRSRS9N112QFA3SEGT","wp-performance","Use when a WordPress page, query or request is slow or needs profiling - TTFB, slow or N+1 queries, Query Monitor, Server-Timing, wp profile and wp doctor, autoloaded options, Redis object cache hit rate, transients, WP_CACHE_KEY_SALT. Adds the runner and Redis notes on top of the official procedure. For Eloquent query design use acorn-data; for PHP type errors use wp-phpstan.","https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fskills\u002Fwp-performance\u002FSKILL.md",[],[187,188,189,107,190,191,192,193,194,195,196,197,198,115,199,200,201,202,24,179],"performance","wp performance","design","query design","official","notes","monitor","doctor","cache","server","redis","page","queries","runner","query","type",{"skillNo":204,"name":205,"nameZh":6,"description":206,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":207,"categories":208,"keywords":209,"publishedAt":39},"01M6GKVZN243XQB5QWZ5ZKMG7P","wp-hooks-lifecycle","Use when adding, moving or debugging WordPress actions and filters in an Acorn project - add_action\u002Fadd_filter priority and accepted_args, where a hook belongs (setup or filters files vs a provider boot()), load order (mu-plugins, plugins_loaded, after_setup_theme, init), when Acorn boots per profile, hooks that never fire on Acorn routes, REST or Livewire requests (template_redirect, wp_head), save_post firing twice in the block editor, the_content priorities. For ACF hooks use acf-native; for provider structure use acorn-stack.","https:\u002F\u002Fgithub.com\u002Fhekivo\u002Fkivo-wise\u002Fblob\u002Fmain\u002Fskills\u002Fwp-hooks-lifecycle\u002FSKILL.md",[],[36,31,210,107,211,212,38,151,103,20,153,115,213,214,215,21,216,157,217,25],"wp hooks lifecycle","init","boot","never","filters","files","structure","filter"]