AtroUIAtroUI
DocsComponentsBlogTheming
StarOwn the UI
  • Introduction
  • Installation
  • Host APIs
  • Registry
  • Theming
  • Brand kit
  • Identity kit
  • Compare
  • Changelog
  • Blog
  • ButtonCLI
  • CardCLI
  • Form SelectCLI
  • TextareaCLI
  • BreadcrumbsCLI
  • ProseCLI
  • Founder AvatarCLI
  • Theme ToggleCLI
  • Theme ProviderCLI
  • LogoCLI
  • Mockup FrameCLI
  • TimelineCLI
  • Fade InCLI
  • StaggerCLI
  • Scroll ProgressCLI
  • Site HeaderCLI
  • Site FooterCLI
  • Bold FooterCLI
  • HeroCLI
  • PrincipleCLI
  • WorkCLI
  • CraftsCLI
  • LabCLI
  • WhoCLI
  • PricingCLI
  • Feature GridCLI
  • Logo CloudCLI
  • FAQCLI
  • Contextual CTACLI
  • Exit IntentCLI
  • Contact FormHost API
  • Calendly EmbedCLI
  • Waitlist FormHost API
  • Newsletter FormHost API
  • JournalCLI
  • Social ShareCLI
  • ResourcesCLI
  • Before / AfterCLI
  • Case StudyCLI
  • AR PortfolioCLI
  • Made With EmbedCLI
  • Count UpCLI
  • Deadline CountdownCLI
  • CurrentlyCLI
  • Project ListCLI
  • Log PreviewCLI
  • ChangelogCLI
  • Command MenuCLI
  • RevealCLI
  • Theme Toggle IconCLI
  • Site Header NarrowCLI
  • Site Footer NarrowCLI
  • Social FloatCLI
  • Reading ShelfCLI
  • Personal HeroCLI
  • ResumeCLI
  • Local ClockCLI
  • Weather ChipCLI
  • Stack ListCLI
  • OG ExamplesCLI
  • OG Live PreviewCLI
  • OG WorkspaceHost API
  • Thumbnail PreviewCLI
  • Thumbnail WorkspaceHost API
  • Project PlannerCLI
  • Scope ChatHost API
  • Live DashboardCLI
  • Analytics ProviderCLI
  • JSON-LDCLI
  • Testimonial SchemaCLI

Loading

Brand & SEO

Identity kit

AtroUI structures design, brand configuration, and technical SEO as a unified pipeline. Most component registries stop at CSS variables. We provide a complete Brand & SEO Identity Kit — so when you install headers, footers, JSON-LD, or favicons, they pull from a single source of truth and stay in sync.

1. Core brand config (getBrand)

Instead of hardcoding your product name or canonical URLs across headers, footers, and SEO scripts, we configure them in a single place. Install the brand helper:

bash
npx shadcn@latest add @atroui/brand

This drops lib/brand.ts into your project, resolving environmental overrides or default fallbacks dynamically:

typescript
// lib/brand.ts
export function getBrand() {
  return {
    name: process.env.NEXT_PUBLIC_SITE_NAME || "My SaaS",
    domain: process.env.NEXT_PUBLIC_SITE_DOMAIN || "mysaas.com",
    email: process.env.NEXT_PUBLIC_SITE_EMAIL || "hello@mysaas.com",
    siteUrl: process.env.NEXT_PUBLIC_SITE_URL || "https://www.mysaas.com",
    tagline: "Own the UI, borrow the API.",
  }
}

To completely rebrand your site chrome, legal notices, and structured data, you only need to configure your environment variables:

bash
NEXT_PUBLIC_SITE_NAME="AstroSaaS"
NEXT_PUBLIC_SITE_DOMAIN="astrosaas.com"
NEXT_PUBLIC_SITE_EMAIL="team@astrosaas.com"
NEXT_PUBLIC_SITE_URL="https://www.astrosaas.com"

2. Schema.org structured data (JSON-LD)

Google and other search engines utilize Schema.org JSON-LD to display rich snippets, star-ratings, and nest directories in the SERP. AtroUI offers headless schema components that automatically read from your brand config. Install the schema package:

bash
npx shadcn@latest add @atroui/json-ld

This registers headless script blocks inside your component catalog. Combine them within your root App Router layout or individual page files:

