# 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. Small Dog Nutrition Tips: Unlock the Secret to a Thriving Pup 2026 | PetEatWell

        Small Dog Nutrition Tips: Unlock the Secret to a Thriving Pup

        Small dogs have unique nutritional needs that really set them apart from bigger breeds. Getting their diet right can seriously impact their health and happiness.

        If you’ve ever wondered why your tiny pup seems pickier than a toddler at dinnertime or struggles with weight issues despite eating “regular” dog food, you’re definitely not alone.

        Small Dog Nutrition Tips: Unlock the Secret to a Thriving Pup

        Small dogs need more calories per pound than large dogs, require smaller kibble sizes, and benefit from more frequent meals to keep their blood sugar steady. Their fast metabolisms and tiny stomachs create a whole set of dietary challenges that catch a lot of dog owners off guard.

        I’ve seen plenty of well-meaning pet parents accidentally underfeed or overfeed their small dogs just because they didn’t realize the rules are different.

        So, how do you build the perfect nutrition plan for your small dog? It comes down to finding the right kibble size, portion control, and knowing when their current diet isn’t cutting it.

        We’ll cover tricks for portion control, how to find great foods that don’t cost a fortune, and the warning signs that it’s time to make a change.

        Small Dog Nutrition Tips – Key Takeaways

        • Small dogs need higher calorie density and more frequent meals than big breeds because of their faster metabolisms.
        • Kibble size and texture really matter for small mouths, so specialized small-breed formulas are usually best.
        • Managing weight and monitoring diet helps prevent common health problems like hypoglycemia and dental issues in small dogs.

        Why Small Dogs Need Special Nutrition

        Small breed dogs burn calories much faster than their larger cousins. Their tiny stomachs can’t hold much, but they need more calories per pound to stay healthy and energetic.

        Unique Metabolic Rates of Small Breeds

        Ever wonder why your Chihuahua seems to have endless energy? Small dogs have higher metabolisms than bigger breeds, so they go through calories at lightning speed.

        Here’s what this means for your pup:

        • Faster calorie burn: Small breeds need about 40 calories per pound of body weight every day.
        • Quick energy depletion: If they skip a meal, their blood sugar can drop quickly.
        • Higher nutrient density required: Every bite needs to be packed with nutrition.

        I’ve seen so many small dog owners get tripped up by this. Your 5-pound Yorkie might eat what looks like a tiny amount, but pound for pound, they’re eating way more calories than a Golden Retriever.

        The metabolism difference is huge. A 70-pound Lab might need 1,400 calories a day, while your 7-pound Maltese needs about 280. That’s about the same calorie-per-pound ratio as a marathon runner!

        This fast metabolism means small dogs are at risk for hypoglycemia (low blood sugar). Missing a meal can cause weakness, trembling, or worse.

        Small Dog vs. Large Dog Nutritional Needs

        Let’s face it—feeding a Pomeranian isn’t anything like feeding a Great Dane. It’s not just about portion size.

        Kibble Size Matters

        Small breeds need kibble that’s actually small enough for their mouths. Those big chunks made for large dogs? Total choking hazards for little pups.

        Protein Requirements

        Small dogs need higher protein percentages in their food:

        • Small breeds: 22-25% minimum protein
        • Large breeds: 18-20% minimum protein

        Fat Content

        Small breed dogs need more healthy fats for energy and a shiny coat. Look for foods with 8-12% fat.

        Feeding Frequency

        Dog SizeMeals Per DayWhy
        Small breeds2-3 mealsPrevents blood sugar drops
        Large breeds1-2 mealsReduces bloat risk

        I always tell small dog parents: your pup’s stomach is about the size of a walnut. They just can’t eat enough in one meal to get all their calories.

        Common Health Risks in Small-Breed Dogs

        Small dogs face some pretty unique health challenges, and the right nutrition can help prevent them. I’ve seen these issues way too often with little breeds.

        Dental Problems

        Dental issues are super common in small breeds. Their tiny mouths get packed with teeth, which leads to:

        • Plaque buildup
        • Tooth loss
        • Gum disease

        Solution: Pick kibble made for small mouths and add dental chews to their routine.

        Obesity

        This one gets me every time. Those portions look so small that a lot of owners add “just a little extra.” But even 5 extra pounds on a 10-pound dog is like you gaining 75 pounds if you weigh 150.

        Luxating Patella

        Small dogs can have kneecap dislocation, and extra weight definitely makes it worse.

        Hypoglycemia

        Small breed puppies especially need frequent meals to avoid dangerous blood sugar crashes. It’s scary how fast it can happen.

        Heart Disease

        Breeds like Cavaliers and Maltese often have heart problems in their genes. Extra weight puts even more strain on their hearts.

        Choosing food made for small breeds with the right kibble size, calorie density, and nutrient balance can make a world of difference.

        Building the Perfect Small Dog Diet

        When I think about small dog nutrition, I picture a Chihuahua trying to crunch on kibble made for a Golden Retriever. It’s just not going to happen.

        Small breeds need diets with the right nutrients, portion sizes, and ingredients that work for their fast metabolisms.

        Essential Nutrients for Small-Breed Health

        Honestly, your Yorkie burns calories like a little furnace compared to the relaxed Great Dane down the street.

        Small dog breeds have much higher metabolic rates per pound. They need more calories in every bite.

        I’ve learned that small dogs need more meat protein and healthy fats to match their energy needs.

        Protein is key. While big dogs might do fine with 18-22% protein, small breeds do best with 25-30% protein content.

        Here’s what I look for in small dog food:

        • High-quality animal protein (chicken, fish, lamb) as the first ingredient
        • Healthy fats like fish oil and chicken fat for more energy
        • DHA for brain development (especially for puppies)
        • Glucosamine and chondroitin for joint support

        Carbohydrate needs are different, too. Small dogs need a blend of carbs that gives quick energy without wild blood sugar swings.

        Dental health nutrients matter a lot. With the same number of teeth as a Great Dane squeezed into a tiny mouth, small breeds get dental disease more easily.

        Feeding Frequency and Portion Control

        If you’ve watched a Pomeranian inhale their food in seconds, you know portion control is a challenge with small breeds.

        Small dogs have tiny stomachs—seriously, toy breeds have stomachs about the size of a walnut. They just can’t eat big meals.

        I suggest feeding 3-4 small meals per day instead of two big ones. This helps prevent hypoglycemia, which small breeds are prone to.

        Portion sizes can get out of hand fast. Just an ounce of extra kibble can mean 20% more calories a day for a small dog. That’s like you accidentally eating an extra 400-500 calories every day!

        Weight monitoring is critical because a few ounces can be 10-20% of their total weight. Imagine gaining 20-30 pounds overnight—yeah, that’s what a half-pound means to a 5-pound Chihuahua.

        I always tell people to measure their dog’s food with a real measuring cup, not just guessing.

        Choosing High-Quality Ingredients

        Here’s the kicker — not all dog food for small breeds is created equal. The marketing? Yeah, it can be misleading.

        The kibble size matters more than you think. Small breed recipes are crafted with smaller sized kibble specifically designed for tiny mouths.

        I’ve watched plenty of small dogs struggle with regular-sized kibble. It’s honestly a little heartbreaking to see them try and fail.

        Premium natural ingredients should be your baseline. Look for named meat sources like “deboned chicken” or “salmon meal”—not vague “meat by-products.”

        What I look for on ingredient lists:

        • Real meat as the first ingredient
        • Limited, recognizable ingredients
        • No artificial colors or preservatives
        • Added vitamins and minerals
        • Probiotics for digestive health

        The nutrient density is everything. Small dogs need nutrient-dense recipes that match their smaller stomach size and deliver maximum nutrition per bite.

        Avoid fillers like corn, wheat, and soy. They just take up space without providing quality nutrition.

        Your small dog’s stomach real estate is too valuable for empty calories.

        1. How much should I feed my small dog daily?

        Feed based on your dog’s ideal weight, not their current weight. Most small dogs need 1/4 to 1 cup of high-quality kibble daily, split into 3-4 meals.

        A 5-pound dog typically needs about 200-250 calories per day. A 15-pound dog needs 400-500 calories.

        2. Can small dogs eat regular dog food?

        Small dogs can technically eat regular dog food, but it’s not ideal. Regular kibble is usually too large, and the nutrient profile doesn’t match their higher metabolic needs.

        Small breed formulas have more calories per cup and pieces sized for tiny mouths.

        3. Why do small dogs need to eat more frequently?

        Small dogs have faster metabolisms and smaller stomachs. They burn through energy quickly and can’t store much food at once.

        Eating 3-4 small meals helps prevent hypoglycemia (low blood sugar), which small breeds are prone to between meals.

        4. What ingredients should I avoid in small dog food?

        Avoid foods with corn, wheat, and soy as main ingredients. Skip artificial colors, preservatives, generic meat by-products, and excessive fillers.

        Also, steer clear of foods with large kibble sizes that are hard for small mouths to chew.

        5. How do I know if my small dog is overweight?

        You should feel your dog’s ribs without pressing hard and see a visible waist from above. For small dogs, even a half-pound gain can be a big deal.

        A 10-pound dog gaining 1 pound is like a 150-pound person gaining 15 pounds.

        Kibble Size, Texture, and Meal Options

        Choosing the right kibble size matters more than you think for your small pup’s health and happiness. The texture impacts their teeth, and meal options can affect everything from digestion to energy.

        Importance of Small Kibble Size

        Ever watched your Chihuahua struggle with regular-sized kibble? It’s kind of painful to see how many small dogs try to chomp down on pieces meant for Golden Retrievers.

        Small kibble size isn’t just about convenience — it’s really about safety and nutrition. Small dogs need appropriately sized kibble to avoid choking and make sure they chew properly.

        Here’s what happens when kibble size is wrong:

        • Too large: Your dog might swallow whole pieces, risking choking
        • Too small: They might not chew, missing out on dental benefits
        • Wrong shape: Can cause jaw strain or make eating tough

        The sweet spot is kibble about 8-10mm in diameter for most small breeds. The right kibble size encourages proper chewing and helps clean teeth, reducing plaque.

        I always tell pet parents to watch their dog eat. If they’re gulping without chewing or struggling to pick up pieces, it’s time to switch sizes.

        Dry vs. Wet Food for Small Breeds

        Let’s be real — both dry and wet food have their place in your small dog’s diet. Which one should you choose, though?

        Dry kibble benefits:

        • Helps clean teeth with chewing action
        • Easier for portion control
        • Longer shelf life, less mess
        • Usually more cost-effective

        Wet food advantages:

        • Higher moisture content (great for hydration)
        • More appealing taste and smell
        • Easier to digest for sensitive stomachs
        • Better for dogs with dental issues

        Small dogs burn energy more quickly than larger dogs, so they need energy-dense foods regardless of format.

        Honestly, I like to mix both. Use dry kibble as the base and add a spoonful of wet food for flavor and moisture.

        This combo gives you the dental benefits of dry food and the palatability of wet. Just remember to adjust portions when mixing to avoid overfeeding.

        Homemade and Fresh Food Options

        Thinking about making your small dog’s meals from scratch? I get it — you want the best for your pup.

        Fresh food can be amazing when you do it right. You control every ingredient and avoid fillers or preservatives.

        Many small dogs with allergies do better on homemade diets. Here’s what works well for small breeds:

        • Lean proteins: Chicken, turkey, fish (cooked, no bones)
        • Safe vegetables: Sweet potatoes, carrots, green beans
        • Healthy grains: Brown rice, quinoa (if no grain allergies)

        But here’s the kicker — homemade diets are tricky to balance. Small dogs need precise nutrition ratios, and getting it wrong can cause real health issues.

        If you’re going homemade:

        1. Consult your vet first about nutritional requirements
        2. Consider working with a veterinary nutritionist
        3. Use calcium supplements (homemade diets often lack this)
        4. Transition slowlymix increasing amounts over 7-10 days

        Fresh commercial options like refrigerated or freeze-dried foods can be a middle ground. They’re nutritionally balanced but still use whole ingredients you can recognize.

        Signs Your Small Dog’s Diet Needs Tweaking

        A small dog sitting next to a bowl of dog food on a wooden floor with a person’s hand nearby in a bright kitchen.

        Small dogs have unique nutritional needs, and their bodies send clear signals when something’s off. From digestive red flags to energy crashes, your tiny companion might be telling you it’s time for a menu makeover.

        Red Flags in Digestion and Energy

        Let’s be real — your small dog’s stomach is basically the size of a golf ball. Even minor diet issues hit hard and fast.

        I’ve noticed that digestive problems like diarrhea and constipation are often the first warning signs. Your pup’s stools should be firm and consistent.

        Watch for these digestive red flags:

        • Loose stools for more than 2 days
        • Straining during bathroom breaks
        • Excessive gas that clears the room
        • Vomiting after meals

        Small breed dogs burn energy differently than larger dogs. If your usually bouncy Chihuahua suddenly becomes a couch potato, their diet might be missing key nutrients.

        Energy crashes can signal inadequate nutrition, especially B vitamins and iron.

        I always tell owners to look for high-quality food with named meat sources.

        Energy warning signs include:

        • Sleeping more than 14 hours daily
        • Reluctance to play or walk
        • Difficulty climbing stairs
        • General lethargy throughout the day

        Small dogs also show unusual weight changes more dramatically. A two-pound weight gain on a Yorkie is like gaining 20 pounds for us.

        Addressing Picky Eating in Small Dogs

        Ever tried convincing a stubborn Pomeranian to eat something they’ve decided against? It’s like negotiating with a furry dictator.

        Small breed dogs are notorious for being picky eaters, but sometimes their pickiness masks a real problem. If your dog suddenly refuses their favorite food, don’t dismiss it as attitude.

        Common reasons small dogs become picky:

        • Food allergies developing over time
        • Dental pain from overcrowded teeth
        • Bowl placement too high or low
        • Stale or rancid kibble

        I’ve seen too many owners give in to their dog’s demands for table scraps. This just creates a cycle where your pup holds out for “better” options.

        Small dogs need nutrient-dense foods because they eat smaller portions. Every bite counts more than it does for a Golden Retriever.

        Try these tactics for picky small breed eaters:

        • Warm the food slightly to enhance aroma
        • Mix in a tablespoon of low-sodium broth
        • Switch to smaller, more frequent meals
        • Make sure the kibble size matches their tiny mouths

        If your small dog consistently refuses food for more than 24 hours, call your vet immediately. Their tiny bodies can’t handle fasting like larger dogs can.

        Weight, Wellness, and Preventing Common Issues

        Small breed dogs face unique health challenges that directly link to their nutrition. Overweight dogs risk joint problems and diabetes.

        Proper feeding helps prevent dental disease and supports sensitive digestion.

        Managing Weight Gain and Overfeeding

        Let’s be real — those puppy dog eyes make it impossible to say no to treats. But here’s the kicker: small breed dogs gain weight faster than you’d think.

        I’ve seen too many Chihuahuas and Yorkies turn into little sausages because their owners don’t realize how quickly calories add up. A 10-pound dog only needs 200-300 calories daily.

        That’s less than most people eat for breakfast.

        Watch for these warning signs:

        • Can’t feel their ribs easily
        • No visible waist when looking from above
        • Trouble jumping on furniture
        • Heavy breathing during short walks

        Measure everything. Seriously, everything.

        Grab a kitchen scale and weigh out their kibble. Those “handful” portions can double their daily calories without you realizing it.

        Portion control tips that work:

        • Feed 2-3 small meals instead of one big bowl
        • Use puzzle feeders to slow down eating
        • Limit treats to 10% of daily calories
        • Switch to low-calorie training treats

        Remember, small-breed dogs need frequent smaller meals because their tiny stomachs can’t handle large portions.

        Dental and Heart Health Through Nutrition

        Ever wonder why small breed dogs have such terrible breath? Their crowded teeth trap food particles like crazy.

        Poor dental health doesn’t just mean stinky kisses — it leads to heart disease.

        Dental disease affects 80% of dogs by age 3, and small breeds get hit hardest. Bacteria from infected gums enters the bloodstream and damages the heart.

        Foods that fight dental problems:

        • Dry kibble designed for tartar control
        • Raw carrots (supervised chewing only)
        • Dental chews sized appropriately
        • Water additives that reduce plaque

        I always tell people to avoid soft, sticky treats. They’re like candy for teeth — they stick around and feed harmful bacteria.

        Heart-healthy nutrition basics:

        • Omega-3 fatty acids from fish oil reduce inflammation
        • Limited sodium prevents fluid retention
        • High-quality protein maintains muscle mass
        • Antioxidants protect against cellular damage

        Small dogs can live longer than big breeds, but only if we keep their hearts healthy.

        Start dental care early and choose foods that work double duty.

        Supporting Sensitive Stomachs

        Small breed dogs act like tiny drama queens when their stomachs get upset. One wrong treat and you’re dealing with diarrhea or vomiting for days.

        Their fast metabolisms mean they process food quickly. It also means digestive upsets hit harder.

        Small dogs can become dehydrated quickly during stomach troubles.

        Common stomach triggers I see:

        • Sudden food changes
        • Too many table scraps
        • Low-quality fillers like corn
        • Artificial colors and preservatives

        Gentle foods that soothe stomachs:

        • Plain boiled chicken and rice
        • Pumpkin puree (not pie filling)
        • Bone broth without onions or garlic
        • Probiotics designed for dogs

        Transition foods slowly over 7-10 days. Mix increasing amounts of new food with decreasing amounts of old food.

        Signs to call the vet immediately:

        • Vomiting more than twice in 24 hours
        • Blood in stool or vomit
        • Lethargy combined with stomach issues
        • Refusing water for more than 6 hours

        Stick to high-quality, easily digestible foods and avoid the temptation to share your dinner.

        Finding & Choosing the Best Dog Food for Small Breeds

        A small dog sitting next to bowls and containers of healthy dog food in a bright kitchen.

        Reading labels carefully and knowing when your tiny companion needs a dietary change can make the difference between a thriving pup and ongoing health struggles.

        Let me walk you through what I’ve learned about spotting quality ingredients and recognizing the warning signs that it’s time to switch foods.

        Label Reading and Ingredient Checklists

        I’ll be honest — the pet food aisle can feel overwhelming when you’re staring at dozens of bags claiming to be “perfect” for your small breed. But here’s what I look for first: high-quality animal protein as the first ingredient.

        Your small dog needs way more calories per pound than my friend’s Great Dane. That’s because small dogs have higher metabolic rates and burn through energy faster than larger breeds.

        Essential ingredients I always check for:

        • Animal protein first (chicken, beef, fish — not “meal” or “by-product”)
        • Healthy fats like fish oil or chicken fat
        • Probiotics for digestive health
        • L-carnitine for muscle maintenance
        • Antioxidants (vitamin E, vitamin C)

        The kibble size matters more than you’d think. I’ve watched tiny dogs struggle with regular-sized kibble, barely able to chew properly.

        Small breed formulas include smaller kibble sizes specifically designed for those little mouths.

        Red flags I avoid:

        • Fillers like corn or wheat as primary ingredients
        • Artificial colors and preservatives
        • Vague terms like “meat meal” without specifying the source

        Look for foods with 400+ calories per cup. Small dogs need that calorie density because they can’t eat huge portions.

        When to Switch Foods or Consult a Vet

        Ever notice your small dog suddenly turning their nose up at dinner? That’s not always just pickiness — it could signal something bigger.

        I recommend consulting with your veterinarian before making any major food changes. They know your dog’s specific health needs better than any online guide.

        Signs it’s time to switch foods:

        • Persistent digestive issues (loose stools, gas)
        • Dull coat or excessive shedding
        • Low energy or weight changes
        • Frequent scratching or skin irritation

        Life stage transitions matter too. Puppies need different nutrition than senior dogs.

        I’ve seen too many owners stick with puppy food way too long or switch to adult food too early.

        If you’re switching foods, do it gradually over 7-10 days. Mix increasing amounts of new food with decreasing amounts of old food.

        This prevents stomach upset that can really knock a small dog off their game.

        When to call your vet immediately:

        • Sudden appetite loss lasting more than 24 hours
        • Vomiting or diarrhea
        • Dramatic weight gain or loss
        • Any behavior changes around mealtime

        Trust me — small dogs are at higher risk for obesity because even a pound or two makes a huge difference on their tiny frames.

        Your vet can help you navigate portion control and choose the right formula for your dog’s activity level.

        Small Dog Nutrition Tips – FAQs

        Small dog nutrition sparks tons of questions, and I get it – tiny pups have big needs packed into those little bodies.

        Let me tackle the most common concerns I hear from fellow small dog parents.

        Here’s the thing – small dogs burn calories like tiny furnaces.
        I’ve learned that small dogs often require a greater calorie intake per pound of body weight compared to their larger cousins.
        Your best bet? Look for calorie-dense formulas specifically made for small breeds.
        These pack more nutrition into smaller portions.
        I always recommend splitting daily food into 2-3 smaller meals. This prevents blood sugar dips that can make tiny dogs shaky or weak.
        Watch the treats though. That single training treat might represent 10% of your Chihuahua’s daily calories.
        I stick to the 10% rule – treats should never exceed 10% of total daily intake.
        Regular weigh-ins help too. I weigh my small dog monthly since even a half-pound gain can mean big trouble for a 5-pound pup.

        Ever noticed a tiny pup with a sensitive stomach? Let’s explore the best hypoallergenic foods for those delicate doggies.

        Small dogs seem extra prone to tummy troubles, don’t they?
        I’ve seen this countless times with nervous little breeds.
        Limited ingredient diets work wonders here. Look for foods with just one protein source and one carb source – like duck and sweet potato.
        Novel proteins help too. If your pup’s been eating chicken forever, try rabbit, venison, or fish instead.
        Sometimes it’s just about giving that digestive system a break.
        I always suggest avoiding foods laden with fillers such as corn, wheat, and soy since these offer little value and can trigger allergies.
        Probiotics are game-changers. Many small dog foods now include them, or you can add a dog-specific probiotic supplement.
        Start any food transition super slowly – like over 10-14 days instead of the usual week. Small dogs need that extra time.

        Gotta love a furball with energy to spare, right? But what are the key ingredients to look for in food to keep that tail wagging?

        Those bouncing bundles of energy need fuel that matches their lifestyle.
        I look for high-quality animal protein as the first ingredient every time.
        Real meat, not meat meal or by-products. Think deboned chicken, salmon, or lamb.
        Protein is particularly crucial for small breeds due to their high energy levels.
        Healthy fats matter just as much. Look for omega-3 and omega-6 fatty acids from fish oil or flaxseed.
        These keep that coat shiny and support brain function.
        Complex carbs like sweet potatoes and brown rice provide steady energy. They won’t cause those crazy sugar spikes that make your pup zoom around then crash.
        I also check for natural antioxidants like blueberries, cranberries, or spinach.
        These support immune health in high-energy dogs who stress their systems more.
        Avoid foods with artificial colors or flavors – your energetic pup doesn’t need chemical additives making them even more wired.

        Little ones have big nutritional needs, don’t they? What specific vitamins and minerals should every pint-sized pup’s diet include?

        You’re absolutely right—small dogs pack huge nutritional needs into tiny packages. I always check labels for these essentials.
        Calcium and phosphorus top my list, especially for growing small breed puppies. These support proper bone development in dogs prone to luxating patella and other joint issues.
        Vitamin D helps absorb that calcium properly. Many small dogs don’t get enough sunshine, so dietary sources become crucial.
        I look for B-vitamins too—especially B12 and folate. These support that fast metabolism and high energy output small dogs are famous for.
        Iron prevents anemia, which I’ve seen more often in toy breeds. Quality dog foods should include chelated minerals that absorb better.
        Antioxidants like Vitamin E and C support immune function. Small dogs can be more susceptible to illness due to their size.
        Don’t forget essential fatty acids. These support everything from brain function to skin health.
        Look for guaranteed analysis levels on the package. It gives a little peace of mind, honestly.

        Now, how about puppies — how does feeding the youngest of the small breeds differ from their grown-up pals?

        Small breed puppies are basically tiny rockets burning through calories. I feed them 3-4 times daily until they’re about 6 months old.
        Here’s what surprised me—small breed puppies need different nutrition than large breed puppies. They need higher calorie density because they can’t eat huge volumes.
        Puppy-specific small breed formulas are essential. Adult food won’t cut it for these guys; the kibble size alone can be a choking hazard for tiny mouths.
        Watch for hypoglycemia signs—weakness, trembling, or lethargy. Small breed puppies can crash fast if they miss meals.
        I transition to adult food around 10-12 months. Small dogs mature faster, so waiting too long doesn’t really make sense.
        Free-feeding doesn’t work with small breed puppies. They need scheduled meals to keep blood sugar steady and support proper growth.

        Let’s get chatty about treats: how can we choose treats that are healthy yet still scrumptious for our discerning tiny companions?

        Small dogs are such treat snobs, aren’t they? Honestly, size matters most—those big biscuits just won’t work for a 4-pound Yorkie.
        Look for training-sized treats—they’re usually small enough and lower in calories. Perfect for those marathon training sessions tiny dogs seem to need.
        I stick to single-ingredient treats when I can. Freeze-dried liver, sweet potato chips, or even little fish like anchovies work great.
        Dental treats serve double duty for small dogs who are prone to tooth problems. Just make sure they’re the right size—no giant bones for tiny pups.

        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