diff --git a/.changeset/silver-bikes-live.md b/.changeset/silver-bikes-live.md
new file mode 100644
index 00000000..42ed303d
--- /dev/null
+++ b/.changeset/silver-bikes-live.md
@@ -0,0 +1,6 @@
+---
+"@snapwp/blocks": patch
+"@snapwp/types": patch
+---
+
+feat: Add support for overloading Synced Pattern blocks.
diff --git a/docs/overloading-wp-behavior.md b/docs/overloading-wp-behavior.md
index bc85e6d7..fa49181e 100644
--- a/docs/overloading-wp-behavior.md
+++ b/docs/overloading-wp-behavior.md
@@ -307,3 +307,92 @@ export default function Page() {
- **Local Styles**: Use CSS Modules (as shown with `styles.module.css`) or any other CSS-in-JS solution for component-specific styling.
- **Global and Theme Styles**: Classes like `wp-block-heading`, `has-text-align-center`, and `has-x-large-font-size` (likely from your WordPress `theme.json` and/or global CSS) are automatically available.
+
+## Overloading Synced Patterns
+
+SnapWP allows you to customize **Synced Patterns** by mapping them to custom React components. This is useful for modifying the structure, design, or behavior of reusable block patterns while keeping WordPress as the content source.
+
+> [!TIP]
+> Synced Patterns are reusable block patterns in WordPress that stay in sync across all instances. When you edit a synced pattern, all instances of that pattern are updated.
+
+### 1. Creating a Custom Component
+
+Create a new React component to modify the rendering of a specific Synced Pattern:
+
+```tsx
+import React from 'react';
+import { BlockData, cn, getClassNamesFromString } from '@snapwp/core';
+
+export default function MyCustomSyncedPattern( {
+ renderedHtml,
+ attributes,
+ children,
+}: BlockData ) {
+ const safeAttributes = attributes || {}; // Ensure attributes are not undefined.
+ const { style } = safeAttributes;
+
+ const classNamesFromString = renderedHtml
+ ? getClassNamesFromString( renderedHtml )
+ : '';
+ const classNames = cn( classNamesFromString );
+
+ return (
+
+ { /* Your custom rendering logic here */ }
+ { children }
+
+ );
+}
+```
+
+### 2. Registering the Custom Component
+
+You can register your custom component either globally or per-route:
+
+#### Global Registration
+
+Add your custom component to the `blockDefinitions` in your `snapwp.config.ts`:
+
+```ts
+import { defineConfig } from '@snapwp/config';
+import MyCustomSyncedPattern from './components/MyCustomSyncedPattern';
+
+export default defineConfig( {
+ blockDefinitions: {
+ CoreSyncedPattern: MyCustomSyncedPattern,
+ },
+} );
+```
+
+#### Per-Route Registration
+
+Override the component for specific routes:
+
+```tsx
+import { EditorBlocksRenderer } from '@snapwp/blocks';
+import MyCustomSyncedPattern from './components/MyCustomSyncedPattern';
+
+const pageBlockDefinitions = {
+ CoreSyncedPattern: MyCustomSyncedPattern,
+};
+
+export default function Page() {
+ return (
+
+ { ( editorBlocks ) => (
+
+ ) }
+
+ );
+}
+```
+
+This allows you to apply the override only on specific routes while using the default block rendering elsewhere.
+
+Now, whenever a `core/synced-pattern` block is encountered, your `MyCustomSyncedPattern` component will be used to render it. Any other blocks will use the default rendering unless you provide a custom component in `blockDefinitions`.
+
+> [!TIP]
+> If a block is overridden both globally (`snapwp.config.ts`) and per-route (`EditorBlocksRenderer` prop), the per-route override takes precedence.
diff --git a/packages/blocks/README.md b/packages/blocks/README.md
index 5176e9a8..9b75a271 100644
--- a/packages/blocks/README.md
+++ b/packages/blocks/README.md
@@ -49,37 +49,38 @@ const blockDefinitions = {
These components provide developer-friendly APIs for rendering core WordPress blocks. If a WordPress block does not have a corresponding component, it will fallback to the `Default` block component, which uses `html-react-parser` under the hood.
-| Type | Component |
-| ------------------ | ---------------- |
-| core-audio | CoreAudio |
-| core-button | CoreButton |
-| core-buttons | CoreButtons |
-| core-code | CoreCode |
-| core-column | CoreColumn |
-| core-columns | CoreColumns |
-| core-cover | CoreCover |
-| core-details | CoreDetails |
-| core-file | CoreFile |
-| core-freeform | CoreFreeform |
-| core-gallery | CoreGallery |
-| core-group | CoreGroup |
-| core-heading | CoreHeading |
-| core-html | CoreHtml |
-| core-image | CoreImage |
-| core-list | CoreList |
-| core-list-item | CoreListItem |
-| core-media-text | CoreMediaText |
-| core-paragraph | CoreParagraph |
-| core-post-content | CorePostContent |
-| core-preformatted | CorePreformatted |
-| core-pullquote | CorePullquote |
-| core-quote | CoreQuote |
-| core-separator | CoreSeparator |
-| core-spacer | CoreSpacer |
-| core-template-part | CoreTemplatePart |
-| core-verse | CoreVerse |
-| core-video | CoreVideo |
-| default | Default |
+| Type | Component |
+| ------------------- | ----------------- |
+| core-audio | CoreAudio |
+| core-button | CoreButton |
+| core-buttons | CoreButtons |
+| core-code | CoreCode |
+| core-column | CoreColumn |
+| core-columns | CoreColumns |
+| core-cover | CoreCover |
+| core-details | CoreDetails |
+| core-file | CoreFile |
+| core-freeform | CoreFreeform |
+| core-gallery | CoreGallery |
+| core-group | CoreGroup |
+| core-heading | CoreHeading |
+| core-html | CoreHtml |
+| core-image | CoreImage |
+| core-list | CoreList |
+| core-list-item | CoreListItem |
+| core-media-text | CoreMediaText |
+| core-paragraph | CoreParagraph |
+| core-post-content | CorePostContent |
+| core-preformatted | CorePreformatted |
+| core-pullquote | CorePullquote |
+| core-quote | CoreQuote |
+| core-separator | CoreSeparator |
+| core-spacer | CoreSpacer |
+| core-synced-pattern | CoreSyncedPattern |
+| core-template-part | CoreTemplatePart |
+| core-verse | CoreVerse |
+| core-video | CoreVideo |
+| default | Default |
## Known Limitations
diff --git a/packages/blocks/src/blocks/core-synced-pattern.tsx b/packages/blocks/src/blocks/core-synced-pattern.tsx
new file mode 100644
index 00000000..9ef0026c
--- /dev/null
+++ b/packages/blocks/src/blocks/core-synced-pattern.tsx
@@ -0,0 +1,46 @@
+import {
+ cn,
+ getClassNamesFromString,
+ getStylesFromAttributes,
+} from '@snapwp/core';
+import type {
+ CoreSyncedPattern as CoreSyncedPatternType,
+ CoreSyncedPatternProps,
+} from '@snapwp/types';
+import type { ReactNode } from 'react';
+
+/**
+ * Renders the core/synced-pattern block.
+ *
+ * @param {Object} props The props for the block component.
+ * @param {CoreSyncedPatternProps['attributes']} props.attributes Block attributes.
+ * @param {ReactNode} props.children The block's children.
+ * @param {CoreSyncedPatternProps['renderedHtml']} props.renderedHtml The block's rendered HTML.
+ *
+ * @return The rendered block.
+ */
+export const CoreSyncedPattern: CoreSyncedPatternType = ( {
+ attributes,
+ children,
+ renderedHtml,
+}: CoreSyncedPatternProps ): ReactNode => {
+ const { style } = attributes || {};
+ const styleObject = getStylesFromAttributes( { style } );
+
+ /**
+ * @todo replace with cssClassName once it's supported.
+ */
+ const classNamesFromString = renderedHtml
+ ? getClassNamesFromString( renderedHtml )
+ : '';
+ const classNames = cn( classNamesFromString );
+
+ return (
+
+ { children }
+
+ );
+};
diff --git a/packages/blocks/src/blocks/index.ts b/packages/blocks/src/blocks/index.ts
index 20fadcb0..80d73898 100644
--- a/packages/blocks/src/blocks/index.ts
+++ b/packages/blocks/src/blocks/index.ts
@@ -24,6 +24,7 @@ import { CorePullquote } from './core-pullquote';
import { CoreQuote } from './core-quote';
import { CoreSeparator } from './core-separator';
import { CoreSpacer } from './core-spacer';
+import { CoreSyncedPattern } from './core-synced-pattern';
import { CoreTemplatePart } from './core-template-part';
import { CoreVerse } from './core-verse';
import { CoreVideo } from './core-video';
@@ -58,6 +59,7 @@ export const blocks: BlockDefinitions = {
CoreQuote,
CoreSeparator,
CoreSpacer,
+ CoreSyncedPattern,
CoreTemplatePart,
CoreVerse,
CoreVideo,
diff --git a/packages/blocks/src/blocks/tests/core-synced-pattern.test.tsx b/packages/blocks/src/blocks/tests/core-synced-pattern.test.tsx
new file mode 100644
index 00000000..7a511f48
--- /dev/null
+++ b/packages/blocks/src/blocks/tests/core-synced-pattern.test.tsx
@@ -0,0 +1,81 @@
+import { render } from '@testing-library/react';
+
+import { CoreSyncedPattern } from '../core-synced-pattern';
+
+describe( 'CoreSyncedPattern Component', () => {
+ it( 'renders children correctly', () => {
+ const { container } = render(
+
+ Test Child
+
+ );
+
+ expect( container ).toHaveTextContent( 'Test Child' );
+ } );
+
+ it( 'applies className from renderedHtml', () => {
+ const renderedHtml = '';
+ const { container } = render(
+
+ Test Child
+
+ );
+
+ const wrapper = container.firstChild;
+ expect( wrapper ).toHaveClass( 'test-class', 'another-class' );
+ } );
+
+ it( 'applies style from attributes', () => {
+ const style = JSON.stringify( { color: 'red', padding: '10px' } );
+ const { container } = render(
+
+ Test Child
+
+ );
+
+ const wrapper = container.firstChild;
+ expect( wrapper ).toHaveStyle( {
+ color: 'red',
+ padding: '10px',
+ } );
+ } );
+
+ it( 'handles empty attributes gracefully', () => {
+ const { container } = render(
+ //@ts-ignore to test undefined props
+
+ Test Child
+
+ );
+
+ expect( container ).toHaveTextContent( 'Test Child' );
+ } );
+
+ it( 'handles empty renderedHtml gracefully', () => {
+ const { container } = render(
+ // @ts-ignore to test undefined props
+
+ Test Child
+
+ );
+
+ expect( container ).toHaveTextContent( 'Test Child' );
+ } );
+
+ it( 'combines className and style correctly', () => {
+ const renderedHtml = '';
+ const style = JSON.stringify( { color: 'blue' } );
+ const { container } = render(
+
+ Test Child
+
+ );
+
+ const wrapper = container.firstChild;
+ expect( wrapper ).toHaveClass( 'test-class' );
+ expect( wrapper ).toHaveStyle( { color: 'blue' } );
+ } );
+} );
diff --git a/packages/types/src/blocks/props/core-synced-pattern.ts b/packages/types/src/blocks/props/core-synced-pattern.ts
new file mode 100644
index 00000000..2ad2d83a
--- /dev/null
+++ b/packages/types/src/blocks/props/core-synced-pattern.ts
@@ -0,0 +1,10 @@
+import type { BaseProps } from '../base';
+import type { ComponentType, PropsWithChildren } from 'react';
+
+export type CoreSyncedPatternProps = PropsWithChildren<
+ BaseProps< {
+ style?: string;
+ } >
+>;
+
+export type CoreSyncedPattern = ComponentType< CoreSyncedPatternProps >;
diff --git a/packages/types/src/blocks/props/index.ts b/packages/types/src/blocks/props/index.ts
index aec869fd..fad209a9 100644
--- a/packages/types/src/blocks/props/index.ts
+++ b/packages/types/src/blocks/props/index.ts
@@ -27,4 +27,5 @@ export * from './core-spacer';
export * from './core-template-part';
export * from './core-verse';
export * from './core-video';
+export * from './core-synced-pattern';
export * from './default';