Payload Plugins
Pluginspayload-dev-tools

How it works

Marker-based plugin discovery, layered gating, server-side draft mode, and why the toolbar persists across navigation.

For AI / LLMs: View Markdown

You don't need any of this to use the plugin — it's here for when you're curious or debugging.

How it works

  • Plugin discovery is marker-based. Each @pro-laico/* plugin stashes its resolved slugs and options on config.custom (payloadSeed, payloadImages, payloadIcons, payloadFonts, payloadMux, payloadRevalidate). The snapshot builder reads those markers off payload.config. No plugin imports, so nothing else is a dependency; third-party setups just show fewer panels.

  • The dev page file passes Payload in. createDevPage({ payload }) takes an app-supplied Payload handle (e.g. getPayload({ config })) — the plugin registers no onInit and stashes no config on globalThis.

  • Seeding goes through the seed plugin's own endpoint. The seed card and toolbar POST to /api/seed: same gate (ENABLE_SEED=true + a logged-in user), same { error, issues } responses, surfaced inline.

  • Draft mode flips server-side. The panel header's draft switch calls GET /api/dev/draft?enable=1|0, which drives Next's draftMode() — the real __prerender_bypass cookie, exactly as a preview route would set it — then refreshes the page you're on so drafts render in or out. It's URL-addressable too (?to=/path redirects after flipping), like /api/dev/stage.

  • The toolbar persists because it lives in the layout. Its rows are client-side <Link>s, so navigating between dev pages never remounts it. It injects one <style> tag (all .pdt-/.pdtp- prefixed, no host theme dependency; --pdt-accent is the override seam), and it only ever receives test labels, never render functions.

  • Gating is layered, and clamped at the top. Every surface asks one question: enabled, which defaults to NODE_ENV === 'development' and can never resolve true under NODE_ENV=production — a deployed build serves no endpoints, no pages, and no toolbar, whatever you pass. true is for the environments in between, like a test run.

    Below that clamp the gate is config-time: when it's off the plugin hands back the config untouched, so the /api/dev* endpoints are never registered — they don't exist rather than 404 per request. The pages and toolbar check the same value per render. The one per-request check is options.access.dev, and it covers the endpoints only; the /dev pages read enabled alone.

    That clamp buys more than secrecy. Because these pages cannot render during a production build, their live Local API reads can never be prerendered — so the snapshot cannot quietly serve the build machine's collection counts to a deployed site. A diagnostics page that lies is worse than one that 404s.

  • It sits beside Next's own dev indicator, on purpose. The launcher borrows its idiom and defaults to the opposite corner (Next's is bottom-left).

On this page