Skip to main content
Plans decide what a workspace can do. A plan config extension adds your own fields to the plan editor, stores them with the plan, and carries them into the snapshot a subscription is based on.

The interface

Implementation

src/PlanConfigExtension.php

Register it

src/Plugin.php
The key you register under namespaces your settings inside the plan, under config.extensions.{key}.

The editor template

The plan editor is an Alpine form bound to a model object. Your template receives key and defaults, and binds inputs into model.config.extensions[key]:
templates/plan.twig
The editor initializes your subtree from getDefaults() when a plan doesn’t have it yet, so you can bind directly without guarding for missing keys.

The snapshot template

Snapshots are historical copies of a plan, so the template is read-only, and the data may predate your extension:
templates/plan-snapshot.twig
Use optional chaining, since older snapshots won’t contain your key.

Read the settings at runtime

Your settings travel with the plan and its snapshots, so read them from the workspace’s subscription:
In Twig, the same data is on the workspace:
Aikeedo stores and displays your settings, but it doesn’t enforce them. Every limit you define has to be checked by your own code, in every path that can create or consume the resource.

Design notes

  • Use null for unlimited, and say so in the field’s help text.
  • Default to off. A new extension must not silently enable a paid capability on every existing plan.
  • Keep keys stable. They’re written into every plan snapshot, and renaming one orphans historical data.
  • Keep it small. Per-plan settings belong here; global configuration belongs on your settings page.

Testing

Your section appears in the plan editor, both for new and existing plans.
Saving a plan persists your values, and reopening shows them.
A snapshot of the plan shows your read-only summary.
A workspace on a plan with the capability disabled is blocked by your checks.
A cap is enforced at the limit, not one over.