Skip to content

Rework website#130

Open
dannysmith wants to merge 25 commits into
mainfrom
rework-website
Open

Rework website#130
dannysmith wants to merge 25 commits into
mainfrom
rework-website

Conversation

@dannysmith

@dannysmith dannysmith commented Feb 17, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Public documentation website launched with a polished landing page, site layout/footer, release notes index, and many published release pages; custom domain, sitemap and robots support.
  • Documentation

    • Extensive user guides added: getting started, editor features, preferences, frontmatter, file management, MDX components, keyboard shortcuts, troubleshooting, and many release notes.
  • Chores

    • CI and deploy pipeline updated to build and publish the website artifacts reliably and generate release pages automatically.

@coderabbitai

coderabbitai Bot commented Feb 17, 2026

Copy link
Copy Markdown

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • AGENTS.md is excluded by !**/*.md

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 99c71678-4d48-48a6-a19f-f6a7acd0de6f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new Astro-based website under website/ (configs, build, pages, components, many MDX docs and release pages), CI workflow changes to build and publish the site (Bun-based steps, artifact/public folder), a release-page generator script, and updated gitignore / editor settings for website artifacts.

Changes

Cohort / File(s) Summary
CI Workflows
\.github/workflows/deploy-website.yml, \.github/workflows/publish-website-artifacts.yml
Add Bun setup and Bun-based install/build steps; change artifact paths to website/dist / website/public; add release-page generation, image localisation, and commit of public artifacts and generated MDX.
Root ignores & editor config
\.gitignore, \.vscode/settings.json
Ignore website build outputs (website/dist/, website/.astro/, website/node_modules/); map *.mdx to Markdown in VSCode.
Website project config & tooling
website/package.json, website/tsconfig.json, website/eslint.config.js, website/prettier.config.js, website/.prettierignore, website/.gitignore
New package manifest, TypeScript config and path aliases, per-site ESLint/Prettier configs, and ignore rules for site build artifacts.
Site config & integrations
website/astro.config.mjs
New Astro configuration with Starlight integration, site metadata, sidebar/navigation, head meta tags, and UI options.
Scripts & content tooling
website/scripts/generate-release-pages.ts, website/src/content.config.ts
New script to fetch/sanitize GitHub releases, download images, and emit MDX release pages; content collection config for docs with date coercion.
Pages, layouts & components
website/src/pages/index.astro, website/src/pages/releases/index.astro, website/src/layouts/Layout.astro, website/src/components/Footer.astro
Add landing page, releases index, global layout (SEO/meta/analytics), and footer component with props and styling.
Documentation content
website/src/content/docs/... (many *.mdx)
Add ~50+ documentation pages covering getting-started, editor features, editing, file-management, frontmatter reference, preferences, troubleshooting, references, and numerous release notes under docs/releases/.
Public assets
website/public/CNAME, website/public/robots.txt
Add custom domain CNAME and robots.txt with sitemap reference.
Misc
website/.gitignore, website/.prettierignore, website/tsconfig.json
Per-site ignore and formatting exclusions, plus TypeScript project settings and path aliases.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Better Updater #129 — Changes to .github/workflows/publish-website-artifacts.yml; directly related to the release-page generation and artifact commit flow added here.
  • Deps-2026-03-12 #153 — Updates root ESLint config to ignore the new website/ directory; coordinates with the new website/eslint.config.js.
  • Windows support #65 — Prior CI/workflow changes around website artifact handling; related to artifact copy/upload semantics modified in this PR.

Poem

🐇 I dug a doc burrow, tidy and bright,
new pages by day and builds in the night.
I boxed up the releases and fed them to CI,
then hopped to the deploy and gave a small cry.
Hooray — docs aglow, with crumbs of delight ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Rework website' is vague and generic, using non-descriptive phrasing that doesn't convey the specific changes made in this substantial changeset. Use a more specific title that highlights the primary change, such as 'Build Astro-based documentation site with Starlight' or 'Add comprehensive website and documentation infrastructure'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rework-website

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (16)
website/src/content/docs/releases/0.1.19.mdx-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Nit: "auto save" → "auto-save".

Per conventional compound-modifier hyphenation, "auto-save" is preferred here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.19.mdx` at line 9, Update the release
note string "Made auto save duration customisable" to use hyphenated
compound-modifier form by changing it to "Made auto-save duration customisable"
(search for the exact phrase "Made auto save duration customisable" in the
release text and replace it).
website/src/content/docs/releases/1.0.4.mdx-8-10 (1)

8-10: ⚠️ Potential issue | 🟡 Minor

#56 won't auto-link on the docs site.

Unlike on GitHub, the #56 issue reference in the rendered website will appear as plain text. Consider replacing it with a full markdown link if you want it clickable for website visitors, e.g. [#56](https://github.com/dannysmith/astro-editor/issues/56).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/1.0.4.mdx` around lines 8 - 10, Replace the
plain-text issue reference "#56" in the release notes with a full markdown link
so it becomes clickable on the docs site; update the string '#56' to a markdown
link like [`#56`](https://github.com/dannysmith/astro-editor/issues/56) in the
release text (the sentence referencing Windows or Linux users) so the rendered
site shows a clickable link.
website/src/content/docs/releases/0.1.29.mdx-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Incomplete sentence in release notes.

This bullet reads "Fixes a bug where boolean fields in sidebar." — the clause after "where" is truncated and doesn't describe what the bug actually was. If this was auto-generated from GitHub release notes, the source release body may need fixing too.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.29.mdx` at line 9, The release note
line "Fixes a bug where boolean fields in sidebar." is truncated—replace it with
a complete, clear sentence describing the actual bug and fix (e.g., "Fixes a bug
where boolean fields in the sidebar were displayed as empty values instead of
true/false" or the accurate reproduction from the commit/release body), update
the same string in website/src/content/docs/releases/0.1.29.mdx, and if this
came from an auto-generated GitHub release body, correct the source release text
so the change persists.
website/src/content/docs/releases/0.1.27.mdx-8-8 (1)

8-8: ⚠️ Potential issue | 🟡 Minor

Typo: duplicate "universal" in the sentence.

"now universal includes a universal binary" should read "now includes a universal binary".

Proposed fix
-The DMG now universal includes a universal binary which should work on both ARM and Intel-based machines. Previously only ARM binaries were included.
+The DMG now includes a universal binary which should work on both ARM and Intel-based machines. Previously only ARM binaries were included.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.27.mdx` at line 8, Fix the duplicated
word in the release note sentence by changing "now universal includes a
universal binary" to "now includes a universal binary"; locate the sentence
containing the phrase "now universal includes a universal binary" in the release
notes (0.1.27) and remove the extra "universal" so the sentence reads correctly.
website/src/content/docs/releases/0.1.24.mdx-9-10 (1)

9-10: ⚠️ Potential issue | 🟡 Minor

Typos in user-facing release notes.

  • Line 9: etcetc. (missing period)
  • Line 10: dependancydependency (misspelling)
✏️ Proposed fix
-- Constraints (character limits, min/max etc), default values and `.describe()` descriptions are now shown in the UI of the right sidebar.
-- Minor bugfixes and technical dependancy updates.
+- Constraints (character limits, min/max etc.), default values and `.describe()` descriptions are now shown in the UI of the right sidebar.
+- Minor bugfixes and technical dependency updates.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.24.mdx` around lines 9 - 10, Fix two
typos in the release notes: update the phrase "etc" to "etc." in the sentence
that mentions "Constraints (character limits, min/max etc)" and correct
"dependancy" to "dependency" in the second bullet so it reads "Minor bugfixes
and technical dependency updates." Make these exact textual replacements in the
file content of 0.1.24.mdx.
website/src/content/docs/releases/0.1.10.mdx-1-10 (1)

1-10: ⚠️ Potential issue | 🟡 Minor

Empty release body may look unfinished to users.

This page renders as just a horizontal rule and a GitHub link with no release content. Consider adding a brief note (e.g., "See the GitHub release for details.") so the page doesn't appear broken.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.10.mdx` around lines 1 - 10, The
release page for title 'v0.1.10' (slug 'releases/v0.1.10') currently renders
only a horizontal rule and the GitHub link; add a short release body under the
frontmatter (below the second '---')—for example a one-line note like "See the
GitHub release for details." or a brief summary of changes—so the page doesn't
appear empty while still linking to the GitHub release URL.
.github/workflows/publish-website-artifacts.yml-130-138 (1)

130-138: ⚠️ Potential issue | 🟡 Minor

Push to main without branch protection safeguards.

The workflow does git push origin main directly. If branch protection rules require PRs or status checks, this will fail. If they don't, concurrent releases could race on the rebase. A single retry or a check for push failure would improve reliability.

Also, if the commit on line 136 produces "No changes to commit", the subsequent git push is harmless but git pull --rebase on line 137 could still fail if there are conflicts from concurrent pushes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-website-artifacts.yml around lines 130 - 138, The
workflow currently always runs git pull --rebase and git push origin main even
when there was no commit and it pushes directly to main which can fail under
branch protection or race; change the step around the git commit/add to capture
the commit exit status and only attempt pull/push if a real commit was created,
and wrap pull/push in a small retry loop with safe push semantics. Concretely:
run git commit -m "..." and capture its exit code (or parse output) instead of
ignoring it; if commit succeeded (exit code 0) then run git pull --rebase origin
main with up to 3 retries on failure (sleep between attempts), then git push
using git push --force-with-lease or a retry loop to avoid clobbering concurrent
changes; if commit reported "No changes to commit" skip pull/push entirely. This
addresses the commands named in the diff: git add, git commit -m "...", git pull
--rebase origin main, and git push origin main.
website/src/content/docs/releases/0.1.31.mdx-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Typo: "Runnigh" → "Running".

-Generated JSON schemas are now **required** for schema fields to show in the sidebar. While `content.config.json` or `content/config.json` schemas are still parsed, they are now **only** used to enrich the generated JSON schemas. Runnigh `astro sync` or `astro dev` or `astro build` in your Astro project will auto-generate these schemas, so this should not negatively affect many users.
+Generated JSON schemas are now **required** for schema fields to show in the sidebar. While `content.config.json` or `content/config.json` schemas are still parsed, they are now **only** used to enrich the generated JSON schemas. Running `astro sync` or `astro dev` or `astro build` in your Astro project will auto-generate these schemas, so this should not negatively affect many users.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.31.mdx` at line 9, Fix the typo
"Runnigh" to "Running" in the release note sentence that starts with "Generated
JSON schemas are now **required**..." so the sentence reads "Running `astro
sync` or `astro dev` or `astro build`..."; update the word "Runnigh" to
"Running" in the document content entry (the release note text).
website/src/content/docs/releases/1.0.6.mdx-8-13 (1)

8-13: ⚠️ Potential issue | 🟡 Minor

First bullet item is not under any section heading.

The trailing-newline fix on line 8 appears to be a bugfix as well, but it sits above the ### Bugfixes heading. Consider moving it under that heading for consistency, or adding a separate heading above it if it's intentionally categorized differently.

Proposed fix
+### Bugfixes
 
 * Trailing newlines are no longer stripped from the end of files on save.
-
-### Bugfixes
-
 * Race condition fix during auto-save.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/1.0.6.mdx` around lines 8 - 13, The bullet
"* Trailing newlines are no longer stripped from the end of files on save."
should be moved under the existing "### Bugfixes" section for consistency; edit
the release notes so that this line is placed after the "### Bugfixes" heading
(or, if intentionally separate, add a short heading above it like "Other
changes") and ensure spacing/blank lines match surrounding markdown and bullet
formatting to keep the document consistent with the other items ("Race condition
fix..." and "Preserve cursor position...").
website/src/layouts/Layout.astro-8-8 (1)

8-8: ⚠️ Potential issue | 🟡 Minor

Default image fallback is the favicon — poor social sharing experience.

When image is not provided, og:image and twitter:image will be set to /favicon.png, which is typically a small icon unsuitable for social media cards (recommended ~1200×630px). Consider using a dedicated default OG image, or omitting the OG/Twitter image tags when no image is provided.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/layouts/Layout.astro` at line 8, The Layout.astro file currently
defaults image to '/favicon.png' via "const { title, description, image =
'/favicon.png' } = Astro.props", which leads to poor social cards; update this
by removing the favicon fallback and either (a) set a proper large default OG
image like '/og-default.png' or (b) leave image undefined and render the
og:image and twitter:image meta tags only when image is truthy—adjust the
conditional logic where og:image and twitter:image are output so it uses the new
default or omits the tags when image is not provided.
website/src/content/docs/releases/0.1.37.mdx-23-23 (1)

23-23: ⚠️ Potential issue | 🟡 Minor

Consider the tone for public-facing release notes.

Line 23 contains explicit language. This is a public documentation page — worth considering whether this aligns with the desired tone for the site.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.37.mdx` at line 23, The release notes
contain explicit language in the line "PS. I fucking love modern CSS ❤️"; update
that sentence to a professional, public-friendly variant (for example: "PS. I
love modern CSS ❤️" or "PS. I'm a big fan of modern CSS ❤️"), or remove the PS
entirely, and commit the change so the public-facing docs reflect the desired
tone; modify the string in website/src/content/docs/releases/0.1.37.mdx where
that exact text appears.
website/src/content/docs/privacy.mdx-8-8 (1)

8-8: ⚠️ Potential issue | 🟡 Minor

Stale "Last updated" date.

The policy says "February 2025" but it's being published in February 2026. Should this be updated to reflect the current date?

Proposed fix
-**Last updated:** February 2025
+**Last updated:** February 2026
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/privacy.mdx` at line 8, Update the stale date string
"**Last updated:** February 2025" in the privacy document to the correct
publication date (e.g., "**Last updated:** February 2026"); locate the exact
line containing the "**Last updated:** February 2025" token in
website/src/content/docs/privacy.mdx and replace the year so the displayed
last-updated date matches the current/final publication date.
website/src/content/docs/releases/1.0.9.mdx-10-11 (1)

10-11: ⚠️ Potential issue | 🟡 Minor

Minor text quality issues in release notes.

  • Line 10: etc)etc.) — period required for the abbreviation in American English.
  • Line 11: markdown link (appears twice) → Markdown link — "Markdown" is a proper noun.
📝 Proposed fix
-- The updater now shows release notes and provides more control over when and how to update (you can skip a version etc).
+- The updater now shows release notes and provides more control over when and how to update (you can skip a version etc.).
-- You can now search for other content items with `Cmd+Shift+K`. Pressing enter will open it in the editor. Pressing `Cmd+Enter` will insert a markdown link to the document under the cursor in the current doc. By default, it will insert a relative path to the markdown file which will probably need fixing in your code editor. You can override this behaviour on a per-collection basis in the preferences: If your astro site publishes `src/content/articles/foo.md` to `/writing/foo`, you can set the Articles URL setting to `/writing/{slug}` and the correct path will be used in the markdown link. This will use the target file's `slug` frontmatter fields (if it exists) or the filename without its extension.
+- You can now search for other content items with `Cmd+Shift+K`. Pressing enter will open it in the editor. Pressing `Cmd+Enter` will insert a Markdown link to the document under the cursor in the current doc. By default, it will insert a relative path to the Markdown file which will probably need fixing in your code editor. You can override this behaviour on a per-collection basis in the preferences: If your astro site publishes `src/content/articles/foo.md` to `/writing/foo`, you can set the Articles URL setting to `/writing/{slug}` and the correct path will be used in the Markdown link. This will use the target file's `slug` frontmatter fields (if it exists) or the filename without its extension.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/1.0.9.mdx` around lines 10 - 11, Update the
release notes text to fix minor style issues: change the abbreviation "etc)" to
"etc.)" and capitalize both occurrences of "markdown link" to "Markdown link"
(they appear in the sentence describing Cmd+Enter behavior and the following
sentence about relative paths). Locate these strings in the 1.0.9 release notes
content (the paragraph describing search and insert behavior) and make the two
exact replacements so punctuation and proper noun capitalization are corrected.
website/src/pages/index.astro-866-880 (1)

866-880: ⚠️ Potential issue | 🟡 Minor

Astro v5 Content Layer: code example uses the legacy type: "content" field.

The code snippet shown to users references type: "content" in the collection definition. In Astro v5, the type field was replaced by loader. Since the page promotes compatibility with "Astro 5+ projects" (line 827), the example should reflect the current API to avoid confusing new users.

As per coding guidelines, Legacy Content Collections are now deprecated and replaced by the Content Layer API. and The type field is replaced by loader.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/pages/index.astro` around lines 866 - 880, The example uses the
deprecated collection option type: "content"; update the snippet to use the
Astro v5 Content Layer API by replacing the type property with loader (e.g.,
change type: "content" to loader: "content") in the defineCollection call
(symbols: defineCollection, posts, collections, z) so the example reflects Astro
5+ usage and exports collections unchanged.
website/src/content/docs/releases/0.1.30.mdx-11-16 (1)

11-16: ⚠️ Potential issue | 🟡 Minor

Inconsistent indentation on nested list items.

Lines 12, 14–16 use 3-space indentation while line 13 uses 2-space indentation. This may cause the Markdown parser to render line 13 at a different nesting level than the other sub-items. Standardize to a consistent indent (e.g., 2 or 3 spaces).

Also on line 12, the phrase "the path (absolute relative to the project root)" reads awkwardly—consider rewording to something like "the absolute path (relative to the project root)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.30.mdx` around lines 11 - 16, Fix the
inconsistent list indentation in the release note by making all nested list
items under the "Astro's `image()` helper" bullet use the same indentation
(choose and apply 2-space indentation to lines mentioning image
dragging/selection, copying to assets, images added from *within* the astro
site, manual editing, previews, and nested `object()` behavior), and reword the
awkward phrase "the path (absolute relative to the project root)" to "the
absolute path (relative to the project root)" so the copied-assets sentence
reads clearly; locate these strings by searching for the bullet that starts with
"Fields which use Astro's `image()` helper" and adjust the subsequent
sub-bullets and the specific copied-assets sentence accordingly.
website/src/content/docs/releases/1.0.3.mdx-12-12 (1)

12-12: ⚠️ Potential issue | 🟡 Minor

Capitalize "Markdown" as a proper noun.

Line 12: "markdown" → "Markdown".

Proposed fix
-- Markers for inline formatting (eg bold, italic) are now subdued in the same way as other markdown syntax.
+- Markers for inline formatting (eg bold, italic) are now subdued in the same way as other Markdown syntax.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/1.0.3.mdx` at line 12, Update the release
note sentence "Markers for inline formatting (eg bold, italic) are now subdued
in the same way as other markdown syntax." by capitalizing the word "markdown"
to "Markdown" so it reads "...other Markdown syntax."; locate that exact
sentence in the 1.0.3 release notes and make the single-word change.
🧹 Nitpick comments (10)
website/src/content/docs/troubleshooting.mdx (1)

2-8: Optional: align description with “coming soon” messaging.

The page body says documentation is coming soon; consider reflecting that in the description to set expectations in listings and SEO.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/troubleshooting.mdx` around lines 2 - 8, The
frontmatter description currently reads 'Common issues and how to resolve them'
but the page body says documentation is coming soon; update the description
field to match the "coming soon" messaging (e.g., 'Documentation coming soon' or
'Content coming soon — troubleshooting guide forthcoming') so listings and SEO
reflect the page state; modify the description entry in the frontmatter (the
description key) to the new text while leaving the title and body intact.
website/src/content/docs/releases/0.1.9.mdx (1)

7-10: Empty release body produces a lonely horizontal rule.

This release page has no descriptive content — just an <hr> followed by the GitHub link. This is likely auto-generated from a GitHub release with an empty body. Consider having the generation script either skip the --- separator when the body is empty, or add a fallback message like "No release notes available."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.9.mdx` around lines 7 - 10, The release
page contains only a horizontal rule ('---') then the GitHub link because the
generator always emits the separator even when the release body is empty; update
the release-generation logic to check the release body (e.g., release.body or
body) and if it's blank/whitespace skip outputting the '---' separator and
instead either emit a fallback line like "No release notes available." or omit
the body block entirely; ensure the check trims whitespace (body?.trim()) before
deciding.
website/package.json (1)

15-15: The check script hardcodes bun run, coupling it to Bun.

While CI uses Bun (per the summary), developers using npm or pnpm locally would hit issues. Consider using a generic runner or documenting the Bun requirement.

-    "check": "astro check && tsc --noEmit && bun run lint && bun run format:check",
+    "check": "astro check && tsc --noEmit && npm run lint && npm run format:check",

Alternatively, if Bun is the canonical runtime, add an engines field to make that explicit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/package.json` at line 15, The "check" npm script currently hardcodes
"bun run" making it fail for non-Bun runtimes; update the "check" script in
package.json (script name: "check") to use a generic runner (e.g., "npm run" or
"pnpm run" equivalents) so it works across package managers, or if Bun is
required, add an "engines" field to package.json declaring "bun" as the required
runtime (and document this in README/CI notes) so developers are aware; pick one
approach and apply it consistently to the "check" script and any other scripts
that use "bun run".
website/scripts/generate-release-pages.ts (2)

169-175: Sequential execSync for each release body is slow and has a minor injection risk.

Each release body is fetched one-by-one synchronously, which will be slow for many releases. More importantly, release.tagName is interpolated directly into a shell command string. While GitHub tag names are unlikely to contain shell metacharacters, this is a command injection vector in principle.

Consider using --json body in the initial gh release list call to fetch everything in one request, or at minimum use execFileSync to avoid shell interpretation:

Safer alternative using execFileSync
+import { execSync, execFileSync } from 'node:child_process'
-import { execSync } from 'node:child_process'
   for (const release of releases) {
-    const body = execSync(
-      `gh release view "${release.tagName}" --repo ${REPO} --json body -q .body`,
-      { encoding: 'utf-8' }
-    )
+    const body = execFileSync(
+      'gh',
+      ['release', 'view', release.tagName, '--repo', REPO, '--json', 'body', '-q', '.body'],
+      { encoding: 'utf-8' }
+    )
     release.body = body
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 169 - 175, The loop
that calls execSync per release using a shell-interpolated tagName (releases,
execSync, release.tagName, REPO) is slow and allows command-injection; fix by
updating the initial gh release listing to request bodies in one JSON call (use
--json body when calling gh release list) so release.body is populated up-front,
or if you must fetch per-release, replace execSync with execFileSync/execFile
and pass the args array (e.g., ['release','view', release.tagName, '--repo',
REPO, '--json', 'body', '-q', '.body']) to avoid shell interpretation and
consider running requests concurrently instead of sequentially.

33-38: isPost1_0 always returns true for major === 1 regardless of minor/patch.

The condition major === 1 && minor >= 0 is always true when major is 1, since minor from a semver parse is never negative. This is equivalent to major >= 1. If the intent is genuinely "version >= 1.0.0", the logic is correct — but the minor >= 0 check is redundant and slightly misleading.

Simplify
 function isPost1_0(tag: string): boolean {
   const match = tag.match(/^v?(\d+)\.(\d+)\.(\d+)/)
   if (!match) return false
-  const [, major, minor] = match.map(Number)
-  return major > 1 || (major === 1 && minor >= 0)
+  const [, major] = match.map(Number)
+  return major >= 1
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 33 - 38, The
isPost1_0 function's condition `major === 1 && minor >= 0` is redundant because
minor is never negative; replace the final return with a clear check for version
>= 1.0.0 (e.g., `return major >= 1`) to simplify intent; keep the existing tag
parsing (the match and the destructured major/minor variables) but change the
return expression in isPost1_0 to `major >= 1` so the logic is correct and less
misleading.
website/astro.config.mjs (1)

50-56: Consider privacy/GDPR compliance for the analytics script.

The Simple Analytics script is injected globally via head. While Simple Analytics is privacy-focused by design, verify that this meets your compliance requirements (e.g., cookie banners, GDPR notice) for all regions where the site is served.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/astro.config.mjs` around lines 50 - 56, The global injection of the
Simple Analytics script (the object with tag: 'script' and attrs including src:
'https://scripts.simpleanalyticscdn.com/latest.js') should be made conditional
on user consent to meet privacy/GDPR requirements: modify the head injection to
load the script only after explicit consent (e.g., via your cookie-consent
component/event), or replace the direct src injection with a small consent-aware
loader that checks consent state and then appends the script element
dynamically, or provide an opt-out flag that prevents adding that script when
consent is not granted; ensure the change references the existing script object
(tag: 'script', attrs.src) so it’s the same asset being loaded conditionally.
.github/workflows/deploy-website.yml (1)

31-40: Consider pinning a Bun version for reproducible builds.

oven-sh/setup-bun@v2 without a bun-version input will use the latest stable Bun release, which could change between runs. For reproducibility, consider pinning:

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2
        with:
          bun-version: '1.x'  # or a specific version
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-website.yml around lines 31 - 40, The GitHub
Actions workflow step "Setup Bun" currently uses oven-sh/setup-bun@v2 with no
version pinned; update that step (the action referenced as oven-sh/setup-bun@v2
in the "Setup Bun" step) to include a with: bun-version input and set it to a
stable version or range (e.g., a specific version like "1.4.0" or a major range
like "1.x") so builds are reproducible across runs; keep the rest of the steps
(Install dependencies and Build website) unchanged.
.github/workflows/publish-website-artifacts.yml (1)

72-128: The shell-based MDX sanitization is fragile and hard to maintain.

The inline awk + sed pipeline for escaping curly braces, stripping sections, etc., is clever but will be difficult to debug or extend. A few specific concerns:

  1. The backtick tracking (line 95) only handles single-backtick inline code. Double-backtick spans (`code` style) will not be detected correctly, potentially escaping braces inside inline code.
  2. If a release body contains the MDX frontmatter delimiter --- on its own line, it could break the generated MDX structure.

The PR summary mentions a dedicated TypeScript script at website/scripts/generate-release-pages.ts — consider using that here instead of duplicating logic in shell, or at minimum add a comment explaining why the shell approach is used in the workflow.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-website-artifacts.yml around lines 72 - 128, The
workflow's shell-based MDX sanitization (CLEAN_BODY using awk/sed in the
"Generate release page" step) is fragile: it mis-tracks code spans (only toggles
on single backticks so multi-backtick code blocks can be mishandled) and can be
broken by literal frontmatter delimiters ('---') in RELEASE_BODY; replace this
inline pipeline by invoking the existing TypeScript utility
(website/scripts/generate-release-pages.ts) to produce the MDX, or if you must
keep shell, add a clear comment and harden CLEAN_BODY to (a) use the TypeScript
script via node to sanitize/escape braces and strip sections consistently, and
(b) ensure it detects fenced code blocks and multi-backtick inline code and
escapes or preserves any '---' frontmatter lines so the generated MDX file
headers (the printf '---' blocks) cannot be corrupted.
website/src/content/docs/getting-started/opening-a-project.mdx (1)

1-8: Stub page — consider a TODO or tracking issue.

This is purely placeholder content. If it will be published to production, users may land on it expecting documentation. Consider either hiding it from navigation until content is ready, or tracking the content work in an issue.

Would you like me to open an issue to track writing the documentation for this page?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/getting-started/opening-a-project.mdx` around lines
1 - 8, This page is a placeholder and should not be published as-is; either add
a clear TODO/tracking link or hide it from navigation until filled. Update the
document with a visible TODO banner and a link to a GitHub issue (or create and
reference a new issue) in the content of the "title: 'Opening a Project'" MDX
file, or remove it from the site nav/config so it won't appear in production;
ensure the change references the "Opening a Project" page so reviewers can find
and complete the tracking issue.
website/src/pages/index.astro (1)

933-942: Render the copyright year at build time instead of client-side.

The <span id="year"> is empty until the inline script runs, causing a brief flash of missing text. Since this is an Astro page, you can compute the year server-side in the frontmatter and avoid the client-side script entirely.

Proposed fix

In the frontmatter (lines 1–3):

 ---
 import Layout from '@layouts/Layout.astro'
+const year = new Date().getFullYear()
 ---

In the footer (lines 933–935):

-          <p class="text-xs text-white/50">
-            &copy; <span id="year"></span> Danny Smith
-          </p>
+          <p class="text-xs text-white/50">
+            &copy; {year} Danny Smith
+          </p>

Then remove the inline script at lines 940–942.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/pages/index.astro` around lines 933 - 942, Compute the year at
build time in the Astro frontmatter (e.g., add a const like year = new
Date().getFullYear() in the top-level frontmatter) and replace the client-side
span that uses id="year" with the server-rendered value (inject the frontmatter
variable into the footer markup instead of leaving <span id="year"></span>),
then remove the inline script that calls
document.getElementById('year').textContent and the script tag with is:inline so
the year is rendered server-side and no client script is needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/publish-website-artifacts.yml:
- Around line 44-70: The workflow step "Copy artifacts to website public folder"
currently copies large binaries (DMG_FILE, MSI_FILE, APPIMAGE_FILE) into the
repo which will bloat git history; instead modify this step to stop committing
installer files and upload them to a release or external storage: replace
copying into website/public with an upload action (e.g., GitHub Releases upload
or S3/R2 upload) that publishes DMG/MSI/AppImage as release assets or to object
storage, then update the site to link/redirect to those hosted URLs (or opt into
Git LFS if you must store in the repo); ensure the step that currently sets
DMG_FILE/MSI_FILE/APPIMAGE_FILE instead calls the appropriate upload action and
writes the external URLs into the website build metadata rather than committing
the binaries into website/public.

In `@website/package.json`:
- Line 24: The package.json pins "zod" at "3.25.76", which is unnecessary and
problematic; remove the direct "zod" dependency (since content.config.ts imports
z via "astro:content"/Astro's re-export) or if other code truly requires zod,
upgrade the package to a compatible v4 (e.g., 4.3.6) and change imports to
import from "zod" directly where used; update package.json to remove or bump
"zod" and ensure any files (notably content.config.ts) keep using import { z }
from "astro:content" or are adjusted to import from "zod" after the upgrade.

In `@website/public/robots.txt`:
- Around line 1-4: The robots.txt references a sitemap at
https://astroeditor.danny.is/sitemap-index.xml but the project lacks the
`@astrojs/sitemap` integration; either add the integration to astro.config.mjs
(register the `@astrojs/sitemap` integration so it generates sitemap-index.xml at
build) or remove the "Sitemap: https://astroeditor.danny.is/sitemap-index.xml"
line from website/public/robots.txt to avoid a broken reference; update
astro.config.mjs to import and include the sitemap integration if you choose the
first option.

In `@website/src/pages/index.astro`:
- Around line 23-67: Replace the in-page Tailwind Play CDN usage: remove the
<script is:inline src="https://cdn.tailwindcss.com"></script> and the inline
tailwind.config assignment in index.astro, install Tailwind as a project
dependency and add the official Astro integration or Vite plugin (e.g.,
`@astrojs/tailwind`), move the theme/customization object into a root Tailwind
config file (tailwind.config.js) and import Tailwind via your global CSS entry
so styles are generated at build time, and update astro.config/mjs to enable the
integration; ensure the page no longer relies on the CDN script or inline
tailwind.config.

In `@website/src/pages/releases/index.astro`:
- Line 37: The link URL is built from release.data.title but should use the
canonical slug; update the anchor href in the releases listing to use
release.data.slug instead of release.data.title (leave the link text as
release.data.title if desired), e.g. modify the <a href={...}> construction that
currently uses release.data.title so it references release.data.slug to ensure
stable routing.

---

Nitpick comments:
In @.github/workflows/deploy-website.yml:
- Around line 31-40: The GitHub Actions workflow step "Setup Bun" currently uses
oven-sh/setup-bun@v2 with no version pinned; update that step (the action
referenced as oven-sh/setup-bun@v2 in the "Setup Bun" step) to include a with:
bun-version input and set it to a stable version or range (e.g., a specific
version like "1.4.0" or a major range like "1.x") so builds are reproducible
across runs; keep the rest of the steps (Install dependencies and Build website)
unchanged.

In @.github/workflows/publish-website-artifacts.yml:
- Around line 72-128: The workflow's shell-based MDX sanitization (CLEAN_BODY
using awk/sed in the "Generate release page" step) is fragile: it mis-tracks
code spans (only toggles on single backticks so multi-backtick code blocks can
be mishandled) and can be broken by literal frontmatter delimiters ('---') in
RELEASE_BODY; replace this inline pipeline by invoking the existing TypeScript
utility (website/scripts/generate-release-pages.ts) to produce the MDX, or if
you must keep shell, add a clear comment and harden CLEAN_BODY to (a) use the
TypeScript script via node to sanitize/escape braces and strip sections
consistently, and (b) ensure it detects fenced code blocks and multi-backtick
inline code and escapes or preserves any '---' frontmatter lines so the
generated MDX file headers (the printf '---' blocks) cannot be corrupted.

In `@website/astro.config.mjs`:
- Around line 50-56: The global injection of the Simple Analytics script (the
object with tag: 'script' and attrs including src:
'https://scripts.simpleanalyticscdn.com/latest.js') should be made conditional
on user consent to meet privacy/GDPR requirements: modify the head injection to
load the script only after explicit consent (e.g., via your cookie-consent
component/event), or replace the direct src injection with a small consent-aware
loader that checks consent state and then appends the script element
dynamically, or provide an opt-out flag that prevents adding that script when
consent is not granted; ensure the change references the existing script object
(tag: 'script', attrs.src) so it’s the same asset being loaded conditionally.

In `@website/package.json`:
- Line 15: The "check" npm script currently hardcodes "bun run" making it fail
for non-Bun runtimes; update the "check" script in package.json (script name:
"check") to use a generic runner (e.g., "npm run" or "pnpm run" equivalents) so
it works across package managers, or if Bun is required, add an "engines" field
to package.json declaring "bun" as the required runtime (and document this in
README/CI notes) so developers are aware; pick one approach and apply it
consistently to the "check" script and any other scripts that use "bun run".

In `@website/scripts/generate-release-pages.ts`:
- Around line 169-175: The loop that calls execSync per release using a
shell-interpolated tagName (releases, execSync, release.tagName, REPO) is slow
and allows command-injection; fix by updating the initial gh release listing to
request bodies in one JSON call (use --json body when calling gh release list)
so release.body is populated up-front, or if you must fetch per-release, replace
execSync with execFileSync/execFile and pass the args array (e.g.,
['release','view', release.tagName, '--repo', REPO, '--json', 'body', '-q',
'.body']) to avoid shell interpretation and consider running requests
concurrently instead of sequentially.
- Around line 33-38: The isPost1_0 function's condition `major === 1 && minor >=
0` is redundant because minor is never negative; replace the final return with a
clear check for version >= 1.0.0 (e.g., `return major >= 1`) to simplify intent;
keep the existing tag parsing (the match and the destructured major/minor
variables) but change the return expression in isPost1_0 to `major >= 1` so the
logic is correct and less misleading.

In `@website/src/content/docs/getting-started/opening-a-project.mdx`:
- Around line 1-8: This page is a placeholder and should not be published as-is;
either add a clear TODO/tracking link or hide it from navigation until filled.
Update the document with a visible TODO banner and a link to a GitHub issue (or
create and reference a new issue) in the content of the "title: 'Opening a
Project'" MDX file, or remove it from the site nav/config so it won't appear in
production; ensure the change references the "Opening a Project" page so
reviewers can find and complete the tracking issue.

In `@website/src/content/docs/releases/0.1.9.mdx`:
- Around line 7-10: The release page contains only a horizontal rule ('---')
then the GitHub link because the generator always emits the separator even when
the release body is empty; update the release-generation logic to check the
release body (e.g., release.body or body) and if it's blank/whitespace skip
outputting the '---' separator and instead either emit a fallback line like "No
release notes available." or omit the body block entirely; ensure the check
trims whitespace (body?.trim()) before deciding.

In `@website/src/content/docs/troubleshooting.mdx`:
- Around line 2-8: The frontmatter description currently reads 'Common issues
and how to resolve them' but the page body says documentation is coming soon;
update the description field to match the "coming soon" messaging (e.g.,
'Documentation coming soon' or 'Content coming soon — troubleshooting guide
forthcoming') so listings and SEO reflect the page state; modify the description
entry in the frontmatter (the description key) to the new text while leaving the
title and body intact.

In `@website/src/pages/index.astro`:
- Around line 933-942: Compute the year at build time in the Astro frontmatter
(e.g., add a const like year = new Date().getFullYear() in the top-level
frontmatter) and replace the client-side span that uses id="year" with the
server-rendered value (inject the frontmatter variable into the footer markup
instead of leaving <span id="year"></span>), then remove the inline script that
calls document.getElementById('year').textContent and the script tag with
is:inline so the year is rendered server-side and no client script is needed.

Comment thread .github/workflows/publish-website-artifacts.yml
Comment thread website/package.json
Comment thread website/public/robots.txt
Comment thread website/src/pages/index.astro
Comment thread website/src/pages/releases/index.astro Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (17)
website/src/content/docs/philosophy.mdx-1-8 (1)

1-8: ⚠️ Potential issue | 🟡 Minor

Consider completing the documentation or marking as draft.

This page is currently a placeholder with no actual content. When users navigate to the Philosophy page, they'll only see "Documentation is coming soon," which may create a suboptimal experience.

Consider one of the following approaches:

  • Complete the philosophy documentation before merging this PR
  • Use Starlight's draft: true frontmatter flag to hide this page from navigation until it's ready
  • Remove this page entirely and add it in a future PR when the content is prepared
📝 Example: Mark as draft
 ---
 title: 'Philosophy'
 description: 'Why Astro Editor exists and the core principles behind it'
+draft: true
 ---
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/philosophy.mdx` around lines 1 - 8, This page is a
placeholder; either complete the Philosophy content or hide it as a draft before
merging: update the frontmatter (title/description) in
website/src/content/docs/philosophy.mdx to include Starlight's draft: true flag
(e.g., add draft: true to the YAML frontmatter) so it is excluded from
navigation, or replace the placeholder body ("Documentation is coming soon.")
with the full philosophical content; ensure you modify the existing frontmatter
and the page body (not a new file) and remove the temporary placeholder if you
publish content.
website/src/content/docs/releases/0.1.27.mdx-8-8 (1)

8-8: ⚠️ Potential issue | 🟡 Minor

Typo: stray "universal" in the sentence.

"The DMG now universal includes a universal binary" has an extra "universal". Should read: "The DMG now includes a universal binary…"

✏️ Proposed fix
-The DMG now universal includes a universal binary which should work on both ARM and Intel-based machines. Previously only ARM binaries were included.
+The DMG now includes a universal binary which should work on both ARM and Intel-based machines. Previously only ARM binaries were included.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.27.mdx` at line 8, There is a
duplicated word in the release note sentence "The DMG now universal includes a
universal binary…"; open website/src/content/docs/releases/0.1.27.mdx, locate
that exact sentence, and remove the stray "universal" so it reads "The DMG now
includes a universal binary which should work on both ARM and Intel-based
machines." Also scan the same paragraph for any other duplicated words and fix
if present.
website/src/content/docs/releases/1.0.4.mdx-8-10 (1)

8-10: ⚠️ Potential issue | 🟡 Minor

Minor text issues: capitalize "Windows" and consider linking the issue reference.

Line 8: "windows" → "Windows" (proper noun).
Line 10: #56 is a bare reference — consider making it a clickable link for readers.

Proposed fix
-Untested builds for windows and Linux are included in this build. macOS Users should see no change in behaviour, though there has been significant refactoring under-the-hood to cater for multi-platform support.
+Untested builds for Windows and Linux are included in this build. macOS users should see no change in behaviour, though there has been significant refactoring under-the-hood to cater for multi-platform support.
 
-If you are encountering new bugs on macOS, please report as usual. If you are a Windows or Linux user, please test the builds out and report any bugs in `#56` to begin with. 🙏
+If you are encountering new bugs on macOS, please report as usual. If you are a Windows or Linux user, please test the builds out and report any bugs in [`#56`](https://github.com/dannysmith/astro-editor/issues/56) to begin with. 🙏
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/1.0.4.mdx` around lines 8 - 10, In the
release note paragraph starting "Untested builds for windows and Linux...", fix
the casing of "windows" to "Windows" and replace the bare issue reference `#56`
with a clickable Markdown link (e.g. `[`#56`](/issues/56)` or a full GitHub issues
URL) so readers can navigate directly to the issue; update the sentence that
mentions Windows/Linux and the trailing "...report any bugs in `#56` to begin
with." accordingly.
website/src/content/docs/releases/0.1.37.mdx-23-23 (1)

23-23: ⚠️ Potential issue | 🟡 Minor

Consider the tone for public-facing documentation.

Line 23 contains informal language with profanity. If this documentation site is customer/user-facing, you may want to soften this line.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.37.mdx` at line 23, The PS line
contains profanity and should be softened or removed for public-facing docs:
locate the line that reads "PS. I fucking love modern CSS ❤️" and replace it
with a neutral, professional alternative (e.g., "PS. I love modern CSS ❤️" or
"PS. Modern CSS is great!") or remove the PS entirely to maintain an appropriate
tone for users.
website/src/content/docs/releases/1.0.9.mdx-10-11 (1)

10-11: ⚠️ Potential issue | 🟡 Minor

Minor text issues in user-facing release notes.

  • Line 10: etcetc. (period required for the abbreviation).
  • Line 11: markdownMarkdown (proper noun, appears twice).
  • Line 13: BugFixesBug Fixes (space between words for consistency with standard section headings).
✏️ Suggested fixes
-- The updater now shows release notes and provides more control over when and how to update (you can skip a version etc).
-- You can now search for other content items with `Cmd+Shift+K`. Pressing enter will open it in the editor. Pressing `Cmd+Enter` will insert a markdown link to the document under the cursor in the current doc. By default, it will insert a relative path to the markdown file which will probably need fixing in your code editor. You can override this behaviour on a per-collection basis in the preferences: If your astro site publishes `src/content/articles/foo.md` to `/writing/foo`, you can set the Articles URL setting to `/writing/{slug}` and the correct path will be used in the markdown link. This will use the target file's `slug` frontmatter fields (if it exists) or the filename without its extension.
+- The updater now shows release notes and provides more control over when and how to update (you can skip a version etc.).
+- You can now search for other content items with `Cmd+Shift+K`. Pressing enter will open it in the editor. Pressing `Cmd+Enter` will insert a Markdown link to the document under the cursor in the current doc. By default, it will insert a relative path to the Markdown file which will probably need fixing in your code editor. You can override this behaviour on a per-collection basis in the preferences: If your astro site publishes `src/content/articles/foo.md` to `/writing/foo`, you can set the Articles URL setting to `/writing/{slug}` and the correct path will be used in the Markdown link. This will use the target file's `slug` frontmatter fields (if it exists) or the filename without its extension.
 
-### BugFixes
+### Bug Fixes
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/1.0.9.mdx` around lines 10 - 11, Update the
release notes text: change "etc" to "etc." in the updater sentence; capitalize
"markdown" to "Markdown" for both occurrences in the search/insert paragraph
(the instances around "insert a markdown link" and "path to the markdown file");
and rename the section heading "BugFixes" to "Bug Fixes" so spacing is
consistent with other headings. Ensure only the textual tokens are edited and
punctuation/capitalization matches the surrounding sentences.
website/src/content/docs/releases/0.1.31.mdx-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Typo: "Runnigh" → "Running".

Proposed fix
-Generated JSON schemas are now **required** for schema fields to show in the sidebar. While `content.config.json` or `content/config.json` schemas are still parsed, they are now **only** used to enrich the generated JSON schemas. Runnigh `astro sync` or `astro dev` or `astro build` in your Astro project will auto-generate these schemas, so this should not negatively affect many users.
+Generated JSON schemas are now **required** for schema fields to show in the sidebar. While `content.config.json` or `content/config.json` schemas are still parsed, they are now **only** used to enrich the generated JSON schemas. Running `astro sync` or `astro dev` or `astro build` in your Astro project will auto-generate these schemas, so this should not negatively affect many users.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.31.mdx` at line 9, Fix the typo
"Runnigh" to "Running" in the release notes sentence that starts with "Runnigh
`astro sync` or `astro dev` or `astro build`..." so the text reads "Running
`astro sync` or `astro dev` or `astro build` in your Astro project will
auto-generate these schemas...". Update the string in the release notes content
where the misspelled token "Runnigh" appears.
website/src/content/docs/releases/1.0.3.mdx-12-12 (1)

12-12: ⚠️ Potential issue | 🟡 Minor

Capitalize "Markdown" as a proper noun.

"markdown" should be "Markdown" since it refers to the markup language by name.

Proposed fix
-- Markers for inline formatting (eg bold, italic) are now subdued in the same way as other markdown syntax.
+- Markers for inline formatting (eg bold, italic) are now subdued in the same way as other Markdown syntax.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/1.0.3.mdx` at line 12, Update the sentence
that currently reads "Markers for inline formatting (eg bold, italic) are now
subdued in the same way as other markdown syntax." to capitalize Markdown as a
proper noun: change "markdown" to "Markdown" in that sentence (the line
containing "Markers for inline formatting (eg bold, italic)...") so it reads
"...the same way as other Markdown syntax."
website/src/content/docs/releases/0.1.30.mdx-10-16 (1)

10-16: ⚠️ Potential issue | 🟡 Minor

Typo: "project route" should likely be "project root" (lines 10 and 15).

Both occurrences refer to file paths relative to the project's root directory, not a route.

Also, the nested list items have inconsistent indentation (mix of 2-space and 3-space), which may cause rendering issues in some Markdown parsers.

Proposed fix
-- Holding option/alt when hovering over an image URL or path in the editor shows a preview in the bottom right. This works for remote images (ie a URL), absolute paths relative to the Astro project route, and relative paths. Relative paths may not work reliably for unusual or complex Astro folder structures.
+- Holding option/alt when hovering over an image URL or path in the editor shows a preview in the bottom right. This works for remote images (ie a URL), absolute paths relative to the Astro project root, and relative paths. Relative paths may not work reliably for unusual or complex Astro folder structures.
-   - Image previews support remote images (ie a URL), absolute paths relative to the Astro project route, and relative paths. Relative paths may not work reliably for unusual or complex Astro folder structures.
+   - Image previews support remote images (ie a URL), absolute paths relative to the Astro project root, and relative paths. Relative paths may not work reliably for unusual or complex Astro folder structures.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.30.mdx` around lines 10 - 16, Replace
the incorrect phrase "project route" with "project root" in both sentences that
mention image preview/paths (the lines starting "Holding option/alt when
hovering over an image URL or path in the editor shows a preview..." and "Image
previews support remote images (ie a URL), absolute paths relative to the Astro
project route, and relative paths."); also normalize the nested list indentation
so all sub-list lines use a consistent spacing (e.g., 2 spaces) to avoid
Markdown rendering issues (check the lines under "Fields which use Astro's
`image()` helper..." and the subsequent bullet points).
website/src/content/docs/releases/0.1.29.mdx-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Incomplete sentence in release notes.

"Fixes a bug where boolean fields in sidebar." appears truncated — it's missing the rest of the clause describing what the bug actually was (e.g., "…were not displayed correctly" or similar).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.29.mdx` at line 9, The release note
sentence "Fixes a bug where boolean fields in sidebar." is incomplete; update
the sentence in the 0.1.29 release notes (the line containing that phrase) to
complete the clause and clarify the fix, e.g., "Fixes a bug where boolean fields
in the sidebar were not displayed correctly" or "Fixes a bug where boolean
fields in the sidebar failed to render their values"; choose the wording that
accurately reflects the fix and replace the truncated sentence accordingly.
website/src/content/docs/releases/0.1.24.mdx-10-10 (1)

10-10: ⚠️ Potential issue | 🟡 Minor

Typo: "dependancy" → "dependency".

-- Minor bugfixes and technical dependancy updates.
+- Minor bugfixes and technical dependency updates.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.24.mdx` at line 10, Replace the
misspelled word "dependancy" with the correct spelling "dependency" in the
release note string ("Minor bugfixes and technical dependancy updates.") so the
line reads "Minor bugfixes and technical dependency updates."; search for the
exact token "dependancy" in the 0.1.24 release MDX content to update it.
website/src/content/docs/releases/0.1.19.mdx-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Minor: "auto save" → "auto-save".

Hyphenate the compound modifier for correctness in user-facing text.

-- Made auto save duration customisable
+- Made auto-save duration customisable
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.19.mdx` at line 9, Replace the phrase
"Made auto save duration customisable" with "Made auto-save duration
customisable" in the release note (update the compound modifier to use a hyphen)
so the user-facing text correctly hyphenates "auto-save".
website/src/pages/index.astro-865-880 (1)

865-880: ⚠️ Potential issue | 🟡 Minor

Code example shows Astro v4 type: "content" syntax.

Since this product targets Astro 5+ projects (line 827: "Point to any Astro 5+ project"), the showcase schema example should use the Astro 5 Content Layer API (loader instead of type: "content"). As per coding guidelines from the Astro v5 library documentation: "The type field is replaced by loader."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/pages/index.astro` around lines 865 - 880, The example uses the
old Astro v4 `type: "content"` syntax; update the defineCollection call for
`posts` to use the Astro v5 Content Layer API by replacing the `type: "content"`
property with `loader: "content"` (keep `defineCollection`, the `schema` object,
and `export const collections = { posts }` unchanged) so the snippet reflects
Astro 5+ usage.
website/src/content/docs/privacy.mdx-8-8 (1)

8-8: ⚠️ Potential issue | 🟡 Minor

"Last updated" date appears stale.

The policy says "February 2025" but this PR is being created in February 2026. If this is a new policy being published now, update the date accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/privacy.mdx` at line 8, The "Last updated:" date in
website/src/content/docs/privacy.mdx is stale (shows "February 2025"); update
that string to the correct publication date (e.g., "February 2026") by editing
the "Last updated:" line in privacy.mdx (or replace with a dynamic date helper
if your content system supports it) so the published policy reflects the current
month and year.
website/src/layouts/Layout.astro-8-8 (1)

8-8: ⚠️ Potential issue | 🟡 Minor

Default image prop (/favicon.png) is unsuitable for Open Graph / Twitter cards.

Favicons are typically small (e.g., 32×32 or 64×64). Social platforms expect OG images around 1200×630. Consider defaulting to a dedicated social sharing image like /og-image.png.

Proposed fix
-const { title, description, image = '/favicon.png' } = Astro.props
+const { title, description, image = '/og-image.png' } = Astro.props
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/layouts/Layout.astro` at line 8, The default image prop in the
Layout component (const { title, description, image = '/favicon.png' } =
Astro.props) uses a favicon which is too small for Open Graph/Twitter cards;
change the default to a dedicated large social image such as '/og-image.png' (or
another 1200x630 image) so OG/Twitter meta tags generated by Layout use an
appropriate-sized image for social previews.
.github/workflows/deploy-website.yml-38-43 (1)

38-43: ⚠️ Potential issue | 🟡 Minor

configure-pages should run before the build step.

actions/configure-pages can inject environment variables (e.g., base path) that the Astro build may consume. Running it after the build means those variables won't be available. Move it before Install dependencies.

Proposed fix
      - name: Setup Bun
        uses: oven-sh/setup-bun@v2

+     - name: Setup Pages
+       uses: actions/configure-pages@v5
+
      - name: Install dependencies
        run: bun install --frozen-lockfile
        working-directory: website

      - name: Build website
        run: bun run build
        working-directory: website

-     - name: Setup Pages
-       uses: actions/configure-pages@v5
-
      - name: Upload artifact
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-website.yml around lines 38 - 43, Move the "Setup
Pages" step (uses: actions/configure-pages@v5) to run before the "Install
dependencies" and "Build website" steps so any environment variables it injects
(e.g., base path) are available to the build; locate the steps named "Setup
Pages" and "Build website" (and the step named "Install dependencies") in the
workflow and reorder them such that configure-pages executes first, then install
dependencies, then run the bun build in the "Build website" step.
website/scripts/generate-release-pages.ts-78-100 (1)

78-100: ⚠️ Potential issue | 🟡 Minor

Code-fence toggle can misfire on lines containing triple-backticks in prose.

line.trimStart().startsWith('```') will toggle inCodeBlock for any line that happens to start with triple backticks — including inline mentions like ```some-text``` on a single line. If a release note contains a single line with opening and closing fences (e.g., an inline example), the toggle flips twice but the second flip happens on the next line starting with ``` — leaving subsequent lines incorrectly marked as inside a code block.

This is an edge case that's unlikely in practice for release notes, but worth noting since the same logic exists in the workflow's awk script.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 78 - 100, The
code-fence toggle in escapeCurlyBraces incorrectly flips only once when a line
starts with ``` which misbehaves for single-line fences like ```example```;
modify the toggling logic in escapeCurlyBraces so it counts occurrences of '```'
in the current line and toggles inCodeBlock that many times (or toggles once
when count%2===1) instead of using line.trimStart().startsWith('```'); keep
using escapeLineOutsideCode for non-code segments and continue to push the
original line, but ensure the presence of multiple backtick sequences on the
same line is handled by the new count-based toggle.
.github/workflows/publish-website-artifacts.yml-130-138 (1)

130-138: ⚠️ Potential issue | 🟡 Minor

git add errors are silently suppressed.

Lines 134-135 redirect stderr and use || true, which means if the files genuinely fail to stage (e.g. path typo, permission issue), the step still succeeds and the commit on Line 136 silently becomes a no-op with "No changes to commit." This masks real failures.

Consider checking that at least the MDX file was staged, since that's always expected to be new:

Proposed improvement
-          git add website/public/astro-editor-latest.dmg website/public/astro-editor-latest.msi website/public/astro-editor-latest.AppImage 2>/dev/null || true
-          git add website/src/content/docs/releases/*.mdx 2>/dev/null || true
-          git commit -m "chore: update installers and add release page for $RELEASE_TAG" || echo "No changes to commit"
+          git add website/public/astro-editor-latest.dmg website/public/astro-editor-latest.msi website/public/astro-editor-latest.AppImage 2>/dev/null || true
+          git add website/src/content/docs/releases/*.mdx
+          git diff --cached --quiet && { echo "No changes to commit"; exit 0; }
+          git commit -m "chore: update installers and add release page for $RELEASE_TAG"

The binary artifacts may legitimately be absent (e.g. a source-only release), so || true there is fine. But the MDX release page should always exist after the previous step, so letting its git add fail loudly surfaces real problems.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-website-artifacts.yml around lines 130 - 138, The
workflow step "Commit website artifacts and release page" currently silences
failures for both artifact and MDX staging; change it so the MDX add is not
suppressed: keep the stderr-redirection/|| true only for the binary adds
(website/public/... .dmg/.msi/.AppImage) but remove "2>/dev/null || true" from
the git add for website/src/content/docs/releases/*.mdx so the job fails if the
release page cannot be staged; additionally add an explicit check after staging
(e.g., verify the MDX path is present in the staged files) and fail the step
with a clear error if the MDX file is missing before committing.
🧹 Nitpick comments (9)
website/src/content/docs/releases/0.1.37.mdx (1)

16-21: GitHub user-attachment image URLs may be ephemeral.

These github.com/user-attachments/assets/ URLs are tied to GitHub's internal asset storage and may expire or become inaccessible over time. Consider hosting these images locally (e.g., in a public/ or assets/ directory) for long-term reliability if this is auto-generated content that you want to persist.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/releases/0.1.37.mdx` around lines 16 - 21, The MDX
uses ephemeral GitHub user-attachment URLs for the two inline images (the <img
alt="Before"> and <img alt="After"> tags); download those image files into the
repo's persistent static assets location (e.g., public/ or assets/), add/commit
the files, and update the src attributes in
website/src/content/docs/releases/0.1.37.mdx to point to the new local paths
(e.g., /assets/... or ./public/...), ensuring the alt, width and height
attributes remain unchanged so the rendered page looks the same.
website/src/pages/releases/index.astro (1)

10-11: Mutating sort — consider creating a new sorted array.

Array.prototype.sort() mutates in place. While releases is a local variable so this isn't a correctness issue, using [...releases].sort(...) or releases.toSorted(...) is a cleaner pattern.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/pages/releases/index.astro` around lines 10 - 11, The current use
of releases.sort(...) mutates the original releases array; change this to
produce a new sorted array instead by using either [...releases].sort((a, b) =>
b.data.date!.getTime() - a.data.date!.getTime()) or releases.toSorted?.((a, b)
=> b.data.date!.getTime() - a.data.date!.getTime()) and assign that result to
sortedReleases so releases remains unchanged; keep the same comparator logic and
the reference to data.date! when creating the new array.
website/src/pages/index.astro (1)

940-942: Footer year script may briefly show empty content.

The <span id="year"></span> renders empty until the inline script executes. Consider using Astro's server-side rendering to set the year at build time:

<!-- In the frontmatter section -->
const year = new Date().getFullYear()
<!-- In the template -->
<span>{year}</span>

This avoids the brief flash of empty content and works without client-side JS.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/pages/index.astro` around lines 940 - 942, The footer currently
uses a client-side inline script (document.getElementById('year').textContent =
new Date().getFullYear()) which causes a flash of empty content for <span
id="year"></span>; instead, compute the year in the Astro frontmatter (const
year = new Date().getFullYear()) and render it server-side into the template
(replace <span id="year"></span> with a server-rendered {year}), then remove the
inline script so no client JS is required.
.github/workflows/deploy-website.yml (1)

31-32: Consider pinning the Bun version for reproducible builds.

Without a version pin, the workflow will use whatever latest Bun version is available, which could introduce unexpected breakage.

Example
      - name: Setup Bun
        uses: oven-sh/setup-bun@v2
+       with:
+         bun-version: "1.x"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-website.yml around lines 31 - 32, The workflow
currently uses the floating action reference "uses: oven-sh/setup-bun@v2" in the
"Setup Bun" step which allows the action to update and can break
reproducibility; change this to a pinned reference (specific release tag or
commit SHA) such as a concrete semver tag or the action's commit SHA, and if
applicable add an explicit bun version via the action input (e.g., bun-version)
to ensure the runtime Bun version is fixed; update the "Setup Bun" step that
currently references oven-sh/setup-bun@v2 accordingly.
website/scripts/generate-release-pages.ts (4)

33-38: isPost1_0 condition is more complex than needed.

major > 1 || (major === 1 && minor >= 0) simplifies to major >= 1, since minor >= 0 is always true for a parsed version number.

Simplification
 function isPost1_0(tag: string): boolean {
   const match = tag.match(/^v?(\d+)\.(\d+)\.(\d+)/)
   if (!match) return false
-  const [, major, minor] = match.map(Number)
-  return major > 1 || (major === 1 && minor >= 0)
+  const [, major] = match.map(Number)
+  return major >= 1
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 33 - 38, The version
check in isPost1_0 is overly complex: after extracting major and minor from
tag.match(...) replace the return expression `major > 1 || (major === 1 && minor
>= 0)` with the simplified `major >= 1`; update the return line in function
isPost1_0 to return major >= 1 (keeping the existing tag.match and destructuring
of major/minor).

161-165: Type mismatch: Release[] asserted but body field is absent until later.

gh release list --json tagName,name,publishedAt does not return body, so the parsed JSON objects lack the body property. Casting to Release[] (which requires body: string) hides this — if a future refactor accesses release.body between lines 165 and 174, it would be undefined at runtime despite TypeScript showing it as string.

Proposed fix: use a partial type for the initial fetch
+interface ReleaseMeta {
+  tagName: string
+  name: string
+  publishedAt: string
+}
+
 // Fetch all releases
 console.log('Fetching releases from GitHub...')
 const json = execSync(
   `gh release list --repo ${REPO} --limit 100 --json tagName,name,publishedAt`,
   { encoding: 'utf-8' }
 )
-const releases: Release[] = JSON.parse(json)
+const releaseMetas: ReleaseMeta[] = JSON.parse(json)

 // Fetch bodies
-console.log(`Found ${releases.length} releases. Fetching bodies...`)
-for (const release of releases) {
+console.log(`Found ${releaseMetas.length} releases. Fetching bodies...`)
+const releases: Release[] = releaseMetas.map((meta) => {
   const body = execSync(
-    `gh release view "${release.tagName}" --repo ${REPO} --json body -q .body`,
+    `gh release view "${meta.tagName}" --repo ${REPO} --json body -q .body`,
     { encoding: 'utf-8' }
   )
-  release.body = body
-}
+  return { ...meta, body }
+})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 161 - 165, The code
parses the GH release list into releases typed as Release[] even though the JSON
lacks body; change the interim type to a summary type (e.g., ReleaseSummary or
Omit<Release,'body'> or Partial<Release>) instead of Release[] so the compiler
reflects that body is absent, update the variable (releases -> releaseSummaries
or keep releases with the new type) and later map/fetch full release bodies
where you actually need them; target the JSON parsing site (the execSync call
and the releases variable) and the Release type reference to make this
type-safe.

159-175: N+1 execSync calls — may be slow and hit API rate limits for many releases.

The script first fetches the release list (1 call), then runs a separate gh release view for each release to get the body (N calls). For 100 releases this means 101 synchronous subprocess spawns, which is slow and may approach the GitHub API rate limit (especially unauthenticated).

Consider fetching bodies in the initial query by using the GraphQL API via gh api graphql, which can return all release bodies in a single request. Alternatively, you could batch with --json body if supported.

Example: single GraphQL call
const json = execSync(
  `gh api graphql -f query='
    {
      repository(owner: "dannysmith", name: "astro-editor") {
        releases(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {
          nodes { tagName name publishedAt description }
        }
      }
    }
  '`,
  { encoding: 'utf-8' }
)
const { data } = JSON.parse(json)
const releases = data.repository.releases.nodes.map((r: any) => ({
  tagName: r.tagName,
  name: r.name,
  publishedAt: r.publishedAt,
  body: r.description,
}))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 159 - 175, The
current N+1 pattern uses execSync to list releases then calls execSync per
release to fetch the body (see execSync, releases, REPO in
generate-release-pages.ts), which is slow and risky; replace this with a single
request that returns bodies (e.g., call gh api graphql once to request
repository.releases.nodes{tagName,name,publishedAt,description} and map
description → body into your Release[]), or if you prefer CLI JSON support use a
single gh release list/gh api call that includes --json body; update the parsing
logic that builds releases (and remove the per-release execSync loop), and add
basic error handling and pagination/fallback if >100 releases or when gh lacks
the needed field.

102-113: Inline code regex doesn't handle multi-backtick spans.

line.split(/(`[^`]*`)/) only handles single-backtick inline code. Double-backtick spans (`` code ``) won't be recognized, so curly braces inside them would be incorrectly escaped. This matches the limitation in the workflow's awk approach. Low risk for release notes content, but documenting the limitation here (e.g., a brief comment) would help future maintainers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 102 - 113, The split
in escapeLineOutsideCode currently uses line.split(/(`[^`]*`)/) which only
detects single-backtick spans; update escapeLineOutsideCode to correctly handle
inline code delimited by any number of backticks by splitting/parsing with a
pattern that matches a run of backticks, captures that same run as the closing
delimiter, and treats those segments as code (e.g., use a regex that captures `+
backticks and uses a backreference or implement a small stateful parser). Ensure
the function still leaves matched code segments unchanged and only escapes
braces in non-code parts; keep the function name escapeLineOutsideCode and its
overall map/join structure or replace with equivalent parsing logic and add a
brief comment noting support for multi-backtick spans.
.github/workflows/publish-website-artifacts.yml (1)

72-128: Duplicated sanitisation logic between workflow and TypeScript script.

The MDX body-cleaning pipeline here (strip leading title, strip installation-instructions section, strip changelog links, escape curly braces outside code) is reimplemented in shell/awk, while website/scripts/generate-release-pages.ts (sanitiseBody + escapeCurlyBraces) does the same thing in TypeScript. If one is updated, the other will silently drift.

Consider extracting the generation into a reusable script and calling it from both the workflow and the batch tool. For example, the workflow could invoke the TS script in single-release mode (e.g., npx tsx scripts/generate-release-pages.ts --tag "$RELEASE_TAG"), removing the need for the inline awk/sed pipeline entirely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-website-artifacts.yml around lines 72 - 128, The
workflow duplicates the MDX sanitisation implemented in
website/scripts/generate-release-pages.ts (sanitiseBody and escapeCurlyBraces);
replace the inline sed/awk pipeline by invoking that TS script in single-release
mode (e.g., add support in generate-release-pages.ts for a
--tag/--single-release flag that reads RELEASE_TAG, fetches the release via the
GitHub API or gh, runs sanitiseBody/escapeCurlyBraces and writes the same MDX
output), then update the workflow to call the script (npx tsx
scripts/generate-release-pages.ts --tag "$RELEASE_TAG") and remove the shell
sanitisation block; ensure the script accepts GITHUB_TOKEN from env and
reproduces the RELEASES_DIR/OUTPUT_FILE behavior so the workflow only needs to
pass env and echo the generated file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@website/src/layouts/Layout.astro`:
- Around line 14-41: The layout's head section (Layout.astro) is missing a named
slot so child pages cannot inject head content; add a <slot name="head" />
inside the <head> element (e.g., after the meta/link tags and before the inline
script) so pages that pass elements with slot="head" (like
website/src/pages/index.astro) will be rendered into the document head.

In `@website/src/pages/index.astro`:
- Line 23: Replace the runtime Tailwind Play CDN script tag (<script is:inline
src="https://cdn.tailwindcss.com"></script>) with a proper build-time Tailwind
integration: remove that script, add and configure a Tailwind setup (e.g.,
install and enable the `@astrojs/tailwind` integration or configure Tailwind via
PostCSS), add a tailwind.config.cjs/tailwind.config.js and include Tailwind
directives in your main CSS entry so styles are generated at build time and
picked up by Astro's bundler.
- Around line 192-230: The header navigation is completely hidden on small
screens because of the div with class "hidden items-center gap-8 md:flex"; add a
mobile menu toggle: introduce a visible hamburger button (with aria-controls and
aria-expanded) that toggles a mobile menu panel, move or duplicate the same
links (anchors to "#features", "#how", "/getting-started/", GitHub link, and the
"#download" download button) into that panel, and ensure the mobile panel is
hidden by default and shown when the toggle state is active (using a simple
client-side state script or Astro/JS toggle) while preserving accessibility
attributes and close behavior.

In `@website/src/pages/releases/index.astro`:
- Around line 35-44: The link href is currently built from release.data.title
which is fragile; change the anchor to use the entry's slug or id instead (e.g.,
use release.slug or release.data.slug, falling back to release.id if needed) so
the URL matches the page path; update the <a> href construction in the mapped
block (sortedReleases.map release) to use that slug/id and preserve the trailing
slash and display text (keep {release.data.title} for label).

---

Nitpick comments:
In @.github/workflows/deploy-website.yml:
- Around line 31-32: The workflow currently uses the floating action reference
"uses: oven-sh/setup-bun@v2" in the "Setup Bun" step which allows the action to
update and can break reproducibility; change this to a pinned reference
(specific release tag or commit SHA) such as a concrete semver tag or the
action's commit SHA, and if applicable add an explicit bun version via the
action input (e.g., bun-version) to ensure the runtime Bun version is fixed;
update the "Setup Bun" step that currently references oven-sh/setup-bun@v2
accordingly.

In @.github/workflows/publish-website-artifacts.yml:
- Around line 72-128: The workflow duplicates the MDX sanitisation implemented
in website/scripts/generate-release-pages.ts (sanitiseBody and
escapeCurlyBraces); replace the inline sed/awk pipeline by invoking that TS
script in single-release mode (e.g., add support in generate-release-pages.ts
for a --tag/--single-release flag that reads RELEASE_TAG, fetches the release
via the GitHub API or gh, runs sanitiseBody/escapeCurlyBraces and writes the
same MDX output), then update the workflow to call the script (npx tsx
scripts/generate-release-pages.ts --tag "$RELEASE_TAG") and remove the shell
sanitisation block; ensure the script accepts GITHUB_TOKEN from env and
reproduces the RELEASES_DIR/OUTPUT_FILE behavior so the workflow only needs to
pass env and echo the generated file.

In `@website/scripts/generate-release-pages.ts`:
- Around line 33-38: The version check in isPost1_0 is overly complex: after
extracting major and minor from tag.match(...) replace the return expression
`major > 1 || (major === 1 && minor >= 0)` with the simplified `major >= 1`;
update the return line in function isPost1_0 to return major >= 1 (keeping the
existing tag.match and destructuring of major/minor).
- Around line 161-165: The code parses the GH release list into releases typed
as Release[] even though the JSON lacks body; change the interim type to a
summary type (e.g., ReleaseSummary or Omit<Release,'body'> or Partial<Release>)
instead of Release[] so the compiler reflects that body is absent, update the
variable (releases -> releaseSummaries or keep releases with the new type) and
later map/fetch full release bodies where you actually need them; target the
JSON parsing site (the execSync call and the releases variable) and the Release
type reference to make this type-safe.
- Around line 159-175: The current N+1 pattern uses execSync to list releases
then calls execSync per release to fetch the body (see execSync, releases, REPO
in generate-release-pages.ts), which is slow and risky; replace this with a
single request that returns bodies (e.g., call gh api graphql once to request
repository.releases.nodes{tagName,name,publishedAt,description} and map
description → body into your Release[]), or if you prefer CLI JSON support use a
single gh release list/gh api call that includes --json body; update the parsing
logic that builds releases (and remove the per-release execSync loop), and add
basic error handling and pagination/fallback if >100 releases or when gh lacks
the needed field.
- Around line 102-113: The split in escapeLineOutsideCode currently uses
line.split(/(`[^`]*`)/) which only detects single-backtick spans; update
escapeLineOutsideCode to correctly handle inline code delimited by any number of
backticks by splitting/parsing with a pattern that matches a run of backticks,
captures that same run as the closing delimiter, and treats those segments as
code (e.g., use a regex that captures `+ backticks and uses a backreference or
implement a small stateful parser). Ensure the function still leaves matched
code segments unchanged and only escapes braces in non-code parts; keep the
function name escapeLineOutsideCode and its overall map/join structure or
replace with equivalent parsing logic and add a brief comment noting support for
multi-backtick spans.

In `@website/src/content/docs/releases/0.1.37.mdx`:
- Around line 16-21: The MDX uses ephemeral GitHub user-attachment URLs for the
two inline images (the <img alt="Before"> and <img alt="After"> tags); download
those image files into the repo's persistent static assets location (e.g.,
public/ or assets/), add/commit the files, and update the src attributes in
website/src/content/docs/releases/0.1.37.mdx to point to the new local paths
(e.g., /assets/... or ./public/...), ensuring the alt, width and height
attributes remain unchanged so the rendered page looks the same.

In `@website/src/pages/index.astro`:
- Around line 940-942: The footer currently uses a client-side inline script
(document.getElementById('year').textContent = new Date().getFullYear()) which
causes a flash of empty content for <span id="year"></span>; instead, compute
the year in the Astro frontmatter (const year = new Date().getFullYear()) and
render it server-side into the template (replace <span id="year"></span> with a
server-rendered {year}), then remove the inline script so no client JS is
required.

In `@website/src/pages/releases/index.astro`:
- Around line 10-11: The current use of releases.sort(...) mutates the original
releases array; change this to produce a new sorted array instead by using
either [...releases].sort((a, b) => b.data.date!.getTime() -
a.data.date!.getTime()) or releases.toSorted?.((a, b) => b.data.date!.getTime()
- a.data.date!.getTime()) and assign that result to sortedReleases so releases
remains unchanged; keep the same comparator logic and the reference to
data.date! when creating the new array.

Comment thread website/src/layouts/Layout.astro
Comment thread website/src/pages/index.astro
Comment thread website/src/pages/index.astro
Comment thread website/src/pages/releases/index.astro
@trueberryless

Copy link
Copy Markdown

Awesome work here 🥳

Small recommendation: If you'd like to automate the changelog pages, you could use the Starlight Changelogs plugin. But if you prefer it manually, you can also just keep it as it is 👍

@dannysmith

Copy link
Copy Markdown
Owner Author

Small recommendation: If you'd like to automate the changelog pages, you could use the Starlight Changelogs plugin. But if you prefer it manually, you can also just keep it as it is 👍

I'm gonna stick to writing release notes by hand in the GH releases. The current process creates a draft Release which I scribble some release notes into in the GH UI. Then when I hit Publish, .github/workflows/publish-website-artifacts.yml commits the new binaries and an entry in the releases content collection.

@trueberryless Will probs be a minute before this PR is merged coz I wanna rewrite all the docs properly (mostly sans LLMs), but when I do you can expect a ping for a code review if you got the time mate 😉🙏

Resolve conflicts in .gitignore (keep both sides) and pnpm-lock.yaml
(accept main's version).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@socket-security

socket-security Bot commented Mar 12, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​ast-grep/​cli@​0.42.0891006695100
Added@​radix-ui/​react-label@​2.1.81001006691100
Added@​radix-ui/​react-separator@​1.1.81001006791100
Added@​radix-ui/​react-aspect-ratio@​1.1.81001006791100
Added@​radix-ui/​react-toggle@​1.1.10991006792100
Added@​radix-ui/​react-slot@​1.2.41001006991100
Added@​radix-ui/​react-switch@​1.2.6991007092100
Added@​radix-ui/​react-collapsible@​1.1.12991007092100
Added@​radix-ui/​react-toggle-group@​1.1.11991007092100
Added@​radix-ui/​react-hover-card@​1.1.15991007192100
Added@​radix-ui/​react-checkbox@​1.3.3991007192100
Added@​typescript-eslint/​parser@​8.57.21001007198100
Added@​radix-ui/​react-radio-group@​1.3.8991007192100
Added@​radix-ui/​react-dropdown-menu@​2.1.16991007192100
Added@​radix-ui/​react-alert-dialog@​1.1.15991007192100
Added@​radix-ui/​react-popover@​1.1.15991007192100
Added@​radix-ui/​react-dialog@​1.1.15991007192100
Added@​radix-ui/​react-tooltip@​1.2.8991007292100
Added@​radix-ui/​react-scroll-area@​1.2.10991007391100
Added@​rolldown/​plugin-babel@​0.2.27310010096100
Added@​radix-ui/​react-select@​2.2.6981007492100
Added@​types/​react-dom@​19.2.31001007587100
Added@​lezer/​highlight@​1.2.31001007681100
Added@​codemirror/​search@​6.6.0991007883100
Added@​types/​react@​19.2.141001007992100
Addedbabel-plugin-react-compiler@​1.0.01001007997100
Added@​vitest/​coverage-v8@​4.1.2991007999100
Added@​codemirror/​state@​6.6.0991007988100
Added@​typescript-eslint/​eslint-plugin@​8.57.2991008098100
Added@​types/​node@​25.5.01001008195100
Added@​codemirror/​commands@​6.10.31001008390100
Added@​semantic-release/​changelog@​6.0.3991009084100
Added@​semantic-release/​git@​10.0.19910010084100
See 29 more rows in the dashboard

View full report

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🧹 Nitpick comments (6)
website/src/content/docs/file-management/ide-integration.mdx (2)

12-12: Consider cross-platform terminology if applicable.

"Reveal in Finder" is macOS-specific. If Astro Editor supports Windows or Linux, consider using platform-agnostic language like "Reveal in File Manager" or noting platform variations (e.g., "Finder/Explorer").

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/file-management/ide-integration.mdx` at line 12,
Replace the macOS-specific label "**Reveal in Finder**" with cross-platform
wording or clarify platform variations: update the text in ide-integration.mdx
to use "Reveal in File Manager" (or "Reveal in Finder/Explorer") or add a
parenthetical note like "(Finder on macOS, Explorer on Windows, Files on Linux)"
so the instruction is accurate across operating systems and easy to find by
searching for the "**Reveal in Finder**" string.

17-17: Same platform consideration for keyboard shortcut.

Cmd+, is macOS-specific. If cross-platform support exists or is planned, consider noting the Windows/Linux equivalent (e.g., Ctrl+,).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/file-management/ide-integration.mdx` at line 17, The
docs currently show a macOS-only shortcut ("Cmd+,") in the IDE preferences
sentence; update the text in
website/src/content/docs/file-management/ide-integration.mdx where the
preferences shortcut is referenced to include cross-platform equivalents (e.g.,
"Cmd+, (macOS) / Ctrl+, (Windows/Linux)") or a parenthetical note like "Cmd+ /
Ctrl+, in preferences" so readers on other platforms see the correct shortcut
when configuring the IDE command.
website/src/content/docs/getting-started/concepts.mdx (1)

17-17: Consider rephrasing the trailing "Etc." for clarity.

The sentence ends with "Etc." which is informal and leaves readers uncertain about what other schema properties might be required. Consider either listing all required properties or rephrasing to clarify these are examples.

📝 Suggested rewording
-Some features require you to have certain properties in your schema. A date field is required for proper ordering in the file list. A boolean field is required to show and filter drafts. A text field is required to show titles in the sidebar. Etc.
+Some features require you to have certain properties in your schema. For example, a date field is required for proper ordering in the file list, a boolean field is required to show and filter drafts, and a text field is required to show titles in the sidebar. See the [Configuration](/configuration) section for details.

Alternatively, if there are no additional required fields, simply remove "Etc." and adjust punctuation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/getting-started/concepts.mdx` at line 17, The
sentence starting "Some features require you to have certain properties in your
schema. A date field..." ends with the informal "Etc." — update that sentence in
website/src/content/docs/getting-started/concepts.mdx by either removing "Etc."
and ending the sentence with a period, or replace "Etc." with a clear qualifier
such as "These are examples" or "for example" (or explicitly list any other
required fields if there are more), ensuring the phrase that begins "Some
features require..." reads as a clear, complete statement.
.gitignore (2)

40-43: LGTM! Optional: consider relying on existing general patterns.

The website build artifacts are correctly ignored. Note that website/dist/ and website/node_modules/ are already covered by the general dist and node_modules patterns (lines 10-11), so these specific entries are redundant—though explicit paths can improve clarity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.gitignore around lines 40 - 43, Remove the redundant specific ignores in
.gitignore: delete the entries "website/dist/" and "website/node_modules/" since
the general "dist" and "node_modules" patterns already cover them; keep
"website/.astro/" if you want the explicit project-specific artifact excluded.
Update the .gitignore so it relies on the existing general patterns and retains
only the project-specific line(s) you need.

45-45: Optional: move .claude/worktrees/ to a separate section.

The .claude/worktrees/ entry is positioned under the "Website build artifacts" comment, but it's not related to website builds. Consider adding a dedicated comment (e.g., # Claude worktrees) or moving it to a more appropriate section for better organization.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.gitignore at line 45, Move the `.claude/worktrees/` entry out of the
"Website build artifacts" section and place it under a dedicated section with a
clear comment (for example `# Claude worktrees`) so the `.claude/worktrees/`
line is grouped with related entries; edit the .gitignore to add the new comment
and relocate the `.claude/worktrees/` line accordingly to improve organization
and clarity.
website/src/content/docs/editor/overview.mdx (1)

6-6: Capitalize Markdown consistently.

Line 6 uses lowercase markdown for both the file format and syntax highlighting. Using Markdown matches standard terminology and reads a bit cleaner in the docs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/editor/overview.mdx` at line 6, Update the two
occurrences of the lowercase word "markdown" in the editor overview text to
"Markdown" so the file format and the reference to syntax highlighting
consistently use the proper capitalized term; locate the sentence in
overview.mdx that currently reads about "markdown or MDX files" and "markdown
syntax highlighting" and change both to "Markdown".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@website/src/content/docs/editing/overview.mdx`:
- Around line 18-21: Update the shortcuts in the overview table so they match
the implemented keymap: change the Redo shortcut from "Cmd+Y" to "Cmd+Shift+Z"
and change Toggle Focus Mode from "Ctrl+Cmd+F" to "Cmd+Shift+F" (these
correspond to the redo and focus-mode bindings defined in the editor keymap in
keymap.ts); ensure the table cells for the Redo and Toggle Focus Mode rows are
updated exactly to those key strings so the docs align with the implemented key
bindings.

In `@website/src/content/docs/frontmatter/image-fields.mdx`:
- Around line 10-18: The example uses image() out of scope; update the
defineCollection call so the schema is a callback that receives the image helper
(e.g., change schema to a function like schema: ({ image }) => ...) and then use
image() and image().optional() inside that returned z.object; modify the blog
constant where defineCollection and schema are defined (symbols:
defineCollection, schema, image, blog) so consumers won't hit a runtime error
when copying the example.

In `@website/src/content/docs/frontmatter/special-fields.mdx`:
- Around line 2-3: The frontmatter description currently states the page covers
only "title" and "description" but the document body also explains "required"
fields; update the frontmatter description to accurately reflect all covered
topics (e.g., include "required" or "required fields") so generated
summaries/snippets are correct. Edit the frontmatter keys at the top of the file
(the title and description entries) to a concise description like "Special
frontmatter fields — title, description, and required fields" or similar that
mentions "required", then save and run the site build to verify summaries
update.

In `@website/src/content/docs/getting-started.mdx`:
- Line 31: Update the table row for the "Main Editor" entry so the word
"Markdown" is capitalized; locate the row that currently reads "| **Main
Editor**   | Clean writing space with markdown syntax highlighting |" in the
docs and change "markdown" to "Markdown" in that string to match the rest of the
page's usage.
- Line 12: Update the Quick Start sentence in getting-started.mdx (the line
referencing content config) to mention both supported config filenames so users
know either location is accepted; replace the current reference to
src/content/config.ts with wording that lists both src/content/config.ts and
src/content.config.ts (the two supported config locations referenced by the
parser/commands in src-tauri), keeping the sentence concise and in the same
style as the existing step.

In `@website/src/content/docs/getting-started/opening-a-project.mdx`:
- Line 6: The text only mentions src/content/config.ts but the app also reads
src/content.config.ts; update the sentence in opening-a-project.mdx to document
both supported config paths (e.g., "src/content/config.ts" and
"src/content.config.ts") so users with the newer layout are covered; reference
the existing wording that says "Astro Editor will automatically scan for content
collections defined in your src/content/config.ts file" and change it to include
both filenames.

In `@website/src/content/docs/philosophy.mdx`:
- Line 12: Update the sentence "3. Add frontmatter for things like description,
tags etc" to include a period after the abbreviation "etc" (i.e., change "etc"
to "etc."). Locate that line in website/src/content/docs/philosophy.mdx and make
the small punctuation edit so the list item reads "3. Add frontmatter for things
like description, tags etc."
- Line 19: Fix the typo in the documentation sentence that currently reads
"There's no mechanism for comitting or publishing in Astro Editor. You should do
that in a code editor or terminal." — change "comitting" to "committing" so the
sentence reads "There's no mechanism for committing or publishing in Astro
Editor. You should do that in a code editor or terminal."
- Line 22: The paragraph in philosophy.mdx mixes British and American spelling
("customisation" vs "customization"); pick one variant (use American English as
suggested) and update all occurrences in this file and nearby docs to use
"customization" consistently (search for and replace "customisation" with
"customization"), ensuring the sentence with "simplicity when in writer mode"
and the recommendation about VSCode/Obsidian uses the chosen spelling
everywhere.
- Line 6: Update the sentence that currently reads "writing or editing prose in
markdown" to capitalize the proper noun "Markdown"; locate the phrase in the
text block (the sentence starting "We're in writer mode when we're writing or
editing prose in markdown") and change "markdown" to "Markdown" so the document
correctly references the markup language.

In `@website/src/content/docs/preferences/collections.mdx`:
- Around line 45-53: The docs overstate fallback behavior; update the "How
Settings Work (Three-Tier Fallback)" section in
website/src/content/docs/preferences/collections.mdx to only claim three-tier
fallback for settings that the backend actually supports (e.g., the
project-level content_directory_override used during collection discovery in
src-tauri/src/parser.rs), and modify the example so it reflects that content
directory overrides are applied at project discovery time rather than
per-collection unless the backend implements per-collection overrides; mention
content_directory_override and the collection discovery path to guide reviewers
to the relevant backend behavior.
- Around line 16-19: Update the wording for the two fields labelled "**Content
Directory**" and "**Assets Directory**" to say these paths are
"project-root-relative" rather than "absolute path"; change the parenthetical
and any explanatory text to clarify examples like `content/blog/` and
`public/blog-images/` are relative to `<project_root>` (project-root-relative)
and not filesystem-absolute, so readers understand how to configure those values
correctly.

In `@website/src/content/docs/reference/advanced-preferences.mdx`:
- Line 10: The doc currently hardcodes a macOS app-data path; instead update
advanced-preferences.mdx to either describe the setting as the generic
application data directory (e.g., "Application data directory returned by
commands.getAppDataDir()") or replace the single macOS example with per‑platform
examples (macOS, Windows, Linux) and note that the code uses
commands.getAppDataDir() in the project registry to resolve the actual path;
ensure the wording makes it clear the shown paths are examples and not
universal.

In `@website/src/content/docs/troubleshooting.mdx`:
- Line 36: Replace the absolute privacy claim in troubleshooting.mdx that reads
"The debug info and log files contain no personal content..." with a neutral
statement clarifying that logs are primarily technical but may include sensitive
details (e.g., file paths, usernames) and advising users to review/redact
sensitive information before sharing; update the sentence in the file to state
the logs are mainly technical and recommend users check for and remove any
personal or identifying data prior to disclosure.

---

Nitpick comments:
In @.gitignore:
- Around line 40-43: Remove the redundant specific ignores in .gitignore: delete
the entries "website/dist/" and "website/node_modules/" since the general "dist"
and "node_modules" patterns already cover them; keep "website/.astro/" if you
want the explicit project-specific artifact excluded. Update the .gitignore so
it relies on the existing general patterns and retains only the project-specific
line(s) you need.
- Line 45: Move the `.claude/worktrees/` entry out of the "Website build
artifacts" section and place it under a dedicated section with a clear comment
(for example `# Claude worktrees`) so the `.claude/worktrees/` line is grouped
with related entries; edit the .gitignore to add the new comment and relocate
the `.claude/worktrees/` line accordingly to improve organization and clarity.

In `@website/src/content/docs/editor/overview.mdx`:
- Line 6: Update the two occurrences of the lowercase word "markdown" in the
editor overview text to "Markdown" so the file format and the reference to
syntax highlighting consistently use the proper capitalized term; locate the
sentence in overview.mdx that currently reads about "markdown or MDX files" and
"markdown syntax highlighting" and change both to "Markdown".

In `@website/src/content/docs/file-management/ide-integration.mdx`:
- Line 12: Replace the macOS-specific label "**Reveal in Finder**" with
cross-platform wording or clarify platform variations: update the text in
ide-integration.mdx to use "Reveal in File Manager" (or "Reveal in
Finder/Explorer") or add a parenthetical note like "(Finder on macOS, Explorer
on Windows, Files on Linux)" so the instruction is accurate across operating
systems and easy to find by searching for the "**Reveal in Finder**" string.
- Line 17: The docs currently show a macOS-only shortcut ("Cmd+,") in the IDE
preferences sentence; update the text in
website/src/content/docs/file-management/ide-integration.mdx where the
preferences shortcut is referenced to include cross-platform equivalents (e.g.,
"Cmd+, (macOS) / Ctrl+, (Windows/Linux)") or a parenthetical note like "Cmd+ /
Ctrl+, in preferences" so readers on other platforms see the correct shortcut
when configuring the IDE command.

In `@website/src/content/docs/getting-started/concepts.mdx`:
- Line 17: The sentence starting "Some features require you to have certain
properties in your schema. A date field..." ends with the informal "Etc." —
update that sentence in website/src/content/docs/getting-started/concepts.mdx by
either removing "Etc." and ending the sentence with a period, or replace "Etc."
with a clear qualifier such as "These are examples" or "for example" (or
explicitly list any other required fields if there are more), ensuring the
phrase that begins "Some features require..." reads as a clear, complete
statement.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 15b08de1-6aa0-4f32-8db9-4f3f9d5faa91

📥 Commits

Reviewing files that changed from the base of the PR and between 64e085f and 1f7689d.

📒 Files selected for processing (34)
  • .gitignore
  • .vscode/settings.json
  • website/src/content/docs/command-palette.mdx
  • website/src/content/docs/editing/content-linker.mdx
  • website/src/content/docs/editing/images-and-files.mdx
  • website/src/content/docs/editing/mdx-components.mdx
  • website/src/content/docs/editing/overview.mdx
  • website/src/content/docs/editor/auto-saving.mdx
  • website/src/content/docs/editor/copyedit-modes.mdx
  • website/src/content/docs/editor/focus-mode.mdx
  • website/src/content/docs/editor/overview.mdx
  • website/src/content/docs/editor/typewriter-mode.mdx
  • website/src/content/docs/file-management/creating-files.mdx
  • website/src/content/docs/file-management/drafts.mdx
  • website/src/content/docs/file-management/filtering-and-sorting.mdx
  • website/src/content/docs/file-management/ide-integration.mdx
  • website/src/content/docs/file-management/overview.mdx
  • website/src/content/docs/frontmatter/basic-fields.mdx
  • website/src/content/docs/frontmatter/image-fields.mdx
  • website/src/content/docs/frontmatter/overview.mdx
  • website/src/content/docs/frontmatter/reference-fields.mdx
  • website/src/content/docs/frontmatter/required-fields.mdx
  • website/src/content/docs/frontmatter/special-fields.mdx
  • website/src/content/docs/getting-started.mdx
  • website/src/content/docs/getting-started/concepts.mdx
  • website/src/content/docs/getting-started/example.mdx
  • website/src/content/docs/getting-started/opening-a-project.mdx
  • website/src/content/docs/philosophy.mdx
  • website/src/content/docs/preferences/collections.mdx
  • website/src/content/docs/preferences/general.mdx
  • website/src/content/docs/preferences/project.mdx
  • website/src/content/docs/reference/advanced-preferences.mdx
  • website/src/content/docs/reference/keyboard-shortcuts.mdx
  • website/src/content/docs/troubleshooting.mdx
🚧 Files skipped from review as they are similar to previous changes (13)
  • website/src/content/docs/frontmatter/basic-fields.mdx
  • website/src/content/docs/command-palette.mdx
  • website/src/content/docs/file-management/creating-files.mdx
  • website/src/content/docs/frontmatter/reference-fields.mdx
  • website/src/content/docs/getting-started/example.mdx
  • website/src/content/docs/frontmatter/required-fields.mdx
  • website/src/content/docs/file-management/overview.mdx
  • website/src/content/docs/editing/mdx-components.mdx
  • website/src/content/docs/editor/typewriter-mode.mdx
  • website/src/content/docs/file-management/drafts.mdx
  • website/src/content/docs/frontmatter/overview.mdx
  • website/src/content/docs/editing/images-and-files.mdx
  • website/src/content/docs/file-management/filtering-and-sorting.mdx

Comment thread website/src/content/docs/editing/overview.mdx Outdated
Comment thread website/src/content/docs/frontmatter/image-fields.mdx
Comment on lines +2 to +3
title: 'Special Fields'
description: 'Special frontmatter fields — title and description'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Update the page description to match the page body.

The frontmatter says this page covers only title and description, but Line 10 also documents required fields. That makes generated summaries/snippets slightly misleading.

✏️ Proposed fix
 title: 'Special Fields'
-description: 'Special frontmatter fields — title and description'
+description: 'Special frontmatter field behaviors for title, description, and required fields'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
title: 'Special Fields'
description: 'Special frontmatter fields — title and description'
title: 'Special Fields'
description: 'Special frontmatter field behaviors for title, description, and required fields'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/frontmatter/special-fields.mdx` around lines 2 - 3,
The frontmatter description currently states the page covers only "title" and
"description" but the document body also explains "required" fields; update the
frontmatter description to accurately reflect all covered topics (e.g., include
"required" or "required fields") so generated summaries/snippets are correct.
Edit the frontmatter keys at the top of the file (the title and description
entries) to a concise description like "Special frontmatter fields — title,
description, and required fields" or similar that mentions "required", then save
and run the site build to verify summaries update.

Comment thread website/src/content/docs/getting-started.mdx Outdated
| Interface Area | Purpose |
| ----------------- | ---------------------------------------------------------------------------- |
| **Left Sidebar** | Browse collections and files, with draft indicators and context menu options |
| **Main Editor** | Clean writing space with markdown syntax highlighting |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Capitalize Markdown in the table entry.

This is a user-facing docs string, and the rest of the page already treats Markdown as a proper noun.

Suggested wording
-| **Main Editor**   | Clean writing space with markdown syntax highlighting                        |
+| **Main Editor**   | Clean writing space with Markdown syntax highlighting                        |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| **Main Editor** | Clean writing space with markdown syntax highlighting |
| **Main Editor** | Clean writing space with Markdown syntax highlighting |
🧰 Tools
🪛 LanguageTool

[uncategorized] ~31-~31: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ...n Editor** | Clean writing space with markdown syntax highlighting ...

(MARKDOWN_NNP)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/getting-started.mdx` at line 31, Update the table
row for the "Main Editor" entry so the word "Markdown" is capitalized; locate
the row that currently reads "| **Main Editor**   | Clean writing space with
markdown syntax highlighting |" in the docs and change "markdown" to "Markdown"
in that string to match the rest of the page's usage.

- There's no mechanism for comitting or publishing in Astro Editor. You should do that in a code editor or terminal.
- There's no way to preview your writing. The best way to do that is by running your astro site locally with `pnpm run dev` and looking at it there.

Because the goal of this **simplicity when in writer mode**, Astro Editor is intentionally opinionated about its UI and limits the user customisation features to _"making it work with your Astro project and no more"_. It's not possible to customise the colour schemes, typeface etc. If you need fine-grained customization & extensibility we recommend using a custom profile in VSCode (or Obsidian) which you've set up for Markdown editing.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Standardize spelling: mixed British/American variants.

The text uses both "customisation" (British) and "customization" (American) in the same sentence. Pick one variant and use it consistently throughout the documentation.

📝 Proposed fix (using American English)
-Because the goal of this **simplicity when in writer mode**, Astro Editor is intentionally opinionated about its UI and limits the user customisation features to _"making it work with your Astro project and no more"_. It's not possible to customise the colour schemes, typeface etc. If you need fine-grained customization & extensibility we recommend using a custom profile in VSCode (or Obsidian) which you've set up for Markdown editing.
+Because the goal of this **simplicity when in writer mode**, Astro Editor is intentionally opinionated about its UI and limits the user customization features to _"making it work with your Astro project and no more"_. It's not possible to customize the color schemes, typeface etc. If you need fine-grained customization & extensibility we recommend using a custom profile in VSCode (or Obsidian) which you've set up for Markdown editing.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Because the goal of this **simplicity when in writer mode**, Astro Editor is intentionally opinionated about its UI and limits the user customisation features to _"making it work with your Astro project and no more"_. It's not possible to customise the colour schemes, typeface etc. If you need fine-grained customization & extensibility we recommend using a custom profile in VSCode (or Obsidian) which you've set up for Markdown editing.
Because the goal of this **simplicity when in writer mode**, Astro Editor is intentionally opinionated about its UI and limits the user customization features to _"making it work with your Astro project and no more"_. It's not possible to customize the color schemes, typeface etc. If you need fine-grained customization & extensibility we recommend using a custom profile in VSCode (or Obsidian) which you've set up for Markdown editing.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~22-~22: Do not mix variants of the same word (‘customization’ and ‘customisation’) within a single text.
Context: ... typeface etc. If you need fine-grained customization & extensibility we recommend using a cu...

(EN_WORD_COHERENCY)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/philosophy.mdx` at line 22, The paragraph in
philosophy.mdx mixes British and American spelling ("customisation" vs
"customization"); pick one variant (use American English as suggested) and
update all occurrences in this file and nearby docs to use "customization"
consistently (search for and replace "customisation" with "customization"),
ensuring the sentence with "simplicity when in writer mode" and the
recommendation about VSCode/Obsidian uses the chosen spelling everywhere.

Comment on lines +16 to +19
- **Content Directory**: Where this collection's files are located (absolute path from project root)
- Example: `content/blog/` means files are in `<project_root>/content/blog/`, not `<project_root>/src/content/blog/`
- **Assets Directory**: Where this collection's assets should be copied (absolute path from project root)
- Example: `public/blog-images/` for blog, `public/docs-images/` for docs

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use “project-root-relative” here, not “absolute path.”

The examples (content/blog/, public/blog-images/) are relative to <project_root>, not filesystem-absolute paths. Calling them “absolute” is misleading for anyone trying to configure these values.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/preferences/collections.mdx` around lines 16 - 19,
Update the wording for the two fields labelled "**Content Directory**" and
"**Assets Directory**" to say these paths are "project-root-relative" rather
than "absolute path"; change the parenthetical and any explanatory text to
clarify examples like `content/blog/` and `public/blog-images/` are relative to
`<project_root>` (project-root-relative) and not filesystem-absolute, so readers
understand how to configure those values correctly.

Comment on lines +45 to +53
## How Settings Work (Three-Tier Fallback)

When Astro Editor needs a setting (like content directory), it looks in this order:

1. **Collection setting** (if configured for this collection)
2. **Project setting** (if configured at project level)
3. **Hard-coded default** (built into the app)

**Example**: If you set project content directory to `content/`, all collections use `content/`. But if you configure the "blog" collection to use `content/blog-posts/`, only the blog collection uses that path while other collections still use `content/`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

The fallback section currently promises broader behavior than the backend snippet shows.

src-tauri/src/parser.rs:95-105 only shows a project-level content_directory_override during collection discovery. As written, this section reads as if settings like content directories always support collection -> project -> default fallback, which is not what the provided implementation evidence shows. Please narrow this section to settings that actually have that behavior, or adjust the example accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/preferences/collections.mdx` around lines 45 - 53,
The docs overstate fallback behavior; update the "How Settings Work (Three-Tier
Fallback)" section in website/src/content/docs/preferences/collections.mdx to
only claim three-tier fallback for settings that the backend actually supports
(e.g., the project-level content_directory_override used during collection
discovery in src-tauri/src/parser.rs), and modify the example so it reflects
that content directory overrides are applied at project discovery time rather
than per-collection unless the backend implements per-collection overrides;
mention content_directory_override and the collection discovery path to guide
reviewers to the relevant backend behavior.


Settings are automatically saved to your system:

- **Location**: `~/Library/Application Support/is.danny.astroeditor/`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't present a macOS path as the universal settings location.

src/lib/project-registry/index.ts:33-74 resolves this directory through commands.getAppDataDir(), so ~/Library/Application Support/is.danny.astroeditor/ is only correct on macOS. This reference page should either describe the app-data directory generically or list per-platform examples.

📝 Suggested wording
-- **Location**: `~/Library/Application Support/is.danny.astroeditor/`
+- **Location**: Your platform's app data directory (for example, `~/Library/Application Support/is.danny.astroeditor/` on macOS)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/reference/advanced-preferences.mdx` at line 10, The
doc currently hardcodes a macOS app-data path; instead update
advanced-preferences.mdx to either describe the setting as the generic
application data directory (e.g., "Application data directory returned by
commands.getAppDataDir()") or replace the single macOS example with per‑platform
examples (macOS, Windows, Linux) and note that the code uses
commands.getAppDataDir() in the project registry to resolve the actual path;
ensure the wording makes it clear the shown paths are examples and not
universal.

5. **Select and copy** the relevant log entries
6. **Send the logs** along with a description of your issue

**Note:** The debug info and log files contain no personal content - only technical information about file paths, app operations, and error details needed for debugging.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid the absolute privacy claim here.

Saying the logs contain "no personal content" is too strong when they can include file paths, which often expose usernames, project names, or other identifying details. Please reword this to tell users the logs are primarily technical and that they should review/redact anything sensitive before sharing.

Suggested wording
-**Note:** The debug info and log files contain no personal content - only technical information about file paths, app operations, and error details needed for debugging.
+**Note:** The debug info and log files are primarily technical, but they may include file paths and other environment details. Please review them before sharing and redact anything sensitive if needed.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**Note:** The debug info and log files contain no personal content - only technical information about file paths, app operations, and error details needed for debugging.
**Note:** The debug info and log files are primarily technical, but they may include file paths and other environment details. Please review them before sharing and redact anything sensitive if needed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/troubleshooting.mdx` at line 36, Replace the
absolute privacy claim in troubleshooting.mdx that reads "The debug info and log
files contain no personal content..." with a neutral statement clarifying that
logs are primarily technical but may include sensitive details (e.g., file
paths, usernames) and advising users to review/redact sensitive information
before sharing; update the sentence in the file to state the logs are mainly
technical and recommend users check for and remove any personal or identifying
data prior to disclosure.

- Add <slot name="head" /> to Layout.astro so child pages can inject head content
- Use release.id instead of release.data.title for release page links
- Use non-mutating sort in releases index
- Simplify isPost1_0 to `major >= 1`
- Fix type safety: use Omit<Release, 'body'> for summaries without body
- Support multi-backtick inline code in escapeLineOutsideCode
- Localise GitHub attachment images in both TS script and CI workflow
- Download 0.1.37 images to public/releases/ and update references
- Skip --- separator for empty release bodies (fix 0.1.9.mdx)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
.github/workflows/publish-website-artifacts.yml (2)

147-150: Silently ignoring missing files may mask failures.

The 2>/dev/null || true pattern suppresses errors if files don't exist, which could hide actual problems (e.g., failed artifact copies or generation). Consider adding explicit checks or at least logging when expected files are missing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-website-artifacts.yml around lines 147 - 150, The
git add commands currently use "2>/dev/null || true" which hides missing files;
replace those silent adds with explicit existence checks and clear logging: for
each pattern (website/public/astro-editor-latest.* ,
website/public/releases/*.png, website/src/content/docs/releases/*.mdx) test if
files exist (e.g., with globbing or "shopt -s nullglob" then check arrays) and
echo a warning or error to stderr if none found, then only run git add when
files exist; ensure the commit step still behaves as intended (keep the commit
message for $RELEASE_TAG) and consider failing the workflow or setting an
explicit non-zero exit when required artifacts are missing.

72-141: Duplicated sanitization logic between workflow and TypeScript script.

The shell-based MDX generation here largely duplicates the logic in website/scripts/generate-release-pages.ts (body sanitization, curly-brace escaping, image downloading, MDX generation). This creates a maintenance burden where changes must be synchronized in two places.

Consider invoking the TypeScript script directly from the workflow instead:

npx tsx website/scripts/generate-release-pages.ts --all

This would require adjusting the script to accept a single-release mode or filter by tag, but would consolidate the logic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-website-artifacts.yml around lines 72 - 141, The
workflow duplicates the release sanitization and MDX generation logic (see
CLEAN_BODY, IMAGE_URLS, IMAGES_DIR, OUTPUT_FILE); replace that shell block by
invoking the existing TypeScript utility
(website/scripts/generate-release-pages.ts) from the workflow (e.g. run npx tsx
website/scripts/generate-release-pages.ts) and adapt the script to support a
single-release mode or tag filter (accept a --tag or --all flag and implement
tag-based processing and image download/curly-brace escaping there) so all
sanitization, image download, and MDX writing happen only in
generate-release-pages.ts.
website/scripts/generate-release-pages.ts (3)

119-145: execSync for curl does not handle download failures.

If curl fails (e.g., network error, 404), execSync will throw, but the error message won't indicate which URL failed. Consider wrapping in try-catch with context:

Proposed improvement
     if (!dryRun) {
-      execSync(`curl -sL -o "${localPath}" "${url}"`)
-      console.log(`    Downloaded image: ${localName}`)
+      try {
+        execSync(`curl -sL --fail -o "${localPath}" "${url}"`)
+        console.log(`    Downloaded image: ${localName}`)
+      } catch (err) {
+        console.warn(`    WARNING: Failed to download ${url}, skipping`)
+      }
     } else {

Adding --fail makes curl return non-zero on HTTP errors (4xx/5xx).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 119 - 145, The
localiseImages function uses execSync with curl which can throw without
contextual info when a download fails; update the download block inside
localiseImages to (1) add the --fail flag to the curl command, (2) wrap the
execSync call in try/catch, and (3) on error log a clear message including the
URL and localPath (and include the caught error.message), then continue to the
next image instead of letting the exception crash the script so non-fatal
failures are handled gracefully while preserving dryRun behavior.

34-39: Unused destructured variable minor.

The minor variable is extracted but never used since only major >= 1 is checked.

Proposed fix
 function isPost1_0(tag: string): boolean {
   const match = tag.match(/^v?(\d+)\.(\d+)\.(\d+)/)
   if (!match) return false
-  const [, major, minor] = match.map(Number)
+  const [, major] = match.map(Number)
   return major >= 1
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 34 - 39, The function
isPost1_0 extracts `minor` from match but never uses it; update isPost1_0 to
avoid the unused destructure by only extracting/using `major` (e.g., read
Number(match[1]) into `major`) and remove `minor` from the destructuring so the
linter warning is resolved while preserving the existing `match` null check and
the return expression `major >= 1`.

189-205: Sequential execSync calls for fetching release bodies could be slow.

For repositories with many releases, making a synchronous gh release view call per release will be slow. This is acceptable for a one-off script, but consider parallel fetching if performance becomes an issue.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 189 - 205, The
current code performs sequential synchronous execSync calls when building
releases (the summaries -> releases mapping that calls `execSync` for each `gh
release view`), which is slow; change this to fetch bodies in parallel by
replacing the `summaries.map` + synchronous `execSync` with an asynchronous
approach (e.g., use `child_process.exec`/promisified exec or `execa`) and run
all per-release `gh release view "${summary.tagName}" --repo ${REPO} --json body
-q .body` calls with Promise.all, then await the results and construct the
`releases: Release[]` array; preserve encoding/formatting and consider simple
rate-limit error handling or batching if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/publish-website-artifacts.yml:
- Around line 110-116: The sed substitution on CLEAN_BODY using the raw $URL and
$LOCAL_NAME is unsafe when those values contain regex metacharacters or the
chosen delimiter; create and use escaped versions (e.g., ESC_URL and
ESC_LOCAL_NAME) that backslash-escape sed-special characters (delimiter, /, &,
|, etc.) before calling sed, or replace the sed step with a literal-safe tool
(awk or parameter expansion) that performs a literal string replacement; update
the loop to compute ESC_URL and ESC_LOCAL_NAME from URL and LOCAL_NAME and use
those escaped names in the sed substitution that updates CLEAN_BODY.

In `@website/scripts/generate-release-pages.ts`:
- Around line 1-23: Replace the fragile import.meta.dirname usage (used in
RELEASES_DIR and IMAGES_DIR) with a Node-compatible approach: compute baseDir
via fileURLToPath(import.meta.url) and path.dirname (import fileURLToPath from
'node:url' and dirname from 'node:path') so the script runs on older Node
versions; additionally add an explicit Node version constraint (e.g., "engines":
{ "node": ">=20.11.0" } in package.json and create a .nvmrc/.node-version with
the same version) to document requirements; finally, remove the unused
destructured variable minor from the isPost1_0() function (or use it if
intended) to eliminate the unused-variable warning.

---

Nitpick comments:
In @.github/workflows/publish-website-artifacts.yml:
- Around line 147-150: The git add commands currently use "2>/dev/null || true"
which hides missing files; replace those silent adds with explicit existence
checks and clear logging: for each pattern (website/public/astro-editor-latest.*
, website/public/releases/*.png, website/src/content/docs/releases/*.mdx) test
if files exist (e.g., with globbing or "shopt -s nullglob" then check arrays)
and echo a warning or error to stderr if none found, then only run git add when
files exist; ensure the commit step still behaves as intended (keep the commit
message for $RELEASE_TAG) and consider failing the workflow or setting an
explicit non-zero exit when required artifacts are missing.
- Around line 72-141: The workflow duplicates the release sanitization and MDX
generation logic (see CLEAN_BODY, IMAGE_URLS, IMAGES_DIR, OUTPUT_FILE); replace
that shell block by invoking the existing TypeScript utility
(website/scripts/generate-release-pages.ts) from the workflow (e.g. run npx tsx
website/scripts/generate-release-pages.ts) and adapt the script to support a
single-release mode or tag filter (accept a --tag or --all flag and implement
tag-based processing and image download/curly-brace escaping there) so all
sanitization, image download, and MDX writing happen only in
generate-release-pages.ts.

In `@website/scripts/generate-release-pages.ts`:
- Around line 119-145: The localiseImages function uses execSync with curl which
can throw without contextual info when a download fails; update the download
block inside localiseImages to (1) add the --fail flag to the curl command, (2)
wrap the execSync call in try/catch, and (3) on error log a clear message
including the URL and localPath (and include the caught error.message), then
continue to the next image instead of letting the exception crash the script so
non-fatal failures are handled gracefully while preserving dryRun behavior.
- Around line 34-39: The function isPost1_0 extracts `minor` from match but
never uses it; update isPost1_0 to avoid the unused destructure by only
extracting/using `major` (e.g., read Number(match[1]) into `major`) and remove
`minor` from the destructuring so the linter warning is resolved while
preserving the existing `match` null check and the return expression `major >=
1`.
- Around line 189-205: The current code performs sequential synchronous execSync
calls when building releases (the summaries -> releases mapping that calls
`execSync` for each `gh release view`), which is slow; change this to fetch
bodies in parallel by replacing the `summaries.map` + synchronous `execSync`
with an asynchronous approach (e.g., use `child_process.exec`/promisified exec
or `execa`) and run all per-release `gh release view "${summary.tagName}" --repo
${REPO} --json body -q .body` calls with Promise.all, then await the results and
construct the `releases: Release[]` array; preserve encoding/formatting and
consider simple rate-limit error handling or batching if needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 9bbc31a5-f4e8-408e-ac19-2d2ed44343ec

📥 Commits

Reviewing files that changed from the base of the PR and between 1f7689d and 5228d6d.

⛔ Files ignored due to path filters (2)
  • website/public/releases/0.1.37-after.png is excluded by !**/*.png
  • website/public/releases/0.1.37-before.png is excluded by !**/*.png
📒 Files selected for processing (6)
  • .github/workflows/publish-website-artifacts.yml
  • website/scripts/generate-release-pages.ts
  • website/src/content/docs/releases/0.1.37.mdx
  • website/src/content/docs/releases/0.1.9.mdx
  • website/src/layouts/Layout.astro
  • website/src/pages/releases/index.astro
✅ Files skipped from review due to trivial changes (1)
  • website/src/content/docs/releases/0.1.37.mdx
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/src/content/docs/releases/0.1.9.mdx
  • website/src/layouts/Layout.astro

Comment on lines +110 to +116
for URL in $IMAGE_URLS; do
IMG_INDEX=$((IMG_INDEX + 1))
LOCAL_NAME="${VERSION}-${IMG_INDEX}.png"
curl -sL -o "${IMAGES_DIR}/${LOCAL_NAME}" "$URL"
CLEAN_BODY=$(printf '%s' "$CLEAN_BODY" | sed "s|${URL}|/releases/${LOCAL_NAME}|g")
echo "Downloaded image: ${LOCAL_NAME}"
done

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential issue with sed substitution when URL contains special characters.

The sed command uses | as a delimiter, but if $URL or $LOCAL_NAME contain pipe characters or other regex metacharacters, the substitution will fail or produce unexpected results.

Consider using a safer approach:

Proposed fix using awk or printf escaping
           for URL in $IMAGE_URLS; do
             IMG_INDEX=$((IMG_INDEX + 1))
             LOCAL_NAME="${VERSION}-${IMG_INDEX}.png"
             curl -sL -o "${IMAGES_DIR}/${LOCAL_NAME}" "$URL"
-            CLEAN_BODY=$(printf '%s' "$CLEAN_BODY" | sed "s|${URL}|/releases/${LOCAL_NAME}|g")
+            CLEAN_BODY="${CLEAN_BODY//"$URL"/"/releases/${LOCAL_NAME}"}"
             echo "Downloaded image: ${LOCAL_NAME}"
           done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-website-artifacts.yml around lines 110 - 116, The
sed substitution on CLEAN_BODY using the raw $URL and $LOCAL_NAME is unsafe when
those values contain regex metacharacters or the chosen delimiter; create and
use escaped versions (e.g., ESC_URL and ESC_LOCAL_NAME) that backslash-escape
sed-special characters (delimiter, /, &, |, etc.) before calling sed, or replace
the sed step with a literal-safe tool (awk or parameter expansion) that performs
a literal string replacement; update the loop to compute ESC_URL and
ESC_LOCAL_NAME from URL and LOCAL_NAME and use those escaped names in the sed
substitution that updates CLEAN_BODY.

Comment on lines +1 to +23
#!/usr/bin/env npx tsx
/**
* Generate release pages from GitHub releases.
*
* Usage:
* npx tsx scripts/generate-release-pages.ts [--all] [--dry-run]
*
* Options:
* --all Include all releases (post-1.0.0 are always included;
* pre-1.0.0 are included without prompting)
* --dry-run Print what would be generated without writing files
*
* Without --all, pre-1.0.0 releases are presented for manual approval.
*/

