# How OpenSEO Handles SEO Configuration: A Technical Deep Dive into the every-app/open-seo Library

> Explore how every-app/open-seo handles SEO configuration. This technical deep dive reveals the buildPageSeo function that centralizes metadata generation for URLs, meta tags, and social media properties.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: deep-dive
- Published: 2026-07-26

---

**OpenSEO centralizes all SEO metadata generation in a TypeScript utility file at [`web/src/lib/seo.ts`](https://github.com/every-app/open-seo/blob/main/web/src/lib/seo.ts), using a `buildPageSeo` function that transforms declarative configuration objects into canonical URLs, HTML meta tags, Open Graph properties, and Twitter Card data.**

The every-app/open-seo repository implements a type-safe, environment-driven approach to SEO management in React applications. By consolidating URL normalization and meta tag generation into reusable helpers, the library ensures consistent SEO patterns across marketing pages, static content, and dynamic routes. Understanding how open-seo handles SEO configuration reveals a pattern that keeps markup declarative while supporting server-side rendering requirements.

## Centralized SEO Utilities in [`web/src/lib/seo.ts`](https://github.com/every-app/open-seo/blob/main/web/src/lib/seo.ts)

The core SEO logic resides in [`web/src/lib/seo.ts`](https://github.com/every-app/open-seo/blob/main/web/src/lib/seo.ts), which exports a suite of utilities for URL management and metadata construction. This file eliminates hardcoded domain strings and duplicate path logic across the application.

### Environment-Driven Site URL Configuration

The library derives the canonical domain from environment variables, prioritizing `process.env.SITE_URL` or falling back to `process.env.VITE_SITE_URL`. If neither variable is present, it defaults to `https://openseo.so`. The `SITE_URL` constant is automatically trimmed of trailing slashes to prevent double-slash errors when concatenating paths.

### Canonical URL Normalization

Two specialized helpers manage URL consistency:

- **`toCanonicalPath`** – Normalizes any path string by ensuring a leading forward slash and removing duplicate trailing slashes.
- **`toCanonicalUrl`** – Combines the normalized path with `SITE_URL` to generate absolute canonical URLs for use in `<link rel="canonical">` tags and Open Graph metadata.

## The `buildPageSeo` Function: Declarative Metadata Generation

The primary interface for page-level SEO is the `buildPageSeo` function, which accepts a configuration object containing `title`, `path`, and optional parameters including `description`, `titleSuffix`, `ogType`, and `imageAlt`.

According to the source code, the function returns a structured object with two arrays:

- **`meta`** – An array of tag definitions covering standard HTML meta tags, Open Graph (`og:title`, `og:url`, etc.), and Twitter Card properties. The function automatically appends a default social card image (`/social-card.png`) and sets sensible defaults for Open Graph type (`website`) and image alt text.
- **`links`** – An array containing the canonical link tag pointing to the fully resolved URL.

Page components import this utility and spread the returned arrays into their `<Head>` or equivalent meta-rendering component, ensuring tags are rendered on the server.

## Real-World Implementation Examples

### Marketing Pages with Custom Metadata

Dynamic marketing landing pages utilize the full `buildPageSeo` API to inject branded titles and rich descriptions. The implementation imports the utility from `@/lib/seo` and maps the returned arrays to JSX elements:

```tsx
import { buildPageSeo, SITE_URL } from "@/lib/seo";

export const Route = createFileRoute("/_marketing")({
  component: () => {
    const seo = buildPageSeo({
      title: "OpenSEO – All‑in‑One SEO Platform",
      path: "/_marketing",
      description:
        "Boost your search rankings with keyword research, rank tracking, and site audits—all in one place.",
      titleSuffix: "OpenSEO",
    });

    return (
      <>
        <Head>
          {seo.meta.map((tag, i) => {
            if (tag.title) return <title key={i}>{tag.title}</title>;
            if (tag.name)
              return <meta key={i} name={tag.name} content={tag.content} />;
            return (
              <meta
                key={i}
                property={tag.property}
                content={tag.content}
              />
            );
          })}
          {seo.links.map((link, i) => (
            <link key={i} rel={link.rel} href={link.href} />
          ))}
        </Head>
        <MarketingLanding />
      </>
    );
  },
});

```

### Static Pages with Default Patterns

Static content pages like "Terms & Conditions" follow the same pattern with minimal configuration, as seen in [`web/src/routes/terms-and-conditions.tsx`](https://github.com/every-app/open-seo/blob/main/web/src/routes/terms-and-conditions.tsx):

```tsx
import { buildPageSeo } from "@/lib/seo";

export const Route = createFileRoute("/terms-and-conditions")({
  component: () => {
    const seo = buildPageSeo({
      title: "Terms & Conditions",
      path: "/terms-and-conditions",
      description: "Read the terms of service for using OpenSEO.",
    });

    return (
      <>
        <Head>{/* Render seo.meta & seo.links */}</Head>
        <TermsAndConditions />
      </>
    );
  },
});

```

## Summary

- **OpenSEO consolidates SEO logic** in [`web/src/lib/seo.ts`](https://github.com/every-app/open-seo/blob/main/web/src/lib/seo.ts), exporting `buildPageSeo`, `toCanonicalPath`, and `toCanonicalUrl` for type-safe metadata management.
- **Environment variables drive the site URL**, with automatic fallback handling and trailing slash normalization to ensure valid canonical links.
- **Declarative configuration** allows developers to define page titles, descriptions, and Open Graph data through a single function call that returns render-ready meta and link arrays.
- **Consistent implementation patterns** appear across marketing and static pages in routes like [`web/src/routes/_marketing/index.tsx`](https://github.com/every-app/open-seo/blob/main/web/src/routes/_marketing/index.tsx) and [`web/src/routes/terms-and-conditions.tsx`](https://github.com/every-app/open-seo/blob/main/web/src/routes/terms-and-conditions.tsx).

## Frequently Asked Questions

### How does OpenSEO determine the base site URL for canonical links?

The library checks `process.env.SITE_URL` first, then `process.env.VITE_SITE_URL`, defaulting to `https://openseo.so` if neither environment variable is set. This value is stored in the `SITE_URL` constant and sanitized to remove trailing slashes before use in URL construction.

### What parameters does the `buildPageSeo` function accept?

The function requires `title` and `path` parameters, with optional overrides for `description`, `titleSuffix`, `ogType`, and `imageAlt`. It automatically generates a default social card image path and Open Graph type when custom values are not provided.

### How are canonical URLs generated in the OpenSEO library?

The `toCanonicalPath` helper normalizes the input path to ensure a leading slash, while `toCanonicalUrl` combines this normalized path with the `SITE_URL` environment variable to produce absolute URLs. These are injected into the `<link rel="canonical">` tag via the `links` array returned by `buildPageSeo`.

### Can individual pages override the default social card image in OpenSEO?

Yes, while `buildPageSeo` provides a default image path of `/social-card.png`, the implementation supports custom Open Graph images through the configuration object. Each page component can pass custom `ogType` and `imageAlt` values to tailor social sharing previews for specific content.