跳到正文
cccskills
免费在 GitHub 公开

provider-swap

Swap the external provider/library that backs a crouton package (e.g. the map renderer, geocoder, editor engine, storage SDK) while keeping the package's public API stable so consuming apps need no changes. Use when asked to "change the X provider", "replace library Y in package Z", "switch from <vendor A> to <vendor B>" inside packages/. Encodes the keep-the-API-stable playbook + the gotchas (dist .d.ts over docs, generator templates, fixtures, dup-dep type clashes).

中文简介正在准备中。当前显示原文说明。

查看安装方法

包含的文件(1)

  • SKILL.md6.8 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Swap a package's external provider (keep the public API)

Replacing the library/SaaS behind a crouton package — the map renderer, the geocoder, the rich-text engine, a storage SDK — is a refactor with an API contract, not a rewrite. The bar: consuming apps (and the generator output) keep working with zero edits. This skill is the playbook + the traps, distilled from the Mapbox→MapLibre swap (#538): a package consumed as a Nuxt layer leaks its provider's types and templates into every app, so the swap has more surface than the component files suggest.

When to use

  • "Change the maps provider", "replace mapbox-gl with maplibre", "switch the geocoder", "swap the editor engine in crouton-editor", "use a different upload SDK".
  • Any task that changes the library or service a packages/* package wraps.
  • Not for adding a brand-new package (use crouton / scaffolding) or for a pure version bump (use dependency-sweep).

Hard gates first (don't skip)

  • ISSUE-FIRST — open the tracking issue before editing (github-tasks). A provider swap is multi-file; an epic + the swap as the unit of work.
  • Packages boundary — editing packages/* needs approval (echo '<pkg>' >> .claude/.package-edit-approved; remove it when done).
  • Decide the non-code questions up front with AskUserQuestion — they change what you build: which library, which tile/style/host, API keys vs keyless, what replaces capabilities the new provider lacks (e.g. MapLibre has no geocoding; Mapbox style URLs are incompatible). Honour repo constraints (OSS, self-hostable, no mandatory SaaS — see ecosystem-check).

The protocol

1. Map the surface before touching code

Grep the package for every public seam, and the whole repo for consumers:

rg -l '<old-lib>|<OldType>|<old-css-prefix>' packages/<pkg>
rg -l 'Crouton<Pkg>|use<Pkg>|<exported-const>' packages apps pocs docs

List: components, composables, server/ routes, app/types, nuxt.config.ts (modules/runtimeConfig/css), crouton.manifest.ts (incl. its generator contribution templates), package.json, CLAUDE.md/README, docs site, .env.example. The manifest's generator template and the docs are the bits most often forgotten.

2. Learn the new library's real API — from the dist, not the docs

Docs sites often 403/whiff. The source of truth is the published types:

npm view <new-lib> version exports peerDependencies
cd /tmp && npm pack <new-lib>@<ver> && tar -xzf *.tgz
# read package/dist/index.d.ts for exact props/events/exports

Confirm: required peers (are the heavy ones optional?), whether it touches window (→ client-only + build.transpile), and which capabilities are missing vs the old provider (plan replacements).

3. Keep the public API stable (the whole point)

  • Same component names, props, slots, emits; same composable names + return shapes.
  • If you must rename internals, re-export the old names as deprecated aliases (e.g. export const OLD_STYLES = NEW_STYLES) so external imports don't break.
  • Same server-route shape: if the proxy's response shape is consumed (e.g. useGeocode expects { features:[{center,...}] }), normalise the new provider's response back to it rather than changing callers.
  • Near-drop-in forks make this easy (maplibre-gl ↔ mapbox-gl: identical Marker/Popup/Map runtime API → only import strings + CSS prefixes change), but verify per-symbol against the .d.ts.

4. Don't forget the generator + config surface

  • A package's crouton.manifest.ts may ship generated form/list templates (enhanceForm/enhanceList) and detection patterns. Update the template to the new provider, and keep its bindings consistent with the package's own components (e.g. the slot→marker :map="map as any" cast — see the type-clash trap below).
  • Update nuxt.config.ts: drop the old module, add build.transpile for ESM deps that hit the DOM, replace token/runtimeConfig with the new keys.
  • Update package.json deps + keywords + a version bump.

5. Sync the docs (large surface)

Package CLAUDE.md + README, the docs site page, the modules/packages tables, and .env.example all name the old provider. Search and update. Add a short migration note (what env vars went away, what URLs are now invalid).

6. Verify — and add a fixture if one is missing

  • pnpm -r --filter './apps/*' typecheck (the consuming-app gate).
  • A package that contributes generator templates needs a fixture that actually generates from it. A typecheck of existing apps can miss the generated path (e.g. velo uses a bespoke form, so the generated map form's type bug only surfaced once with-maps generated one). Add/extend an e2e fixture (e2e/CLAUDE.md) that exercises the swapped surface; run e2e-smoke.

Gotchas (each one bit during #538)

  • Docs site blocks fetching → npm pack + read .d.ts (step 2).
  • Capability gaps → the new provider may not do everything the old did (MapLibre: no geocoding, incompatible style URLs). Decide the replacement with the user before coding (step "Hard gates").
  • CSS class prefixes change (.mapboxgl-* → .maplibregl-*) — grep styles.
  • Duplicate-dependency type clash — if the monorepo has two versions of the new lib (a transitive old one + your new one), the same class can have two type identities; a slot value typed by one won't satisfy a prop typed by the other ("missing _privateMethod from type Map$1"). Cast at the boundary (as any) consistently, matching how the package's own components already bind it.
  • Generated-template path is untyped-tested until a fixture generates it (step 6).
  • Don't widen contribution scope by accident — a package's generator contribution should only apply when the app uses that package; collection-name reservations are global footguns (see #558).

Output

A PR (Closes #NN) where: the public API is byte-stable for consumers, the new provider is keyless/self-hostable per constraints (or the key is documented), docs carry a migration note, and a fixture proves a generated consuming surface still boots + works. Run postmortem at epic close — provider swaps are exactly the kind of first-of-their-kind work whose lessons should feed back here.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

a11y

免费

Accessibility review for Vue surfaces — the code-cleaning analog of /code-review and /simplify, pointed at WCAG/ARIA. Reviews just your diff (or a package/file), rates findings by severity, and either comments inline on the PR (--comment) or applies the safe fixes for you (--fix). Steers the depth-aware `a11y` subagent. Use when asked to "check accessibility", "a11y this", "audit ARIA/keyboard", or run /a11y.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

ask-human

免费

Emit a blocking question the owner can read in ~10 seconds and answer in one reply — the scannable, recommendation-first handoff every agent posts when it hits a fork it can't own. Leads with the one decision + a recommendation, carries the 🤖 provenance header, doubles as the

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

audit

免费

Audit packages for documentation completeness, detect drift between code and docs, and maintain documentation quality across the monorepo. Use when checking package docs, running audits, or reviewing documentation health.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

Author a placeable layout block that looks right at ANY pane size. The one hard rule — size to the PANE with container queries (@container), never the viewport — plus list/form playbooks and the sizing contract (minWidth etc.) the viability metric reads. Use when adding/converting a croutonLayoutBlocks block, or when a block overflows/breaks in a narrow pane.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

When a bug or regression is reported, the FIRST step — before fixing — is to research how and when it was introduced (git archaeology), then record that finding on the tracking issue/PR. Use the moment a bug, error, broken build, or "this used to work" is reported, before writing a fix. Produces a first-bad-commit (or "not a code regression") note you paste onto the issue.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

commit

免费

Smart, granular git commits following monorepo conventions. Analyzes changes, filters to session-relevant files, groups by intent, and uses conventional commit format. Use when committing code changes.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

查看 FriendlyInternet 的全部技能

报告此技能的问题