Skip to content

Astro

@easeo/astro is a build-time integration. It injects the site config into the Vite define map and, optionally, emits an SEO contract after the build. Page metadata itself is generated with buildSeoPayload from @easeo/core.

Prerequisites

  • Node 20 or newer.
  • Astro 3 or newer.
  • A site-wide SEOConfig.

Install

npm install @easeo/astro

Quick start

// astro.config.mjs
import { defineConfig } from "astro/config";
import easeo from "@easeo/astro";

export default defineConfig({
  integrations: [
    easeo({
      config: {
        canonicalHost: "example.com",
        publicBaseUrl: "https://example.com",
        siteName: "Example",
      },
    }),
  ],
});

Options

Option Type Description
config SEOConfig Required. Site-wide settings
contract SEOContractConfig Optional. Emits .easeo/contract.json after the build

Hooks it registers

Hook Effect
astro:config:setup Defines __EASEO_CONFIG__ in the Vite define map
astro:build:done Writes .easeo/contract.json when contract is set

Patterns

---
import { buildSeoPayload } from "@easeo/core";
const payload = buildSeoPayload(
  { entityType: "page", title: "About", description: "About us." },
  "/about",
  { canonicalHost: "example.com", publicBaseUrl: "https://example.com" }
);
---
<html>
  <head><Fragment set:html={payload.renderHtml()} /></head>
  <body><h1>About</h1></body>
</html>

Emit a contract

easeo({
  config: { canonicalHost: "example.com", publicBaseUrl: "https://example.com" },
  contract: { canonicalHost: "example.com", scheme: "https" },
});

The contract is written to the build output directory:

dist/
└── .easeo/
    └── contract.json

Commit it or upload it as a build artifact, then gate deployments on a diff. See Contracts in CI.

Troubleshooting

Symptom Cause
.easeo/contract.json missing contract option not set, or the build failed before astro:build:done
Head tags missing payload.renderHtml() not injected into the layout

Notes

  • The output directory is resolved with fileURLToPath, so paths with spaces work correctly.
  • The contract file uses the canonical snake_case format that matches the published JSON schema.