Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions .agents/skills/blog-authoring/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
name: blog-authoring
description: Use when creating, editing, previewing, or publishing blog posts through the local working-copy flow, especially when the task involves `content/blog`, `npm run blog:*` commands, or `/blog-preview/...` URLs.
---

# Neon Blog Authoring

Default editing workflow:

1. Work in the site repository.
2. Edit the local working copy under `content/blog/`.
3. Run the local site to visually inspect the result.
4. Publish the snapshot into the configured remote blog-content branch with the provided CLI.

Do not default to editing the remote source-of-truth repository directly unless the user explicitly asks for it.

## Required checks

Before changing content, verify the current state:

```bash
git branch --show-current
npm run blog:status
```

If `content/blog` is missing, initialize it:

```bash
npm run blog:bootstrap
```

If the user explicitly wants to refresh the working copy from remote state:

```bash
npm run blog:sync -- --force
```

## Core workflow

### 1. Edit locally

Edit only:

- `content/blog/posts/*.md`
- `content/blog/authors/data.json`
- `content/blog/categories/data.json`

Then run:

```bash
npm run dev
```

Use the local app to review:

- `/blog`
- `/blog/<slug>`

### 2. Publish to a branch in `blog`

Use the built-in CLI:

```bash
npm run blog:publish-branch -- --branch <branch-name>
```

Defaults:

- if `--branch` is omitted, the current git branch name is used
- the command pushes the current `content/blog` snapshot into the configured remote content repository
- the command prints preview URLs under `/blog-preview/...`

### 3. Review branch preview

Open the generated preview URL, for example:

```text
/blog-preview/<slug>?branch=<branch>&secret=<secret>
```

If the preview returns `404`, treat that as “access denied or missing branch/slug”. Do not assume the route is public.

## Guardrails

- Prefer `content/blog` in the current repository as the editing surface.
- Do not overwrite existing `content/blog` automatically; only use `blog:sync -- --force` when the user explicitly wants a refresh.
- Do not push to the main source-of-truth remote accidentally. If you must work in a separate source repo directly, inspect `git remote -v` first and confirm which remote is safe to push to.
- When credentials are missing, limit yourself to local editing and local preview; explain exactly which publish/preview actions are blocked.
- Do not touch unrelated local files such as `src/scripts/compare-sites.js`.

## References

Load only what you need:

- Commands and environment expectations: `references/commands.md`
76 changes: 76 additions & 0 deletions .agents/skills/blog-authoring/references/commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Commands

## Blog CLI

Run these from the site repository:

```bash
npm run blog:bootstrap
npm run blog:sync -- --force
npm run blog:status
npm run blog:publish-branch -- --branch <branch-name>
npm run dev
npm run build
```

Behavior:

- `blog:bootstrap`: materializes `content/blog` only if it is missing
- `blog:sync -- --force`: replaces the local working copy from the branch source or CDN
- `blog:status`: shows current branch, whether a matching branch exists in the configured `blog` repo, whether local content exists, and whether local content differs from remote
- `blog:publish-branch`: publishes the current `content/blog` snapshot into the configured `blog` repo branch and prints preview URLs

## Environment needed for publish / branch preview

Expected in env:

```bash
BLOG_CDN_URL=...
BLOG_REPO_OWNER=...
BLOG_REPO_NAME=...
BLOG_GITHUB_TOKEN=...
BLOG_PREVIEW_SECRET=...
```

Notes:

- `BLOG_GITHUB_TOKEN` is currently used for both branch fetches and `blog:publish-branch`, so it needs write access to the configured remote content repo.
- Without the repo credentials, local editing still works, but publishing and branch-aware remote fetches do not.

## Useful git checks

Current branch in `website`:

```bash
git branch --show-current
```

Remotes in a separate source repo:

```bash
git remote -v
```

Use this before pushing directly from a separate source repo. Prefer a personal/fork remote over the source-of-truth remote unless the user explicitly asks otherwise.

## Preview routes

Examples:

```text
/blog-preview/<slug>?branch=<branch>&secret=<secret>
```

Expected behavior:

- valid branch + valid secret -> preview page
- missing/invalid secret -> `404`
- missing branch or missing slug -> `404`

## Editing targets

Only edit these blog-content working copy files unless the user explicitly asks otherwise:

- `content/blog/posts/*.md`
- `content/blog/authors/data.json`
- `content/blog/categories/data.json`
29 changes: 24 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
NEXT_PUBLIC_DEFAULT_SITE_URL=http://localhost:3000

WP_GRAPHQL_URL=https://neondatabase.wpengine.com/graphql
WP_GRAPHQL_USER_AGENT=
WP_GRAPHQL_AUTH_TOKEN=
WP_PREVIEW_SECRET=

NEXT_PUBLIC_GITHUB_PATH=https://github.com/neondatabase/website/tree/main/

NEXT_PUBLIC_NEON_STATUS_API=https://7687492087503394.hostedstatus.com/1.0/status/6878fc85709daa75be6c7e3c
Expand All @@ -19,3 +14,27 @@ NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
GITHUB_APP_SECRET=
GITHUB_APP_CLIENT_ID=

DEPLOY_POSTGRES_DATABASE_URL=
DEPLOY_POSTGRES_NEON_API_KEY=
DEPLOY_POSTGRES_UPSTASH_REDIS_REST_URL=
DEPLOY_POSTGRES_UPSTASH_REDIS_REST_TOKEN=

NEON_BRANCHING_DEMO_PROJECT_ID=
NEON_BRANCHING_DEMO_PARENT_ID=
NEON_BRANCHING_DEMO_API_KEY=

NEON_BRANCHING_DEMO_DB_CONNECTION_STRING=
NEON_BRANCHING_DEMO_DB_PGHOST_DEFAULT=
NEON_BRANCHING_DEMO_DB_PGDATABASE="neondb"
NEON_BRANCHING_DEMO_DB_PGUSER="neondb_owner"
NEON_BRANCHING_DEMO_DB_PGPASSWORD=

NEON_BRANCHING_DEMO_QSTASH_TOKEN=
QSTASH_CURRENT_SIGNING_KEY=
QSTASH_NEXT_SIGNING_KEY=

BLOG_CDN_URL=
BLOG_REPO_OWNER=
BLOG_REPO_NAME=
BLOG_GITHUB_TOKEN=
BLOG_PREVIEW_SECRET=
1 change: 0 additions & 1 deletion .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ jobs:
wait-on: 'http://localhost:3000'
env:
NEXT_PUBLIC_DEFAULT_SITE_URL: http://localhost:3000
WP_GRAPHQL_URL: ${{ secrets.WP_GRAPHQL_URL }}
NEXT_PUBLIC_GITHUB_PATH: ${{ secrets.NEXT_PUBLIC_GITHUB_PATH }}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,6 @@ package-lock.json

# Evals directory (test validation for documentation)
.evals/
content/blog

# Blog content gets imported automatically
content/blog
Loading