import { execSync } from 'node:child_process'
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
import * as readline from 'node:readline'

const RELEASES_DIR = join(import.meta.dirname, '../src/content/docs/releases')
const IMAGES_DIR = join(import.meta.dirname, '../public/releases')
const REPO = 'dannysmith/astro-editor'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if package.json specifies Node version requirements
echo "=== Checking package.json engines field ==="
fd -t f "package.json" --exec cat {} | jq -r '.engines // "No engines field"' 2>/dev/null | head -5

echo ""
echo "=== Checking for .nvmrc or .node-version ==="
cat .nvmrc 2>/dev/null || cat .node-version 2>/dev/null || echo "No version file found"

Repository: dannysmith/astro-editor

Length of output: 263


🏁 Script executed:

#!/bin/bash
# Get the full file to verify all issues mentioned in the scratchpad
cat -n website/scripts/generate-release-pages.ts

Repository: dannysmith/astro-editor

Length of output: 9253


Verify Node.js version compatibility for import.meta.dirname and fix unused variable.

import.meta.dirname (lines 21–22) requires Node.js 20.11.0 or 21.2.0+. No version constraints are documented in package.json or via .nvmrc/.node-version. Add an explicit Node version requirement to prevent runtime failures.

Additionally, the minor variable in isPost1_0() (line 37) is destructured but never used—remove it or use it if intended.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 1 - 23, Replace the
fragile import.meta.dirname usage (used in RELEASES_DIR and IMAGES_DIR) with a
Node-compatible approach: compute baseDir via fileURLToPath(import.meta.url) and
path.dirname (import fileURLToPath from 'node:url' and dirname from 'node:path')
so the script runs on older Node versions; additionally add an explicit Node
version constraint (e.g., "engines": { "node": ">=20.11.0" } in package.json and
create a .nvmrc/.node-version with the same version) to document requirements;
finally, remove the unused destructured variable minor from the isPost1_0()
function (or use it if intended) to eliminate the unused-variable warning.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (6)
website/scripts/generate-release-pages.ts (5)

