eddev 2.3.12 → 2.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/app/entry/MetaTags.d.ts.map +1 -1
  2. package/dist/app/entry/MetaTags.js +2 -0
  3. package/dist/app/lib/blocks/block-utils.d.ts +2 -2
  4. package/dist/app/lib/blocks/block-utils.d.ts.map +1 -1
  5. package/dist/app/lib/blocks/block-utils.js +10 -3
  6. package/dist/app/lib/blocks/editor/root-blocks.d.ts.map +1 -1
  7. package/dist/app/lib/blocks/editor/root-blocks.js +2 -2
  8. package/dist/app/lib/devtools/hooks/useTailwind.d.ts +45 -45
  9. package/dist/app/lib/hooks/query-hooks.d.ts +8 -8
  10. package/dist/app/lib/hooks/query-hooks.d.ts.map +1 -1
  11. package/dist/app/lib/hooks/query-hooks.js +2 -1
  12. package/dist/app/lib/runtime/apiConfig.d.ts +15 -0
  13. package/dist/app/lib/runtime/apiConfig.d.ts.map +1 -1
  14. package/dist/app/server/proxy-wp-admin.d.ts.map +1 -1
  15. package/dist/app/server/proxy-wp-admin.js +1 -0
  16. package/dist/app/server/server-context.d.ts +2 -2
  17. package/dist/app/server/server-context.d.ts.map +1 -1
  18. package/dist/app/utils/trpc-client.d.ts.map +1 -1
  19. package/dist/app/utils/trpc-client.js +19 -3
  20. package/dist/node/cli/version.d.ts +1 -1
  21. package/dist/node/cli/version.js +1 -1
  22. package/dist/node/compiler/dev-server.js +1 -1
  23. package/dist/node/compiler/get-vite-config.d.ts.map +1 -1
  24. package/dist/node/compiler/get-vite-config.js +1 -0
  25. package/dist/node/compiler/vinxi-app.d.ts +1 -1
  26. package/dist/node/compiler/vinxi-app.d.ts.map +1 -1
  27. package/dist/node/utils/fetch-wp.d.ts.map +1 -1
  28. package/dist/node/utils/fetch-wp.js +2 -1
  29. package/dist/node/utils/fs.d.ts +22 -19
  30. package/dist/node/utils/fs.d.ts.map +1 -1
  31. package/package.json +2 -2
  32. package/skills/eddev/SKILL.md +156 -0
  33. package/skills/eddev/docs/acf/admin-panel-widgets.mdx +99 -0
  34. package/skills/eddev/docs/acf/custom-enums.mdx +75 -0
  35. package/skills/eddev/docs/acf/custom-fields.mdx +131 -0
  36. package/skills/eddev/docs/acf.mdx +31 -0
  37. package/skills/eddev/docs/blocks/block-definition.mdx +189 -0
  38. package/skills/eddev/docs/blocks/core-blocks.mdx +86 -0
  39. package/skills/eddev/docs/blocks/data-and-editing.mdx +219 -0
  40. package/skills/eddev/docs/blocks/editor-config.mdx +157 -0
  41. package/skills/eddev/docs/blocks/nested-blocks.mdx +129 -0
  42. package/skills/eddev/docs/blocks/overview.mdx +58 -0
  43. package/skills/eddev/docs/blocks/template-parts.mdx +131 -0
  44. package/skills/eddev/docs/config.mdx +200 -0
  45. package/skills/eddev/docs/design/color.mdx +185 -0
  46. package/skills/eddev/docs/design/favicons.mdx +103 -0
  47. package/skills/eddev/docs/design/grid.mdx +120 -0
  48. package/skills/eddev/docs/design/icons.mdx +197 -0
  49. package/skills/eddev/docs/design/responsive-scaling.mdx +312 -0
  50. package/skills/eddev/docs/design/type.mdx +125 -0
  51. package/skills/eddev/docs/devtool/cli.mdx +201 -0
  52. package/skills/eddev/docs/devtool/overlay.mdx +5 -0
  53. package/skills/eddev/docs/getting-started.mdx +53 -0
  54. package/skills/eddev/docs/graphql/extending.mdx +186 -0
  55. package/skills/eddev/docs/graphql/fragments.mdx +107 -0
  56. package/skills/eddev/docs/graphql/global-data.mdx +47 -0
  57. package/skills/eddev/docs/graphql/infinite-queries.mdx +95 -0
  58. package/skills/eddev/docs/graphql/mutation-hooks.mdx +111 -0
  59. package/skills/eddev/docs/graphql/query-hooks.mdx +122 -0
  60. package/skills/eddev/docs/graphql/tooling.mdx +50 -0
  61. package/skills/eddev/docs/graphql.mdx +97 -0
  62. package/skills/eddev/docs/guides/color-schemes.mdx +204 -0
  63. package/skills/eddev/docs/guides/integrations.mdx +3 -0
  64. package/skills/eddev/docs/guides/page-transitions.mdx +5 -0
  65. package/skills/eddev/docs/guides/seo.mdx +5 -0
  66. package/skills/eddev/docs/guides/state-management.mdx +5 -0
  67. package/skills/eddev/docs/infra/caching.mdx +9 -0
  68. package/skills/eddev/docs/infra/deployment.mdx +13 -0
  69. package/skills/eddev/docs/infra/local.mdx +5 -0
  70. package/skills/eddev/docs/infra/security.mdx +11 -0
  71. package/skills/eddev/docs/routing/api.mdx +731 -0
  72. package/skills/eddev/docs/routing/custom.mdx +123 -0
  73. package/skills/eddev/docs/routing/full-details.mdx +37 -0
  74. package/skills/eddev/docs/routing/wordpress.mdx +70 -0
  75. package/skills/eddev/docs/routing.mdx +18 -0
  76. package/skills/eddev/docs/serverless/functions.mdx +436 -0
  77. package/skills/eddev/docs/serverless.mdx +202 -0
  78. package/skills/eddev/docs/snippets/automated-block-layouts.mdx +97 -0
  79. package/skills/eddev/docs/snippets/custom-routes-and-urls.mdx +91 -0
  80. package/skills/eddev/docs/snippets/multiple-editable-zones.mdx +87 -0
  81. package/skills/eddev/docs/snippets/querying-specific-blocks.mdx +164 -0
  82. package/skills/eddev/docs/snippets/submitting-forms-to-rpc.mdx +91 -0
  83. package/skills/eddev/docs/snippets/svgs.mdx +38 -0
  84. package/skills/eddev/docs/snippets/type-safe-acf-dropdowns.mdx +72 -0
  85. package/skills/eddev/docs/snippets.mdx +19 -0
  86. package/skills/eddev/docs/software.mdx +19 -0
  87. package/skills/eddev/docs/stack/how-it-works.mdx +50 -0
  88. package/skills/eddev/docs/stack/overview.mdx +56 -0
  89. package/skills/eddev/docs/stack/spa-vs-ssr.mdx +52 -0
  90. package/skills/eddev/docs/views/app-view.mdx +97 -0
  91. package/skills/eddev/docs/views/page-templates.mdx +82 -0
  92. package/skills/eddev/docs/views/queries.mdx +116 -0
  93. package/skills/eddev/docs/views.mdx +63 -0
  94. package/skills/eddev/index.mdx +79 -0
  95. package/tsconfig.app.json +2 -2
