diff --git a/raw/performance__overview.md b/raw/_processed/performance__overview.md similarity index 100% rename from raw/performance__overview.md rename to raw/_processed/performance__overview.md diff --git a/wiki/_master-index.md b/wiki/_master-index.md index 387c623..72772db 100644 --- a/wiki/_master-index.md +++ b/wiki/_master-index.md @@ -35,7 +35,7 @@ This 3-hop pattern works for hundreds of articles without vector search. | [[wiki/reports/_index\|reports/]] | Weekly and monthly summaries — generate: `uv run python scripts/report-generator.py --weekly` | 1 | | [[wiki/infrastructure/_index\|infrastructure/]] | Server inventory: all 10 SSH hosts — optical, optical-dev, optical-prod, baic, librechat, modocmms, box-cli, aimpress, pve | 12 | | [[wiki/testing/_index\|testing/]] | Web app testing: functional, performance, security, UI types; TDD/BDD/Agile methodologies; Selenium/Cypress/Playwright/JMeter/OWASP ZAP tools | 1 | -| [[wiki/payloadcms/_index\|payloadcms/]] | Full Payload CMS reference — getting started, config, database (Postgres/MongoDB/SQLite), all 22 field types, access control, hooks, authentication (cookies, JWT, API keys, custom strategies, token data), admin UI, custom components, Lexical rich text, live preview, versions/drafts, Local/REST/GraphQL APIs, queries, plugins, jobs queue, upload, ecommerce, production deploy, TypeScript, migration guides, i18n, localization, hierarchy | 111 | +| [[wiki/payloadcms/_index\|payloadcms/]] | Full Payload CMS reference — getting started, config, database (Postgres/MongoDB/SQLite), all 22 field types, access control, hooks, authentication (cookies, JWT, API keys, custom strategies, token data), admin UI, custom components, Lexical rich text, live preview, versions/drafts, Local/REST/GraphQL APIs, queries, plugins, jobs queue, upload, ecommerce, production deploy, TypeScript, migration guides, i18n, localization, hierarchy | 112 | | [[wiki/shared-patterns/_index\|shared-patterns/]] | Oliver Agency standard library patterns: httpx, structlog, pydantic-settings, alembic — reuse before writing from scratch | 4 | | [[wiki/mistakes/_index\|mistakes/]] | Anti-patterns extracted from sessions — per-stack running lists (fastapi, react, docker, postgres, general) — injected at session start | 5 | diff --git a/wiki/concepts/figma-code-connect-api-gotchas.md b/wiki/concepts/figma-code-connect-api-gotchas.md index 0222b5f..538a321 100644 --- a/wiki/concepts/figma-code-connect-api-gotchas.md +++ b/wiki/concepts/figma-code-connect-api-gotchas.md @@ -8,6 +8,8 @@ updated: 2026-05-15 # Figma Code Connect API — Gotchas and Type Traps + + Collected from writing `.figma.tsx` Code Connect files and iterating with the MCP. All of these fail silently or with opaque errors. --- @@ -109,6 +111,30 @@ const node = figma.currentPage.findInstance({ --- +## 7. VARIANT Enum Mapping Must Be Exhaustive + +When mapping a Figma VARIANT property to a code prop via `figma.widget.usePropertyMenu`, every possible variant value must be listed. Missing values silently produce `undefined`, which is then injected into JSX — no error thrown, malformed output. + +```ts +// BAD — "Outline" variant not listed → produces undefined +figma.codeConnect.VARIANT('ButtonVariant', { + 'Default': 'primary', + 'Ghost': 'ghost', + // 'Outline' missing → node with Outline variant → prop = undefined +}) + +// GOOD — enumerate all values +figma.codeConnect.VARIANT('ButtonVariant', { + 'Default': 'primary', + 'Ghost': 'ghost', + 'Outline': 'outline', // ← exhaustive +}) +``` + +**How to audit:** list all possible values of the Figma property via `node.componentPropertyDefinitions[propName].variantOptions` and cross-check against the VARIANT mapping. + +--- + ## Related - [[wiki/concepts/figma-code-connect-plan-requirements|figma-code-connect-plan-requirements]] — MCP vs CLI plan requirements diff --git a/wiki/concepts/figma-design-to-code-workflow.md b/wiki/concepts/figma-design-to-code-workflow.md index 802e140..2850146 100644 --- a/wiki/concepts/figma-design-to-code-workflow.md +++ b/wiki/concepts/figma-design-to-code-workflow.md @@ -9,7 +9,7 @@ sources: - "raw/Add custom rules and instructions.md" - "daily/2026-05-13.md" created: 2026-05-13 -updated: 2026-05-13 +updated: 2026-05-15 --- # Figma Design-to-Code — Workflow & Best Practices @@ -168,6 +168,57 @@ Get the `variableKey` from `get_variable_defs` (MCP) or from the Figma dev panel --- +## `use_figma` — Build Pattern (Atomic Section-per-Call) + +When writing designs INTO Figma via `use_figma`, process one section per call. This limits error blast radius — if one section fails, others already written are unaffected and the call can be retried in isolation. + +``` +# WRONG — one call, entire page +use_figma(sections=[hero, cards, footer, cta]) + +# CORRECT — one call per section +use_figma(sections=[hero]) +use_figma(sections=[cards]) +use_figma(sections=[footer]) +``` + +**Layer naming is generic by default.** `use_figma` uses design-system labels for layer names (e.g. `Frame`, `Rectangle`), not component names. Rename critical layers explicitly after creation if semantic naming is required. + +--- + +## Component Default Props — Source Code Is the Authority + +When implementing from Figma, component defaults (variant, size, state) must be read from **source code**, not inferred from JSX props visible in the Figma export. + +A component may visually appear in its "primary" state in Figma while the source default is actually `variant="secondary"`. Relying on the Figma screenshot to infer the default leads to incorrect output. + +```ts +// Source code is the authority for defaults +// BAD: infer from Figma screenshot → "this button looks primary, so default is primary" +// GOOD: read component file → const Button = ({ variant = 'secondary' } = {}) => ... +``` + +--- + +## Screenshots — Full View Hides Text Truncation + +`get_screenshot` on a full page or large frame at reduced resolution **hides text truncation** — clipped text looks normal at small scale but is cut off in reality. + +**Always screenshot individual sections by node ID** when validating text-heavy components: + +``` +# BAD — full page screenshot at low resolution +get_screenshot(fileKey, fileKey) # root node = whole file + +# GOOD — per-section by node ID +get_screenshot(fileKey, "123:456") # specific section node +get_screenshot(fileKey, "123:789") # another section +``` + +Use the node IDs from `get_metadata` to identify section-level nodes. + +--- + ## Common Failure Modes | Symptom | Cause | Fix | diff --git a/wiki/payloadcms/_index.md b/wiki/payloadcms/_index.md index d90c6c0..a4ba1e2 100644 --- a/wiki/payloadcms/_index.md +++ b/wiki/payloadcms/_index.md @@ -29,7 +29,8 @@ | [[wiki/payloadcms/ecommerce-advanced\|Ecommerce — Advanced / Piecemeal Collections API]] | All 8 `create*Collection` factory functions with full prop/access tables + TS types (CurrenciesConfig, Currency, CountryType, InventoryConfig) | raw/ecommerce__advanced.md | 2026-05-15 | | [[wiki/payloadcms/ecommerce-frontend\|Ecommerce — Frontend React Utilities]] | EcommerceProvider, useCart, usePayments (2-step checkout), useAddresses, useCurrency, useEcommerceConfig, useEcommerce; session management (onLogin, onLogout, mergeCart) | raw/ecommerce__frontend.md | 2026-05-15 | | [[wiki/payloadcms/ecommerce-payment-adapters\|Ecommerce — Payment Adapters]] | Payment adapter pattern, Stripe setup + webhooks (local CLI), custom adapter interface (initiatePayment/confirmOrder/group field), client-side adapter, security gotchas | raw/ecommerce__payments.md | 2026-05-15 | -| [[wiki/payloadcms/production\|Production & Performance]] | Deployment, Docker, building without DB, abuse prevention, performance optimization patterns | raw/production__*.md, raw/performance__overview.md | 2026-05-15 | +| [[wiki/payloadcms/production\|Production & Performance]] | Deployment, Docker, building without DB, abuse prevention, performance optimization patterns | raw/production__*.md | 2026-05-15 | +| [[wiki/payloadcms/performance-overview\|Performance Optimization]] | DB proximity, indexes, block references, cached instance, direct DB calls, hooks/validation perf, Turbopack, devBundleServerPackages | raw/performance__overview.md | 2026-05-15 | | [[wiki/payloadcms/typescript\|TypeScript]] | Native TS support, `generate:types` CLI, `interfaceName` for reusable interfaces, TS language service plugin | raw/typescript__*.md | 2026-05-15 | | [[wiki/payloadcms/migration-troubleshooting\|Migration & Troubleshooting]] | v2→v3 and v3→v4 migration guides, codemod, dependency dedup fix, hierarchy feature, Vercel Content Link, examples | raw/migration-guide__*.md, troubleshooting, hierarchy, integrations | 2026-05-15 | | [[wiki/payloadcms/react-hooks\|React Hooks]] | All `@payloadcms/ui` hooks: useField, useForm, useAllFormFields, useDocumentInfo, useAuth, useConfig, usePayloadAPI, and more | raw/admin__react-hooks.md | 2026-05-15 | diff --git a/wiki/payloadcms/performance-overview.md b/wiki/payloadcms/performance-overview.md new file mode 100644 index 0000000..1d0f52e --- /dev/null +++ b/wiki/payloadcms/performance-overview.md @@ -0,0 +1,148 @@ +--- +title: "Payload CMS — Performance Optimization" +aliases: [payloadcms-performance, payload-performance] +tags: [payloadcms, performance, optimization, nextjs] +sources: [raw/performance__overview.md] +created: 2026-05-15 +updated: 2026-05-15 +--- + +# Payload CMS — Performance Optimization + +Guide to making Payload apps run as fast as possible — database, APIs, Admin Panel, and local dev. + +## Database + +### Proximity +- Host database in the **same region** as the server — cross-region latency is significant + +### Indexes +- Add `index: true` to any field queried frequently → avoids full document scans +- See [[wiki/payloadcms/database-indexes|Database Indexes]] for compound indexes and gotchas + +### Queries +- Combine multiple query optimizations together: `select`, `depth`, `limit`, `populate` +- See [[wiki/payloadcms/queries|Queries]] → Performance section for `depth`/`select` patterns + +## API Request Lifecycle + +Payload's request lifecycle includes hooks, access control, and validations — all add overhead. + +### Hooks +- Write **lightweight hooks** — avoid blocking operations or unnecessary DB calls +- Offload long-running tasks to [[wiki/payloadcms/jobs-queue|Jobs Queue]] +- Prevent memory leaks (no unclosed streams, unbounded arrays) +- See [[wiki/payloadcms/hooks|Hooks]] → Performance section + +### Validations +- Async or heavy validation functions → only run when necessary +- Gate expensive validators with early-exit conditions +- See [[wiki/payloadcms/fields-overview|Fields Overview]] → Validation Performance section + +### Custom Admin Components +- Apply React best practices: **memoization**, **lazy loading**, avoid unnecessary re-renders +- Use [`@next/bundle-analyzer`](https://nextjs.org/docs/app/guides/package-bundling) to identify large components +- See [[wiki/payloadcms/custom-components-authoring|Custom Components — Authoring Guide]] → Performance section + +## Config-Level Optimizations + +### Block References +Reuse a block definition across multiple collections without duplicating config: + +```ts +const config = buildConfig({ + blocks: [ + { slug: 'TextBlock', fields: [{ name: 'text', type: 'text' }] }, + ], + collections: [ + { + slug: 'posts', + fields: [{ name: 'content', type: 'blocks', blockReferences: ['TextBlock'], blocks: [] }], + }, + { + slug: 'pages', + fields: [{ name: 'content', type: 'blocks', blockReferences: ['TextBlock'], blocks: [] }], + }, + ], +}) +``` + +**Why:** fewer fields to traverse for permission processing; less data sent to Admin Panel. + +### Cached Payload Instance +Never instantiate Payload more than once — use `getPayload`: + +```ts +import { getPayload } from 'payload' +import config from '@payload-config' + +const payload = await getPayload({ config }) +``` + +## Direct Database Calls + +Bypass hooks, access control, and validation for known-safe operations: + +```ts +// Single DB round-trip instead of fetch→update→fetch +await payload.db.updateOne({ + collection: 'posts', + id: post.id, + data: { title: 'New Title' }, + returning: false, // skip returning the updated doc — saves one DB call +}) +``` + +> **Warning:** direct calls skip hooks, validations, and do NOT start a transaction automatically. +> `returning: false` is only available on `payload.db.*` — not the Local API. + +## Frontend Bundle + +### Tree-shake `@payloadcms/ui` +Only in non-admin code (front-end imports): + +```ts +// Bad — bundles entire UI library +import { Button } from '@payloadcms/ui' + +// Good — tree-shaken +import { Button } from '@payloadcms/ui/elements/Button' +``` + +Admin Panel custom components can still use `import { Button } from '@payloadcms/ui'` safely. + +## Local Development Speed + +### Turbopack (Next.js 15) +```json +{ "scripts": { "dev": "next dev --turbo" } } +``` +Next.js 16+ enables Turbopack by default. + +### Skip Server Bundle During Dev +Avoids compiling thousands of Payload modules on each dev restart. +Enabled by default in `create-payload-app` ≥ v3.28.0: + +```ts +// next.config.js +export default withPayload(nextConfig, { devBundleServerPackages: false }) +``` + +## Key Takeaways + +- **Same-region DB** is the single biggest latency win — do this first +- **Index frequently queried fields** — `index: true` is cheap to add, big query speedup +- **Use `payload.db.updateOne` with `returning: false`** when you don't need the result back +- **Block references** reduce config size and Admin Panel data transfer +- **`getPayload`** — never call `getPayload({ config })` multiple times; it returns a cached instance +- **Hooks are the main lifecycle cost** — keep them synchronous where possible, offload heavy work to jobs +- **Dev performance:** `--turbo` + `devBundleServerPackages: false` dramatically reduces cold start time +- **Frontend bundle:** always use full import paths for `@payloadcms/ui` outside the Admin Panel + +## Related + +- [[wiki/payloadcms/database-indexes|Database Indexes]] — single-field and compound indexes +- [[wiki/payloadcms/queries|Queries]] — depth, select, populate optimization +- [[wiki/payloadcms/hooks|Hooks]] — hook performance patterns +- [[wiki/payloadcms/jobs-queue|Jobs Queue]] — offload heavy work from hooks +- [[wiki/payloadcms/production|Production & Performance]] — full production deployment guide diff --git a/wiki/payloadcms/plugins-api.md b/wiki/payloadcms/plugins-api.md index 6e80d82..693d7ae 100644 --- a/wiki/payloadcms/plugins-api.md +++ b/wiki/payloadcms/plugins-api.md @@ -221,6 +221,26 @@ Run tests (Jest): cd dev && pnpm test ``` +## Seeding Data in Dev Environment + +For development and testing, seed the database via `PAYLOAD_SEED=true`: + +```ts +// dev/src/server.ts +if (process.env.PAYLOAD_SEED === 'true') { + await seed(payload) +} + +// dev/src/seed.ts +export const seed = async (payload: Payload): Promise => { + payload.logger.info('Seeding data...') + await payload.create({ + collection: 'new-collection', + data: { title: 'Seeded title' }, + }) +} +``` + ## Best Practices - **Enable/disable option** — provide `enabled?: boolean` so users can disable without uninstalling