Skip to content

Post visibility refactor: isPostVisible, siteMeta, sitemap filter#78

Merged
hasparus merged 10 commits into
mainfrom
claude/post-visibility-refactor
Jun 2, 2026
Merged

Post visibility refactor: isPostVisible, siteMeta, sitemap filter#78
hasparus merged 10 commits into
mainfrom
claude/post-visibility-refactor

Conversation

@hasparus

@hasparus hasparus commented Apr 21, 2026

Copy link
Copy Markdown
Owner

Summary

Three small, independent refactors that emerged while making haspar.us agent-ready:

  1. isPostVisible helper — replaces scattered `!p.frontmatter.draft` filters across `BaseLayout`, `llms.txt`, `llms-full.txt`, and the markdown endpoint. Adds a new `hidden` frontmatter flag (never rendered, even in dev) alongside the existing `draft` (hidden in prod). Non-breaking.

  2. `src/lib/siteMeta.ts` — single override point for `SITE_NAME` + `SITE_BLURB`, replacing the two `TODO(downstream)` comments in `llms.txt.ts` and `BaseLayout.astro`. Downstream consumers can extend this module with `AUTHOR` and thread it through their own `PostLayout` / `rss`.

  3. Sitemap filter — `@astrojs/sitemap` was previously unfiltered, so hidden/draft posts leaked into `sitemap-index.xml` even though every other endpoint (llms.txt, BaseLayout post list) filtered them. `getHiddenPostUrls()` scans `/posts` at config-load time and passes hidden URL paths to sitemap's `filter` hook. No change for zaduma's own demo content (no hidden posts), but downstream sites (e.g. haspar.us has `nie-trzeba` and `rpg` marked `hidden`) now stay out of the sitemap automatically.

Test plan

  • `pnpm build` passes; all 10 pages render
  • `sitemap-0.xml` unchanged for current demo content
  • Manually verified: adding `hidden: true` to a demo post removes it from sitemap + llms.txt + post list

Open in Devin Review

Replaces scattered `!p.frontmatter.draft` filters with a single
`isPostVisible(frontmatter)` helper used by BaseLayout, llms.txt,
llms-full.txt, and the markdown endpoint.

Adds PostFrontmatter.hidden alongside the existing draft field:
- draft: hidden in PROD, visible in dev (unchanged semantics)
- hidden: never rendered (new)

Non-breaking: existing `draft: true` posts behave identically.
Gives downstream a single file to override instead of duplicating the
constants across llms.txt.ts and BaseLayout.astro. Also drops the two
`TODO(downstream)` comments — the override point is now explicit.
Previously, @astrojs/sitemap saw every prerendered page, so posts with
`hidden: true` (or `draft: true` in prod) leaked into sitemap-index.xml
even though they were filtered out of BaseLayout's post list and the
llms.txt endpoints.

getHiddenPostUrls() scans /posts at config-load time, extracts the set
of hidden URL paths, and the sitemap `filter` hook drops them.

Zaduma's own demo content has no hidden/draft posts, so behavior is
unchanged — but downstream consumers (e.g. sites that stash unpublished
notes under /posts) now stay out of the sitemap automatically.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 1 potential issue.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment on lines +49 to +52
/** Hidden in PROD, visible in dev. */
draft?: boolean;
/** Never rendered, including in dev. */
hidden?: boolean;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Incomplete migration: [...path].astro still generates pages for hidden posts

The PR introduces hidden on PostFrontmatter (documented as "Never rendered, including in dev") and the centralized isPostVisible helper, but src/pages/[...path].astro:24-25 still uses the old !post.frontmatter.draft check in a PROD-only guard. This means posts with hidden: true will still have full HTML pages generated and accessible at their URL in both dev and production. The same incomplete migration applies to src/pages/index.astro:14-15, which will still list hidden posts on the homepage.

Prompt for agents
The PR introduces the `hidden` field on PostFrontmatter and creates `isPostVisible` to centralize visibility logic, but two critical pages were not updated:

1. src/pages/[...path].astro (lines 24-25): This is the main route that generates HTML pages for each post. It still uses the old pattern `if (import.meta.env.PROD) { posts = posts.filter((post) => !post.frontmatter.draft); }`. It needs to import and use `isPostVisible` instead, so hidden posts never get page routes.

2. src/pages/index.astro (lines 14-15): This is the homepage post listing. Same old pattern. Needs to use `isPostVisible` so hidden posts don't appear in the listing.

Both files should be updated to match the pattern used in BaseLayout.astro, [...path].md.ts, llms.txt.ts, and llms-full.txt.ts — replace the PROD-only draft check with `.filter(p => isPostVisible(p.frontmatter))`.

Additionally, src/pages/rss.xml.ts has no visibility filtering at all and should also be updated.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

hasparus added 7 commits June 1, 2026 23:13
Replace PROD-only draft filter with isPostVisible in [...path].astro,
index.astro, and add visibility filtering to rss.xml.ts so hidden posts
are excluded from page routes, the homepage listing, and the RSS feed.

Also ignore *.md in eslint (root README failed TS parser).
Sitemap exclusion derived from hiddenPostUrls treated draft:true as
hidden unconditionally and built /slug/ (trailing slash), drifting from
the runtime isPostVisible policy (draft hidden only in PROD) and risking
silent slash-mismatch re-inclusion.

- isPostVisible takes optional { isProd } so the build-time scanner reuses
  the exact same policy (import.meta.env-safe outside Vite)
- getHiddenPostPaths (was getHiddenPostUrls) applies isPostVisible and
  returns canonical no-trailing-slash paths via shared postPath helper
- postPath: single path-normalization rule, used by both the scanner and
  urlOutsideOfPagesDirPlugin
- sitemap filter strips trailing slash on both sides before lookup
Attempt to fix CI hang on 'playwright install --with-deps chromium'.
Add timeout-minutes guards and non-interactive apt env to surface
which half of '--with-deps' hangs and fail fast instead of stalling.
@hasparus hasparus merged commit 31f92de into main Jun 2, 2026
3 checks passed
@hasparus hasparus deleted the claude/post-visibility-refactor branch June 2, 2026 16:34
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.

1 participant