diff --git a/raw/fields__overview.md b/raw/_processed/fields__overview.md
similarity index 100%
rename from raw/fields__overview.md
rename to raw/_processed/fields__overview.md
diff --git a/wiki/_master-index.md b/wiki/_master-index.md
index f6935e4..c57f06a 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 | 73 |
+| [[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 | 74 |
| [[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/payloadcms/_index.md b/wiki/payloadcms/_index.md
index 0ed73e0..8fd7b45 100644
--- a/wiki/payloadcms/_index.md
+++ b/wiki/payloadcms/_index.md
@@ -74,3 +74,4 @@
| [[wiki/payloadcms/fields-join\|Join Field]] | Virtual bi-directional relationship field — zero-overhead reverse lookup, custom junction tables, polymorphic, query options across all APIs | raw/fields__join.md | 2026-05-15 |
| [[wiki/payloadcms/fields-json\|JSON Field]] | Stores native JSON in DB (not string) — jsonSchema validation + Monaco typeahead, local/remote schemas, vs Code Field | raw/fields__json.md | 2026-05-15 |
| [[wiki/payloadcms/fields-number\|Number Field]] | Numeric field — min/max validation, hasMany array mode, step admin control, unique/index, virtual, custom components | raw/fields__number.md | 2026-05-15 |
+| [[wiki/payloadcms/fields-overview\|Fields Overview]] | Cross-cutting field config: virtual fields (boolean + path), validation (context, perf, reuse), defaultValue, admin options (condition, disabled, components), custom components (Field/Cell/Filter/Label/Error/Diff), reserved names | raw/fields__overview.md | 2026-05-15 |
diff --git a/wiki/payloadcms/fields-overview.md b/wiki/payloadcms/fields-overview.md
new file mode 100644
index 0000000..09eb5d2
--- /dev/null
+++ b/wiki/payloadcms/fields-overview.md
@@ -0,0 +1,353 @@
+---
+title: "Fields Overview — Config, Validation, Virtual, Admin Options"
+aliases: [payload-fields-overview, payload-field-config]
+tags: [payloadcms, fields, validation, virtual-fields, admin-panel]
+sources: [raw/fields__overview.md]
+created: 2026-05-15
+updated: 2026-05-15
+---
+
+# Fields Overview — Config, Validation, Virtual, Admin Options
+
+Fields are the building blocks of Payload. They define the DB schema **and** auto-generate Admin Panel UI. This article covers shared config capabilities that apply across all field types: virtual fields, validation, default values, admin options, and custom components.
+
+See [[wiki/payloadcms/fields-basic|Fields: Basic]] for scalar field types and [[wiki/payloadcms/fields-complex|Fields: Complex]] for structural/relational types.
+
+---
+
+## Field Categories
+
+| Category | Purpose | `name` required? |
+|----------|---------|-----------------|
+| **Data** | Stored in DB | Yes |
+| **Presentational** | Layout only (Row, Collapsible, unnamed Tabs/Group, UI) | No |
+| **Virtual** | Computed/derived, not stored | Yes |
+
+### Data Fields (full list)
+
+Array, Blocks, Checkbox, Code, Date, Email, Group (named), JSON, Number, Point, Radio, Relationship, Rich Text, Select, Tabs (named), Text, Textarea, Upload
+
+### Presentational Fields
+
+Collapsible, Row, Tabs (unnamed), Group (unnamed), UI
+
+### Virtual Fields
+
+- **Join** — purpose-built virtual type for bi-directional relationships
+- **Any field** with `virtual: true` or `virtual: 'path.to.value'`
+
+---
+
+## Virtual Field Configuration
+
+Any data field type can be made virtual by adding the `virtual` property.
+
+### Boolean virtual — computed via hook
+
+```ts
+{
+ name: 'fullName',
+ type: 'text',
+ virtual: true,
+ hooks: {
+ afterRead: [({ siblingData }) =>
+ `${siblingData.firstName} ${siblingData.lastName}`
+ ]
+ }
+}
+```
+
+### String path virtual — resolves relationship data
+
+```ts
+{
+ name: 'authorName',
+ type: 'text',
+ virtual: 'author.name' // author relationship must exist on the same collection
+}
+```
+
+**Path syntax rules:**
+- Dot notation traverses relationships: `author.profile.bio`
+- `hasMany` relationships return arrays: `categories.title` → `['Tech', 'News']`
+- Source relationship field **must** exist in the same schema
+- Resolved at query time, not stored
+
+**Use cases:** display relationship names without ID, computed word counts, formatted summaries.
+
+```json
+// API response includes virtual fields alongside real ones
+{
+ "id": "123",
+ "title": "My Post",
+ "author": "64f123...",
+ "authorName": "John Doe",
+ "categoryTitles": ["Tech", "News"],
+ "wordCount": 450
+}
+```
+
+---
+
+## Field Names
+
+- Must be **unique** among siblings
+- Follow JavaScript identifier conventions: start with letter or `_`, only letters/numbers/`_`
+- **Avoid** hyphens (breaks GraphQL enum generation) and leading digits
+- **Reserved names** (cannot be used): `__v`, `salt`, `hash`, `file`, `status` (with Postgres + drafts)
+
+---
+
+## Default Values
+
+```ts
+// Static
+{ name: 'status', type: 'text', defaultValue: 'draft' }
+
+// Dynamic function — runs on create/update
+{
+ name: 'attribution',
+ type: 'text',
+ defaultValue: ({ user, locale, req }) =>
+ `${translation[locale]} ${user.name}`
+}
+```
+
+Dynamic `defaultValue` receives: `user`, `locale`, `req` (use `req.payload` for Local API calls). Can be `async`.
+
+---
+
+## Validation
+
+Fields auto-validate based on type and options (`required`, `min`, `max`). Override with `validate`:
+
+```ts
+{
+ name: 'myField',
+ type: 'text',
+ validate: (value, { user, data, siblingData, operation, id, req, event }) =>
+ Boolean(value) || 'This field is required'
+}
+```
+
+Returns `true` (valid) or an error string.
+
+### Validation Context (`ctx`)
+
+| Property | Description |
+|----------|-------------|
+| `data` | Full document being edited |
+| `siblingData` | Fields in same parent |
+| `operation` | `'create'` or `'update'` |
+| `path` | Array path: `['group', 'myArray', '1', 'field']` |
+| `id` | Document ID (undefined during create) |
+| `req` | HTTP request with `payload`, `user`, etc. |
+| `event` | `'onChange'` or `'submit'` |
+
+### Localized error messages
+
+```ts
+validate: (value, { req: { t } }) =>
+ Boolean(value) || t('validation:required')
+```
+
+### Reuse built-in validators
+
+```ts
+import { text } from 'payload/shared'
+
+validate: (val, args) => {
+ if (val === 'bad') return 'Cannot be "bad"'
+ return text(val, args) // delegate to built-in
+}
+```
+
+Available: `array, blocks, checkbox, code, date, email, json, number, point, radio, relationship, richText, select, tabs, text, textarea, upload`
+
+### Validation performance
+
+Admin Panel validates on **every change**. For expensive ops (DB queries), gate on `event`:
+
+```ts
+validate: async (val, { event }) => {
+ if (event === 'onChange') return true
+ const response = await fetch(`/api/check?val=${val}`)
+ return response.ok || 'Invalid value'
+}
+```
+
+---
+
+## Field-level Hooks
+
+```ts
+{
+ name: 'myField',
+ type: 'text',
+ hooks: {
+ beforeValidate: [...],
+ beforeChange: [...],
+ afterChange: [...],
+ afterRead: [...]
+ }
+}
+```
+
+See [[wiki/payloadcms/hooks|Hooks]] for full details.
+
+---
+
+## Field-level Access Control
+
+```ts
+{
+ name: 'sensitiveData',
+ type: 'text',
+ access: {
+ read: ({ req: { user } }) => Boolean(user?.isAdmin),
+ create: () => false,
+ update: ({ req: { user } }) => Boolean(user?.isAdmin),
+ }
+}
+```
+
+See [[wiki/payloadcms/access-control|Access Control]] for full details.
+
+---
+
+## Custom ID Fields
+
+Override auto-generated ID:
+
+```ts
+fields: [
+ {
+ name: 'id',
+ type: 'number', // or 'text'
+ required: true,
+ }
+]
+```
+
+- Only `number` or `text` types allowed
+- Text IDs must not contain `/` or `.` characters
+
+---
+
+## Admin Options
+
+Configured via `admin: {}` on any field:
+
+| Option | Description |
+|--------|-------------|
+| `condition` | `(data, siblingData, ctx) => boolean` — show/hide field |
+| `components` | Swap individual UI parts (see Custom Components below) |
+| `description` | Help text (string, function, or React component) |
+| `position` | `'sidebar'` or `'main'` (default) |
+| `width` | CSS width — useful in `row` fields |
+| `style` | Inline CSS on root element |
+| `className` | CSS class on root element |
+| `readOnly` | UI-only; no effect on API |
+| `disabled` | Hide from all admin surfaces (`true`) or specific ones (object) |
+| `hidden` | Converts to `` — still submits |
+
+### `admin.disabled` granular control
+
+```ts
+admin: { disabled: { column: true, filter: true } }
+// Keys: field, column, filter, groupBy, bulkEdit
+```
+
+UI fields default to `disabled: { bulkEdit: true }`.
+
+### Conditional Logic
+
+```ts
+{
+ name: 'greeting',
+ type: 'text',
+ admin: {
+ condition: (data, siblingData, { blockData, path, user }) => {
+ return Boolean(data.enableGreeting)
+ }
+ }
+}
+```
+
+---
+
+## Custom Components
+
+Swap any part of a field's UI via `admin.components`:
+
+| Component | Renders in | Notes |
+|-----------|-----------|-------|
+| `Field` | Edit View — the input | Use `useField()` hook to manage value |
+| `Cell` | List View — table cell | Use `DefaultCellComponentProps` / `DefaultServerCellComponentProps` |
+| `Filter` | List View — filter dropdown | Receives `disabled, onChange, operator, value` |
+| `Label` | Anywhere labels appear | |
+| `Error` | Below input on validation fail | |
+| `Description` | Below label | Use component for dynamic/reactive help text |
+| `Diff` | Version Diff View | Only visible when versioning is enabled |
+| `beforeInput` | Before `` element | Array of components |
+| `afterInput` | After `` element | Array of components |
+
+### Field component — managing value
+
+```tsx
+'use client'
+import { useField } from '@payloadcms/ui'
+
+export const CustomTextField = () => {
+ const { value, setValue } = useField()
+ return setValue(e.target.value)} value={value} />
+}
+```
+
+### TypeScript for custom components
+
+```ts
+import type {
+ TextFieldClientComponent,
+ TextFieldServerComponent,
+ TextFieldLabelClientComponent,
+ TextFieldDescriptionClientComponent,
+ TextFieldErrorClientComponent,
+ TextFieldDiffClientComponent,
+} from 'payload'
+```
+
+Convention: `{FieldType}{ComponentRole}{ServerOrClient}Component` (e.g. `TextFieldLabelClientComponent`)
+
+### Cell component example
+
+```tsx
+'use client'
+import type { DefaultCellComponentProps } from 'payload'
+
+export const PriceCellComponent: React.FC = ({ cellData, rowData }) => {
+ const currency = rowData.currency || 'USD'
+ return {new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(cellData)}
+}
+```
+
+---
+
+## Key Takeaways
+
+- **Three categories**: Data (stored), Presentational (layout), Virtual (computed/derived)
+- **Any field can be virtual** with `virtual: true` (hook-computed) or `virtual: 'path.string'` (relationship path)
+- **Virtual path fields** auto-resolve relationship data without a DB column; `hasMany` → returns arrays
+- **Reserved field names** (`__v`, `salt`, `hash`, `file`, `status` with Postgres+drafts) cause silent config sanitization
+- **Validation** runs on every keystroke in Admin — use `event === 'onChange'` guard for expensive async checks
+- **`validate` returns** `true` (valid) or an error message string
+- **`defaultValue`** can be async; receives `{ user, locale, req }` — use `req.payload` for Local API
+- **`admin.disabled`** accepts boolean or object with keys `{ field, column, filter, groupBy, bulkEdit }`
+- **Custom components** registered via path strings in `admin.components`; use `useField()` to wire value
+- **TypeScript types** follow `{FieldType}{Role}{Env}Component` naming convention
+
+---
+
+## Sources
+
+- `raw/fields__overview.md` — https://payloadcms.com/docs/fields/overview