# GitHub and Next.js

> Publish as pull requests on your own repo, whatever it's built with: where articles go, how they match your posts, hand-written HTML sites, auto-merge, and the render routes Seovyn builds for Next.js sites.

If your site is built from a Git repository, Seovyn publishes by opening a **pull request** that adds the article as a Markdown file. Your usual build then deploys it.

## Connect GitHub

:::steps
### Create a token

At github.com/settings/tokens, create a personal access token with the `repo` scope.

### Paste it

On **Publishing**, choose **GitHub** under **For developers**, paste the token and connect. Seovyn lists your repositories.

### Choose where articles go

| Setting | Meaning |
|---|---|
| **Repository** | `owner/repo` |
| **Branch** | The branch pull requests target, `main` by default |
| **Content path** | Where files go. Seovyn fills it in from your repo (see below); otherwise `content/{type}/{slug}.md` |

In the path, `{slug}` is the article's slug, `{type}` is `blog`, `comparison` or `landing` (the addresses `/blog/…`, `/compare/…` and `/features/…`), and `{date}` is the publish date, like `2026-01-31`.

### Decide on auto-merge

Turn on **Auto-merge content PRs** and each article's pull request is merged as soon as it opens: you already reviewed the article when you approved it. Leave it off to merge yourself.
:::

## Your repo, as it is

When you save the repository, Seovyn reads it: the framework (from `package.json` and config files), the folder your posts already live in, and how their frontmatter is written. Articles then go where your site already renders posts, in a form its build accepts. The **Content path** field says what it found; type a different path to override it.

| Your site | Where articles go | What changes |
|---|---|---|
| Astro (content collection) | `src/content/blog/{slug}.md` | The date is written as `pubDate`, which the collection's schema requires |
| Remix / React Router | `posts/{slug}.md` | The summary is written as `summary` if your posts use it |
| SvelteKit | `src/posts/{slug}.md` | `published: true` is added when your posts carry it |
| Nuxt Content, Eleventy | `content/blog/{slug}.md` | Nothing: the defaults match |
| Jekyll | `_posts/{date}-{slug}.md` | Named by date, as Jekyll requires; your posts' `layout` is copied |
| Hugo (page bundles) | `content/posts/{slug}/index.md` | |
| Next.js with its own posts folder | That folder | Seovyn doesn't add render routes, since your site already renders posts |

These are examples: Seovyn goes by the folder and fields your own posts use, not a fixed list.

### Sites of hand-written HTML

A site with no build step and no Markdown, just HTML pages, can't render a Markdown file. Seovyn writes each article as an HTML page instead, made from one of your existing posts: your head, header, footer, styles and scripts stay, and the title, description, canonical link, heading, date and article change. The same pull request adds the post to your blog's list page and home page (modelled on the entries already there) and to `sitemap.xml`.

## What's in each file

Each article is a Markdown file: frontmatter, then the body. Values are written as quoted strings and lists, so any static site generator can read them.

```markdown title="content/blog/how-to-warm-up-a-sending-domain.md"
---
title: "How to warm up a new sending domain"
slug: "how-to-warm-up-a-sending-domain"
description: "A day-by-day plan for building a new domain's reputation without landing in spam."
date: "2026-10-03T09:30:00.000Z"
type: "blog"
tags: ["deliverability", "email", "dns"]
metaTitle: "How to Warm Up a New Sending Domain (Day-by-Day Plan)"
metaDescription: "Warm up a new sending domain without hurting deliverability: daily volumes, what to monitor, and the mistakes that land mail in spam."
focusKeyword: "how to warm up a sending domain"
readingMinutes: 8
sources: ["https://…", "https://…"]
image: "https://…"
imageAlt: "How to warm up a new sending domain"
author: "Jane Doe"
---

Warming up a domain means…
```

`updated` is added when an article is refreshed. `sourceUrl` is added when the article came from a source. Fields with nothing to say are left out. The date, summary, tags and image use your posts' own names where they differ (above).

## Render routes for Next.js

Adding Markdown files isn't enough on its own: something has to *render* them, or the addresses return 404. When your repo already has posts, whatever renders them renders Seovyn's too. For a **Next.js App Router** site without them, Seovyn reads your repo (your layout, typography and navigation), generates matching page routes, opens a pull request, and merges it itself. It runs within a minute or two of saving the repo, and the **Render your content** card on Publishing shows its status. The routes include the cover image, breadcrumbs and structured data, and a sitemap.

> [!IMPORTANT] Only Next.js App Router is supported for this step
> On another framework with no posts yet, add a page that renders the content path's Markdown files (or add one post by hand, and Seovyn follows it), or use the [webhook](/docs/webhook-reference). If your branch is protected, Seovyn can't merge the render-routes pull request; merge it by hand.

## Updates and new links

A refreshed article, a new search snippet, or links added to older articles arrive as pull requests too, changing the existing files at the same paths. With auto-merge on, they merge the same way.

## Search engine indexing

Seovyn also commits a small key file (`public/{key}.txt`) directly to your base branch, so supporting search engines can be told about new pages. It's the one write that skips the pull request. See [Search engine indexing](/docs/indexnow).