tsx
// app/layout.tsx
import { SiteGraphJsonLd } from "@/components/seo/json-ld"

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <SiteGraphJsonLd />
        {children}
      </body>
    </html>
  )
}

For technical docs or long-form developer articles, inject article metadata onto pages dynamically:

tsx
// app/blog/[slug]/page.tsx
import { ArticleJsonLd } from "@/components/seo/json-ld"

export default function BlogPost({ post }) {
  return (
    <article>
      <ArticleJsonLd
        title={post.title}
        description={post.description}
        slug={post.slug}
        date={post.date}
        basePath="/blog"
      />
      <h1>{post.title}</h1>
    </article>
  )
}

3. Next.js metadata and canonical paths

Search engines penalize duplicate path strings. To prevent index pollution, ensure a stable metadataBase is set in the root layout metadata so relative paths resolve to the absolute canonical URL automatically.

typescript
// app/layout.tsx
import { Metadata } from "next"
import { getBrand } from "@/lib/brand"

const brand = getBrand()

export const metadata: Metadata = {
  metadataBase: new URL(brand.siteUrl),
  title: {
    default: `${brand.name} - ${brand.tagline}`,
    template: `%s · ${brand.name}`,
  },
  description: "High-performance dark-first component catalog.",
  alternates: {
    canonical: "/",
  },
}

4. 2026 Favicon and SERP checklist

Modern search results display your brand favicon right next to your snippet link. If you only provide a legacy favicon, Google may display a generic globe, lowering organic click-through rates.

To configure your favicons in a Next.js App Router project using AtroUI specifications, place these in your public/ directory:

  • /icon.svg — standard scalable icon, used by modern browser tabs.
  • /favicon-48.png — 48x48 PNG icon specifically required by Google Search crawler.
  • /favicon-96.png, /favicon-192.png — high-dpi assets.
  • /apple-touch-icon.png — 180x180 mobile app tile.

Then, reference them absolutely via relative URLs in your layout metadata:

typescript
// app/layout.tsx
export const metadata = {
  // ...
  icons: {
    icon: [
      { url: "/icon.svg", type: "image/svg+xml" },
      { url: "/favicon-48.png", sizes: "48x48", type: "image/png" },
      { url: "/favicon-96.png", sizes: "96x96", type: "image/png" },
      { url: "/favicon-192.png", sizes: "192x192", type: "image/png" },
      { url: "/favicon.ico", sizes: "48x48" },
    ],
    apple: [
      { url: "/apple-touch-icon.png", sizes: "180x180", type: "image/png" },
    ],
  },
}

5. Sitemap and robots generation

App Router supports automated dynamic sitemaps and search crawler instructions natively. Build your dynamic crawl tree using the dynamic sitemap helper:

typescript
// app/sitemap.ts
import type { MetadataRoute } from "next"
import { getBrand } from "@/lib/brand"

export default function sitemap(): MetadataRoute.Sitemap {
  const brand = getBrand()
  const lastModified = new Date()

  return [
    {
      url: brand.siteUrl,
      lastModified,
      changeFrequency: "weekly",
      priority: 1,
    },
    {
      url: `${brand.siteUrl}/docs`,
      lastModified,
      changeFrequency: "monthly",
      priority: 0.8,
    },
  ]
}

And drop crawler rules into app/robots.ts:

typescript
// app/robots.ts
import type { MetadataRoute } from "next"
import { getBrand } from "@/lib/brand"

export default function robots(): MetadataRoute.Robots {
  const brand = getBrand()
  return {
    rules: {
      userAgent: "*",
      allow: "/",
    },
    sitemap: `${brand.siteUrl}/sitemap.xml`,
    host: brand.siteUrl,
  }
}

SEO Discipline: Brand ≠ CONTENT

AtroUI maintains a strict division of data to avoid typical template mistakes:

  • Brand Profile — configured globally via environment variables (getBrand), powering headers, footers, JSON-LD, sitemaps, and default mail handles.
  • Section Copy (CONTENT) — configured locally at the top of individual block files, representing the exact words displayed in marketing components (e.g. `DEFAULT_BRAND` on dynamic heroes).

This boundary ensures your product is immediately indexable on your production URL, with no generic template strings leaking into Google's index.