Skip to content

Instantly share code, notes, and snippets.

@jasperf
Last active May 1, 2025 03:51
Show Gist options
  • Save jasperf/750bf94df6c68d2ce48abab41283d2b8 to your computer and use it in GitHub Desktop.
Save jasperf/750bf94df6c68d2ce48abab41283d2b8 to your computer and use it in GitHub Desktop.
Register Patterns in Sage 11 theme as loading from patterns directory by default does not work
<?php
/**
* Register custom block pattern categories and patterns.
*/
add_action('init', function () {
// First register the block type
register_block_type('nynaeve/website-packages', [
'render_callback' => function ($attributes, $content) {
return $content; // Simply return the content as is
},
]);
// Register standard pattern categories that our patterns may use
register_block_pattern_category(
'pricing',
[
'label' => __('Pricing', 'nynaeve'),
]
);
// Register our custom pattern category
register_block_pattern_category(
'nynaeve-patterns',
[
'label' => __('Nynaeve Patterns', 'nynaeve'),
]
);
/**
* Get processed pattern content with caching
*
* @param string $pattern_file Path to pattern file
* @return string Processed pattern content
*/
function get_processed_pattern_content($pattern_file)
{
static $cache = [];
if (isset($cache[$pattern_file])) {
return $cache[$pattern_file];
}
// Capture output from the pattern file
ob_start();
include $pattern_file;
$output = ob_get_clean();
// Store in cache for future use
$cache[$pattern_file] = $output;
return $output;
}
/**
* Extract pattern metadata from file contents
*
* @param string $file_contents The contents of the pattern file
* @return array Associative array of pattern metadata
*/
function extract_pattern_metadata($file_contents)
{
$metadata = [
'title' => '',
'slug' => '',
'description' => '',
'categories' => [],
];
// Extract all metadata at once with a single regex
preg_match_all('/(?:Title|Slug|Categories|Description):\s*(.+)$/m', $file_contents, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$line = $match[0];
$value = trim($match[1]);
if (strpos($line, 'Title:') === 0) {
$metadata['title'] = __($value, 'nynaeve');
} elseif (strpos($line, 'Slug:') === 0) {
$metadata['slug'] = $value;
} elseif (strpos($line, 'Description:') === 0) {
$metadata['description'] = __($value, 'nynaeve');
} elseif (strpos($line, 'Categories:') === 0) {
$metadata['categories'] = array_map('trim', explode(',', $value));
}
}
// Set default category if none specified
if (empty($metadata['categories'])) {
$metadata['categories'] = ['nynaeve-patterns'];
}
return $metadata;
}
/**
* Get theme files modification timestamp
* Used to invalidate cache when files change
*
* @return int Latest modification timestamp
*/
function get_patterns_modification_time()
{
$pattern_files = glob(get_theme_file_path('resources/patterns/*.php'));
$latest_time = 0;
foreach ($pattern_files as $file) {
$mod_time = filemtime($file);
if ($mod_time > $latest_time) {
$latest_time = $mod_time;
}
}
return $latest_time;
}
/**
* Register all block patterns from the patterns directory
*
* This function scans the theme's patterns directory for PHP files,
* extracts metadata from each pattern file (title, slug, description, categories),
* and registers each pattern with WordPress. It handles error logging
* for file access issues and provides meaningful defaults when metadata is missing.
*
* Each registered pattern is tracked in the returned array for cache management
* and later verification of registration status.
*
* @return array Registered patterns data as [slug => string, file => string]
*/
function register_all_block_patterns()
{
$pattern_files = glob(get_theme_file_path('resources/patterns/*.php'));
$registered = [];
foreach ($pattern_files as $file) {
try {
$file_contents = file_get_contents($file);
if ($file_contents === false) {
error_log("Nynaeve: Failed to read pattern file: {$file}");
continue;
}
// Extract all metadata at once
$metadata = extract_pattern_metadata($file_contents);
if (empty($metadata['slug'])) {
continue;
}
// Set title default if needed
if (empty($metadata['title'])) {
$metadata['title'] = basename($file);
}
// Get pattern content
$pattern_content = get_processed_pattern_content($file);
register_block_pattern(
$metadata['slug'],
[
'title' => $metadata['title'],
'description' => $metadata['description'],
'content' => $pattern_content,
'categories' => $metadata['categories'],
]
);
$registered[] = [
'slug' => $metadata['slug'],
'file' => wp_normalize_path($file),
];
} catch (\Exception $e) {
error_log("Nynaeve: Error registering pattern from {$file}: ".$e->getMessage());
}
}
return $registered;
}
// Auto-register all patterns from resources/patterns directory
// Use transient caching to improve performance
if (function_exists('register_block_pattern')) {
// Get cached pattern data
$patterns_data = get_transient('nynaeve_registered_patterns');
$last_mod_time = get_transient('nynaeve_patterns_last_modified');
$current_mod_time = get_patterns_modification_time();
// Check if cache needs refreshing:
// 1. No cached patterns
// 2. Pattern files have been modified since cache was created
if (! $patterns_data || ! $last_mod_time || $current_mod_time > $last_mod_time) {
$patterns_data = register_all_block_patterns();
if (! empty($patterns_data)) {
set_transient('nynaeve_registered_patterns', $patterns_data, DAY_IN_SECONDS);
set_transient('nynaeve_patterns_last_modified', $current_mod_time, DAY_IN_SECONDS);
}
} else {
// Check if we need to re-register any patterns
// (e.g., after plugin updates that might clear registrations)
$needs_refresh = false;
if (! empty($patterns_data)) {
foreach ($patterns_data as $pattern) {
if (! registered_pattern_exists($pattern['slug'])) {
$needs_refresh = true;
break;
}
}
if ($needs_refresh) {
$patterns_data = register_all_block_patterns();
set_transient('nynaeve_registered_patterns', $patterns_data, DAY_IN_SECONDS);
}
}
}
// Apply filters to allow other code to refresh patterns
add_filter('nynaeve_refresh_block_patterns', function ($refresh) {
if ($refresh) {
delete_transient('nynaeve_registered_patterns');
delete_transient('nynaeve_patterns_last_modified');
}
return $refresh;
});
}
}, 9); // Lower priority so it runs BEFORE other pattern registrations
/**
* Check if a registered pattern exists
*
* @param string $pattern_slug The pattern slug to check
* @return bool Whether the pattern exists
*/
function registered_pattern_exists($pattern_slug)
{
if (! class_exists('\WP_Block_Patterns_Registry') || ! method_exists('\WP_Block_Patterns_Registry', 'get_instance')) {
return false;
}
$registry = \WP_Block_Patterns_Registry::get_instance();
return $registry->is_registered($pattern_slug);
}
<?php
/**
* Title: FAQ Section
* Slug: nynaeve/faq-section
* Description: A collapsible FAQ section with common questions and answers.
* Categories: text, nynaeve-patterns
* Keywords: faq, questions, answers, collapsible
* Viewport Width: 1500
* Block Types: core/group
* Inserter: true
*/
?>
<!-- wp:group {"align":"full","className":"faq-section-container has-bggray-background-color","style":{"spacing":{"padding":{"top":"4rem","right":"2rem","bottom":"4rem","left":"2rem"}}}} -->
<div class="wp-block-group faq-section-container has-bggray-background-color has-background alignfull" style="padding-top:4rem;padding-right:2rem;padding-bottom:4rem;padding-left:2rem">
<!-- wp:heading {"className":"faq-heading","textAlign":"center","textColor":"black","fontSize":"3xl","fontFamily":"open-sans"} -->
<h2 class="faq-heading has-black-color has-text-color has-text-align-center has-3xl-font-size has-open-sans-font-family">Frequently Asked Questions</h2>
<!-- /wp:heading -->
<!-- wp:group {"className":"faq-items","style":{"spacing":{"blockGap":"1rem"}}} -->
<div class="wp-block-group faq-items">
<!-- wp:group {"className":"faq-item","style":{"spacing":{"blockGap":"0"}}} -->
<div class="wp-block-group faq-item">
<!-- wp:heading {"level":3,"className":"faq-question","fontSize":"lg","fontFamily":"open-sans","textColor":"black"} -->
<h3 class="faq-question has-black-color has-text-color has-lg-font-size has-open-sans-font-family">What's included in the Standard package?</h3>
<!-- /wp:heading -->
<!-- wp:paragraph {"className":"faq-answer","textColor":"textbodygray","fontFamily":"open-sans"} -->
<p class="faq-answer has-textbodygray-color has-text-color has-open-sans-font-family">You'll receive a 3–5‑page site built on our customizable block theme, hosted on a shared server, fully responsive, with basic on‑page SEO and a vertical‑specific child‑theme tailored to your brand.</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
<!-- wp:group {"className":"faq-item","style":{"spacing":{"blockGap":"0"}}} -->
<div class="wp-block-group faq-item">
<!-- wp:heading {"level":3,"className":"faq-question","fontSize":"lg","fontFamily":"open-sans","textColor":"black"} -->
<h3 class="faq-question has-black-color has-text-color has-lg-font-size has-open-sans-font-family">What's included in the Premium package?</h3>
<!-- /wp:heading -->
<!-- wp:paragraph {"className":"faq-answer","textColor":"textbodygray","fontFamily":"open-sans"} -->
<p class="faq-answer has-textbodygray-color has-text-color has-open-sans-font-family">The Premium package includes a customized Sage based hybrid theme with bespoke design components, version control, VPS hosting on our Trellis stack for optimal performance, comprehensive SEO setup and optimization, advanced analytics integration, and a 6-month maintenance plan with regular updates and support.</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
<!-- wp:group {"className":"faq-item","style":{"spacing":{"blockGap":"0"}}} -->
<div class="wp-block-group faq-item">
<!-- wp:heading {"level":3,"className":"faq-question","fontSize":"lg","fontFamily":"open-sans","textColor":"black"} -->
<h3 class="faq-question has-black-color has-text-color has-lg-font-size has-open-sans-font-family">How long does each package take to launch?</h3>
<!-- /wp:heading -->
<!-- wp:list {"className":"faq-answer","textColor":"textbodygray","fontFamily":"open-sans"} -->
<ul class="faq-answer has-textbodygray-color has-text-color has-open-sans-font-family">
<li><strong>Standard:</strong> ~2–3 weeks from kickoff to go‑live.</li>
<li><strong>Premium:</strong> ~4–6 weeks, including design mockups, development sprints, and initial SEO setup.</li>
</ul>
<!-- /wp:list -->
</div>
<!-- /wp:group -->
<!-- wp:group {"className":"faq-item","style":{"spacing":{"blockGap":"0"}}} -->
<div class="wp-block-group faq-item">
<!-- wp:heading {"level":3,"className":"faq-question","fontSize":"lg","fontFamily":"open-sans","textColor":"black"} -->
<h3 class="faq-question has-black-color has-text-color has-lg-font-size has-open-sans-font-family">What is a "hybrid theme"?</h3>
<!-- /wp:heading -->
<!-- wp:paragraph {"className":"faq-answer","textColor":"textbodygray","fontFamily":"open-sans"} -->
<p class="faq-answer has-textbodygray-color has-text-color has-open-sans-font-family">It's a custom WordPress theme base on Sage combining block‑based templates for easy content editing with classic PHP templates for bespoke design elements—giving you the best of both worlds.</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
<!-- wp:group {"className":"faq-item","style":{"spacing":{"blockGap":"0"}}} -->
<div class="wp-block-group faq-item">
<!-- wp:heading {"level":3,"className":"faq-question","fontSize":"lg","fontFamily":"open-sans","textColor":"black"} -->
<h3 class="faq-question has-black-color has-text-color has-lg-font-size has-open-sans-font-family">What does the 6‑month maintenance plan cover?</h3>
<!-- /wp:heading -->
<!-- wp:paragraph {"className":"faq-answer","textColor":"textbodygray","fontFamily":"open-sans"} -->
<p class="faq-answer has-textbodygray-color has-text-color has-open-sans-font-family">Monthly core, plugin, and theme updates; security monitoring; performance tweaks; and up to 4 small content or styling changes per month.</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
<!-- wp:group {"className":"faq-item","style":{"spacing":{"blockGap":"0"}}} -->
<div class="wp-block-group faq-item">
<!-- wp:heading {"level":3,"className":"faq-question","fontSize":"lg","fontFamily":"open-sans","textColor":"black"} -->
<h3 class="faq-question has-black-color has-text-color has-lg-font-size has-open-sans-font-family">Do I need to supply content and images?</h3>
<!-- /wp:heading -->
<!-- wp:paragraph {"className":"faq-answer","textColor":"textbodygray","fontFamily":"open-sans"} -->
<p class="faq-answer has-textbodygray-color has-text-color has-open-sans-font-family">Yes—client‑provided copy and high‑res images streamline the build. We can recommend stock sources or content‑writing partners if needed.</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
<!-- wp:group {"className":"faq-item","style":{"spacing":{"blockGap":"0"}}} -->
<div class="wp-block-group faq-item">
<!-- wp:heading {"level":3,"className":"faq-question","fontSize":"lg","fontFamily":"open-sans","textColor":"black"} -->
<h3 class="faq-question has-black-color has-text-color has-lg-font-size has-open-sans-font-family">What is the Trellis stack?</h3>
<!-- /wp:heading -->
<!-- wp:paragraph {"className":"faq-answer","textColor":"textbodygray","fontFamily":"open-sans"} -->
<p class="faq-answer has-textbodygray-color has-text-color has-open-sans-font-family">Trellis is a modern, Ansible‑driven provisioning system for WordPress, providing automated security, caching, and server hardening—ideal for high‑performance VPS hosting.</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
<?php
/**
* Title: Modern Pricing Table
* Slug: nynaeve/modern-pricing-table
* Description: A modern comparison of website packages with pricing and feature details in a two-column layout.
* Categories: pricing, nynaeve-patterns
* Keywords: pricing, packages, features, columns, websites, comparison
* Viewport Width: 1500
* Block Types: core/group
* Post Types:
* Inserter: true
*/
?>
<!-- wp:group {"metadata":{"categories":["pricing, nynaeve-patterns"],"patternName":"nynaeve/modern-pricing-table","name":"Modern Pricing Table"},"align":"full","className":"modern-pricing-table-container has-bggray-background-color","style":{"spacing":{"padding":{"right":"2rem","left":"2rem","top":"4rem","bottom":"4rem"}},"backgroundColor":{"slug":"bggray","name":"BgGray","color":"#ebeced"}},"backgroundColor":"primary-accent"} -->
<div class="wp-block-group alignfull modern-pricing-table-container has-bggray-background-color has-primary-accent-background-color has-background" style="padding-top:4rem;padding-right:2rem;padding-bottom:4rem;padding-left:2rem"><!-- wp:heading {"className":"has-text-align-center","textColor":"black","fontSize":"3xl","fontFamily":"open-sans"} -->
<h2 class="wp-block-heading has-text-align-center has-black-color has-text-color has-open-sans-font-family has-3-xl-font-size">Website Packages.</h2>
<!-- /wp:heading -->
<!-- wp:paragraph {"align":"center","className":"pricing-subtitle","textColor":"textbodygray","fontSize":"lg"} -->
<p class="has-text-align-center pricing-subtitle has-textbodygray-color has-text-color has-lg-font-size">Choose the package that best fits your business needs</p>
<!-- /wp:paragraph -->
<!-- wp:group {"layout":{"type":"constrained","contentSize":"64rem"}} -->
<div class="wp-block-group"><!-- wp:group -->
<div class="wp-block-group"><!-- wp:columns {"style":{"spacing":{"blockGap":{"top":"2rem","left":"2rem"}}}} -->
<div class="wp-block-columns"><!-- wp:column {"style":{"border":{"width":"1px","color":"#cbcbcb","radius":"0.5rem"},"spacing":{"padding":{"top":"2rem","right":"2rem","bottom":"2rem","left":"2rem"}}},"backgroundColor":"base"} -->
<div class="wp-block-column has-border-color has-base-background-color has-background" style="border-color:#cbcbcb;border-width:1px;border-radius:0.5rem;padding-top:2rem;padding-right:2rem;padding-bottom:2rem;padding-left:2rem"><!-- wp:heading {"style":{"spacing":{"margin":{"bottom":"0.5rem"}}}} -->
<h2 class="wp-block-heading" style="margin-bottom:0.5rem">Standard</h2>
<!-- /wp:heading -->
<!-- wp:paragraph {"style":{"spacing":{"margin":{"top":"0","bottom":"1.5rem"}}},"textColor":"textbodygray","fontSize":"lg"} -->
<p class="has-textbodygray-color has-text-color has-lg-font-size" style="margin-top:0;margin-bottom:1.5rem">Perfect for small websites that need a professional presence.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3,"style":{"spacing":{"margin":{"top":"1.5rem","bottom":"1.5rem"}}}} -->
<h3 class="wp-block-heading" style="margin-top:1.5rem;margin-bottom:1.5rem"><strong>€799</strong> <span style="font-weight:normal;font-size:1rem;color:#98999a">starting price</span></h3>
<!-- /wp:heading -->
<!-- wp:group -->
<div class="wp-block-group"><!-- wp:group {"className":"feature-item"} -->
<div class="wp-block-group feature-item"><!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
<div class="wp-block-group"><!-- wp:image {"width":"24px","height":"24px","className":"feature-icon"} -->
<figure class="wp-block-image is-resized feature-icon"><img src="<?php echo esc_url(get_theme_file_uri('resources/images/icons/pricing/check-circle.svg')); ?>" alt="Check icon" style="width:24px;height:24px"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph {"textColor":"textbodygray"} -->
<p class="has-textbodygray-color has-text-color">Shared hosting with trusted hosting partners</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
<!-- wp:separator {"className":"is-style-separator-dotted is-style-default","style":{"color":{"background":"#cbcbcb"}}} -->
<hr class="wp-block-separator has-text-color has-alpha-channel-opacity has-background is-style-separator-dotted is-style-default" style="background-color:#cbcbcb;color:#cbcbcb"/>
<!-- /wp:separator -->
<!-- wp:group {"className":"feature-item"} -->
<div class="wp-block-group feature-item"><!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
<div class="wp-block-group"><!-- wp:image {"width":"24px","height":"24px","className":"feature-icon"} -->
<figure class="wp-block-image is-resized feature-icon"><img src="<?php echo esc_url(get_theme_file_uri('resources/images/icons/pricing/check-circle.svg')); ?>" alt="Check icon" style="width:24px;height:24px"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph {"textColor":"textbodygray"} -->
<p class="has-textbodygray-color has-text-color">Responsive, mobile friendly design</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
<!-- wp:separator {"className":"is-style-separator-dotted","style":{"color":{"background":"#cbcbcb"}}} -->
<hr class="wp-block-separator has-text-color has-alpha-channel-opacity has-background is-style-separator-dotted" style="background-color:#cbcbcb;color:#cbcbcb"/>
<!-- /wp:separator -->
<!-- wp:group {"className":"feature-item"} -->
<div class="wp-block-group feature-item"><!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
<div class="wp-block-group"><!-- wp:image {"width":"24px","height":"24px","className":"feature-icon"} -->
<figure class="wp-block-image is-resized feature-icon"><img src="<?php echo esc_url(get_theme_file_uri('resources/images/icons/pricing/check-circle.svg')); ?>" alt="Check icon" style="width:24px;height:24px"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph {"textColor":"textbodygray"} -->
<p class="has-textbodygray-color has-text-color">Basic SEO setup</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
<!-- wp:separator {"className":"is-style-separator-dotted","style":{"color":{"background":"#cbcbcb"}}} -->
<hr class="wp-block-separator has-text-color has-alpha-channel-opacity has-background is-style-separator-dotted" style="background-color:#cbcbcb;color:#cbcbcb"/>
<!-- /wp:separator -->
<!-- wp:group {"className":"feature-item"} -->
<div class="wp-block-group feature-item"><!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
<div class="wp-block-group"><!-- wp:image {"width":"24px","height":"24px","className":"feature-icon"} -->
<figure class="wp-block-image is-resized feature-icon"><img src="<?php echo esc_url(get_theme_file_uri('resources/images/icons/pricing/check-circle.svg')); ?>" alt="Not included icon" style="width:24px;height:24px"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph {"textColor":"textbodygray"} -->
<p class="has-textbodygray-color has-text-color">Turnkey Theme tailored to your business</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
<!-- wp:buttons {"style":{"spacing":{"margin":{"top":"2rem"}}},"layout":{"type":"flex","justifyContent":"left"}} -->
<div class="wp-block-buttons" style="margin-top:2rem"><!-- wp:button {"backgroundColor":"black","textColor":"base","className":"is-style-fill","style":{"border":{"radius":"0.5rem"}}} -->
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-color has-black-background-color has-text-color has-background wp-element-button" style="border-radius:0.5rem">Get Started</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons --></div>
<!-- /wp:group --></div>
<!-- /wp:column -->
<!-- wp:column {"style":{"border":{"color":"#017cb6","width":"2px","radius":"0.5rem"},"spacing":{"padding":{"top":"2rem","right":"2rem","bottom":"2rem","left":"2rem"}}},"backgroundColor":"black"} -->
<div class="wp-block-column has-border-color has-black-background-color has-background" style="border-color:#017cb6;border-width:2px;border-radius:0.5rem;padding-top:2rem;padding-right:2rem;padding-bottom:2rem;padding-left:2rem"><!-- wp:heading {"className":"premium-heading","style":{"spacing":{"margin":{"bottom":"0.5rem"}}},"textColor":"white"} -->
<h2 class="wp-block-heading premium-heading has-white-color has-text-color" style="margin-bottom:0.5rem">Premium <span class="has-ctablue-color has-text-color has-background has-xs-font-size" style="border-radius:1rem;background-color:#e8f7fd;padding:0.5rem 1rem;font-size:0.75rem;margin-left:0.5rem"><strong>MOST POPULAR</strong></span></h2>
<!-- /wp:heading -->
<!-- wp:paragraph {"style":{"spacing":{"margin":{"top":"0","bottom":"1.5rem"}}},"textColor":"white","fontSize":"lg"} -->
<p class="has-white-color has-text-color has-lg-font-size" style="margin-top:0;margin-bottom:1.5rem">Fully customized solution with advanced features.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3,"style":{"spacing":{"margin":{"top":"1.5rem","bottom":"1.5rem"}}},"textColor":"white"} -->
<h3 class="wp-block-heading has-white-color has-text-color" style="margin-top:1.5rem;margin-bottom:1.5rem"><strong>€2499</strong> <span style="font-weight:normal;font-size:1rem;color:#98999a">starting price</span></h3>
<!-- /wp:heading -->
<!-- wp:group -->
<div class="wp-block-group"><!-- wp:group {"className":"feature-item"} -->
<div class="wp-block-group feature-item"><!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
<div class="wp-block-group"><!-- wp:image {"width":"24px","height":"24px","className":"feature-icon","style":{"color":{"duotone":["#ffffff","#ffffff"]}}} -->
<figure class="wp-block-image is-resized feature-icon"><img src="<?php echo esc_url(get_theme_file_uri('resources/images/icons/pricing/check-circle.svg')); ?>" alt="Check icon" style="width:24px;height:24px"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph {"textColor":"white"} -->
<p class="has-white-color has-text-color">Premium VPS hosting (Trellis stack with Micro Caching, A+ SSL, WP CLI)</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
<!-- wp:separator {"className":"is-style-separator-dotted","style":{"color":{"background":"#ffffff40"}}} -->
<hr class="wp-block-separator has-text-color has-alpha-channel-opacity has-background is-style-separator-dotted" style="background-color:#ffffff40;color:#ffffff40"/>
<!-- /wp:separator -->
<!-- wp:group {"className":"feature-item"} -->
<div class="wp-block-group feature-item"><!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
<div class="wp-block-group"><!-- wp:image {"width":"24px","height":"24px","className":"feature-icon","style":{"color":{"duotone":["#ffffff","#ffffff"]}}} -->
<figure class="wp-block-image is-resized feature-icon"><img src="<?php echo esc_url(get_theme_file_uri('resources/images/icons/pricing/check-circle.svg')); ?>" alt="Check icon" style="width:24px;height:24px"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph {"textColor":"white"} -->
<p class="has-white-color has-text-color">Custom hybrid theme (block + classic elements)
</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
<!-- wp:separator {"className":"is-style-separator-dotted","style":{"color":{"background":"#ffffff40"}}} -->
<hr class="wp-block-separator has-text-color has-alpha-channel-opacity has-background is-style-separator-dotted" style="background-color:#ffffff40;color:#ffffff40"/>
<!-- /wp:separator -->
<!-- wp:group {"className":"feature-item"} -->
<div class="wp-block-group feature-item"><!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
<div class="wp-block-group"><!-- wp:image {"width":"24px","height":"24px","className":"feature-icon","style":{"color":{"duotone":["#ffffff","#ffffff"]}}} -->
<figure class="wp-block-image is-resized feature-icon"><img src="<?php echo esc_url(get_theme_file_uri('resources/images/icons/pricing/check-circle.svg')); ?>" alt="Check icon" style="width:24px;height:24px"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph {"textColor":"white"} -->
<p class="has-white-color has-text-color">Advanced SEO optimization</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
<!-- wp:separator {"className":"is-style-separator-dotted","style":{"color":{"background":"#ffffff40"}}} -->
<hr class="wp-block-separator has-text-color has-alpha-channel-opacity has-background is-style-separator-dotted" style="background-color:#ffffff40;color:#ffffff40"/>
<!-- /wp:separator -->
<!-- wp:group {"className":"feature-item"} -->
<div class="wp-block-group feature-item"><!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
<div class="wp-block-group"><!-- wp:image {"width":"24px","height":"24px","className":"feature-icon","style":{"color":{"duotone":["#ffffff","#ffffff"]}}} -->
<figure class="wp-block-image is-resized feature-icon"><img src="<?php echo esc_url(get_theme_file_uri('resources/images/icons/pricing/check-circle.svg')); ?>" alt="Check icon" style="width:24px;height:24px"/></figure>
<!-- /wp:image -->
<!-- wp:paragraph {"textColor":"white"} -->
<p class="has-white-color has-text-color">6-month maintenance plan</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
<!-- wp:buttons {"style":{"spacing":{"margin":{"top":"2rem"}}},"layout":{"type":"flex","justifyContent":"left"}} -->
<div class="wp-block-buttons" style="margin-top:2rem"><!-- wp:button {"backgroundColor":"base","textColor":"black","style":{"border":{"radius":"0.5rem"}}} -->
<div class="wp-block-button"><a class="wp-block-button__link has-black-color has-base-background-color has-text-color has-background wp-element-button" style="border-radius:0.5rem">Get Started</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons --></div>
<!-- /wp:group --></div>
<!-- /wp:column --></div>
<!-- /wp:columns --></div>
<!-- /wp:group --></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment