# Frontend Runtime Extension Contract (V1) This document defines the stable frontend runtime integration surface for plugins that extend FrontEdit in the browser. ## Purpose This contract answers four questions for external integrations: 1. How another plugin may open and control FrontEdit editing. 2. What schema-resolved runtime data FrontEdit guarantees to expose. 3. Which lifecycle hooks and events are stable for observing editing and the standard FrontEdit save flow. 4. Which globals and implementation details are explicitly private. ## Scope This contract covers the browser runtime only. It does not define: 1. PHP handler registration. 2. Schema authoring rules. 3. Internal editor-state layout. 4. REST endpoint internals or private save helpers. 5. Internal DOM classes or data attributes unless explicitly documented here. ## Stability Model FrontEdit exposes one stable base namespace for browser integrations: ```js window.MWP.SFE.PublicApi ``` When FrontEdit Pro is active, FrontEdit also exposes one optional pro-only namespace: ```js window.MWP.SFE.ProApi ``` Everything else on `window.MWP.SFE` is private unless this document explicitly says otherwise. ### Two-tier contract This document uses two stability tiers: 1. `V1 committed surface` External plugins may rely on these methods, events, and return shapes. 2. `Candidate APIs under evaluation` These are roadmap items only. They are not part of the stable contract and may change or never ship. ### Versioning The runtime extension contract is versioned independently from the schema contract. `window.MWP.SFE.PublicApi` must expose: ```js SFE.PublicApi.getApiInfo(); ``` Expected shape: ```js { apiVersion: 1, namespace: 'window.MWP.SFE.PublicApi', features: { editorControl: true, runtimeInspection: true, editableBlockDiscovery: true, editingRuntimeResolution: true, publicOperationContracts: true, operations: true, operationPreflight: true, listOperationContracts: true, mediaInspection: true, mediaSessionControl: true, explicitStaging: true, events: true, blockRefresh: true } } ``` Version rules: 1. Additive methods, additive event payload fields, and additive snapshot fields are minor-safe. 2. Removing or renaming methods, changing event semantics, or changing documented return-shape meaning requires an `apiVersion` bump. 3. Private internals may change at any time without notice. ## Public Namespace Rules External plugins may: 1. Call documented `SFE.PublicApi.*` methods. 2. Call documented `SFE.ProApi.*` methods only when the pro plugin is active and the method is documented here as pro-only. 3. Subscribe only to documented `SFE.PublicApi` events. 4. Store and compare documented snapshot data returned by the API. External plugins must not: 1. Monkey-patch FrontEdit methods. 2. Directly mutate `window.MWP.SFE` objects unless a documented API explicitly allows it. 3. Depend on underscore-prefixed properties. 4. Rebuild schema runtime resolution, media descriptor resolution, or block-state hydration from private internals when a public API exists. ## V1 Committed Surface ### Discovery #### Server-side AI discovery When the WordPress Abilities API is available, an authorized FrontEdit editor may call the following post-scoped, read-only abilities: 1. `mwpsfe/list-editable-blocks` with `post_id` to retrieve selectable block UUIDs, block types, edit handler IDs, and source-text summaries. 2. `mwpsfe/get-editable-block` with `post_id` and `uuid` to retrieve focused content for one already-authorized editable block. 3. `mwpsfe/get-public-operation-contract` with `post_id` and `uuid` to retrieve the handler-derived public operation contract and its current public input state for one already-authorized editable block. 4. `mwpsfe/get-frontend-runtime-contract` with `post_id` to retrieve this canonical browser contract. These abilities authorize the current user against the exact requested post; they do not discover WordPress posts/pages, execute browser methods, or create an external save path. WordPress core remains responsible for page discovery. Once the browser runtime is present, integrations must still verify availability through `SFE.PublicApi.getApiInfo()` and use `SFE.PublicApi.getEditableBlocks()` to enumerate the live page. #### Server-side `current_operation_state` `mwpsfe/get-public-operation-contract` returns an immutable `contract` and a separate mutable `current_operation_state` array. Each record is: ```json { "componentId": "content", "operationId": "rewrite_text", "state": { "runs": [] } } ``` The record's `state` object contains only the public inputs declared by that operation. FrontEdit derives these values from the owning handler's schema and current parsed block state; it never publishes attributes, bindings, selectors, or executor metadata. Integrations must use this projection when a generated proposal needs to preserve a current text, media, link, or setting value. They must not reconstruct an equivalent map from raw block attributes. `core/list` keeps its documented browser-owned current-state surface through `SFE.PublicApi.getListStructure(...)` and its operation descriptor through `SFE.PublicApi.getListOperationContract(...)`, because its runtime list-item UUIDs are session-scoped rather than server-side generic operation IDs. #### `getEditableBlocks() -> EditableBlock[]` Return the FrontEdit-editable blocks currently known to the live page runtime. ```js const blocks = SFE.PublicApi.getEditableBlocks(); const match = blocks.find(block => block.contentText.includes('Pricing')); ``` Each entry is a `BlockSnapshot` plus `contentText`, which is normalized text from the current rendered block element. Use its `uuid` with `resolveEditingRuntime(...)` before choosing a documented edit operation. This method is the supported browser discovery path; integrations must not scrape private FrontEdit DOM attributes to enumerate UUIDs. #### Human save handoff An integration may inspect a block, open FrontEdit, and apply documented runtime operations or staging. It must then hand control to the authorized human to review and complete FrontEdit's standard save UI. V1 has no external direct-save API. #### `getApiInfo()` ```js const info = SFE.PublicApi.getApiInfo(); ``` Returns the contract version and feature flags for this runtime. ### Editor Control #### `openEditor(options) -> Promise` Open FrontEdit editing for a target block through the supported runtime path. ```js await SFE.PublicApi.openEditor({ uuid, element, handlerId, componentId, mode: 'edit', source: 'external' }); ``` Rules: 1. `uuid` is required. 2. `element` is optional when the block can be resolved from `uuid`. 3. `handlerId` is optional when FrontEdit can resolve the applicable handler for the block. 4. `componentId` is optional. When supplied, FrontEdit targets the documented editable component for the session. 5. `mode` defaults to `'edit'`. 6. `source` is a caller label for diagnostics and event payloads. Returns an `EditorSnapshot` when FrontEdit opened an editor session, otherwise `null`. #### `closeEditor(options = {}) -> boolean` Close the active editor session through the supported runtime path. ```js SFE.PublicApi.closeEditor({ uuid, restoreOriginal: true, reason: 'api', source: 'external' }); ``` Rules: 1. `uuid` is optional. When omitted, FrontEdit closes the active editor if one exists. 2. `restoreOriginal` defaults to `true`. 3. `reason` is an informational reason token. 4. `source` is a caller label for diagnostics and event payloads. Returns `true` when a close was attempted through the active supported editor session, otherwise `false`. #### `isEditorOpen() -> boolean` Returns whether FrontEdit currently has an active editor session. #### `getActiveEditor() -> EditorSnapshot|null` Returns a stable snapshot of the current active editor session. The return value is a snapshot, not a mutable live internal object. ### Runtime Inspection #### `resolveRuntime(options) -> ResolvedRuntime|null` Resolve the schema-aware runtime view FrontEdit would use for editing. ```js const runtime = SFE.PublicApi.resolveRuntime({ uuid, element, handlerId }); ``` Returns a stable runtime snapshot for the target block or `null` when no supported runtime could be resolved. #### `resolveEditingRuntime(options) -> ResolvedEditingRuntime|null` Resolve the richer schema-driven editing runtime FrontEdit would use for active editing or proposal materialization. ```js const runtime = SFE.PublicApi.resolveEditingRuntime({ uuid, element, handlerId, blockState, attributeChanges }); ``` Returns a detailed editing runtime snapshot with resolved component metadata and live component element references. Rules: 1. `uuid`, `element`, and `handlerId` follow the same resolution rules as `resolveRuntime()`. 2. `blockState` is optional. When supplied, FrontEdit resolves the runtime against that staged block state instead of the current session baseline. 3. `attributeChanges` is optional. When supplied, FrontEdit resolves the runtime against those pending block attribute changes. 4. The returned runtime data is read-only snapshot data except for documented DOM element references inside component entries. #### `getEditOperationContract(options) -> EditOperationContract|null` Return FrontEdit's read-only, schema-derived contract for AI or other generated operation proposals. It is a compact projection of the currently resolved handler components and their `editor.operations`; it does not expose a DOM element, route, save control, nonce, or mutable editor state. ```js const contract = SFE.PublicApi.getEditOperationContract({ uuid, element, handlerId }); ``` ```ts type EditOperationContract = { contractVersion: 1; uuid: string; operations: Array<{ id: string; componentId: string; inputs: Record; values?: Array; allowedRunFormats?: string[]; requiredRunFormatAttributes?: Record; }>; }; ``` Rules: 1. Use this contract to discover the exact operations, allowed values, and required inputs for this live block. Do not infer them from a block name or toolbar label. 2. The contract deliberately excludes attribute paths, selectors, executor kinds, serialization behavior, routes, and mutable editor internals. 3. It is not an authorization or mutation API. Generated proposals remain untrusted and must pass FrontEdit preflight before apply. 4. A handler must explicitly mark an operation `publicOperation: true` before it appears here. FrontEdit does not maintain a second public allowlist or synthesize generic operations from a block type. 5. `allowedRunFormats`, when present for a `rich_text_runs` input, contains the handler-declared format tokens permitted in each returned run. `requiredRunFormatAttributes`, when present, maps a format token to the minimum named values that must be present in that run's `formatAttributes[formatToken]` object. It exposes neither rendering tags, optional format data, selectors, nor mutation details. 6. List editing retains its established UUID-oriented list API. Its legal operation kinds and inputs are exposed separately through `getListOperationContract(...)`; they are not part of this generic generated-proposal envelope. #### `getEditableComponents(options) -> EditableComponent[]` Returns the runtime-editable components for the resolved block. #### `getDefaultComponent(options) -> EditableComponent|null` Returns the default editable component for the resolved block, if one exists. ### Public Operation Runtime V1 uses one attribute-free public operation envelope: ```js const operations = [ { id: operation.id, componentId: operation.componentId, inputs: { /* only values declared by getEditOperationContract() */ } } ]; const preflight = SFE.PublicApi.preflightOperations({ uuid, operations }); if (preflight?.valid === true) { SFE.PublicApi.applyOperations({ uuid, operations }); } ``` #### `preflightOperations(options) -> OperationPreflightResult|null` Validate an opaque operation batch against an already open editor without mutating DOM, history, preview state, or saved content. ```ts type OperationPreflightResult = { uuid: string; valid: boolean; validatedOperationIds: string[]; errors: Array<{ code: string; id?: string; componentId?: string }>; }; ``` #### `applyOperations(options) -> OperationResult|null` Stage the same preflighted opaque batch through FrontEdit's shared schema executor. FrontEdit resolves the operation locally from the active handler, performs normal preview and history work, and leaves review, save, and cancel under its normal editor lifecycle. Rules: 1. Call `openEditor(...)` explicitly before preflight or apply. 2. Each operation must exactly match a declaration from `getEditOperationContract(...)`. 3. Callers must not send `kind`, `attribute`, `attributes`, `bindingSource`, DOM selectors, or serialization metadata. 4. Callers processing generated or untrusted content must require `valid === true` before apply. 5. This is a staging API, never a direct-save API. `applyOperations(...)` returns `appliedOperationCount` in addition to its operation ID summary. Integrations that generate a batch must treat the stage as failed unless that count equals the requested operation count. ### V1 Operation Recipes All non-list mutations use the schema-derived operation envelope. Discover the operation on the live block, open that block's editor, preflight the exact batch, then apply the same batch. FrontEdit owns the resulting preview, history, review, cancel, and save lifecycle. #### Operation Envelope ```js const contract = SFE.PublicApi.getEditOperationContract({ uuid, element, handlerId }); if (!contract) { throw new Error('No edit-operation contract is available for this block.'); } const getOperation = predicate => { const operation = contract.operations.find(predicate); if (!operation) { throw new Error('The requested operation is not supported by this block.'); } return operation; }; const stage = async operations => { const preflight = SFE.PublicApi.preflightOperations({ uuid, operations }); if ( preflight?.valid !== true || preflight.validatedOperationIds.length !== operations.length ) { throw new Error('FrontEdit rejected the operation batch.'); } const result = SFE.PublicApi.applyOperations({ uuid, operations }); if (result?.appliedOperationCount !== operations.length) { throw new Error('FrontEdit did not stage every operation.'); } return result; }; ``` Every generic operation has exactly this shape: ```js { id: operation.id, componentId: operation.componentId, inputs: { // Exactly the declared input names and values for this operation. } } ``` Use the operation's `inputs` map as the complete field contract. Include every required input, omit optional inputs you do not need, and do not send `kind`, attribute paths, selectors, binding metadata, or other internal fields. #### Text Replacement Find an operation that declares a `rich_text_runs` input and submit the complete replacement run sequence for that component: ```js const rewrite = getOperation(operation => ( operation.componentId === 'content' && operation.inputs.runs?.type === 'rich_text_runs' )); await SFE.PublicApi.openEditor({ uuid, element, handlerId, componentId: rewrite.componentId }); await stage([{ id: rewrite.id, componentId: rewrite.componentId, inputs: { runs: [ { text: 'Updated copy', formats: [], formatAttributes: {} } ] } }]); ``` Use only `allowedRunFormats` exposed by that operation. When `requiredRunFormatAttributes` declares values for a format, include them in the matching run's `formatAttributes` object. #### Scalar Block Setting Settings such as alignment or heading level are schema operations with a declared scalar input. The concrete ID, component, allowed values, and any additional inputs come from the resolved contract: ```js const alignment = getOperation(operation => ( operation.componentId === 'content' && operation.inputs.value?.type === 'scalar' && Array.isArray(operation.values) && operation.values.includes('center') )); await SFE.PublicApi.openEditor({ uuid, element, handlerId, componentId: alignment.componentId }); await stage([{ id: alignment.id, componentId: alignment.componentId, inputs: { value: 'center' } }]); ``` If the declared operation has additional required inputs, include those exact fields in `inputs`. For example, a column-scoped setting can require a `columns` input in addition to `value`. #### Host Link Update For an anchor-host component, select the operation that declares the URL input and provide its declared optional link settings only when needed: ```js const link = getOperation(operation => ( operation.componentId === 'label' && operation.inputs.href?.type === 'url' )); await SFE.PublicApi.openEditor({ uuid, element, handlerId, componentId: link.componentId }); await stage([{ id: link.id, componentId: link.componentId, inputs: { href: 'https://example.com/pricing', new_tab: true } }]); ``` #### Media URL Replacement When the live operation contract declares a URL input for a media component, stage the URL as a generic operation. The operation ID remains contract-owned: ```js const media = getOperation(operation => ( operation.componentId === 'image' && operation.inputs.url?.type === 'url' )); await SFE.PublicApi.openEditor({ uuid, element, handlerId, componentId: media.componentId }); await stage([{ id: media.id, componentId: media.componentId, inputs: { url: 'https://example.com/uploads/updated-image.jpg', source: 'input' } }]); ``` Include `attachmentId` only when the media source provides one. When the contract declares `source`, use `library` for a WordPress media-library item or `input` for a direct URL. For a selected WordPress media-library or upload item, use the documented [`applyActiveMediaSelection(options)`](#applyactivemediaselectionoptions---editorsnapshotnull) method in [Media Inspection And Session Control](#media-inspection-and-session-control). That method's reference includes its required active-session setup and exact request shape. ### List Runtime V1 retains the public list-tree runtime for `core/list`-style blocks that are edited as one root block while exposing nested item/list structure to external callers. #### `getListStructure(options) -> ListNode|null` Return the current live structural snapshot for one open or discoverable list block. ```js const structure = SFE.PublicApi.getListStructure({ uuid, element }); ``` Rules: 1. `uuid` is required unless `element` can be resolved to a block UUID. 2. The target block must resolve to a live `UL` or `OL` root. 3. The return value is a read-only structural snapshot of the live DOM tree. #### `getListOperationContract(options) -> ListOperationContract|null` Return the FrontEdit-owned, read-only operation descriptor for one live list root. This is the machine-readable source of truth for public list operation kinds and their exact input fields. Integrations must use it rather than maintaining a separate list-operation catalog. ```js const contract = SFE.PublicApi.getListOperationContract({ uuid, element }); ``` ```ts type ListOperationContract = { contractVersion: 1; uuid: string; operations: Array<{ kind: string; inputs: Record; }>; }; ``` Rules: 1. `uuid` is required unless `element` can be resolved to a block UUID. 2. The target must resolve to a live `UL` or `OL` root. 3. Each `inputs` map is exact: callers must not add an input not declared for that operation. 4. `existing_list_item_uuid` accepts an item UUID from the current `getListStructure(...)` result. `new_list_item_uuid` is a fresh caller-owned item UUID for an insertion. `direct_list_item_html` is direct item text HTML and must not contain `li`, `ul`, or `ol` wrappers. 5. This is an inspection API, not mutation authority. Callers still must use `preflightListOperations(...)` successfully before `applyListOperations(...)`. #### `applyListOperations(options) -> ListOperationResult|null` Apply one or more structural list mutations as one runtime batch. #### `preflightListOperations(options) -> ListOperationPreflightResult|null` Validate a UUID-oriented list batch against the open FrontEdit list editor without mutating it. ```js const preflight = SFE.PublicApi.preflightListOperations({ uuid, operations }); if (preflight?.valid === true) { SFE.PublicApi.applyListOperations({ uuid, operations }); } ``` Return shape: ```ts type ListOperationPreflightResult = { uuid: string; valid: boolean; validatedOperationKinds: string[]; errors: Array<{ code: string; index?: number }>; }; ``` `insert_child` validates its supplied insertion command during preflight. Its internal follow-up indent is resolved only during the subsequent FrontEdit apply because the new runtime item does not exist until that point. ```js const result = SFE.PublicApi.applyListOperations({ uuid, operations: [ { kind: 'update_list_item_text', itemUuid: '7db1a4ff-8e25-4f7d-a806-9328d473bb96', contentHtml: 'Alpha' }, { kind: 'toggle_list_type', itemUuid: '7db1a4ff-8e25-4f7d-a806-9328d473bb96', } ] }); ``` Rules: 1. `uuid` is required. 2. The target list editor must already be open. 3. `operations` are applied in order against the live mutated tree. 4. Every operation must supply the correct documented UUID target token family for its kind. 5. FrontEdit resolves each operation's runtime UUIDs against the current post-mutation tree immediately before that operation runs. 6. Public callers must use only operation kinds and exact inputs advertised by `getListOperationContract(...)`. 7. Some public operations may expand into multiple internal primitive mutations. For example, `insert_child` inserts the new item after the parent item, then indents it so the tracker creates the nested child list through the normal editor path. 8. Successful batches return one updated list structure snapshot. #### Current V1 list operation descriptor The contract currently advertises: 1. `update_list_item_text` 2. `insert_before` 3. `insert_after` 4. `insert_child` 5. `remove_list_item` 6. `move_before` 7. `move_after` 8. `indent_list_item` 9. `outdent_list_item` 10. `toggle_list_type` These are the public API kinds only. Internally FrontEdit still executes lower-level primitive list operations such as `insert_list_item`, `move_list_item`, and `toggle_list_type`, but only the descriptor returned by `getListOperationContract(...)` is the machine-readable runtime contract. #### List operation payloads | Kind | Required fields | Optional fields | Description | | --- | --- | --- | --- | | `update_list_item_text` | `kind`, `itemUuid`, `contentHtml` | -- | Replaces the direct text HTML for one existing list item. | | `insert_before` | `kind`, `newItemUuid`, `targetItemUuid`, `contentHtml` | -- | Inserts a new sibling item before the target item. | | `insert_after` | `kind`, `newItemUuid`, `targetItemUuid`, `contentHtml` | -- | Inserts a new sibling item after the target item. | | `insert_child` | `kind`, `newItemUuid`, `targetItemUuid`, `contentHtml` | -- | Creates a new child item under the target item. | | `remove_list_item` | `kind`, `itemUuid` | -- | Removes one existing list item and its nested children. | | `move_before` | `kind`, `itemUuid`, `targetItemUuid` | -- | Moves an existing item before the target item. | | `move_after` | `kind`, `itemUuid`, `targetItemUuid` | -- | Moves an existing item after the target item. | | `indent_list_item` | `kind`, `itemUuid` | -- | Indents one existing item through the normal editor list behavior. | | `outdent_list_item` | `kind`, `itemUuid` | -- | Outdents one existing item through the normal editor list behavior. | | `toggle_list_type` | `kind`, `itemUuid` | -- | Toggles the containing list for the referenced item between ordered and unordered. | `contentHtml` is required for operations that create or replace item content. It represents the direct item text HTML only. It must not include wrapping `
  • `, `
      `, or `
        ` elements. Consumers must derive whether an operation carries content from its `direct_list_item_html` input descriptor, not from a copied operation-kind allowlist. #### Public target-token rules Public list operations must use only the documented runtime UUID token family for their kind. FrontEdit rejects public operations that omit the required token. 1. `update_list_item_text`, `remove_list_item`, `indent_list_item`, and `outdent_list_item` target one existing list item and must provide `itemUuid`. 2. `insert_before` and `insert_after` must provide `newItemUuid` plus `targetItemUuid`. 3. `insert_child` must provide `newItemUuid` plus `targetItemUuid`. If the target item does not already own a child list, FrontEdit creates the required nested list automatically. 4. `move_before` and `move_after` must provide `itemUuid` plus `targetItemUuid`. 5. `toggle_list_type` must provide `itemUuid`. FrontEdit resolves that item to its current containing list immediately before the toggle runs. 6. Public callers must use only the documented camelCase keys above. Any other keys are outside the API contract. 7. Public callers must not rely on cursor or selection state. Cursor-based inference is reserved for internal editor-originated calls only. #### Runtime UUID ownership List-item UUIDs and list-node UUIDs have different ownership rules. 1. Public callers are responsible for generating UUIDs for newly created list items. 2. FrontEdit is responsible for generating and managing UUIDs for list nodes. 3. Public callers must not create, assign, or mutate list-node UUIDs directly. 4. When a structural operation creates a new nested list, FrontEdit assigns the resulting `listUuid`. 5. Public list operations target items, not list nodes, even though returned structure snapshots still expose `listUuid` values. #### Recommended UUID convention FrontEdit does not enforce a specific caller UUID format for public list operations. Recommended convention: 1. Use RFC 4122 version 4 UUID strings for `itemUuid`, `targetItemUuid`, and `newItemUuid`. 2. Generate one fresh UUID for every new list item the caller intends to create. 3. Treat runtime UUIDs as session-scoped cursor tokens only. Do not persist or reuse them after the list editor closes or the page reloads. #### `ListNode` `getListStructure()` and successful list-operation results return recursive list nodes plus item nodes so child lists remain distinct from the list items that own them. A list node contains: 1. `listUuid` (string): session-scoped runtime UUID for this list node 2. `listPath` (string): empty string for the root list, or the parent item path that owns this nested child list 3. `ordered` (boolean): whether this specific list node is `OL` 4. `items` (array): direct child list items for this list node Each item contains: 1. `itemUuid` (string): session-scoped runtime UUID for this item 2. `path` (string): item tree path 3. `pathLabel` (string): human-readable 1-based path label 4. `depth` (number): zero-based nesting depth 5. `contentHtml` (string): direct item text HTML only 6. `childList` (`ListNode|null`): nested list node owned by this item, or `null` Example: ```json { "listUuid": "e183f2b5-2f90-4ca2-8ea8-c3d8c72ab2c1", "listPath": "", "ordered": false, "items": [ { "itemUuid": "7db1a4ff-8e25-4f7d-a806-9328d473bb96", "path": "0", "pathLabel": "1", "depth": 0, "contentHtml": "a", "childList": { "listUuid": "fd818143-75d8-4ae9-8f3f-798d54150472", "listPath": "0", "ordered": false, "items": [ { "itemUuid": "c71fad00-2d1f-4f70-b0fc-84681f5ef8a0", "path": "0_0", "pathLabel": "1.1", "depth": 1, "contentHtml": "b", "childList": { "listUuid": "2cd9f476-1d91-45e5-bd0b-ae981b78a111", "listPath": "0_0", "ordered": false, "items": [ { "itemUuid": "b2f4ffad-edbc-48e9-950d-2716b5bf6942", "path": "0_0_0", "pathLabel": "1.1.1", "depth": 2, "contentHtml": "c", "childList": null } ] } } ] } } ] } ``` #### `ListOperationResult` Successful list runtime mutations return: 1. `uuid` (string): target block UUID 2. `operationsApplied` (array of strings): normalized operation kinds applied in order 3. `structure` (`ListNode`): updated live list structure snapshot ### Media Inspection And Session Control #### `getMediaContext(options) -> MediaContext|null` Resolve the media-editable context for a block or specific component. ```js const mediaContext = SFE.PublicApi.getMediaContext({ uuid, element, handlerId, componentId }); ``` Returns `null` when the target block is not media-editable through the documented runtime surface. #### `getMediaDescriptor(options) -> MediaDescriptor|null` Returns the stable media descriptor for the selected file component, if one exists. #### `isMediaEditable(options) -> boolean` Returns whether the resolved block exposes a file-editable component through the public runtime contract. #### `applyActiveMediaSelection(options) -> EditorSnapshot|null` Apply one selected media item to the current active schema-media editor session through FrontEdit's supported runtime path. ```js const editor = SFE.PublicApi.applyActiveMediaSelection({ uuid, url, attachmentId, source: 'library' }); ``` Rules: 1. `uuid` is required and must match the current active editor session. 2. `url` is required. 3. `attachmentId` is optional. 4. `source` may be `'library'` or `'input'` and defaults to the input-style save transition when omitted. 5. Returns an updated `EditorSnapshot` when the active media session accepted the selection, otherwise `null`. ### Explicit Staging V1 supports explicit block-state staging only. Staging is editor preparation, not external save execution. External plugins may stage block state and open or guide the FrontEdit editor, but the user must complete saving through FrontEdit's standard save UI and normal FrontEdit save workflow. #### `stageBlockState(stage) -> void` Stage a temporary block-state payload for one block so that subsequent editor open and hydration flows may consume it through FrontEdit's supported staging path. ```js SFE.PublicApi.stageBlockState({ uuid, handlerId, blockState, source: 'external' }); ``` Rules: 1. `uuid` is required. 2. `handlerId` is optional metadata for the caller and diagnostics. 3. `blockState` must match the shape FrontEdit's canonical block hydration path expects. 4. Staged block state is temporary and applies only through the documented FrontEdit runtime path. 5. Staged changes do not create a supported external save path in V1. #### `clearStagedBlockState(uuid) -> void` Clear any currently staged block state for the given block UUID. ### Session Utilities #### `on(eventName, handler) -> unsubscribeFn` Subscribe to one documented runtime event. ```js const unsubscribe = SFE.PublicApi.on('save:after', payload => { // observe successful save completion }); ``` Returns an unsubscribe function equivalent to calling `off(eventName, handler)`. #### `off(eventName, handler) -> void` Remove a previously registered event handler. #### `refreshBlock(uuid, options?) -> Promise` Request that FrontEdit refresh the live DOM for one block through its supported refresh path and return the resulting `BlockSnapshot`. ### Dirty State, Page Context, and Lookup Utilities #### `getDirtyBlocks() -> DirtyBlock[]` Returns a stable summary of the blocks that currently have unsaved changes in the active runtime session. #### `hasDirtyBlocks() -> boolean` Returns whether any block currently has unsaved changes. #### `isBatchSessionActive() -> boolean` Returns whether FrontEdit currently has an active batch-edit session. #### `resetDirtyBlocks(uuids, options?) -> boolean` Reset the tracked dirty batch state for the supplied block UUIDs back to the current batch-session baseline. ### Pro-only Session Utilities These methods exist only when FrontEdit Pro is active on the page. #### `ensureBatchSession() -> Promise` Ensure the shared batch-edit session exists before downstream runtime checks or mutations depend on it. ```js const ready = await SFE.ProApi.ensureBatchSession(); ``` Rules: 1. This method is available only on `window.MWP.SFE.ProApi`. 2. It returns `false` when batch editing is unavailable or disabled for the current page. 3. It may be called repeatedly; repeated calls are safe and reuse any in-flight session bootstrap work. #### `getPageContext() -> PageContext` Returns a stable page-level runtime snapshot. #### `getRestContext() -> RestContext` Returns the REST context FrontEdit guarantees to expose for supported runtime integrations. #### `setRestNonce(nonce) -> RestContext` Update the REST nonce FrontEdit should use for subsequent supported runtime requests on the current page. ```js const restContext = SFE.PublicApi.setRestNonce(refreshedNonce); ``` Rules: 1. `nonce` must be a non-empty string. 2. This updates only the current page runtime state. It does not fetch or mint a new nonce on its own. 3. Callers should use this after their own authenticated nonce-refresh flow succeeds. 4. The return value is the updated `RestContext`. #### `getElementByUuid(uuid) -> Element|null` Returns the current live DOM element for a block UUID, if present. #### `getUuidForElement(element) -> string` Returns the FrontEdit block UUID for the supplied element, or an empty string when none is available. #### `getBlockSnapshot(uuid) -> BlockSnapshot|null` Returns a stable summary snapshot for one block UUID. #### `getEditableBlocks() -> EditableBlock[]` Returns the stable live-page discovery snapshots described above. ## Stable Snapshot Shapes Snapshots are plain data contracts. They are not live editor-state objects and must not be mutated to control FrontEdit. ### `EditorSnapshot` ```json { "uuid": "8d63...", "handlerId": "core_image", "mode": "edit", "blockName": "core/image", "componentType": "file", "componentId": "image", "saveStrategy": "single", "hasMediaSession": true, "isDirty": false, "isDraftSession": false, "isBatchSession": false } ``` Required fields: 1. `uuid` 2. `handlerId` 3. `mode` 4. `blockName` 5. `componentType` 6. `componentId` 7. `saveStrategy` 8. `hasMediaSession` 9. `isDirty` 10. `isDraftSession` 11. `isBatchSession` Field notes: 1. `hasMediaSession` is `true` when the active editor host currently exposes the supported media-selection control surface used by `SFE.PublicApi.applyActiveMediaSelection(...)`. ### `ResolvedRuntime` ```json { "uuid": "8d63...", "handlerId": "core_cover", "blockName": "core/cover", "schemaVersion": 1, "mode": "mixed", "defaultComponentId": "image", "components": [] } ``` Required fields: 1. `uuid` 2. `handlerId` 3. `blockName` 4. `schemaVersion` 5. `mode` 6. `defaultComponentId` 7. `components` ### `EditableComponent` ```json { "id": "image", "label": "Image", "type": "file", "selector": "figure", "default": true, "target": { "selector": "img", "attribute": "src", "mediaType": "image" }, "mediaDescriptor": { "componentId": "image", "scopeSelector": "figure", "targetSelector": "img", "attribute": "src", "mediaType": "image" } } ``` Required fields: 1. `id` 2. `label` 3. `type` 4. `selector` 5. `default` Optional fields: 1. `required` 2. `placeholder` 3. `target` 4. `mediaDescriptor` 5. `editor` ### `MediaDescriptor` ```json { "componentId": "image", "scopeSelector": "figure", "targetSelector": "img", "attribute": "src", "mediaType": "image" } ``` Required fields: 1. `componentId` 2. `scopeSelector` 3. `targetSelector` 4. `attribute` 5. `mediaType` ### `MediaContext` ```json { "supported": true, "componentId": "image", "mediaType": "image", "accept": "image/*", "label": "image block", "descriptor": { "componentId": "image", "scopeSelector": "figure", "targetSelector": "img", "attribute": "src", "mediaType": "image" } } ``` Required fields: 1. `supported` 2. `componentId` 3. `mediaType` 4. `accept` 5. `label` 6. `descriptor` ### `DirtyBlock` ```json { "uuid": "8d63...", "handlerId": "core_paragraph", "blockName": "core/paragraph", "beforeRaw": "

        Old

        ", "afterRaw": "

        New

        " } ``` Required fields: 1. `uuid` 2. `handlerId` 3. `blockName` 4. `beforeRaw` 5. `afterRaw` ### `PageContext` ```json { "postId": 123, "permissions": { "can_publish": true, "can_draft": false, "can_comment": true, "can_batch": true }, "hasDraftPreview": false, "isEditorOpen": false, "activeMode": "" } ``` Required fields: 1. `postId` 2. `permissions` 3. `hasDraftPreview` 4. `isEditorOpen` 5. `activeMode` ### `RestContext` ```json { "baseUrl": "https://example.com/wp-json/", "namespaceUrl": "https://example.com/wp-json/mwpsfe/v1/", "nonce": "..." } ``` Required fields: 1. `baseUrl` 2. `namespaceUrl` 3. `nonce` ### `BlockSnapshot` ```json { "uuid": "8d63...", "blockName": "core/image", "handlerIds": ["core_image", "core_image_comment"], "isPending": false, "pendingInfo": null, "elementPresent": true } ``` Required fields: 1. `uuid` 2. `blockName` 3. `handlerIds` 4. `isPending` 5. `pendingInfo` 6. `elementPresent` ### `EditableBlock` An `EditableBlock` contains every `BlockSnapshot` field plus: ```json { "contentText": "Visible normalized text from this block" } ``` `contentText` is the current rendered text used for live-page matching. It is not serialized Gutenberg block markup and must not be used as a write payload. ## Stable Events V1 events are observable only. They provide visibility into FrontEdit runtime lifecycle. They are not interception points and do not allow cancellation, mutation, or alternate control flow through event payload side effects. ### Subscription rules 1. Consumers may subscribe only through `SFE.PublicApi.on()`. 2. Consumers must treat event payloads as snapshots. 3. Event payload objects must not be mutated. ### `editor:opened` Fires after FrontEdit has opened an editor session through a supported path. Payload: ```json { "source": "external", "editor": {} } ``` Required fields: 1. `source` 2. `editor` as `EditorSnapshot` ### `editor:beforeClose` Fires before FrontEdit closes an editor session through a supported path. Payload: ```json { "source": "api", "reason": "api", "editor": {} } ``` Required fields: 1. `source` 2. `reason` 3. `editor` as `EditorSnapshot` ### `editor:closed` Fires after FrontEdit closes an editor session through a supported path. Payload: ```json { "source": "api", "reason": "api", "editor": {} } ``` Required fields: 1. `source` 2. `reason` 3. `editor` as `EditorSnapshot` ### `editor:componentChanged` Fires when FrontEdit changes the active editable component within one editor session. Payload: ```json { "source": "sfe", "editor": {} } ``` Required fields: 1. `source` 2. `editor` as `EditorSnapshot` ### `save:before` Fires when FrontEdit is about to begin a supported save path. Payload: ```json { "source": "sfe", "editor": {}, "saveStrategy": "single" } ``` Required fields: 1. `source` 2. `editor` as `EditorSnapshot` 3. `saveStrategy` ### `save:after` Fires after FrontEdit completes a supported save path successfully. Payload: ```json { "source": "sfe", "editor": {}, "saveStrategy": "single", "success": true } ``` Required fields: 1. `source` 2. `editor` as `EditorSnapshot` 3. `saveStrategy` 4. `success` ### `save:error` Fires when FrontEdit's supported save path fails. Payload: ```json { "source": "sfe", "editor": {}, "saveStrategy": "single", "message": "REVISION_CONFLICT" } ``` Required fields: 1. `source` 2. `editor` as `EditorSnapshot` 3. `saveStrategy` 4. `message` ### `block:staged` Fires after `stageBlockState()` records a staged block-state payload. Payload: ```json { "source": "external", "uuid": "8d63...", "handlerId": "core_image" } ``` Required fields: 1. `source` 2. `uuid` 3. `handlerId` ### `block:stageCleared` Fires after `clearStagedBlockState()` clears a staged block-state payload. Payload: ```json { "source": "external", "uuid": "8d63..." } ``` Required fields: 1. `source` 2. `uuid` ### `block:refreshed` Fires after FrontEdit refreshes a block's live DOM through the supported refresh path. Payload: ```json { "source": "sfe", "block": {} } ``` Required fields: 1. `source` 2. `block` as `BlockSnapshot` ## Candidate APIs Under Evaluation The following APIs are not part of V1 and are intentionally non-contractual in this document: 1. `consumeMediaSelection()` 2. `getActiveMediaSession()` 3. `registerBlockStateProvider()` 4. `unregisterBlockStateProvider()` These remain candidate APIs under evaluation so FrontEdit can improve its internal runtime boundaries before committing to stable provider or live media-session semantics. ## Private Runtime Boundary The following names and object families are explicitly private and unsupported for external integrations: 1. `SFE.Context` 2. `SFE.ManagerData` 3. `SFE.SchemaRuntime` 4. `SFE.MediaHelper` 5. `SFE.Api` 6. `SFE.SaveHelpers` 7. `SFE.SaveHooks` 8. `SFE.BlockSerializer` 9. `SFE.BatchEditManager` 10. `SFE.ResolveBlockState` 11. `SFE.ResolveEditorStrategy` 12. Raw `handler.client_config` 13. Raw editor-state objects 14. Underscore-prefixed properties such as `_mwpSchemaRuntime` and `_mwpSchemaMediaSession` 15. Undocumented DOM classes and data attributes Private APIs may change without a public contract version notice. ## Extension Rules External runtime integrations must follow these rules: 1. Use `window.MWP.SFE.PublicApi` as the only supported JS entry point. 2. Use FrontEdit runtime inspection APIs instead of re-resolving schema handlers or media descriptors from private state. 3. Use explicit staging APIs instead of overriding global block-state resolvers. 4. Use documented lifecycle events instead of patching editor open or close methods. 5. Use stable snapshots only for observation and coordination, never for direct mutation of live FrontEdit state. 6. Preserve FrontEdit's canonical save pipeline and do not bypass block serialization rules. 7. Do not treat V1 as a supported direct-save API; saving remains user-driven through standard FrontEdit controls. 8. When an integration refreshes the shared REST nonce during a long-lived session, it should synchronize FrontEdit through `SFE.PublicApi.setRestNonce(...)` instead of mutating `SFE.ManagerData` directly. Large Breed Dog Nutrition: 5 Deadly Food Mistakes 2026 | PetEatWell

        Large Breed Dog Nutrition: 5 Deadly Food Mistakes

        Ever wonder if you’re feeding your large breed dog the right way? Large breed dogs have unique nutritional needs that differ from smaller dogs—they need controlled growth rates and specific nutrient ratios to avoid developmental problems.

        I’ve seen too many well-meaning pet parents unknowingly set their gentle giants up for joint issues and health problems just because they treat their Great Dane like a supersized Chihuahua.

        Large Breed Dog Nutrition

        What works for my neighbor’s Beagle could actually harm your German Shepherd or Golden Retriever. Large breed dogs face specific nutritional problems that require careful attention to calcium levels, growth rates, and feeding schedules.

        Getting it wrong during puppyhood can lead to painful conditions that last a lifetime.

        I’ll walk you through the science-backed feeding strategies that support healthy bone development and the must-have nutrients that keep joints strong. Let’s talk about the common mistakes even experienced dog owners make when choosing food for their big dogs.

        Key Takeaways

        • Large breed dogs need controlled growth rates with specific calcium and phosphorus ratios to prevent bone problems
        • Puppies should eat specially formulated large breed food to avoid growing too fast and damaging their joints
        • Adult large breeds require careful weight management and joint-supporting nutrients throughout their lives

        The Unique Nutrition Needs of Large and Giant Breed Dogs

        Large and giant breed dogs face completely different metabolic challenges than their smaller cousins. They need carefully balanced calories and controlled growth rates to avoid serious joint problems.

        I’ve seen too many Great Dane puppies develop hip dysplasia because their owners didn’t understand these critical differences.

        What Sets Large Dogs Apart

        Your dog’s size creates unique nutritional demands that can’t be ignored.

        Growth Rate Control is Everything

        Large dogs grow at lightning speed during their first year. A Chihuahua reaches adult size at 6 months, but your German Shepherd might not stop growing until 18-24 months.

        This extended growth period means nutritional problems of large and giant breed dogs can develop quickly if you don’t get nutrition right.

        Joint Development Vulnerability

        Your large breed puppy’s joints start as soft cartilage that slowly hardens. Feed them too much calcium or let them grow too fast, and you’re setting them up for:

        • Hip dysplasia
        • Elbow dysplasia
        • Osteochondrosis

        Metabolic Differences You Can’t Ignore

        Giant breed dogs actually have slower metabolisms per pound than small dogs. They need fewer calories per pound of body weight than a Yorkie.

        Common Nutrition Myths for Big Breeds

        I hear these myths all the time at the clinic.

        Myth: “More Protein = Bigger, Stronger Dog”

        Nope. The influence of dietary protein content on growth in giant breed dogs shows that excess protein just creates faster growth that damages joints.

        The Reality: Large breed puppies need 22-24% protein maximum. Small breed puppies can handle 28-30%.

        Myth: “Puppy Food Until They’re Done Growing”

        This one makes me cringe. Regular puppy food has too many calories for large breeds.

        Your Mastiff puppy needs specific large-breed puppy food with controlled calcium and phosphorus ratios.

        Myth: “Free Feeding is Fine”

        Never free-feed a large breed puppy. Studies show Great Dane puppies fed ad libitum developed significantly more joint problems than those on controlled portions.

        Myth: “Adult Food at 1 Year”

        Giant breeds like Saint Bernards aren’t done growing until 24 months. Switch too early and you’ll stunt their development.

        How Energy and Calorie Needs Shift by Size

        This is where size really matters for your dog’s health.

        Calorie Needs by Size Category:

        Dog SizeAdult Calories per Pound
        Small (under 20 lbs)40-50 calories
        Large (50-90 lbs)20-25 calories
        Giant (over 90 lbs)18-22 calories

        Why Large Dogs Need Fewer Calories Per Pound

        It’s like heating a house. A small house loses heat faster than a mansion. Small dogs have more surface area relative to their body mass, so they burn energy faster.

        Age-Related Calorie Shifts

        Your large breed dog’s calorie needs change a lot as they age:

        • Puppyhood (4-12 months): Highest calorie density needed
        • Adolescence (1-2 years): Gradual reduction as growth slows
        • Adulthood (2-6 years): Stable, moderate calories
        • Senior (7+ years): Energy requirements decrease by 10-20%

        The Growth Rate Sweet Spot

        I recommend large breed puppies gain 2-4 pounds per week maximum. Any faster and you’re risking joint damage. Any slower might mean underfeeding or health issues.

        Check your puppy’s body condition every week. You should feel their ribs easily but not see them sticking out.

        Feeding Large Breed Puppies: Growing Right, Not Just Fast

        Two large breed puppies being fed nutritious food by a caring adult in a cozy indoor setting with a growth chart and dog toys nearby.

        Large breed puppies need special nutrition to prevent joint problems and ensure healthy development. The wrong food can cause rapid growth that damages bones and leads to lifelong issues.

        Why Regular Puppy Food Isn’t Enough

        I’ve seen too many owners feed their Great Dane puppy the same food as a Chihuahua. Here’s the truth: regular puppy food makes large breed puppies grow too fast.

        Standard puppy foods pack in more calories per cup than growth diets designed for large breed dogs. This creates a dangerous situation.

        When your German Shepherd puppy grows too quickly, their bones can’t keep up. The soft growth plates get stressed and damaged.

        Key differences between regular and large breed puppy food:

        • Calories: Large breed formulas have fewer calories per cup
        • Minerals: Lower calcium and phosphorus levels
        • Growth rate: Designed for steady, controlled development

        It’s kind of like building a house. You wouldn’t rush the foundation just to finish faster. The same goes for your puppy’s skeleton.

        Preventing Hip Dysplasia and Growth Disorders

        Hip dysplasia isn’t just genetic—nutrition plays a huge role. I wish more owners knew this before it’s too late.

        Fast growing large breed puppies on diets low in proper nutrients develop serious problems. But feeding too many calories creates issues too.

        Growth disorders from wrong nutrition:

        • Hip dysplasia
        • Elbow dysplasia
        • Wobbler syndrome
        • Panosteitis (growing pains)

        The goal is moderate growth rates rather than maximum speed. Your Labrador puppy should gain weight steadily, not shoot up like a rocket.

        Signs of too-rapid growth:

        • Limping or favoring legs
        • Reluctance to play or exercise
        • Swollen joints
        • Difficulty getting up

        Proper large breed puppy nutrition prevents skeletal diseases by controlling mineral content. It’s like giving your puppy’s bones time to mature properly.

        Spotting the Right Puppy Food Label

        Dog food labels can feel like reading a foreign language. Let me break down what actually matters for your large breed puppy.

        Look for these exact phrases on the label:

        • “Formulated for large breed puppies”
        • “Meets AAFCO nutritional standards for large breed growth”
        • “For puppies over 70 pounds adult weight”

        Key numbers to check:

        • Calcium: 1.2-1.8% maximum
        • Phosphorus: 1.0-1.6% maximum
        • Fat: 12-15% (not higher)
        • Protein: 22-26%

        Avoid foods that just say “for all life stages.” Your Saint Bernard puppy isn’t the same as a Yorkie.

        Red flags on labels:

        • High calcium percentages (over 2%)
        • “Maximum growth” claims
        • No mention of large breeds
        • Generic “puppy food” without specifics

        I always tell owners to check the feeding guidelines too. Large breed formulas recommend different portions based on expected adult weight.

        The first ingredient should be a named meat source. If you see “meal” don’t panic—chicken meal is actually more concentrated protein than fresh chicken.

        Quick label check:

        1. Find “large breed puppy” on the front
        2. Check calcium levels
        3. Verify AAFCO statement
        4. Look at feeding guidelines for your puppy’s size

        Must-Have Nutrients for Large Breed Dog Health

        A large healthy dog standing outdoors surrounded by illustrations of protein, calcium, omega-3 sources, vitamins, and joint supplements.

        Large breed dogs need specific nutrients to support their massive frames and prevent joint problems that can steal years from their lives. I’ve seen too many Great Danes and German Shepherds struggle with hip issues because their owners didn’t understand the power of proper nutrition.

        High-Quality Protein: Meat, Fish, and Eggs

        Your gentle giant needs premium protein to build those powerful muscles without putting stress on developing joints. I can’t tell you how many times I’ve watched large breed puppies grow too fast on cheap kibble packed with plant proteins.

        Fish gives your dog complete amino acids plus omega-3s that fight inflammation. Think salmon, mackerel, or sardines—not mystery “fish meal” from questionable sources.

        Eggs pack all essential amino acids in perfect ratios. I feed my own dogs whole eggs twice a week because they’re nature’s protein powerhouse.

        Here’s what I look for in quality protein sources:

        • Named meats (chicken, beef, lamb) – not “poultry meal”
        • Fresh fish listed in the first three ingredients
        • Whole eggs rather than egg powder

        The magic number? About 22-26% protein for large breed puppies and 18-22% for adults. Too much protein makes them grow too fast, leading to joint problems later.

        Powerhouse Minerals and Vitamins

        Large breed dogs walk a tightrope with minerals—too little causes deficiencies, too much creates joint disasters. I’ve learned this the hard way watching friends’ dogs develop hip dysplasia from improper calcium ratios.

        Calcium and phosphorus must stay balanced at 1.2:1 ratio. When this gets out of whack, your dog’s bones grow wrong. Period.

        Glucosamine and chondroitin aren’t just for old dogs. I start my large breeds on these joint protectors early because prevention beats treatment every time.

        Key minerals your giant needs:

        MineralWhy It MattersBest Sources
        CalciumBone developmentBone meal, dairy
        PhosphorusWorks with calciumMeat, fish
        ZincImmune functionRed meat, eggs
        CopperJoint healthLiver, shellfish

        Proper nutrition systems ensure harmonious growth in large breeds through careful mineral balance.

        The Importance of Fatty Acids (EPA & DHA)

        Your big dog’s joints take a beating every day. EPA and DHA fatty acids act like internal oil changes, keeping everything moving smoothly and reducing inflammation that destroys cartilage.

        I feed fish oil daily because these omega-3s don’t just help joints—they boost brain function and keep coats shiny. Your German Shepherd’s intelligence depends partly on proper fatty acid nutrition.

        EPA fights inflammation at the cellular level. Think of it as your dog’s personal fire department, putting out inflammatory fires before they damage joints.

        DHA supports brain development and function. Large breed puppies need this for proper cognitive development during their extended growth phases.

        Best sources I recommend:

        • Wild-caught fish oil (not farm-raised)
        • Krill oil for better absorption
        • Flaxseed oil as a plant-based backup

        Aim for 20-55mg of combined EPA/DHA per pound of body weight daily. So my 80-pound Lab gets about 1,600-4,400mg daily through supplements and fish-based meals.

        Balanced diets avoid nutritional deficiencies while supporting optimal health in large breed dogs.

        Choosing the Best Food for Every Life Stage

        Three large breed dogs representing puppy, adult, and senior life stages, each with a bowl of food suited to their nutritional needs.

        Picking the right large breed dog food changes as your gentle giant ages from a playful adult to a wise senior. Adult dogs need balanced nutrition to maintain their energy, while senior pups require specialized formulas to support aging joints and slower metabolisms.

        Adult Large Breed Dog Food

        Let me tell you—feeding an adult large breed dog isn’t just about filling a bigger bowl. I’ve learned that dog food for large breeds needs specific protein and fat ratios to keep these magnificent dogs healthy without adding unnecessary weight to their frames.

        Dry dog food works great for most adult large breeds. Look for formulas with 22-26% protein and 12-15% fat.

        These percentages give your dog steady energy without overloading their system. I always check the first ingredient.

        It should be a named meat source like “chicken” or “salmon”—not “meat by-products.” This tells me the food prioritizes quality protein.

        Key features to look for:

        • Glucosamine and chondroitin for joint support
        • Controlled calcium levels (1.2-1.8%)
        • L-carnitine to maintain lean muscle mass
        • Omega fatty acids for coat health

        Wet dog food can work too, but it’s pricier per serving. Many owners mix both—using wet food as a topper to make dry kibble more appealing.

        This combo gives you cost savings plus flavor variety. Adult large breed dogs typically eat 3-5 cups daily, split into two meals.

        I recommend measuring portions rather than free-feeding, since proper body condition maintenance prevents joint stress and other health issues.

        Senior Nutrition: Aging Gracefully

        When my large breed dog hit seven years old, I noticed subtle changes. Less bouncing around the yard, slower morning rises, maybe a bit more gray around the muzzle.

        That’s when I switched to senior-specific nutrition. Senior large breed dog food contains fewer calories but more nutrients.

        These formulas typically have 18-25% protein to maintain muscle mass while accounting for decreased activity levels.

        Essential senior dog food features:

        • Enhanced glucosamine levels (800mg minimum)
        • Added antioxidants like vitamin E and C
        • Easily digestible proteins
        • Reduced phosphorus for kidney support
        • Higher fiber content for digestive health

        I prefer dry dog food for seniors because the kibble helps scrape tartar from aging teeth. However, if your senior dog has dental issues, soaking kibble or switching to wet dog food makes eating easier.

        Dogs’ life stages alter nutritional approaches, and senior dogs often need smaller, more frequent meals.

        I feed my senior large breed dog 2-3 smaller portions daily instead of two large ones. Watch for appetite changes, weight fluctuations, or eating difficulties.

        These signs might indicate it’s time to adjust their diet or consult your vet about specialized senior nutrition needs.

        Spotlight Ingredients for Joint & Bone Health

        Glucosamine and chondroitin work like repair crews for your large breed’s cartilage, while early prevention can save your dog from painful hip dysplasia and joint problems down the road.

        How Glucosamine and Chondroitin Help

        Let’s be real—if you’ve got a German Shepherd or Great Dane, you’re probably already worried about their joints. I get it.

        Glucosamine acts like your dog’s personal cartilage mechanic. It helps rebuild the cushiony stuff between bones that wears down over time.

        Cartilage is basically the shock absorbers in your car. Without enough glucosamine, those shock absorbers get bumpy and worn out.

        Chondroitin teams up with glucosamine to keep cartilage flexible and hydrated. It’s like adding oil so things keep moving smoothly.

        From veterinary experts who treat joint disease, I’ve learned you won’t see results overnight. Give it at least 4-6 weeks.

        Key benefits include:

        • Reduced joint inflammation
        • Better cartilage repair
        • Improved mobility in arthritic dogs
        • Slower progression of joint damage

        These supplements work best for mild to moderate cases. Severe arthritis needs more aggressive treatment.

        Preventing Joint Issues in Large Dogs

        Ever watched a Golden Retriever puppy try to navigate stairs? Those awkward movements aren’t just cute—they’re your first clue about joint health.

        Hip dysplasia hits large breeds hardest. I’m talking Labs, Rottweilers, and Saint Bernards.

        The good news? Joint supplements can start as early as 8 weeks old for at-risk puppies.

        My prevention strategy:

        • Start supplements during puppyhood for high-risk breeds
        • Maintain healthy weight (every extra pound stresses joints)
        • Choose joint-support diets with omega-3 fatty acids
        • Provide controlled exercise, not marathon sessions

        Weight matters more than you think. A 10-pound overweight dog puts 30-60 pounds of extra pressure on their joints with each step.

        Think about it—would you want to carry a heavy backpack everywhere you go?

        Red flags to watch for:

        • Reluctance to jump or climb stairs
        • Stiffness after naps
        • Decreased playfulness
        • Subtle gait changes

        Feeding Strategies and Weight Management Tips

        Managing your large breed dog’s weight really comes down to controlling their calories. Regularly check their body condition score so you can catch any weight changes early.

        Portion Control vs. Free Feeding

        Picture this: you leave a full bowl of kibble out for your German Shepherd, thinking you’re being kind. By evening, it’s gone—and your pup is begging for more.

        Free feeding is your large breed dog’s fast track to obesity. When food sits out all day, you lose track of how much your dog eats.

        I always recommend measured portions at set meal times. Here’s why this works better:

        Portion Control Benefits:

        • You track exact calorie intake daily
        • Prevents overeating and food guarding
        • Makes it easier to adjust food amounts
        • Helps with house training schedules

        How to portion correctly:

        1. Use a measuring cup, not a random scoop
        2. Follow feeding guidelines on your dog food bag
        3. Divide daily amount into 2-3 meals
        4. Adjust calories monthly based on your dog’s weight changes

        Most large breed dogs need 20-30 calories per pound of body weight daily. A 70-pound Golden Retriever needs about 1,400-2,100 calories depending on activity level.

        Assessing Body Condition Score at Home

        You don’t need a vet visit to check if your dog is getting chubby. Learning to assess body condition at home helps you catch weight gain before it becomes a problem.

        The hands-on test works best. Stand behind your dog and place your hands on their ribcage.

        What you should feel:

        • Ideal weight: Ribs easily felt with light pressure, no fat covering
        • Overweight: Need firm pressure to feel ribs through fat layer
        • Underweight: Ribs visible and easily felt with no pressure

        Visual cues from the side:

        • Look for a visible “tuck” where the belly curves up toward the back legs
        • The chest should be wider than the waist when viewed from above

        Veterinary nutritionists recommend checking body condition score monthly. I suggest doing this simple check during your regular grooming routine.

        Red flags to watch for:

        • Can’t feel ribs without pressing hard
        • No waist tuck visible
        • Fat deposits around the neck and shoulders
        • Heavy breathing during normal activity

        If your dog scores above ideal, reduce their daily calories by 10-15%. Recheck in two weeks.

        Frequently Asked Questions

        A large breed dog sitting next to a bowl of nutritious dog food with small icons representing vitamins and health around them.

        Large breed dog nutrition raises specific questions about calcium ratios, feeding schedules, and growth requirements. I’ll address the most common concerns from giant breed owners about proper nutrition timing and kibble selection.

        What’s the ideal balance of calcium and phosphorus in food for a puppy that’s going to grow up big and strong?

        Here’s the thing about calcium and phosphorus—I see too many owners going overboard thinking more equals stronger bones.
        The magic ratio is 1.2:1 calcium to phosphorus. That’s what large and giant breed puppies need for healthy development.
        Too much calcium actually slows growth and causes joint problems. I’ve watched owners supplement thinking they’re helping, but they’re creating issues.
        Your puppy’s kibble should contain 0.7-1.2% calcium and 0.6-1.1% phosphorus on a dry matter basis. Check the guaranteed analysis on the bag.
        Never add calcium supplements unless your vet specifically recommends it. Quality large breed puppy foods already have the right balance built in.

        Let’s be real, what’s on the top list of kibble for your gentle giants in their early stages?

        I always tell new giant breed owners to look for AAFCO-approved large breed puppy formulas first.
        Royal Canin Giant Puppy consistently ranks high because it controls growth rate perfectly. Hill’s Science Diet Large Breed Puppy is another solid choice I recommend often.
        Purina Pro Plan Focus Large Breed Puppy offers great value without compromising nutrition. The protein stays around 26-30% which prevents rapid growth spurts.
        Avoid grain-free formulas for large breed puppies. Recent studies link them to heart problems, and I’ve seen too many issues firsthand.
        Look for foods with glucosamine and chondroitin already added. Your puppy’s joints will thank you later when they’re carrying 100+ pounds.

        Ever wondered what’s the prime choice when it comes to dry food for your sizable companion?

        Adult large breed dogs need different nutrition than puppies, and I get this question constantly.
        Hill’s Science Diet Adult Large Breed remains my top recommendation. The kibble size matches their mouth, and the formula supports joint health perfectly.
        Purina Pro Plan Large Breed Adult offers excellent digestibility. I love that it includes real chicken as the first ingredient.
        Royal Canin Maxi Adult works well for dogs 56-100 pounds. Their Giant Adult formula handles the 100+ pound dogs beautifully.
        Key features I look for: protein around 21-26%, fat content 10-15%, and added joint supplements. The nutritional needs of adult large breed dogs differ significantly from smaller breeds.

        You know that look your pup gives you during mealtime? What’s in the bowl that keeps their tails wagging?

        That expectant stare gets me every time, and I know exactly what creates that excitement.
        Real meat as the first ingredient makes the biggest difference in palatability. Chicken, beef, or fish—dogs know quality when they taste it.
        Added flavor enhancers like chicken fat or natural flavors boost appeal. But I prefer foods that taste good because of quality ingredients, not artificial additives.
        Texture matters more than you think. Large breed dogs prefer bigger kibble they can actually crunch. Those tiny pieces just get inhaled without satisfaction.
        Mix in small amounts of wet food or bone broth for extra appeal. Just keep it under 10% of their daily calories to maintain nutritional balance.
        Fresh water always available keeps them happy and healthy. I see too many owners forget this basic need.

        Giant breed owners, have you checked out the latest buzz on nutritious meals for your colossal canines?

        The pet food industry keeps evolving, and I’m seeing some exciting developments for giant breeds specifically.
        Fresh food delivery services now offer giant breed formulas. Companies like Farmer’s Dog and Ollie create custom portions based on your dog’s exact weight and activity level.
        Freeze-dried raw foods are gaining popularity because they’re convenient but still provide raw nutrition benefits. Just add warm water and serve.
        Functional ingredients are the new trend I’m watching. Foods with prebiotics, probiotics, and omega-3s built right in support overall health better than ever.
        Limited ingredient diets help identify food sensitivities that giant breeds often develop. Blue Buffalo Basics and Hill’s Prescription Diet offer excellent options.

        Looking to fill that big food dish? What guidelines should you follow to ensure you’re meeting all their growth needs?

        Feeding a giant breed puppy isn’t about guessing—it’s about careful choices.
        Feed 3-4 smaller meals daily until they’re 6 months old. Those big bellies just can’t handle huge meals safely, and smaller portions help prevent bloat.
        Grab a measuring cup, not a scoop. I’ve seen plenty of folks just eyeball it, but these puppies really need precise amounts based on their weight right now.
        Monitor body condition weekly. You should feel their ribs without seeing them. If they get too chubby, joint issues can stick around for life.
        Switch to adult food somewhere between 12 and 18 months, but it depends on the breed. Great Danes seem to mature faster than Saint Bernards—so it’s worth checking your specific dog’s timeline.
        Never free-feed large breed puppies. Scheduled meals keep overeating in check and make house training easier. Plus, you’ll spot any appetite changes that could mean something’s up with their health.

        As an Amazon Associate, we may earn a commission from qualifying purchases if you click on the links within this article. Learn more.

        Leave a Reply