# How open-seo.ts Handles SEO Metadata Generation in Open-SEO

> Discover how open-seo.ts generates SEO metadata by aggregating data from Google Search Console and Lighthouse, normalizing it, and rendering Open Graph and Twitter Card tags.

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

---

**The [`open-seo.ts`](https://github.com/every-app/open-seo/blob/main/open-seo.ts) module orchestrates a three-stage pipeline that aggregates data from Google Search Console and Lighthouse, normalizes it with fallback defaults, and renders complete Open Graph and Twitter Card meta tags for the HTML head.**

The [`open-seo.ts`](https://github.com/every-app/open-seo/blob/main/open-seo.ts) file serves as the central orchestration layer for SEO metadata generation in the every-app/open-seo repository. It transforms raw performance data from external services into structured HTML meta tags ready for injection into the document head. Understanding this workflow is essential for developers customizing SEO behavior in Open-SEO applications.

## Data Aggregation Stage in open-seo.ts

The first stage retrieves live SEO signals from integrated analytics services. The module imports **GscService** (Google Search Console) and **LighthouseService** to fetch current performance metrics.

`GscService.getPerformance` retrieves the latest title, description, and image-alt signals for the current project. Concurrently, the Lighthouse service enriches the dataset with performance scores and canonical URL information.

*Source:* [`src/serverFunctions/searchPerformance.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/searchPerformance.ts)

## Normalization and Fallback Defaults

Raw payloads undergo strict validation before rendering. The `normalizeSeoMetadata` and `applyDefaults` helper functions ensure every required field is present.

These functions guarantee that `title`, `description`, `ogImage`, and `canonicalUrl` fields exist, falling back to project-level defaults when specific pages lack customized values. This defensive programming prevents incomplete meta tag generation.

*Source:* [`src/server/lib/seo/metadata.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/seo/metadata.ts)

## Meta-Tag Rendering Export

The final stage converts normalized data into renderable HTML head elements. The exported `generateMetaTags` function returns an array of meta-tag objects matching frameworks like Remix's `meta` export or Vite's `head` configuration.

The function automatically injects **Open Graph** (`og:*`) and **Twitter Card** tags to maximize social-share visibility across platforms.

*Source:* [`src/open-seo.ts`](https://github.com/every-app/open-seo/blob/main/src/open-seo.ts)

### Implementation Example

The following example demonstrates consuming the generator in a route component:

```tsx
// Example: Using the exported generator in a route component
import { generateMetaTags } from '@/open-seo';

export const meta = async ({ params }) => {
  const seoData = await fetchSeoData(params.projectId);
  return generateMetaTags(seoData);
};

```

### Core Generation Logic

The simplified implementation constructs the meta-tag array:

```ts
// Example: The core generator (simplified)
export function generateMetaTags(data: SeoPayload) {
  const meta = [
    { name: 'title', content: data.title },
    { name: 'description', content: data.description },
    { property: 'og:title', content: data.title },
    { property: 'og:description', content: data.description },
    { property: 'og:image', content: data.ogImage },
    { property: 'og:url', content: data.canonicalUrl },
    { name: 'twitter:card', content: 'summary_large_image' },
  ];
  return meta;
}

```

## Summary

- **[`open-seo.ts`](https://github.com/every-app/open-seo/blob/main/open-seo.ts)** acts as the thin orchestration layer coordinating SEO metadata generation across the application.
- **Data aggregation** pulls real-time signals from Google Search Console via `GscService.getPerformance` and Lighthouse performance scores.
- **Normalization** ensures data integrity through `normalizeSeoMetadata` and `applyDefaults` with project-level fallbacks.
- **Rendering** outputs framework-agnostic meta-tag arrays compatible with Remix, Vite, and other React-based frameworks.
- The pipeline supports **Open Graph** and **Twitter Card** specifications for comprehensive social media optimization.

## Frequently Asked Questions

### What services does open-seo.ts use to gather SEO data?

According to the every-app/open-seo source code, the module imports `GscService` and `LighthouseService`. It calls `GscService.getPerformance` to retrieve title, description, and image-alt signals, while Lighthouse provides performance scores and canonical URL data.

### How does open-seo.ts handle missing metadata fields?

The module delegates to `normalizeSeoMetadata` and `applyDefaults` in [`src/server/lib/seo/metadata.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/seo/metadata.ts). These functions validate the presence of required fields including `title`, `description`, `ogImage`, and `canonicalUrl`, applying project-level defaults when specific values are absent.

### What output format does generateMetaTags return?

The `generateMetaTags` function returns an array of objects where each object represents a meta or link tag. The structure matches the shape expected by modern framework meta exports, such as Remix's `meta` function or Vite's head configuration, facilitating direct injection into the HTML head.

### Does open-seo.ts support social media meta tags?

Yes. The implementation automatically generates Open Graph (`og:title`, `og:description`, `og:image`, `og:url`) and Twitter Card (`twitter:card`) tags alongside standard SEO meta tags. This ensures optimized rendering when content is shared across social platforms.