@@ -0,0 +1,129 @@
1
+ # Nested Blocks (/docs/blocks/nested-blocks)
2
+
3
+ **Blocks within blocks**
4
+
5
+ Nested blocks let a block contain other blocks. Use them for layouts like sections, cards, accordions, button rows, reusable rich-text areas, and template-part slots.
6
+
7
+ The `<InnerBlocks />` component is the child block container.
8
+
9
+ ```tsx filename="blocks/content/section.tsx"
10
+ import { defineBlock, EditableText, InnerBlocks } from "eddev/blocks"
11
+
12
+ export const meta: BlockMeta = {
13
+ title: "Section",
14
+ tags: ["#root"],
15
+ }
16
+
17
+ export default defineBlock("content/section", () => {
18
+ return (
19
+ <section className="grid-auto">
20
+ <EditableText as="h2" store="title" defaultValue="Enter a title" />
21
+ <InnerBlocks allowedBlocks={["#inline"]} />
22
+ </section>
23
+ )
24
+ })
25
+ ```
26
+
27
+ You can only have one `InnerBlocks` in a block. This is a WordPress/Gutenberg limitation. If a block needs multiple editable zones, see `SlotBlocks` below.
28
+
29
+ ## Allowed Blocks [#allowed-blocks]
30
+
31
+ Use `allowedBlocks` to control what can be inserted inside the container.
32
+
33
+ ```tsx
34
+ <InnerBlocks allowedBlocks={["core/paragraph", "core/list", "content/button-row"]} />
35
+ ```
36
+
37
+ Entries can be specific block names or tags. Tags are usually cleaner when several blocks should be allowed in the same context.
38
+
39
+ ```tsx filename="blocks/content/button-row.tsx"
40
+ export const meta: BlockMeta = {
41
+ title: "Button Row",
42
+ tags: ["#inline"],
43
+ }
44
+
45
+ export default defineBlock("content/button-row", () => {
46
+ return <InnerBlocks allowedBlocks={["#buttons"]} />
47
+ })
48
+ ```
49
+
50
+ ```tsx filename="blocks/content/button.tsx"
51
+ export const meta: BlockMeta = {
52
+ title: "Button",
53
+ tags: ["#buttons"],
54
+ }
55
+ ```
56
+
57
+ WordPress core blocks can also be tagged and allowed this way. See [Core Blocks](./core-blocks) for the PHP-side setup.
58
+
59
+ The unprefixed `root` tag is the framework default, but our examples use explicit `#root` and set `rootBlocks` in `blocks/_editor.tsx`.
60
+
61
+ ## Templates And Locking [#templates-and-locking]
62
+
63
+ `InnerBlocks` can insert default child blocks and control how much authors can change the list.
64
+
65
+ ```tsx
66
+ <InnerBlocks
67
+ allowedBlocks={["content/card-grid-item"]}
68
+ defaultBlocks={[["content/card-grid-item", {}]]}
69
+ templateLock="insert"
70
+ />
71
+ ```
72
+
73
+ * `defaultBlocks` are inserted when the container is empty.
74
+ * `headerTemplate` and `footerTemplate` keep blocks pinned to the start or end.
75
+ * `template` defines the whole child block list.
76
+ * `templateLock="all"` prevents moving, inserting, or deleting.
77
+ * `templateLock="insert"` prevents inserting or removing, but allows moving existing blocks.
78
+ * `templateLock="contentOnly"` locks structure but allows rich text editing.
79
+ * `templateLock="none"` or `false` leaves the list editable.
80
+
81
+ Use these sparingly. A good rule is to lock structural wrapper blocks, but keep content blocks flexible.
82
+
83
+ ## Appenders And Editor Classes [#appenders-and-editor-classes]
84
+
85
+ `adminClassName` adds a class to the editor-only wrapper. `appender` changes the inserter UI.
86
+
87
+ ```tsx
88
+ <InnerBlocks
89
+ allowedBlocks={["content/card-grid-item"]}
90
+ adminClassName="grid grid-cols-3 gap-4"
91
+ appender={{ type: "simple" }}
92
+ />
93
+ ```
94
+
95
+ Supported appender types are `default`, `button`, `button2`, `simple`, or a custom appender created with `createAppender`.
96
+
97
+ ## Rendering Children Yourself [#rendering-children-yourself]
98
+
99
+ Most blocks can render `<InnerBlocks />` directly. If the parent needs to inspect child blocks, use `useInnerBlocks()`.
100
+
101
+ ```tsx
102
+ import { defineBlock, InnerBlocks, useInnerBlocks } from "eddev/blocks"
103
+
104
+ export default defineBlock("content/card-grid", () => {
105
+ const blocks = useInnerBlocks()
106
+ const columns = blocks.length === 3 ? "grid-cols-3" : "grid-cols-2"
107
+
108
+ return (
109
+ <div className={columns}>
110
+ <InnerBlocks allowedBlocks={["content/card-grid-item"]} />
111
+ </div>
112
+ )
113
+ })
114
+ ```
115
+
116
+ `useInnerBlocks()` returns block data with metadata added, including `slug`, `tags`, and `flags`.
117
+
118
+ ## Multiple Editable Zones [#multiple-editable-zones]
119
+
120
+ Use `SlotBlocks` only when a block genuinely needs multiple independent editable zones.
121
+
122
+ ```tsx
123
+ import { SlotBlocks } from "eddev/blocks"
124
+
125
+ <SlotBlocks id="primary" allowedBlocks={["#menu"]} />
126
+ <SlotBlocks id="cta" template={[["content/button", {}]]} templateLock="insert" />
127
+ ```
128
+
129
+ `SlotBlocks` stores hidden `core/slot-group` blocks inside the parent and renders each slot separately. It is useful for complex headers, mega menus, or app-like layouts, but it is more complex than a normal `InnerBlocks` container.
@@ -0,0 +1,58 @@
1
+ # Overview (/docs/blocks/overview)
2
+
3
+ **The basics of creating Gutenberg blocks**
4
+
5
+ Blocks are the main editing unit for page content. In an eddev theme, a block is usually a React component in `blocks/**/*.tsx`, with optional metadata and a paired GraphQL query.
6
+
7
+ Most sites only need a small set of block conventions:
8
+
9
+ * `blocks/content/section.tsx` defines a block component.
10
+ * `blocks/content/section.graphql` selects the ACF or WordPress data passed to that component.
11
+ * `blocks/_editor.tsx` controls which blocks authors can add for each post type or template.
12
+ * `blocks/_core.tsx` optionally replaces the frontend rendering of WordPress core blocks.
13
+ * Views render block content with `<ContentBlocks blocks={props.page?.contentBlocks} />`.
14
+
15
+ ## The Short Version [#the-short-version]
16
+
17
+ ```tsx filename="blocks/content/section.tsx"
18
+ import { defineBlock, EditableText, InnerBlocks } from "eddev/blocks"
19
+
20
+ export const meta: BlockMeta = {
21
+ title: "Section",
22
+ tags: ["#root"],
23
+ }
24
+
25
+ export default defineBlock("content/section", () => {
26
+ return (
27
+ <section className="grid-auto">
28
+ <div className="col-span-12 md:col-span-3">
29
+ <EditableText as="h2" store="title" defaultValue="Enter a title" />
30
+ </div>
31
+ <div className="col-span-12 md:col-span-9">
32
+ <InnerBlocks allowedBlocks={["#inline"]} />
33
+ </div>
34
+ </section>
35
+ )
36
+ })
37
+ ```
38
+
39
+ `defineBlock("content/section", ...)` should match the file path without `blocks/` or `.tsx`. This is what lets generated block props line up with the right component.
40
+
41
+ ## Data Flow [#data-flow]
42
+
43
+ Block data is not passed straight from ACF into React. eddev parses Gutenberg content in WordPress, runs the matching `blocks/**/*.graphql` query for each ACF block, and sends the selected data to React as typed props.
44
+
45
+ That extra query step is useful: a block can select exactly the fields it needs, follow relationships like post objects or media fields, and reuse fragments from `queries/fragments`.
46
+
47
+ ## Editor Flow [#editor-flow]
48
+
49
+ The editor is configured separately from individual blocks. Use block `tags` for broad authoring contexts like `#root`, `#inline`, or `#card-grid-item`, then use `blocks/_editor.tsx` to decide which tags or block names are available for a given post type or template.
50
+
51
+ Keep the first pass simple:
52
+
53
+ * define the block component
54
+ * add ACF fields only when inline editing is not enough
55
+ * add a GraphQL file only for data the component needs
56
+ * constrain where it appears with tags and editor config
57
+
58
+ The rest of this section covers those pieces in that order.
@@ -0,0 +1,131 @@
1
+ # Template Parts (/docs/blocks/template-parts)
2
+
3
+ **Reusable site sections powered by blocks**
4
+
5
+ Template parts are reusable block-backed sections of a theme, such as a site footer, site header, menu, or global callout. They are edited in WordPress, queried as app data, and rendered anywhere in React with `ContentBlocks`.
6
+
7
+ Use template parts for content that belongs to the site shell rather than one page.
8
+
9
+ ## Define A Template Part Block [#define-a-template-part-block]
10
+
11
+ Set `templatePart` on the block metadata.
12
+
13
+ ```tsx filename="blocks/parts/footer.tsx"
14
+ import { defineBlock, EditableText } from "eddev/blocks"
15
+ import { Link } from "eddev/routing"
16
+
17
+ export const meta: BlockMeta = {
18
+ title: "Site Footer",
19
+ inserter: false,
20
+ templatePart: {
21
+ area: "footer",
22
+ slug: "siteFooter",
23
+ },
24
+ }
25
+
26
+ export default defineBlock("parts/footer", (props) => {
27
+ return (
28
+ <footer>
29
+ <Link href={props.contactLink ?? "/contact"}>
30
+ <EditableText store="contactLink" defaultValue="Let's have a chat" />
31
+ </Link>
32
+ </footer>
33
+ )
34
+ })
35
+ ```
36
+
37
+ `slug` becomes the field name under `templateParts` in GraphQL. `area` tells WordPress what kind of template part this is. `inserter: false` is usually right, because authors should edit the template part itself rather than adding this block manually to pages.
38
+
39
+ ## Add A Block Query [#add-a-block-query]
40
+
41
+ Template part blocks can have their own paired GraphQL files, just like normal blocks.
42
+
43
+ ```graphql filename="blocks/parts/footer.graphql"
44
+ query {
45
+ block {
46
+ parts_footer {
47
+ contactLink
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ ## Query The Template Part [#query-the-template-part]
54
+
55
+ Template parts can be queried anywhere a normal GraphQL file can select `templateParts`.
56
+
57
+ For site shell content, select the template part from app data so it is available around every route:
58
+
59
+ ```graphql filename="views/_app.graphql"
60
+ query CommonData {
61
+ templateParts {
62
+ siteFooter {
63
+ contentBlocks
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ Then render it with `ContentBlocks`.
70
+
71
+ ```tsx filename="features/site/Footer.tsx"
72
+ import { ContentBlocks } from "eddev/blocks"
73
+ import { useAppData } from "eddev/hooks"
74
+
75
+ export function Footer() {
76
+ const footer = useAppData((data) => data.templateParts?.siteFooter)
77
+ return <ContentBlocks blocks={footer?.contentBlocks} />
78
+ }
79
+ ```
80
+
81
+ Finally, include the component in `_app.tsx` so it appears around every route.
82
+
83
+ ```tsx filename="views/_app.tsx"
84
+ import { Footer } from "@features/site/Footer"
85
+ import { RouteDisplay, useRoute } from "eddev/routing"
86
+ import { defineView } from "eddev/views"
87
+
88
+ export default defineView("_app", () => {
89
+ const route = useRoute()
90
+
91
+ return (
92
+ <>
93
+ <RouteDisplay route={route} />
94
+ <Footer />
95
+ </>
96
+ )
97
+ })
98
+ ```
99
+
100
+ You do not have to use `_app.graphql` or `useAppData`. Blocks and views can query template parts directly when they need globally-defined content in a specific place.
101
+
102
+ ```graphql filename="blocks/content/callout.graphql"
103
+ query CalloutBlock {
104
+ block {
105
+ content_callout {
106
+ heading
107
+ }
108
+ }
109
+ templateParts {
110
+ siteFooter {
111
+ contentBlocks
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ That pattern is useful for callouts, reusable panels, or other blocks that need shared content without making it global app data.
118
+
119
+ eddev automatically constrains the matching template-part editor to the block declared in `templatePart`, so the editing surface stays focused.
120
+
121
+ ## When To Use This [#when-to-use-this]
122
+
123
+ Template parts are a good fit for:
124
+
125
+ * site headers and footers
126
+ * global navigation or mega menus
127
+ * reusable site-wide panels
128
+ * shared error page content
129
+ * content that should be edited once and rendered on many routes
130
+
131
+ Do not use template parts for ordinary per-page blocks. If content belongs to a page or post, keep it in that page or post's `contentBlocks`.
@@ -0,0 +1,200 @@
1
+ # Configuration (/docs/config)
2
+
3
+ **Configure eddev projects with theme-level JSON settings.**
4
+
5
+ eddev projects are configured with `ed.config.json` in the theme root. The file is read by the JavaScript build/server process and, for some options, by the WordPress PHP runtime.
6
+
7
+ The generated `.ed.config.schema.json` file gives editor autocomplete and validation. It is generated from the Zod schema in eddev, so treat that schema as the source of truth when an option changes.
8
+
9
+ ```json filename="ed.config.json"
10
+ {
11
+ "$schema": ".ed.config.schema.json",
12
+ "version": "2",
13
+ "legacyStitches": false,
14
+ "favicon": {
15
+ "mode": "svg"
16
+ },
17
+ "serverless": {
18
+ "enabled": true,
19
+ "uploads": "remote",
20
+ "plugins": "remote",
21
+ "admin": "hide",
22
+ "themeAssets": ["assets/**/*"],
23
+ "originProtection": {
24
+ "requireLogin": false
25
+ },
26
+ "endpoints": {
27
+ "cms.website.com": "website.com"
28
+ }
29
+ },
30
+ "cache": {
31
+ "*": {
32
+ "pageDataTTL": 300,
33
+ "appDataTTL": 300,
34
+ "queryHooksTTL": 300,
35
+ "serverless": {
36
+ "isr": true,
37
+ "dataCache": "in-memory"
38
+ },
39
+ "wordpress": {
40
+ "cacheHeaders": true,
41
+ "transients": true
42
+ }
43
+ }
44
+ },
45
+ "devUI": "enabled"
46
+ }
47
+ ```
48
+
49
+ <Callout type="info">
50
+ Keep `cache` and `serverless.endpoints` explicit on production projects. The JavaScript side applies schema defaults, but the WordPress PHP side also reads parts of the raw JSON file.
51
+ </Callout>
52
+
53
+ ## Where To Go Next [#where-to-go-next]
54
+
55
+ <Cards>
56
+ <Card icon="<CogIcon />" title="Serverless" href="/docs/serverless">
57
+ Configure the JavaScript host that renders the public frontend.
58
+ </Card>
59
+
60
+ <Card icon="<CogIcon />" title="RPC Functions" href="/docs/serverless/functions">
61
+ Add TypeScript server routes for project-specific APIs.
62
+ </Card>
63
+
64
+ <Card icon="<CogIcon />" title="Favicons" href="/docs/design/favicons">
65
+ Choose how eddev prepares favicon files for the theme.
66
+ </Card>
67
+
68
+ <Card icon="<CogIcon />" title="GraphQL Caching" href="/docs/graphql#caching">
69
+ Tune cache behavior for view, app, and runtime query data.
70
+ </Card>
71
+ </Cards>
72
+
73
+ ## Top-Level Options [#top-level-options]
74
+
75
+ | Option | What It Does |
76
+ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
77
+ | `$schema` | Points editors at `.ed.config.schema.json` for autocomplete and validation. |
78
+ | `version` | Config format version. Current projects should use `"2"`. |
79
+ | `favicon` | Controls favicon generation. See [Favicons](/docs/design/favicons). |
80
+ | `legacyMetadata` | Enables older comment-based metadata parsing for projects that still need it. New projects should use exported metadata. |
81
+ | `legacyStitches` | Marks the project as using the old Stitches styling setup. New projects should leave this as `false`. |
82
+ | `trackers` | Adds standard tracking snippets such as GA4 or GTM. |
83
+ | `serverless` | Controls serverless deployment, proxied assets, admin URL behavior, endpoint mappings, CORS, and CSP. See [Serverless](/docs/serverless). |
84
+ | `cache` | Controls WordPress and serverless data/response caching. See [Serverless cache settings](/docs/serverless#cache) and [GraphQL caching](/docs/graphql#caching). |
85
+ | `devUI` | Enables or disables the eddev development UI. Use `"enabled"` for normal development. |
86
+
87
+ ## `favicon` [#favicon]
88
+
89
+ `favicon` controls how eddev prepares favicon assets during the build.
90
+
91
+ | Mode | Use When |
92
+ | ------ | ------------------------------------------------------------------------------------- |
93
+ | `auto` | WordPress Site Icon should handle favicons. No `.ico` is generated by eddev. |
94
+ | `svg` | The project has a single SVG favicon source, optionally with light and dark variants. |
95
+ | `pngs` | The project has multiple PNG favicon source files. |
96
+
97
+ The favicon page should carry the asset naming and export details once it is filled out: [Favicons](/docs/design/favicons).
98
+
99
+ ## `serverless` [#serverless]
100
+
101
+ Most current projects deploy the public frontend to Vercel and keep WordPress as the CMS and route authority. `serverless` controls that deployment shape.
102
+
103
+ | Option | What It Does |
104
+ | ------------------------------- | ------------------------------------------------------------------------------------------------------ |
105
+ | `enabled` | Enables serverless deployment support. |
106
+ | `uploads` | Chooses whether upload URLs are remote origin URLs or proxied through the serverless deployment. |
107
+ | `plugins` | Chooses whether plugin asset URLs are remote origin URLs or proxied through the serverless deployment. |
108
+ | `admin` | Controls whether WordPress admin/API URLs are proxied or hidden on the serverless deployment. |
109
+ | `originProtection.requireLogin` | Forces eddev Access Control for the WordPress origin. |
110
+ | `themeAssets` | Lists theme asset folders to include in the serverless deployment. |
111
+ | `endpoints` | Maps WordPress hostnames to serverless hostnames for RPC and SPA/admin calls. |
112
+ | `cors.origins` | Adds extra CORS origins beyond hosts inferred from `endpoints`. |
113
+ | `csp` | Configures Content Security Policy for the serverless app. |
114
+
115
+ Use the serverless overview for deployment flow, `SITE_URL`, `SITE_API_KEY`, Access Control, endpoint mappings, and cache behavior: [Serverless](/docs/serverless).
116
+
117
+ ## `cache` [#cache]
118
+
119
+ `cache` is a map of WordPress origin hostnames to cache settings. Use `"*"` as the default, and add exact or wildcard host entries when staging and production need different behavior.
120
+
121
+ ```json filename="ed.config.json"
122
+ {
123
+ "cache": {
124
+ "*.staging.website.com": {
125
+ "pageDataTTL": 60,
126
+ "appDataTTL": 60,
127
+ "queryHooksTTL": 60,
128
+ "serverless": {
129
+ "isr": false,
130
+ "dataCache": "none"
131
+ },
132
+ "wordpress": {
133
+ "cacheHeaders": false,
134
+ "transients": false
135
+ }
136
+ },
137
+ "*": {
138
+ "pageDataTTL": 300,
139
+ "appDataTTL": 300,
140
+ "queryHooksTTL": 300,
141
+ "serverless": {
142
+ "isr": true,
143
+ "dataCache": "in-memory"
144
+ },
145
+ "wordpress": {
146
+ "cacheHeaders": true,
147
+ "transients": true
148
+ }
149
+ }
150
+ }
151
+ }
152
+ ```
153
+
154
+ Cache host keys are matched as hostnames. Ports are ignored, exact hostnames win over wildcard patterns, and `"*"` is the fallback.
155
+
156
+ | Option | What It Does |
157
+ | ------------------------ | ---------------------------------------------------------------------------------------- |
158
+ | `pageDataTTL` | Seconds to cache route data and rendered page responses. |
159
+ | `appDataTTL` | Seconds to cache global app data from `views/_app.graphql`. |
160
+ | `queryHooksTTL` | Seconds to cache named runtime GraphQL query hook responses. |
161
+ | `serverless.isr` | Enables serverless response caching/ISR for pages and data routes. |
162
+ | `serverless.dataCache` | `in-memory` uses the serverless LRU/SWR data cache. `none` fetches WordPress every time. |
163
+ | `wordpress.cacheHeaders` | Allows WordPress data responses to emit cache headers. |
164
+ | `wordpress.transients` | Allows WordPress to cache GraphQL results in transients. |
165
+
166
+ Individual GraphQL files can still override the duration with `# ttl: 300` or disable caching with `# nocache`; see [GraphQL caching](/docs/graphql#caching).
167
+
168
+ ## `trackers` [#trackers]
169
+
170
+ `trackers` embeds standard tracking snippets collected by eddev.
171
+
172
+ ```json filename="ed.config.json"
173
+ {
174
+ "trackers": [
175
+ {
176
+ "provider": "ga4",
177
+ "id": "G-XXXXXXXXXX"
178
+ },
179
+ {
180
+ "provider": "gtm",
181
+ "id": "GTM-XXXXXXX"
182
+ }
183
+ ]
184
+ }
185
+ ```
186
+
187
+ Supported providers are `ga4` and `gtm`. Serverless CSP can auto-detect common tracker origins when CSP is enabled.
188
+
189
+ <Callout>
190
+ If you've got Slim SEO installed, you can just put them in Settings -> Slim SEO -> Code.
191
+ </Callout>
192
+
193
+ ## Legacy Flags [#legacy-flags]
194
+
195
+ `legacyMetadata` and `legacyStitches` are compatibility switches for older projects. Leave them off unless the project already depends on those older conventions.
196
+
197
+ * `legacyMetadata` keeps support for older metadata extraction.
198
+ * `legacyStitches` marks the site as using the old Stitches styling path.
199
+
200
+ New projects should use exported block/view metadata and the current CSS/Tailwind setup.