Skip to content

Phase 2: per-plugin adoption sweep of the new core primitives #136

Description

@olliethedev

Context

Tracking issue for phase 2 of the v3.0.0 core simplification. Phase 1 builds the primitives (#127 ✅, #130 ✅, #128, #129, #131, #132, #133 — core only); this issue tracks adopting them across all plugins, one PR per plugin so each plugin is touched exactly once.

Blog goes first and establishes the reference pattern; its PR should be reviewed with extra care since the other seven copy it.

Per-plugin task list

Each plugin PR does ALL of the following in one pass:

  1. Migrate query-keys.ts + client/hooks/*.tsx to createResource (Internal resource-hook factory: deduplicate query-keys/hooks boilerplate across plugins #129); keep public hook names and query-key-defs.ts SSG discriminators intact
  2. Migrate form components to resource useForm, including field-level StackError mapping (Internal resource-hook factory: deduplicate query-keys/hooks boilerplate across plugins #129)
  3. Adopt useSelect where the plugin has a relation picker (Internal resource-hook factory: deduplicate query-keys/hooks boilerplate across plugins #129)
  4. Replace direct sonner imports with useNotify() (Notification provider: pluggable notify() instead of hardcoded sonner toasts in every plugin #131)
  5. Convert UI strings to t(key, default) with namespaced keys (i18n provider: translatable plugin UI strings with English defaults #132)
  6. Wrap permission-sensitive controls in <CanAccess> (Auth provider contract: centralized identity + permissions (getIdentity/can) across client and backend #128)
  7. Move list/filter/pagination state to useListState (URL-synced list state: filters, tabs, and pagination survive refresh, back button, and sharing #133)
  8. Delete plugin-local legacy code: error helpers, SHARED_QUERY_CONFIG copy, hand-wired form logic, plugin-local guard implementations
  9. Point the plugin's E2E/unit coverage at the new paths (do not leave tests validating deleted code)

Cross-cutting dual paths (override type fields, onBefore*PageRendered types, CommentThread identity props, StackProvider fallback logic) are NOT removed here — that is phase 3, after the last sweep lands.

Plugins

  • blog (reference migration)
  • cms
  • form-builder
  • comments
  • kanban
  • media
  • ui-builder
  • ai-chat

Acceptance criteria

  • All 8 plugins migrated; public hook APIs unchanged
  • Zero plugin-local copies of error helpers / shared query config (rg verified)
  • Zero direct sonner imports in plugin components
  • Blog reference numbers hold: query-keys.ts + hooks (~1000 lines) collapse to ~150 lines of declarations
  • Server-side Zod validation failure renders as inline field error, not a generic toast (unit test, per plugin with forms)
  • All unit + E2E suites green after each plugin PR (main stays shippable throughout)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions