---
title: "Build SEO into a headless CMS so Google indexes every page"
description: "Add SEO fields to Contentful, Strapi, or Sanity models, render metadata and JSON-LD on the server, and generate sitemaps and redirects from CMS data."
canonical: "https://scalewithsearch.com/articles/headless-cms-seo-developers"
date: "2026-03-20"
modified: "2026-09-25"
---
## Site navigation

- [Scale With Search](https://scalewithsearch.com/)
- Real estate
  - Real estate
    - [Real estate](https://scalewithsearch.com/for/real-estate)
- Work
  - Start here
    - [Send your brief](https://scalewithsearch.com/work#send-your-brief)
    - [Prepare your six-question brief](https://scalewithsearch.com/work#prepare-your-six-question-brief)
  - Build
    - [Site build, content library with SEO, signal desk](https://scalewithsearch.com/work)
- For your business
  - Trades and home services
    - [Auto body and collision shops](https://scalewithsearch.com/for/auto-body-and-collision-shops)
    - [Foundation and home repair contractors](https://scalewithsearch.com/for/foundation-and-home-repair)
    - [Garage door and fencing contractors](https://scalewithsearch.com/for/garage-door-and-fencing-contractors)
    - [HVAC contractors](https://scalewithsearch.com/for/hvac-contractors)
    - [Janitorial and commercial cleaning companies](https://scalewithsearch.com/for/janitorial-and-commercial-cleaning)
    - [Locksmiths](https://scalewithsearch.com/for/locksmiths)
    - [Moving companies](https://scalewithsearch.com/for/moving-companies)
    - [Pest control companies](https://scalewithsearch.com/for/pest-control-companies)
    - [Plumbing and electrical contractors](https://scalewithsearch.com/for/plumbing-and-electrical-contractors)
    - [Restoration and water or fire damage companies](https://scalewithsearch.com/for/restoration-and-water-fire-damage)
    - [Roofing companies](https://scalewithsearch.com/for/roofing-companies)
    - [Towing companies](https://scalewithsearch.com/for/towing-companies)
    - [Tree services and landscaping companies](https://scalewithsearch.com/for/tree-services-and-landscaping)
    - [Solar installers](https://scalewithsearch.com/for/solar-installation)
    - [General contractors](https://scalewithsearch.com/for/general-contractors-and-construction)
    - [Paving, concrete, and flooring contractors](https://scalewithsearch.com/for/paving)
  - Practices and professional services
    - [Bookkeeping and tax practices](https://scalewithsearch.com/for/bookkeeping-and-tax-practices)
    - [Dental practices](https://scalewithsearch.com/for/dental-practices)
    - [Family and criminal defense law firms](https://scalewithsearch.com/for/family-and-criminal-defense-law-firms)
    - [Med spas and aesthetics practices](https://scalewithsearch.com/for/med-spas-and-aesthetics)
    - [Personal injury law firms](https://scalewithsearch.com/for/personal-injury-law-firms)
    - [Veterinary clinics](https://scalewithsearch.com/for/veterinary-clinics)
    - [Gyms and fitness studios](https://scalewithsearch.com/for/fitness)
    - [Therapy and outpatient health practices](https://scalewithsearch.com/for/therapy-and-outpatient-health)
    - [Medical billing companies](https://scalewithsearch.com/for/medical-billing)
    - [Insurance agencies](https://scalewithsearch.com/for/insurance-agencies)
    - [Financial advisors](https://scalewithsearch.com/for/financial-advisors)
    - [Property management companies](https://scalewithsearch.com/for/property-management)
    - [Recruiting and staffing agencies](https://scalewithsearch.com/for/recruiting-and-staffing)
    - [Architects and interior designers](https://scalewithsearch.com/for/architects-and-interior-designers)
    - [Logistics and supply chain companies](https://scalewithsearch.com/for/logistics-and-supply-chain)
  - Agencies, MSPs, and manufacturing
    - [IT and managed service providers](https://scalewithsearch.com/for/it-and-managed-service-providers)
    - [Machine shops and precision manufacturers](https://scalewithsearch.com/for/machine-shops-and-precision-manufacturing)
    - [Marketing agencies and freelancers](https://scalewithsearch.com/for/marketing-agencies-and-freelancers)
    - [SEO agencies and consultants](https://scalewithsearch.com/for/seo-agencies-and-consultants)
    - [Small manufacturers and fabricators](https://scalewithsearch.com/for/small-manufacturers-and-fabricators)
  - Restaurants, shops, studios, and nonprofits
    - [Restaurants and hospitality businesses](https://scalewithsearch.com/for/restaurants-and-hospitality)
    - [Retail stores and ecommerce sellers](https://scalewithsearch.com/for/retail-and-ecommerce)
    - [Photographers, event planners, and travel agents](https://scalewithsearch.com/for/photographers)
    - [Churches and nonprofits](https://scalewithsearch.com/for/churches-and-nonprofits)
  - [All industries](https://scalewithsearch.com/for/)
- Learn
  - For your office
    - [Office job guides](https://scalewithsearch.com/guides/)
    - [Browser calculators](https://scalewithsearch.com/tools/)
  - Start here
    - [How it works](https://scalewithsearch.com/how-it-works)
    - [Free Starter Kit](https://scalewithsearch.com/kit/business-memory-starter-kit.zip)
    - [Synthetic specimen](https://scalewithsearch.com/specimen/working-session-specimen.zip)
  - Guides
    - [The Complete Guide to Business Memory for AI Agents](https://scalewithsearch.com/articles/business-memory-for-ai-agents-guide)
    - [The Complete Small-Business Guide to AI Agent Governance](https://scalewithsearch.com/articles/ai-agent-governance-guide-small-business)
    - [The Complete Guide to Leaving Vendor AI Memory](https://scalewithsearch.com/articles/leaving-vendor-ai-memory-guide)
  - Articles by cluster
    - [Business memory](https://scalewithsearch.com/articles/business-memory-for-ai-agents-guide)
    - [Agent governance](https://scalewithsearch.com/articles/ai-agent-governance-guide-small-business)
    - [Migration and ownership](https://scalewithsearch.com/articles/leaving-vendor-ai-memory-guide)
  - For machines
    - [llms.txt](https://scalewithsearch.com/llms.txt)
    - [llms-full.txt](https://scalewithsearch.com/llms-full.txt)
    - [Machine view](https://scalewithsearch.com/?view=machine)
- Company
  - Evidence
    - [Proof](https://scalewithsearch.com/proof)
  - Company
    - [About](https://scalewithsearch.com/about)

# Build SEO into a headless CMS so Google indexes every page.

A team moves its site from WordPress to Contentful and Next.js. The new site is faster. Two weeks after launch, Search Console shows 300 pages with the same title and no meta description. The sitemap still lists the old WordPress URLs.

A headless CMS delivers content through an API, not as HTML pages. That gives developers freedom: any frontend framework, one content source for the website and the mobile app, and deployment to edge networks. It also removes the SEO features that a traditional CMS gives you by default. This article shows how to put those features back. The work covers SEO fields in the content model, metadata in server HTML, and structured data. It also covers sitemaps, redirects, canonical URLs, and the right rendering method.

## See what the CMS no longer does for you

In a traditional CMS such as WordPress, content and presentation live together. Plugins such as Yoast and Rank Math generate meta tags, sitemaps, and structured data. The CMS manages slugs, redirects, and canonical tags.

In a headless CMS such as Contentful, Strapi, or Sanity, content is structured JSON. The frontend fetches it through an API. The developer builds every SEO feature by hand: meta tags, URLs, sitemaps, redirects, and structured data.

If nobody builds them, pages ship without metadata, URLs follow no rule, the sitemap is missing, and Google may index empty shells. Plan these features before the first template, not after launch.

## Step 1: add SEO fields to the content model

SEO fields belong in the content model. Without them, the frontend has nothing to render.

Add these fields to every indexable content type, such as articles, blog posts, and product pages:

| Field | Type | Purpose | Example |
|---|---|---|---|
| `slug` | Short text | URL identifier | `best-crm-for-real-estate` |
| `meta_title` | Short text, 60 characters maximum | Title tag in search results | `Best CRM for Real Estate Agents` |
| `meta_description` | Long text, 160 characters maximum | Description in search results | `Compare three real estate CRMs on features, pricing, and reviews.` |
| `canonical_url` | Short text | Preferred URL when duplicates exist | `https://example.com/blog/best-crm` |
| `og_image` | Media | Image for social previews | Asset reference |
| `focus_keyword` | Short text | Target keyword, for internal tracking | `best crm for real estate` |
| `noindex` | Boolean | Keeps the page out of search results | `false` |
| `publish_date` | Date and time | Publication date | `2026-02-08` |
| `last_updated` | Date and time | Last material change | `2026-02-08` |

Add an `alt_text` field to every image asset as well. The frontend renders it into the `alt` attribute.

Here is the model in Contentful:

```json
{
  "name": "Blog Post",
  "fields": [
    { "id": "title", "name": "Title", "type": "Symbol" },
    { "id": "slug", "name": "Slug", "type": "Symbol", "required": true },
    { "id": "meta_title", "name": "Meta Title", "type": "Symbol", "validations": [{ "size": { "max": 60 }}] },
    { "id": "meta_description", "name": "Meta Description", "type": "Text", "validations": [{ "size": { "max": 160 }}] },
    { "id": "canonical_url", "name": "Canonical URL", "type": "Symbol" },
    { "id": "og_image", "name": "OG Image", "type": "Link", "linkType": "Asset" },
    { "id": "noindex", "name": "No Index", "type": "Boolean", "default": false },
    { "id": "body", "name": "Body", "type": "RichText" },
    { "id": "publish_date", "name": "Publish Date", "type": "Date" },
    { "id": "last_updated", "name": "Last Updated", "type": "Date" }
  ]
}
```

### Validate slugs in the CMS

A slug must be unique, URL-safe, and predictable. Use lowercase letters, numbers, and single hyphens only: `best-crm-for-real-estate`, not `Best CRM for Real Estate` or `best--crm`.

In Contentful, add a unique validation and a pattern:

```json
{
  "id": "slug",
  "type": "Symbol",
  "required": true,
  "validations": [
    {
      "unique": true,
      "regexp": {
        "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
      }
    }
  ]
}
```

In Strapi, use the UID field type. It generates the slug from the title and enforces uniqueness.

In Sanity, use the `slug` type with a source field:

```javascript
{
  name: 'slug',
  type: 'slug',
  options: {
    source: 'title',
    maxLength: 96,
  },
  validation: Rule => Rule.required()
}
```

## Step 2: render metadata in the server HTML

The frontend must write the meta tags from CMS data into the HTML it sends. Googlebot then reads them in the first crawl, before any rendering.

### Next.js App Router

In the App Router, export `generateMetadata` from the route:

```javascript
export async function generateMetadata({ params }) {
  const { slug } = await params;
  const post = await fetchPostBySlug(slug);
  return {
    title: post.meta_title || post.title,
    description: post.meta_description,
    alternates: { canonical: post.canonical_url || `https://example.com/blog/${post.slug}` },
    robots: post.noindex ? { index: false, follow: false } : undefined,
    openGraph: {
      title: post.meta_title || post.title,
      description: post.meta_description,
      type: 'article',
      publishedTime: post.publish_date,
      images: post.og_image ? [post.og_image.url] : [],
    },
    twitter: { card: 'summary_large_image' },
  };
}
```

### Next.js Pages Router

In the Pages Router, use `next/head` in a shared component:

```javascript
import Head from 'next/head';

export default function SEOHead({ page }) {
  const { meta_title, meta_description, canonical_url, og_image, noindex, publish_date } = page;

  return (
    <Head>
      <title>{meta_title || page.title}</title>
      <meta name="description" content={meta_description} />
      {canonical_url && <link rel="canonical" href={canonical_url} />}
      {noindex && <meta name="robots" content="noindex, nofollow" />}
      <meta property="og:title" content={meta_title || page.title} />
      <meta property="og:description" content={meta_description} />
      {og_image && <meta property="og:image" content={og_image.url} />}
      <meta property="og:type" content="article" />
      <meta name="twitter:card" content="summary_large_image" />
      {publish_date && <meta property="article:published_time" content={publish_date} />}
    </Head>
  );
}
```

Use it on each page, and load the data at build time:

```javascript
import SEOHead from '../components/SEOHead';

export default function BlogPost({ post }) {
  return (
    <>
      <SEOHead page={post} />
      <article>
        <h1>{post.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.body }} />
      </article>
    </>
  );
}

export async function getStaticProps({ params }) {
  const post = await fetchPostBySlug(params.slug);
  return { props: { post } };
}
```

### React without server rendering

A client-rendered React app can set tags with `react-helmet` or its maintained fork `react-helmet-async`:

```javascript
import { Helmet } from 'react-helmet';

export default function BlogPost({ post }) {
  return (
    <>
      <Helmet>
        <title>{post.meta_title}</title>
        <meta name="description" content={post.meta_description} />
        <link rel="canonical" href={post.canonical_url} />
        {post.noindex && <meta name="robots" content="noindex" />}
      </Helmet>
      <article>
        <h1>{post.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.body }} />
      </article>
    </>
  );
}
```

These tags are not in the initial HTML. Googlebot sees them only after it renders the page. For pages that must rank, render on the server or at build time. The [Googlebot rendering guide](/articles/googlebot-javascript-rendering) shows how to test what Google receives.

## Step 3: add structured data on the server

Put JSON-LD in the HTML that the server sends. Google can read JSON-LD that JavaScript adds later, but server output removes a failure point. The [JSON-LD guide for developers](/articles/structured-data-jsonld-developers) covers more types.

Generate Article markup from the post:

```javascript
export function generateArticleSchema(post) {
  return {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": post.title,
    "description": post.meta_description,
    "image": post.og_image?.url,
    "datePublished": post.publish_date,
    "dateModified": post.last_updated || post.publish_date,
    "author": {
      "@type": "Person",
      "name": post.author?.name,
      "url": post.author?.url,
    },
    "publisher": {
      "@type": "Organization",
      "name": "Your Company",
      "logo": { "@type": "ImageObject", "url": "https://example.com/logo.png" }
    }
  };
}
```

Write it into the page head:

```javascript
<Head>
  <script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(generateArticleSchema(post)) }}
  />
</Head>
```

Generate Product markup for commerce pages:

```javascript
export function generateProductSchema(product) {
  return {
    "@context": "https://schema.org",
    "@type": "Product",
    "name": product.name,
    "image": product.images.map(img => img.url),
    "description": product.meta_description,
    "sku": product.sku,
    "brand": { "@type": "Brand", "name": product.brand },
    "offers": {
      "@type": "Offer",
      "url": `https://example.com/products/${product.slug}`,
      "priceCurrency": "USD",
      "price": product.price,
      "availability": product.in_stock ? "https://schema.org/InStock" : "https://schema.org/OutOfStock"
    }
  };
}
```

Test each template with the Google Rich Results Test.

## Step 4: generate the sitemap from CMS data

A sitemap lists the URLs you want crawled and when each one last changed. Google ignores the `changefreq` and `priority` values, but it uses `lastmod` when the value is accurate. Set `lastmod` from `last_updated`, and change `last_updated` only for material edits. The [XML sitemap guide](/articles/xml-sitemap-best-practices-developers) covers sitemap indexes for large sites.

### Build-time sitemap

Generate the file during the build:

```javascript
const fs = require('fs');
const { fetchAllPosts } = require('../lib/contentful');

async function generateSitemap() {
  const posts = await fetchAllPosts();
  const urls = posts.filter(post => !post.noindex).map(post => `
  <url>
    <loc>https://example.com/blog/${post.slug}</loc>
    <lastmod>${post.last_updated || post.publish_date}</lastmod>
  </url>`).join('');

  const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${urls}
</urlset>`;

  fs.writeFileSync('public/sitemap.xml', sitemap);
}

generateSitemap();
```

Run it before the framework build in `package.json`:

```json
{
  "scripts": {
    "build:sitemap": "node scripts/generate-sitemap.js",
    "build": "npm run build:sitemap && next build"
  }
}
```

### Runtime sitemap

For a site with thousands of pages that change often, serve the sitemap from a route. In the App Router, add `app/sitemap.js`:

```javascript
export default async function sitemap() {
  const posts = await fetchAllPosts();
  return posts
    .filter(post => !post.noindex)
    .map(post => ({
      url: `https://example.com/blog/${post.slug}`,
      lastModified: post.last_updated || post.publish_date,
    }));
}
```

In the Pages Router, write the XML from an API route such as `pages/api/sitemap.xml.js`. Then add a rewrite from `/sitemap.xml` to that route in `next.config.js`. A runtime sitemap always reflects the CMS, with no rebuild. It adds an API call to each sitemap request, so cache the response.

Exclude every `noindex` page from the sitemap. A sitemap that lists `noindex` pages sends Google two conflicting signals.

## Step 5: manage redirects and canonical URLs

### Store redirects in the CMS

When editors change slugs, the old URLs must redirect. Give editors a Redirect content type:

```json
{
  "name": "Redirect",
  "fields": [
    { "id": "from_url", "name": "From URL", "type": "Symbol" },
    { "id": "to_url", "name": "To URL", "type": "Symbol" },
    { "id": "redirect_type", "name": "Type", "type": "Symbol", "validations": [{ "in": ["301", "302"] }] }
  ]
}
```

Load the redirects when Next.js reads its configuration:

```javascript
const { fetchRedirects } = require('./lib/contentful');

module.exports = async () => {
  const redirects = await fetchRedirects();
  return {
    async redirects() {
      return redirects.map(r => ({
        source: r.from_url,
        destination: r.to_url,
        permanent: r.redirect_type === '301',
      }));
    },
  };
};
```

Editors then manage redirects without code changes. The configuration loads at build time, so a new redirect needs a new deployment. Next.js sends a 308 status for `permanent: true` and a 307 status otherwise. Google treats 308 like 301 and 307 like 302.

### Set canonical URLs

When the same content exists at more than one URL, name the preferred one:

```javascript
<link rel="canonical" href={post.canonical_url || `https://example.com/blog/${post.slug}`} />
```

Use a canonical tag in three cases. A sorted or filtered URL such as `?sort=price` points to the base URL. Syndicated copies on other sites point to your original. Tracking parameters point to the clean URL.

Do not point every page of a paginated series to page 1. Page 2 holds different items than page 1. Give each paginated page a self-referencing canonical. The [canonical tag guide for developers](/articles/canonical-tags-developers) covers more edge cases.

If you publish in more than one language, add locale fields. Generate one URL for each locale, such as `/en/blog/slug` and `/es/blog/slug`, and add `hreflang` tags that list every version.

## Step 6: pick a rendering method for each template

Every page that must rank needs HTML from the server or from the build.

Use static site generation for articles, marketing pages, and product pages whose stock and price change rarely:

```javascript
export async function getStaticProps({ params }) {
  const post = await fetchPostBySlug(params.slug);
  return { props: { post } };
}

export async function getStaticPaths() {
  const posts = await fetchAllPosts();
  return {
    paths: posts.map(p => ({ params: { slug: p.slug } })),
    fallback: 'blocking', // Builds new slugs on first request
  };
}
```

Use server-side rendering for content that changes by the minute, such as live scores, and for personal pages:

```javascript
export async function getServerSideProps({ params }) {
  const post = await fetchPostBySlug(params.slug);
  return { props: { post } };
}
```

Use incremental static regeneration for content that changes now and then, such as prices or comment counts. Add `revalidate: 3600` to the `getStaticProps` return value to rebuild a page at most once each hour. In the App Router, export `revalidate` from the route file.

Static generation is enough for most content sites. Use server rendering only when content changes often or depends on the user. Either way, Googlebot receives full HTML at once and does not wait in the render queue.

## Connect each CMS to Next.js

For Contentful, install the SDK with `npm install contentful`:

```javascript
const contentful = require('contentful');

const client = contentful.createClient({
  space: process.env.CONTENTFUL_SPACE_ID,
  accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
});

export async function fetchPostBySlug(slug) {
  const entries = await client.getEntries({
    content_type: 'blogPost',
    'fields.slug': slug,
    limit: 1,
  });
  return entries.items[0]?.fields;
}
```

For Strapi, call the REST API. Strapi 5, released in 2024, returns fields at the top level of each entry. Strapi 4 wrapped them in `attributes`:

```javascript
export async function fetchPostBySlug(slug) {
  const res = await fetch(`${process.env.STRAPI_URL}/api/posts?filters[slug][$eq]=${encodeURIComponent(slug)}&populate=*`);
  const data = await res.json();
  return data.data[0]; // Strapi 4: data.data[0]?.attributes
}
```

For Sanity, install the client with `npm install @sanity/client`:

```javascript
import { createClient } from '@sanity/client';

const client = createClient({
  projectId: process.env.SANITY_PROJECT_ID,
  dataset: 'production',
  apiVersion: '2023-01-01',
  useCdn: true,
});

export async function fetchPostBySlug(slug) {
  const query = `*[_type == "post" && slug.current == $slug][0]`;
  return client.fetch(query, { slug });
}
```

WordPress can also run headless through its REST API. The SEO plugins still store their fields, and Yoast exposes its output through the API. Your frontend must still render it. If your CMS has no custom fields for SEO, you have three options. Move to a CMS that has them, add a small API layer that stores the fields, or hard-code SEO in the frontend. The last option does not scale.

A mobile app alone does not get content into Google Search. Google indexes web pages, so you need a web frontend with crawlable HTML.

## Check the build before launch

- Every indexable content type has `slug`, `meta_title`, `meta_description`, `canonical_url`, and `noindex`.
- Meta tags come from CMS data and appear in the server HTML.
- JSON-LD appears in the server HTML and passes the Rich Results Test.
- `sitemap.xml` exists, lists only indexable pages, and carries accurate `lastmod` values.
- Redirects live in the CMS or a configuration file.
- Pages that must rank use SSG, ISR, or SSR, not client-side rendering.
- URLs follow a clean pattern such as `/blog/slug`, not `/posts?id=123`.
- Images carry alt text from the CMS.
- Internal links are `<a href>` elements, not click handlers.
- URL Inspection in Search Console shows complete content for each template.

----

```text
                  .|########||.                                       .|########||.                                       .|########||.
               |##||.      .||##|.                                 |##||.      .||##|.                                 |##||.      .||##|.
             |#|.              .|#|.                             |#|.              .|#|.                             |#|.              .|#|.
           |#|                    |#|                          |#|                    |#|                          |#|                    |#|
         .#|                        |#.                      .#|                        |#.                      .#|                        |#.
        .#.                          .#|                    .#.                          .#|                    .#.                          .#|
       |#.                            .#|                  |#.                            .#|                  |#.                            .#|
      |#             ......             #|                |#             ......             #|                |#             ......             #|
     .#           ||#########|           #|              .#           ||#########|           #|              .#           ||#########|           #|
    .#.         |######||######|.        .#.            .#.         |######||######|.        .#.            .#.         |######||######|.        .#.
    #.        .##|###|##|#|######|        .#            #.        .##|###|##|#|######|        .#            #.        .##|###|##|#|######|        .#
   ||        |##|#||||||||||||#||#|        ||          ||        |##|#||||||||||||#||#|        ||          ||        |##|#||||||||||||#||#|        ||
   #        |#||||||||||||||||||||#|        #.         #        |#||||||||||||||||||||#|        #.         #        |#||||||||||||||||||||#|        #.
  ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||
  #       .#||||||||||||||||||||||||#|       #        #       .#||||||||||||||||||||||||#|       #        #       .#||||||||||||||||||||||||#|       #
 ||   ....|||#||||||##|#|||#|#||##||||....|. ||      ||   ....|||#||||||##|#|||#|#||##||||....|. ||      ||   ....|||#||||||##|#|||#|#||##||||....|. ||
 #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#      #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#      #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#
 #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.     #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.     #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.
.|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||    .|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||    .|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||
||   |....  #. ....|#.      |. ...|. ....||   ||    ||   |....  #. ....|#.      |. ...|. ....||   ||    ||   |....  #. ....|#.      |. ...|. ....||   ||
#.  .||||||##||||||##||####|||||||#||||||#|   .#    #.  .||||||##||||||##||####|||||||#||||||#|   .#    #.  .||||||##||||||##||####|||||||#||||||#|   .#
#    .||####|###########################|.     #    #    .||####|###########################|.     #    #    .||####|###########################|.     #
#      .#||||||.#.|| # |. ..# #| #|||||#|      #    #      .#||||||.#.|| # |. ..# #| #|||||#|      #    #      .#||||||.#.|| # |. ..# #| #|||||#|      #
#      .#|||||| ..  |# ## |#| ...#|#|||#|      #    #      .#|||||| ..  |# ## |#| ...#|#|||#|      #    #      .#|||||| ..  |# ## |#| ...#|#|||#|      #
#      .#|||#|# .# .#| #| ##|.#..#|||||#|      #    #      .#|||#|# .# .#| #| ##|.#..#|||||#|      #    #      .#|||#|# .# .#| #| ##|.#..#|||||#|      #
#      .#||||||############|######|||||#|      #    #      .#||||||############|######|||||#|      #    #      .#||||||############|######|||||#|      #
#   |...||#||||||#||||#|#||||||#|||||#||| |.|  #    #   |...||#||||||#||||#|#||||||#|||||#||| |.|  #    #   |...||#||||||#||||#|#||||||#|||||#||| |.|  #
#. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#    #. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#    #. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#
|| |  ...||  ...##| |  #| .|. |. #####  .. .| ||    || |  ...||  ...##| |  #| .|. |. #####  .. .| ||    || |  ...||  ...##| |  #| .|. |. #####  .. .| ||
|| ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||    || ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||    || ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||
.# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.    .# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.    .# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.
 #.|||||||#############################| ||| .#      #.|||||||#############################| ||| .#      #.|||||||#############################| ||| .#
 ||       ##||#||#||||||#||#||#||#||##.      ||      ||       ##||#||#||||||#||#||#||#||##.      ||      ||       ##||#||#||||||#||#||#||#||##.      ||
  #       .#|||||||||#||#|||||||||||#|       #        #       .#|||||||||#||#|||||||||||#|       #        #       .#|||||||||#||#|||||||||||#|       #
  ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||
  .#        |#||||||||||||||||||||#|        #.        .#        |#||||||||||||||||||||#|        #.        .#        |#||||||||||||||||||||#|        #.
   ||        |#||||||||||||||||||#|        ||          ||        |#||||||||||||||||||#|        ||          ||        |#||||||||||||||||||#|        ||
    #.        .######|#|#########|        .#            #.        .######|#|#########|        .#            #.        .######|#|#########|        .#
    .#.         |#####||||#####|         .#.            .#.         |#####||||#####|         .#.            .#.         |#####||||#####|         .#.
     |#           ||########||           #.              |#           ||########||           #.              |#           ||########||           #.
      |#             ......             #|                |#             ......             #|                |#             ......             #|
       |#.                            .#|                  |#.                            .#|                  |#.                            .#|
        |#.                          .#.                    |#.                          .#.                    |#.                          .#.
         .#|                        |#.                      .#|                        |#.                      .#|                        |#.
           |#|                    |#|                          |#|                    |#|                          |#|                    |#|
            .|#|.              .|#|.                            .|#|.              .|#|.                            .|#|.              .|#|.
               |##||.      .||##|                                  |##||.      .||##|                                  |##||.      .||##|
                 .||########||.                                      .||########||.                                      .||########||.

Scale With Search  2026  [scalewithsearch.com](https://scalewithsearch.com)
```
