# Upgrading

> Plainkit 0.28.0. Generated by scripts/build-skills.mjs from CHANGELOG.md and core/tools/api-surface.mjs. Do not edit: change the source and run the generator.

This is a blast-radius recipe, not a changelog readout: the goal is a checklist of what to change in *this app*, not a summary of what Plainkit changed in the abstract.

## 1. Find the two versions

The installed version is `dist/manifest.json`'s `version` field, or the `PK_VERSION` export of `dist/js/version.js`. The target is the version you are moving to (latest release unless the user names one).

## 2. Pull what changed between them

`CHANGELOG.md` (`https://github.com/skulmunkie/plainkit/blob/main/CHANGELOG.md`, not shipped in the package) has one section per released version, with `### Breaking`, `### Removed`, `### Changed`, `### Fixed`, `### Added` and `### Notes` subsections; every entry names the affected element, component or export and its issue number. Read every version's section between the installed one and the target (a target that is an unreleased build of `main` or `next` has its newest entries only as the fragments in the repository's `changelog/unreleased/` folder: read those too), and pull out `Breaking`/`Removed`/`Changed` entries first (these are the ones that can break a build or change behaviour silently) and `Added` second (opportunities, not urgent). A running app already surfaces one more signal for free: an element or a Blazor component that is deprecated but not yet removed logs a one-time console/ILogger warning (`js/deprecation.js`) naming what to use instead — check the app's own logs, not just the changelog, for anything still on borrowed time.

## 3. Cross-reference against this app's own code

A changelog entry only matters if the app uses what it names. For every tag, component, parameter, event or slot the step above turned up, search the app itself (not the Plainkit source) for it — grep for the Razor component name or the element tag, the parameter name, the event name. The output of this step is specific: "this app uses `PkTable`'s `EmptyContent` in 3 files, and the changelog says it was renamed," not "`EmptyContent` was renamed."

## 3b. Let the app tell you about removed CSS classes

Removed classes (retired class-based components, removed `u-*` utilities) are silent: nothing fails, the styling just disappears, and a grep for names you did not know to look for misses them. `js/compat-warn.js` is an opt-in module (zero cost unless imported): `import { checkCompatClasses } from './plainkit/js/compat-warn.js'; checkCompatClasses();` in a dev build logs each retired or removed class it finds in the running app, once, with a replacement (scope `compat`, warn level). Load the app's main pages with it on and add every warning to the checklist. Do not ship the call to production.

## 4. Produce a checklist, most severe first

Group the matches from step 3 by severity (breaking first), each with the file(s) it appears in — the shape a person or another agent can work through and tick off, not a wall of prose.

## 5. Say what is mechanical and what needs a judgment call

A renamed parameter or component is a mechanical find-and-replace: make the change yourself. A removed component with no direct replacement, or a behaviour change with no compile-time signal, needs a person to decide: flag it on the checklist instead of guessing.

## 5b. Names and behaviour that changed (SDK)

Nothing is removed without a Breaking entry in the changelog; these are the ones that need a search of the app:

- `createPage` no longer runs its own busy timers: `pk-loading-overlay` owns the rule (`delay`, `min-time`, both default 0 on the element; the page hands it 150 and 300). An app that sets `busy` on its own overlay now sets `delay` and `min-time` there when it needs them.
- `pk-data-table` and `pk-lookup-picker` take plain props only (`columns`, `page-size`, `label`, `filters`, `empty` ...); there is no `config` (removed: a one-key-per-prop migration is in the changelog). A leftover `config` is ignored, with a one-time console warning: search the app, plain HTML and JS-only pages included, for `config=` and `.config =` on these two tags. `pk-data-table` also has `add-label` and `pk-add`.
- `pk-field-list` hides a slotted `dt`/`dd` pair whose `dd` is empty (`show-empty` keeps it): an app that kept empty pairs for layout adds `show-empty`. A light-DOM content element opts out of the hidden-until-defined rule with `"preUpgrade": "visible"` in its meta.
- `pk-page-header` draws a breadcrumb from `crumbs` (JSON), `home-href` and `back-link`; the `breadcrumb` slot still works. The `pk-breadcrumb` it draws is inside the header's shadow tree, no longer a child in the page DOM: a test, script or style that queries `pk-page-header pk-breadcrumb` (or `pk-breadcrumb` on the page) for the trail finds nothing now; read `crumbs`, or reach through `header.shadowRoot`.

## 6. Report what you found back upstream

An upgrade often turns up something Plainkit itself should fix. File it on `https://github.com/skulmunkie/plainkit/issues` instead of leaving it as a private workaround. File when you find: a bug during or after the upgrade; a gap or missing feature the app works around; a deprecation with no clear replacement; or an inaccuracy in the docs or these skills. A common upgrade-time enhancement is a supported way to test code that depends on an element.

Before you file, search the existing issues, open and closed, for the same problem. If one exists, add a comment with your case and version instead of opening a duplicate; a closed one may be fixed in a newer version than you have.

Write it so a stranger can act on it: a generic, reusable title that names the element, component or export and not your app; the smallest repro you can make (a few lines, not your page); actual versus expected behaviour; and the affected Plainkit version. Leave out app-specific names, data, page paths and any other internal details. Give the type in the title or as a label (bug, enhancement or docs) so triage is quick.

Record the stopgap in the app next to the code that needs it, with the issue link, and remove it in the pull request that bumps Plainkit to the version containing the fix.