134-135: Shell command injection risk with untrusted URLs.

The URL is interpolated directly into a shell command. While GitHub attachment URLs follow a predictable pattern, if the regex were to match an unexpected string, it could be exploited.

🛡️ Consider using spawn with argument array instead of execSync with string interpolation
+import { spawnSync } from 'node:child_process'

-      execSync(`curl -sL -o "${localPath}" "${url}"`)
+      spawnSync('curl', ['-sL', '-o', localPath, url], { stdio: 'inherit' })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 134 - 135, The
execSync call that interpolates url into a shell string (in the block guarded by
dryRun, referencing execSync, localPath and url) is vulnerable to shell
injection; replace it with a safe child_process invocation that passes arguments
as an array (e.g., spawnSync or execFile) or use a native HTTP client
(fetch/node-fetch/https) to download to localPath so the url is not interpreted
by a shell, and ensure you still honor dryRun and surface errors from the
download call.

79-101: Code fence detection doesn't handle ~~~ fences.

The escapeCurlyBraces function only checks for triple-backtick fences (```). Markdown also supports tilde fences (~~~), which could lead to incorrect brace escaping if release notes use them.

🔧 Handle both fence styles
   for (const line of lines) {
-    if (line.trimStart().startsWith('```')) {
+    const trimmed = line.trimStart()
+    if (trimmed.startsWith('```') || trimmed.startsWith('~~~')) {
       inCodeBlock = !inCodeBlock
       result.push(line)
       continue
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 79 - 101, The code
fence detection in escapeCurlyBraces only toggles inCodeBlock on lines starting
with '```', so tilde fences '~~~' are not recognized; update the check in
escapeCurlyBraces (and the local handling around the trimmed line) to detect
both fenced code markers by computing const trimmed = line.trimStart() and
toggling inCodeBlock when trimmed.startsWith('```') ||
trimmed.startsWith('~~~'), leaving the rest of the logic (including calls to
escapeLineOutsideCode) unchanged.

197-205: Synchronous execSync calls in a loop may be slow.

Fetching release bodies one-by-one with execSync is blocking and sequential. For repositories with many releases, this could take a significant amount of time.

This is acceptable for a manual/infrequent script, but if performance becomes an issue, consider batching or parallelizing the requests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 197 - 205, The loop
in generate-release-pages.ts that builds releases from summaries uses blocking
execSync calls (see summaries.map and execSync) which is slow; replace the
synchronous per-release calls with an asynchronous, parallel approach: either
use a non-blocking exec (child_process.exec or a Promise-based execa) called for
each summary and await Promise.all to fetch bodies concurrently, or switch to
the GitHub API client (octokit) to request release bodies in batch; update the
releases construction to await the parallel fetches and return the same {
...summary, body } shape so downstream code using releases remains unchanged.

34-39: Unused variable minor in destructuring.

The minor variable is extracted but never used since only major >= 1 is checked.

🧹 Suggested cleanup
 function isPost1_0(tag: string): boolean {
   const match = tag.match(/^v?(\d+)\.(\d+)\.(\d+)/)
   if (!match) return false
-  const [, major, minor] = match.map(Number)
+  const [, major] = match.map(Number)
   return major >= 1
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 34 - 39, The function
isPost1_0 currently destructures both major and minor from match but only uses
major, causing an unused variable; update the destructuring in isPost1_0 to only
extract the major version (or use a throwaway name like _minor) from the regex
match so the unused variable is removed, keeping the rest of the logic (const [,
major] = match.map(Number); return major >= 1) intact and ensuring no linter
warnings.

129-131: Assumes all GitHub attachment images are PNGs.

The localiseImages function hardcodes .png extension regardless of the actual image format. GitHub user-attachments can be JPEGs, GIFs, or other formats.

🖼️ Consider detecting format or using a generic extension

One approach is to use curl -sI to check the Content-Type header, or simply preserve a generic extension like .img and let the browser handle MIME detection. Alternatively, keep .png if you're confident all uploads are PNGs.

-    const localName = `${version}-${i + 1}.png`
+    // Consider fetching Content-Type or using original extension if available
+    const localName = `${version}-${i + 1}.png` // TODO: detect actual format
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 129 - 131, The
localiseImages code hardcodes ".png" when building localName (using urls.forEach
and version), which breaks for JPEG/GIF attachments; modify localiseImages to
determine each image's real extension before saving—either by fetching the URL
headers (e.g., a HEAD request to read Content-Type) or by extracting and
preserving the original filename/extension from the URL/response, then use that
extension when composing localName and updating result; ensure fallback to a
safe generic extension (e.g., .img) if detection fails and update any code that
writes/serves the file to use the detected extension.
.github/workflows/publish-website-artifacts.yml (1)

147-150: Git add with 2>/dev/null || true silently ignores failures.

While this prevents the workflow from failing when files don't exist, it also masks legitimate errors. Consider checking file existence explicitly or using git add --ignore-missing (if available) for clearer intent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-website-artifacts.yml around lines 147 - 150, The
git add lines currently swallow all errors with "2>/dev/null || true"; change
them to explicitly handle missing files by either using "git add
--ignore-missing" for the three add commands or guard each add with an existence
check (e.g., test -e) before calling git add so real git failures aren't hidden;
keep the final git commit -m "chore: update installers and add release page for
$RELEASE_TAG" behavior but remove the error-silencing on the add commands (refer
to the git add lines adding website/public/astro-editor-latest.* ,
website/public/releases/*.png, and website/src/content/docs/releases/*.mdx to
locate the exact statements).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/publish-website-artifacts.yml:
- Around line 72-139: The bash step duplicates and diverges from the existing
TypeScript logic; instead of the CLEAN_BODY sanitization, call the existing
script (website/scripts/generate-release-pages.ts) to generate the MDX so
behavior (Full Changelog stripping, curly-brace escaping, H2 stripping) remains
consistent—add a prior step to install Node/Bun runtime, then invoke the TS
script with RELEASE_TAG (and/or output dir) so IMAGES_DIR/IMAGE_URLS handling
and output file creation are handled by the single canonical implementation;
remove the inline awk/sed sanitization and the image-download loop from this
job.
- Around line 83-86: The sed patterns that sanitize RELEASE_BODY are too strict:
update the CLEAN_BODY pipeline to make the H2 match accept leading whitespace by
changing the H2 sed expression (the one using /^## *\(🚀 *\)\{0,1\}Astro Editor
v[0-9]/d) to allow optional leading whitespace (e.g., use a pattern with
^[[:space:]]* before the ##) and broaden the Full Changelog sed (the one using
/^\*\*Full Changelog\*\*/d) to also match the trailing colon or optional
punctuation after "**Full Changelog**" (e.g., allow an optional ":"/space/URL
suffix) so it reliably removes that line in real release notes.

---

Nitpick comments:
In @.github/workflows/publish-website-artifacts.yml:
- Around line 147-150: The git add lines currently swallow all errors with
"2>/dev/null || true"; change them to explicitly handle missing files by either
using "git add --ignore-missing" for the three add commands or guard each add
with an existence check (e.g., test -e) before calling git add so real git
failures aren't hidden; keep the final git commit -m "chore: update installers
and add release page for $RELEASE_TAG" behavior but remove the error-silencing
on the add commands (refer to the git add lines adding
website/public/astro-editor-latest.* , website/public/releases/*.png, and
website/src/content/docs/releases/*.mdx to locate the exact statements).

In `@website/scripts/generate-release-pages.ts`:
- Around line 134-135: The execSync call that interpolates url into a shell
string (in the block guarded by dryRun, referencing execSync, localPath and url)
is vulnerable to shell injection; replace it with a safe child_process
invocation that passes arguments as an array (e.g., spawnSync or execFile) or
use a native HTTP client (fetch/node-fetch/https) to download to localPath so
the url is not interpreted by a shell, and ensure you still honor dryRun and
surface errors from the download call.
- Around line 79-101: The code fence detection in escapeCurlyBraces only toggles
inCodeBlock on lines starting with '```', so tilde fences '~~~' are not
recognized; update the check in escapeCurlyBraces (and the local handling around
the trimmed line) to detect both fenced code markers by computing const trimmed
= line.trimStart() and toggling inCodeBlock when trimmed.startsWith('```') ||
trimmed.startsWith('~~~'), leaving the rest of the logic (including calls to
escapeLineOutsideCode) unchanged.
- Around line 197-205: The loop in generate-release-pages.ts that builds
releases from summaries uses blocking execSync calls (see summaries.map and
execSync) which is slow; replace the synchronous per-release calls with an
asynchronous, parallel approach: either use a non-blocking exec
(child_process.exec or a Promise-based execa) called for each summary and await
Promise.all to fetch bodies concurrently, or switch to the GitHub API client
(octokit) to request release bodies in batch; update the releases construction
to await the parallel fetches and return the same { ...summary, body } shape so
downstream code using releases remains unchanged.
- Around line 34-39: The function isPost1_0 currently destructures both major
and minor from match but only uses major, causing an unused variable; update the
destructuring in isPost1_0 to only extract the major version (or use a throwaway
name like _minor) from the regex match so the unused variable is removed,
keeping the rest of the logic (const [, major] = match.map(Number); return major
>= 1) intact and ensuring no linter warnings.
- Around line 129-131: The localiseImages code hardcodes ".png" when building
localName (using urls.forEach and version), which breaks for JPEG/GIF
attachments; modify localiseImages to determine each image's real extension
before saving—either by fetching the URL headers (e.g., a HEAD request to read
Content-Type) or by extracting and preserving the original filename/extension
from the URL/response, then use that extension when composing localName and
updating result; ensure fallback to a safe generic extension (e.g., .img) if
detection fails and update any code that writes/serves the file to use the
detected extension.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: f225c4ca-b22e-44bb-8713-e858f4c77d53

📥 Commits

Reviewing files that changed from the base of the PR and between 1f7689d and 5228d6d.

⛔ Files ignored due to path filters (2)
  • website/public/releases/0.1.37-after.png is excluded by !**/*.png
  • website/public/releases/0.1.37-before.png is excluded by !**/*.png
📒 Files selected for processing (6)
  • .github/workflows/publish-website-artifacts.yml
  • website/scripts/generate-release-pages.ts
  • website/src/content/docs/releases/0.1.37.mdx
  • website/src/content/docs/releases/0.1.9.mdx
  • website/src/layouts/Layout.astro
  • website/src/pages/releases/index.astro
🚧 Files skipped from review as they are similar to previous changes (4)
  • website/src/content/docs/releases/0.1.37.mdx
  • website/src/content/docs/releases/0.1.9.mdx
  • website/src/layouts/Layout.astro
  • website/src/pages/releases/index.astro

Comment on lines +72 to +139
- name: Generate release page
run: |
RELEASE_BODY=$(gh release view "$RELEASE_TAG" --json body -q .body)
VERSION="${RELEASE_TAG#v}"
DATE=$(gh release view "$RELEASE_TAG" --json publishedAt -q .publishedAt | cut -dT -f1)

# Sanitise body for MDX:
# - Strip leading H2 title
# - Strip "Installation Instructions" section and everything after
# - Strip "Full Changelog" links
# - Escape curly braces outside code spans/blocks
CLEAN_BODY=$(printf '%s\n' "$RELEASE_BODY" | \
sed '/^## *\(🚀 *\)\{0,1\}Astro Editor v[0-9]/d' | \
sed '/^### Installation Instructions/,$d' | \
sed '/^\*\*Full Changelog\*\*/d' | \
awk '
/^```/ { in_code = !in_code }
in_code { print; next }
{
line = ""
n = split($0, chars, "")
in_tick = 0
for (i = 1; i <= n; i++) {
if (chars[i] == "`") in_tick = !in_tick
if (!in_tick && chars[i] == "{") { line = line "" "&#123;"; continue }
if (!in_tick && chars[i] == "}") { line = line "" "&#125;"; continue }
line = line chars[i]
}
print line
}
' | \
sed -e :a -e '/^[[:space:]]*$/{ $d; N; ba; }')

# Download GitHub attachment images to local repo
IMAGES_DIR="website/public/releases"
mkdir -p "$IMAGES_DIR"
IMAGE_URLS=$(printf '%s\n' "$CLEAN_BODY" | grep -oE 'https://github\.com/user-attachments/assets/[a-f0-9-]+' | sort -u || true)
IMG_INDEX=0
for URL in $IMAGE_URLS; do
IMG_INDEX=$((IMG_INDEX + 1))
LOCAL_NAME="${VERSION}-${IMG_INDEX}.png"
curl -sL -o "${IMAGES_DIR}/${LOCAL_NAME}" "$URL"
CLEAN_BODY=$(printf '%s' "$CLEAN_BODY" | sed "s|${URL}|/releases/${LOCAL_NAME}|g")
echo "Downloaded image: ${LOCAL_NAME}"
done

# Generate MDX file
RELEASES_DIR="website/src/content/docs/releases"
mkdir -p "$RELEASES_DIR"
OUTPUT_FILE="$RELEASES_DIR/${VERSION}.mdx"

{
printf '%s\n' "---"
printf '%s\n' "title: 'v${VERSION}'"
printf '%s\n' "description: 'Astro Editor v${VERSION}'"
printf '%s\n' "date: ${DATE}"
printf '%s\n' "slug: 'releases/v${VERSION}'"
printf '%s\n' "---"

if [ -n "$CLEAN_BODY" ]; then
printf '\n%s\n\n%s\n' "$CLEAN_BODY" "---"
fi

printf '\n%s\n' "[View on GitHub](https://github.com/dannysmith/astro-editor/releases/tag/${RELEASE_TAG})"
} > "$OUTPUT_FILE"

echo "Generated release page: $OUTPUT_FILE"
cat "$OUTPUT_FILE"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Duplicated sanitization logic diverges from the TypeScript implementation.

This inline bash reimplements the release page generation logic that already exists in website/scripts/generate-release-pages.ts. The implementations have subtle differences that may produce inconsistent results:

  1. Full Changelog stripping (line 86): Bash uses /^\*\*Full Changelog\*\*/d which only matches lines starting with **Full Changelog**, while TypeScript uses /\*\*Full Changelog\*\*:.*$/gm which matches anywhere and requires the colon.

  2. Curly brace escaping (lines 87-101): The bash awk tracks single backticks character-by-character, but doesn't handle multi-backtick delimiters like `` `code` `` that the TypeScript version supports via regex splitting.

  3. H2 title stripping (line 84): Minor regex differences in whitespace handling.

Consider invoking the TypeScript script directly instead of maintaining parallel implementations:

🔧 Suggested approach: Use the existing script
       - name: Generate release page
         run: |
-          RELEASE_BODY=$(gh release view "$RELEASE_TAG" --json body -q .body)
-          # ... 60+ lines of bash sanitization ...
+          cd website
+          npx tsx scripts/generate-release-pages.ts --all
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

This requires setting up Node/Bun in an earlier step, but ensures consistent behavior between manual and automated generation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-website-artifacts.yml around lines 72 - 139, The
bash step duplicates and diverges from the existing TypeScript logic; instead of
the CLEAN_BODY sanitization, call the existing script
(website/scripts/generate-release-pages.ts) to generate the MDX so behavior
(Full Changelog stripping, curly-brace escaping, H2 stripping) remains
consistent—add a prior step to install Node/Bun runtime, then invoke the TS
script with RELEASE_TAG (and/or output dir) so IMAGES_DIR/IMAGE_URLS handling
and output file creation are handled by the single canonical implementation;
remove the inline awk/sed sanitization and the image-download loop from this
job.

Comment thread .github/workflows/publish-website-artifacts.yml
dannysmith and others added 2 commits March 17, 2026 15:42
* origin/main:
  Fix ordering of versions
  chore(deps): bump wrangler
Fix incorrect keyboard shortcuts in docs (Redo: Cmd+Shift+Z, Focus Mode:
Cmd+Shift+F), fix typo "comitting", document both config file paths
(src/content/config.ts and src/content.config.ts), fix image field
example to use schema callback, fix shell injection in generate-release-pages
by using execFileSync, remove unused variable, and add cross-reference
comments between duplicated sanitization logic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
website/scripts/generate-release-pages.ts (1)

195-209: Consider using execFileSync for gh CLI calls to avoid shell interpolation.

While the tagName comes from GitHub's API and is unlikely to be malicious, using execSync with string interpolation is a less safe pattern. The curl call on line 139 correctly uses execFileSync.

♻️ Safer approach using execFileSync
-  const json = execSync(
-    `gh release list --repo ${REPO} --limit 100 --json tagName,name,publishedAt`,
-    { encoding: 'utf-8' }
-  )
+  const json = execFileSync(
+    'gh',
+    ['release', 'list', '--repo', REPO, '--limit', '100', '--json', 'tagName,name,publishedAt'],
+    { encoding: 'utf-8' }
+  )
-    const body = execSync(
-      `gh release view "${summary.tagName}" --repo ${REPO} --json body -q .body`,
-      { encoding: 'utf-8' }
-    )
+    const body = execFileSync(
+      'gh',
+      ['release', 'view', summary.tagName, '--repo', REPO, '--json', 'body', '-q', '.body'],
+      { encoding: 'utf-8' }
+    )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/scripts/generate-release-pages.ts` around lines 195 - 209, The gh CLI
calls that build command strings with execSync (used to list releases and to
fetch each release body in generate-release-pages.ts where json, summaries and
releases are created) should be replaced with execFileSync to avoid shell
interpolation: call execFileSync('gh',
['release','list','--repo',REPO,'--limit','100','--json','tagName,name,publishedAt'],
{ encoding: 'utf-8' }) and similarly call execFileSync('gh', ['release','view',
summary.tagName, '--repo', REPO, '--json', 'body', '-q', '.body'], { encoding:
'utf-8' }) inside the summaries.map; ensure you pass summary.tagName as a
separate arg (not interpolated), preserve the encoding option, and trim the
returned body string if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@website/src/content/docs/getting-started.mdx`:
- Line 18: Update the keyboard shortcut text to show both macOS and
Windows/Linux variants: replace the standalone "Cmd+S" mention in the "Start
Writing" step with a cross-platform phrasing that references the codebase's
"mod+s" mapping (e.g., "Cmd+S (macOS) / Ctrl+S (Windows/Linux)" or "mod+s —
Cmd+S on macOS, Ctrl+S on Windows/Linux") so readers on all platforms see the
correct shortcut.
- Line 35: Update the macOS-only shortcut text that currently reads "Cmd+1" and
"Cmd+2" to include Windows/Linux variants by referencing the cross-platform
mapping used in the codebase (mod+1 → Cmd+1 on macOS and Ctrl+1 on
Windows/Linux, mod+2 → Cmd+2 on macOS and Ctrl+2 on Windows/Linux); replace the
strings "Cmd+1" and "Cmd+2" with a concise phrasing that shows both variants
(e.g., "Cmd/Ctrl+1" and "Cmd/Ctrl+2" or "mod+1 / Ctrl+1" style) so readers on
all platforms see the correct keyboard shortcuts.

---

Nitpick comments:
In `@website/scripts/generate-release-pages.ts`:
- Around line 195-209: The gh CLI calls that build command strings with execSync
(used to list releases and to fetch each release body in
generate-release-pages.ts where json, summaries and releases are created) should
be replaced with execFileSync to avoid shell interpolation: call
execFileSync('gh',
['release','list','--repo',REPO,'--limit','100','--json','tagName,name,publishedAt'],
{ encoding: 'utf-8' }) and similarly call execFileSync('gh', ['release','view',
summary.tagName, '--repo', REPO, '--json', 'body', '-q', '.body'], { encoding:
'utf-8' }) inside the summaries.map; ensure you pass summary.tagName as a
separate arg (not interpolated), preserve the encoding option, and trim the
returned body string if needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 2204d70e-6f67-4db6-8f8f-7da64917ad1a

📥 Commits

Reviewing files that changed from the base of the PR and between 5228d6d and 10f1377.

📒 Files selected for processing (7)
  • .github/workflows/publish-website-artifacts.yml
  • website/scripts/generate-release-pages.ts
  • website/src/content/docs/editing/overview.mdx
  • website/src/content/docs/frontmatter/image-fields.mdx
  • website/src/content/docs/getting-started.mdx
  • website/src/content/docs/getting-started/opening-a-project.mdx
  • website/src/content/docs/philosophy.mdx
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/src/content/docs/getting-started/opening-a-project.mdx
  • website/src/content/docs/editing/overview.mdx


3. **Open a File**: Click on any markdown or MDX file in the file list to open it in the main editor. The editor will show your content without the frontmatter, which appears in the right sidebar.

4. **Start Writing**: Begin editing. Your changes are automatically saved every 2 seconds, and you can manually save anytime with `Cmd+S`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Include Windows/Linux keyboard shortcut variant.

The shortcut Cmd+S only applies to macOS. The codebase uses mod+s which maps to Ctrl+S on Windows/Linux. Consider documenting both variants for cross-platform users.

Suggested wording
-4. **Start Writing**: Begin editing. Your changes are automatically saved every 2 seconds, and you can manually save anytime with `Cmd+S`.
+4. **Start Writing**: Begin editing. Your changes are automatically saved every 2 seconds, and you can manually save anytime with `Cmd+S` (Mac) or `Ctrl+S` (Windows/Linux).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
4. **Start Writing**: Begin editing. Your changes are automatically saved every 2 seconds, and you can manually save anytime with `Cmd+S`.
4. **Start Writing**: Begin editing. Your changes are automatically saved every 2 seconds, and you can manually save anytime with `Cmd+S` (Mac) or `Ctrl+S` (Windows/Linux).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/getting-started.mdx` at line 18, Update the keyboard
shortcut text to show both macOS and Windows/Linux variants: replace the
standalone "Cmd+S" mention in the "Start Writing" step with a cross-platform
phrasing that references the codebase's "mod+s" mapping (e.g., "Cmd+S (macOS) /
Ctrl+S (Windows/Linux)" or "mod+s — Cmd+S on macOS, Ctrl+S on Windows/Linux") so
readers on all platforms see the correct shortcut.

| **Right Sidebar** | Dynamic frontmatter forms generated from your Astro collection schemas |
| **Top Bar** | Project name, window controls, and menu access |

Both sidebars can be hidden using `Cmd+1` (left) and `Cmd+2` (right) for distraction-free writing. The panels remember their sizes and visibility between sessions.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Include Windows/Linux keyboard shortcut variants for sidebar toggles.

Same as above—Cmd+1 and Cmd+2 are macOS-specific. The codebase uses mod+1 and mod+2, which map to Ctrl+1 and Ctrl+2 on Windows/Linux.

Suggested wording
-Both sidebars can be hidden using `Cmd+1` (left) and `Cmd+2` (right) for distraction-free writing. The panels remember their sizes and visibility between sessions.
+Both sidebars can be hidden using `Cmd+1`/`Ctrl+1` (left) and `Cmd+2`/`Ctrl+2` (right) for distraction-free writing. The panels remember their sizes and visibility between sessions.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Both sidebars can be hidden using `Cmd+1` (left) and `Cmd+2` (right) for distraction-free writing. The panels remember their sizes and visibility between sessions.
Both sidebars can be hidden using `Cmd+1`/`Ctrl+1` (left) and `Cmd+2`/`Ctrl+2` (right) for distraction-free writing. The panels remember their sizes and visibility between sessions.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/content/docs/getting-started.mdx` at line 35, Update the
macOS-only shortcut text that currently reads "Cmd+1" and "Cmd+2" to include
Windows/Linux variants by referencing the cross-platform mapping used in the
codebase (mod+1 → Cmd+1 on macOS and Ctrl+1 on Windows/Linux, mod+2 → Cmd+2 on
macOS and Ctrl+2 on Windows/Linux); replace the strings "Cmd+1" and "Cmd+2" with
a concise phrasing that shows both variants (e.g., "Cmd/Ctrl+1" and "Cmd/Ctrl+2"
or "mod+1 / Ctrl+1" style) so readers on all platforms see the correct keyboard
shortcuts.

* origin/main:
  Formatting issues
  Improve UI font handling on Linux (#167)
  Fix Content Linker
  Update docs and complete tasks
  Upgrade vite
  Update jsdom
  Update knip
  Upgrade lucide-react from 0.564 to 1.7
  Upgrade @ast-grep/cli from 0.41 to 0.42
  Update deps
  Upgrade deps
  Update task doc to reflect completed phases
  Upgrade notify crate from v8 to v9.0.0-rc.2
  Add file watcher error recovery and periodic rescan
  Fix macOS window close to hide instead of quit
  chore(deps): bump rustls-webpki from 0.103.9 to 0.103.10 in /src-tauri
  chore(deps): bump wrangler
  chore(deps): bump tar from 0.4.44 to 0.4.45 in /src-tauri
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants