> For the complete documentation index, see [llms.txt](https://suigar.gitbook.io/suigar-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://suigar.gitbook.io/suigar-docs/seo/subprojects/blog-site.md).

# Blog site

Last reviewed: 2026-07-13

Applies to `blog-site/`, the database-backed Next.js + Tailwind blog served under `/blog`.

## Current Anchors

* Blog URLs: `blog-site/src/lib/site-config.ts`.
* Global metadata: `blog-site/src/app/layout.tsx`.
* Post metadata and canonicals: `blog-site/src/app/posts/[slug]/page.tsx`.
* Sitemap: `blog-site/src/app/sitemap.ts`.
* Robots: `blog-site/src/app/robots.ts`.
* RSS/Atom feeds: `blog-site/src/app/rss.xml/route.ts`, `blog-site/src/app/atom.xml/route.ts`, and `blog-site/src/lib/blog-feed.ts`.
* On-demand revalidation: `blog-site/src/app/api/revalidate/route.ts` and `blog-site/src/lib/blog-revalidation.ts`.
* Runtime DB assets: `blog-site/src/app/assets/blog/db/[...path]/route.ts`.
* Runtime build verification: `blog-site/scripts/verify-runtime-build.mjs`.
* Content model: `blog-site/db/migrations/`.
* Content access and local fallback: `blog-site/src/lib/blog-content.ts`.

## Deployment Reality

The blog is now designed for a Next.js standalone runtime with ISR, not a static S3 export. Homepage, post pages, sitemap, RSS, and Atom use 60-second revalidation, and `/blog/api/revalidate/` can refresh the same surfaces immediately after a DB write.

Practical consequences:

* A published DB post can render on its own URL on first request when `dynamicParams` is enabled.
* Homepage, sitemap, RSS, and Atom discover the new post within 60 seconds, or immediately when the secured revalidation endpoint is called with the post slug.
* Database-backed images under `/assets/blog/db/*` are served by the runtime route, so new post images are not blocked by an old static asset export.
* The old S3 static deploy is retired for freshness-sensitive production publishing. Production must run the standalone Next server behind `/blog`; otherwise DB inserts will not be search-visible immediately.
* Local or scripted builds may set `NEXT_DIST_DIR` to isolate Next's build directory from a running dev server.

## Canonical Policy

* Mainnet canonical root: `https://suigar.com/blog`.
* Testnet root: `https://testnet.suigar.com/blog`.
* Testnet blog URLs must not compete with production content. Non-mainnet builds should emit root noindex metadata and blocking `robots.txt`.
* Non-mainnet blog sitemap output should contain no URL entries.
* Non-mainnet blog feed output should not advertise published posts, because feeds are also discovery surfaces.
* Post canonical URLs should use the trailing-slash shape currently generated by `blog-site/src/app/posts/[slug]/page.tsx`.
* The blog homepage canonical should use the trailing-slash `blogSiteUrl` root.
* The blog homepage should be the editorial hub, not a duplicate of the product homepage.

## Current Runtime State

Checked locally on 2026-05-28:

* `next build` emits a standalone server and 60-second ISR for homepage, post pages, sitemap, RSS, and Atom.
* `/blog/api/revalidate/` returns HTTP 401 without a valid secret and HTTP 200 with the expected revalidated paths when authorized.
* `/blog/sitemap.xml` lists only `https://suigar.com/blog/` and blog post URLs.
* `/blog/robots.txt` advertises only `https://suigar.com/sitemap_index.xml`.
* Blog sitemap entries include content-derived `lastmod` and omit ignored `changefreq`/`priority` hints.
* `/blog/rss.xml` and `/blog/atom.xml` include published post URLs on mainnet.
* `/blog/assets/blog/db/*` serves DB-backed image assets with image content types.
* Rendered homepage links no longer duplicate the base path as `/blog/blog/...`.

Production follow-up:

* The old S3 static deploy path is retired in CI.
* Live production still needs `/blog` routed to the standalone Next runtime before DB inserts become immediately visible to users and crawlers.

## Post Requirements

Every indexable post needs:

* Search intent: the problem, query family, or decision the reader has.
* Primary audience: player, affiliate, partner, Sui ecosystem reader, builder, liquidity participant, or existing Suigar user.
* Suigar angle: original product context, on-chain casino mechanics, launch detail, strategy, data, tutorial, or ecosystem perspective.
* Slug: short, descriptive, stable, lowercase, and readable.
* Title: specific and natural; no keyword stuffing.
* Excerpt and SEO description: clear promise of what the reader gets.
* Tags: useful for internal grouping, not a substitute for content structure.
* Author/context: visible enough to support trust.
* Internal links: relevant product and docs links when they help the reader act.
* Source/claim ledger: internal record for factual claims, dates, product state, odds, mechanics, and external references.
* Visible substance: enough original content that the page is useful without search traffic.

## Blog Index Requirements

The index page must stay useful even when the post list is empty:

* Keep the title below 60 characters after the Next title template is applied.
* Keep the meta description below 160 characters.
* Include one clear H1 for page structure; it may be visually hidden when the post list or empty state already carries the visible page context.
* Include RSS/Atom auto-discovery links in the rendered head.
* Include default Open Graph/Twitter image metadata.
* Include WebPage and BreadcrumbList JSON-LD.
* Do not add generic SEO filler to the blog index. Prefer real article cards and a concise empty state until posts exist.
* Keep non-mainnet builds `noindex`; do not remove testnet blocking just to satisfy a crawler audit.

## AI Blog Generation Rules

* Use `../blog-generation.md` before drafting.
* AI may generate briefs, outlines, drafts, metadata, link suggestions, and critique reports.
* AI must not publish mass low-value posts, trend-chasing posts without Suigar relevance, fake freshness, unsupported gambling/financial claims, repeated intros, or word-count-driven filler.
* Any new editorial constraint learned during review must be added to the constraint registry in `../blog-generation.md`.

## Sorank Publishing Webhook

* Endpoint: `POST /api/blog/webhooks/sorank` on the backend API host.
* Testnet URL: `https://testnet-api.suigar.com/api/blog/webhooks/sorank`.
* Mainnet URL: `https://mainnet-api.suigar.com/api/blog/webhooks/sorank`.
* Authentication: Sorank must send `Authorization: Bearer <SORANK_WEBHOOK_SECRET>`.
* `webhook.test` must return a 2xx response without creating a post.
* `article.published` writes or updates a `published` row in `blog_posts`, records `delivery_id` in `blog_webhook_deliveries`, and then attempts blog refresh.
* While `/blog/` is served by the edge snapshot, set `BLOG_PUBLISH_GITHUB_TOKEN` so the webhook can dispatch `blog-site.yaml` and refresh the HTML, RSS, Atom, and sitemap files after DB insertion.
* When the standalone blog runtime is the live serving layer, set `BLOG_REVALIDATION_SECRET` and keep `/blog/api/revalidate` available so the webhook can refresh ISR paths directly.

## Validation

Run for blog type/content-model/metadata changes:

```bash
pnpm --filter @suigar/blog-ui exec tsc -p tsconfig.typecheck.json --noEmit --incremental false
```

Use for rendering or runtime changes:

```bash
pnpm --filter @suigar/blog-ui run build
pnpm --filter @suigar/blog-ui run verify:runtime
node scripts/seo/check-live-sitemap-system.mjs
```

Manual SEO checks:

* Inspect rendered homepage and post metadata.
* Confirm sitemap includes intended published posts only.
* Confirm `rss.xml` and `atom.xml` are valid XML feeds with canonical blog URLs.
* Confirm rendered homepage HTML includes RSS/Atom feed auto-discovery links with `rel="alternate"` and the correct feed MIME types.
* Confirm `/api/revalidate/` rejects missing/incorrect secrets and refreshes homepage, post, sitemap, RSS, and Atom paths when authorized.
* Confirm a DB-backed image under `/assets/blog/db/*` returns the expected image content type from the runtime route.
* Confirm robots and root metadata do not create testnet/mainnet competition.
* Confirm the deployed `/blog` route reaches the standalone Next runtime, not the retired S3 static export.
* Check social previews for at least one homepage URL and one post URL.
* Review each generated post against the AI critique checklist.

## Next Improvements

* Wire the standalone runtime deployment and CloudFront/frontend `/blog` origin so production gets the ISR behavior already implemented in the app.
* Add `BlogPosting` structured data once visible author/date/image fields are consistently reliable.
* Add a post preflight script for required SEO fields, internal links, metadata length, and source ledger presence.
* Feed Search Console query/page performance into `../status.md` and `../optimization-log.md`.
