PHPackages                             rondodevs/craft-toolkit - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. rondodevs/craft-toolkit

ActiveCraft-plugin

rondodevs/craft-toolkit
=======================

Internal Craft CMS toolkit: site config overrides, KV/edge cache purge helpers, static labels and related utilities.

v0.0.10(2w ago)0100↓37.5%MITPHPPHP &gt;=8.4

Since Jul 12Pushed 2w agoCompare

[ Source](https://github.com/rondodevs/craft-toolkit)[ Packagist](https://packagist.org/packages/rondodevs/craft-toolkit)[ RSS](/packages/rondodevs-craft-toolkit/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (2)Versions (11)Used By (0)

Craft Toolkit
=============

[](#craft-toolkit)

Internal Craft CMS plugin bundling a set of control panel utilities:

- **Site Config** — CP-editable overrides for site name/URL on top of env defaults, exposed via GraphQL.
- **KV Cache** — settings and controls to purge an external edge/KV cache (tags or full flush) when entries/assets change.
- **Static Labels** — CP-editable label overrides per site, exposed via GraphQL.
- **Average Color** — enable/disable and per-volume control for automatic average-color calculation on image assets, with a check of which volumes already have an `averageColor` field in their field layout. The `media` volume is selected by default when present.
- **Org Schema** — CP panel with per-site defaults for the schema.org identity (Organization, LocalBusiness, MedicalClinic/MedicalBusiness, Person, ...: name, logo, one or more addresses, `sameAs` social profiles, contact info), exposed via GraphQL for Nuxt SEO's [default schema.org identity](https://nuxtseo.com/docs/schema-org/guides/default-schema-org). Plus an **Org Schema** field type to attach one or more arbitrary schema.org pieces (Article, Product, Event, MedicalClinic, FAQPage, ...) to individual entries, each with type-specific basic fields (e.g. NAP + geo-coordinates + opening hours for locations) and a JSON escape hatch for anything else.
- Misc handlers: a CP alert when the default GraphQL route is missing, and a site-request redirect controller.

Requirements
------------

[](#requirements)

- Craft CMS 5.0.0 or later
- PHP 8.2 or later

Getting started (development)
-----------------------------

[](#getting-started-development)

Requires [DDEV](https://ddev.com) and Docker/OrbStack running locally.

1. Clone the repo and start DDEV (spins up `web`/`db` containers, no host PHP needed):

    ```
    git clone git@github.com:rondodevs/craft-toolkit.git
    cd craft-toolkit
    ddev start
    ```
2. Install the plugin's own dependencies, so your IDE resolves `craft\...` classes:

    ```
    ddev composer install
    ```
3. Install the playground's dependencies (symlinks this plugin in via the `path`repository already committed in `playground/composer.json`):

    ```
    ddev exec --dir /var/www/html/playground composer install
    ```
4. Create the playground's local env file (DB credentials are injected automatically by DDEV; leave `CRAFT_APP_ID`/`CRAFT_SECURITY_KEY` blank, `craft install` fills them in):

    ```
    cp playground/.env.example.dev playground/.env
    ```
5. Install Craft — since `playground/config/project/project.yaml` is already committed, this provisions the DB schema and applies that project config automatically:

    ```
    ddev exec --dir /var/www/html/playground php craft install \
      --interactive=0 \
      --username=admin \
      --email=you@example.com \
      --password=changeme123 \
      --site-name="Toolkit Playground" \
      --site-url="https://craft-toolkit-playground.ddev.site" \
      --language=en-US

    ddev exec --dir /var/www/html/playground php craft plugin/install toolkit
    ```
6. Open  and log in.

From here, edit anything under `src/` and reload the CP — changes are live via the symlinked plugin, no reinstall step. See [DDEV playground](#ddev-playground)below for how the playground itself was scaffolded and how to regenerate it from scratch if it ever needs a reset.

Installation
------------

[](#installation)

### From Packagist (once published)

[](#from-packagist-once-published)

```
composer require rondodevs/craft-toolkit
```

Then install the plugin in the Craft control panel, or via:

```
php craft plugin/install toolkit
```

### Local development (path repository)

[](#local-development-path-repository)

While developing this plugin alongside a Craft project, add a `path` repository to the consuming project's `composer.json` so Composer symlinks it instead of downloading a tagged release:

```
{
    "repositories": [
        {
            "type": "path",
            "url": "../../studio-fes/craft-toolkit",
            "options": { "symlink": true }
        }
    ],
    "require": {
        "rondodevs/craft-toolkit": "*"
    }
}
```

Adjust the `url` to the relative (or absolute) path to this directory, then run `composer update rondodevs/craft-toolkit`. Changes made here are picked up immediately in the consuming project without republishing.

### DDEV playground

[](#ddev-playground)

For interactive testing (CP, GraphQL, utilities) this repo ships a DDEV project rooted at the repo root with its docroot at `playground/web`. The `playground/` directory holds a full Craft install that requires this plugin via a local `path` repository (symlinked), so edits under `src/` are picked up immediately — no reinstall needed. It's gitignored; regenerate it anytime with:

```
ddev start
rm -rf playground   # only if it already exists and you want a clean slate
ddev exec composer create-project craftcms/craft playground --no-interaction
```

Then edit `playground/composer.json`:

```
{
    "repositories": [
        { "type": "path", "url": "..", "options": { "symlink": true } }
    ],
    "require": {
        "rondodevs/craft-toolkit": "*"
    }
}
```

```
ddev exec --dir /var/www/html/playground composer update --no-interaction

ddev exec --dir /var/www/html/playground php craft install \
  --interactive=0 \
  --username=admin \
  --email=you@example.com \
  --password=changeme123 \
  --site-name="Toolkit Playground" \
  --site-url="https://craft-toolkit-playground.ddev.site" \
  --language=en-US

ddev exec --dir /var/www/html/playground php craft plugin/install toolkit
```

Then visit `https://craft-toolkit-playground.ddev.site/admin/login`.

Org Schema (schema.org / Nuxt SEO)
----------------------------------

[](#org-schema-schemaorg--nuxt-seo)

Two pieces work together to feed [Nuxt SEO's schema-org module](https://nuxtseo.com/docs/schema-org/getting-started/introduction):

- **Toolkit → Org Schema** (CP panel): per-site defaults for the site's schema.org identity — `Organization`, `Corporation`, `NGO`, `LocalBusiness`, `ProfessionalService`, `MedicalBusiness`, `MedicalClinic`, `EducationalOrganization` or `Person` — following the shape expected by Nuxt SEO's [default schema.org identity](https://nuxtseo.com/docs/schema-org/guides/default-schema-org)(`name`, `legalName`, `url`, `logoUrl`, `description`, `email`, `telephone`, `sameAs`, `addresses`). `logoUrl` is picked via a native Craft asset selector (upload or choose an existing image) rather than typed as a raw URL, and resolved to its URL for output. Fields shown in the CP adjust to what each type actually defines per schema.org (verified against schema.org directly):

    FieldShown for`legalName`, `logoUrl``Organization`, `Corporation`, `NGO`, `LocalBusiness`, `ProfessionalService`, `MedicalBusiness`, `MedicalClinic`, `EducationalOrganization` — **not** `Person` (schema.org's `Person` has neither property)`priceRange``LocalBusiness`, `ProfessionalService`, `MedicalBusiness`, `MedicalClinic` — defined directly on `LocalBusiness``openingHours`the same `LocalBusiness` types, **plus** `EducationalOrganization` — `EducationalOrganization` inherits `openingHours` from `CivicStructure` (`Thing > Place > CivicStructure > EducationalOrganization`), but does *not* inherit `priceRange` from anywhere in its hierarchy`addresses` supports **multiple locations** — for a multi-clinic/multi-branch business, add one per physical location. Since `priceRange` and `openingHours` are properties of a physical *place* in schema.org (not of the identity as a whole), they live on **each address** rather than on the identity, and each location can have its own value — so two locations of the same `MedicalClinic` can have different hours. `openingHours` is entered via a day-picker + open/close time per schedule and compiled into an array of schema.org strings, e.g. `["Mo-Fr 09:00-18:00", "Sa 10:00-14:00"]`. Exposed via GraphQL:

    ```
    query OrgSchema($site: String!) {
      orgSchema(site: $site) {
        type
        name
        legalName
        url
        logoUrl
        sameAs
        addresses {
          streetAddress
          addressLocality
          addressRegion
          postalCode
          addressCountry
          priceRange
          openingHours
        }
      }
    }
    ```

    For a multi-location business (e.g. a medical group with several clinics), use `MedicalBusiness` here for the sitewide identity with one address (and its own price range/hours) per clinic. If a location also needs its own dedicated page, model it as its own entry instead and put its NAP/geo/hours on that entry via the **Org Schema field** below with `@type` set to `MedicalClinic` (or `Dentist`/`Physician`/`Hospital`/`Pharmacy`) — its basic fields cover name, telephone, street address/locality/region/postal code/country (merged into a nested `address`), latitude/longitude (merged into a nested `geo`), `openingHours` and `priceRange`.
- **Org Schema field**: a field type you can add to any field layout to attach one or more arbitrary schema.org pieces (`Article`, `Product`, `Event`, `FAQPage`, `HowTo`, ...) to a specific entry/element. Each row is a `@type` plus a JSON object of additional properties; GraphQL exposes each piece pre-merged and ready to parse:

    ```
    {
      entry(slug: "my-entry") {
        ... on blog_default_Entry {
          orgSchema {
            json
          }
        }
      }
    }
    ```

In Nuxt, combine both with `useSchemaOrg()` — the site-wide identity via `defineOrganization()`/`definePerson()`, and the entry-level pieces passed through as raw schema.org objects:

```
const { data } = await useAsyncQuery(OrgSchemaQuery, { site: 'default' })
const { data: entry } = await useAsyncQuery(EntryQuery, { slug })

useSchemaOrg([
  defineOrganization({
    name: data.value.orgSchema.name,
    logo: data.value.orgSchema.logoUrl,
    sameAs: data.value.orgSchema.sameAs,
    address: data.value.orgSchema.addresses, // one, or an array for multi-location businesses
  }),
  // Each location entry's own Org Schema field (e.g. @type: MedicalClinic) already
  // contains a ready-to-use JSON-LD piece with NAP, geo, openingHours, priceRange...
  ...(entry.value.orgSchema ?? []).map((piece) => JSON.parse(piece.json)),
])
```

Publishing to Packagist
-----------------------

[](#publishing-to-packagist)

1. Push this repository to GitHub (e.g. `github.com/rondodevs/craft-toolkit`).
2. Tag a release, e.g. `git tag v1.0.0 && git push --tags`.
3. On [packagist.org](https://packagist.org), submit the GitHub repository URL.
4. Enable the GitHub Packagist webhook (Packagist "Settings" tab -&gt; instructions, or add it manually under the GitHub repo's Settings -&gt; Webhooks) so new tags are picked up automatically.
5. From then on, `composer require rondodevs/craft-toolkit` resolves the package for anyone with access to the repository.

License
-------

[](#license)

MIT

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance96

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Total

10

Last Release

20d ago

PHP version history (2 changes)v0.0.1PHP ^8.2

v0.0.2PHP &gt;=8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/ec2d7160598615578acedb1b9ccb7be71b9307435431bb9d6765ab0b685f842a?d=identicon)[plcdnl](/maintainers/plcdnl)

---

Top Contributors

[![plcdnl](https://avatars.githubusercontent.com/u/32842043?v=4)](https://github.com/plcdnl "plcdnl (13 commits)")

---

Tags

cmsCraftcraftcmscraft-plugintoolkit

### Embed Badge

![Health badge](/badges/rondodevs-craft-toolkit/health.svg)

```
[![Health](https://phpackages.com/badges/rondodevs-craft-toolkit/health.svg)](https://phpackages.com/packages/rondodevs-craft-toolkit)
```

###  Alternatives

[verbb/formie

The most user-friendly forms plugin for Craft.

102406.3k79](/packages/verbb-formie)[verbb/vizy

A flexible visual editor field for Craft.

4252.4k1](/packages/verbb-vizy)[verbb/hyper

A user-friendly links field for Craft.

24158.0k15](/packages/verbb-hyper)[verbb/events

A full-featured plugin for event management and ticketing.

2412.3k](/packages/verbb-events)[verbb/icon-picker

A slick field to pick icons from. Supports SVGs, Sprites, Webfonts, Font Awesome and more.

16174.4k7](/packages/verbb-icon-picker)[verbb/tablemaker

Create customizable and user-defined table fields.

40181.7k2](/packages/verbb-tablemaker)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
