CodeForPhilly / CodeForPhilly/codeforphilly-ng

Revive blog posts as a content-typed gitsheets sheet (revises the deferred decision)

Đang mở
#45 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
TypeScript
Star
1
Fork
1
Merge trung bình
5 ngày 3 giờ
Pull request đã merge (30 ngày)
9

Mô tả

[specs/deferred.md](https://github.com/CodeForPhilly/codeforphilly-ng/blob/main/specs/deferred.md) currently says blog posts get replaced by "staff-authored markdown files in the code repo at `apps/web/src/content/blog/.md`, shipped via PR." That decision predates [gitsheets v1.2](https://github.com/JarvusInnovations/gitsheets/releases/tag/v1.2.0)'s content-typed records.

With v1.2 we can give blog posts their own gitsheets sheet — markdown bodies + TOML frontmatter — and get a better outcome than files-in-code-repo:

## Why this beats the original deferral

| Concern | Files-in-code-repo | Content-typed sheet |
|---|---|---|
| PR-reviewable | ✅ | ✅ |
| Publish cadence | Tied to web deploys | Immediate on data-repo merge |
| Tags / cross-links | Ad-hoc frontmatter | Native `TagAssignment` |
| Author attribution | Hand-stamp in frontmatter | Native `Person` reference |
| Snapshot inclusion | Not in data snapshot | In the snapshot (pseudonymized) |
| API serving | Bespoke Vite handler | Existing read API pipeline |
| `/blog` index cost | Bundle every post into web build | `queryAll({ withBody: false })` |
| laddr-import revival | Out of scope | Resurrect `blog_posts` table on the existing one-shot import |

## Sheet shape

```toml
# .gitsheets/blog-posts.toml
[gitsheet]
root = 'blog-posts'
path = '${{ slug }}'

[gitsheet.format]
type = 'markdown'
body = 'body'

[gitsheet.schema]
$ref = './schemas/BlogPost.schema.json'
```

`BlogPost` entity (in `packages/shared/src/schemas/blog-post.ts`):
- `id` UUIDv7
- `legacyId` (laddr's `BlogPost.ID`, for the importer's idempotence)
- `slug` (kebab-case, slug-handle conventions)
- `title`
- `summary` (short markdown — stays in frontmatter)
- `authorId` → Person
- `postedAt` (iso8601)
- `editedAt` nullable
- `featuredImageKey` nullable (attachment via gitsheets)
- `deletedAt` nullable (soft-delete)
- `body` (the markdown body — the designated content field)
- standard `createdAt` / `updatedAt`

## Routing

Add to the SPA:
- `/blog` — index (paginated, optional tag filter)
- `/blog/:slug` — detail
- `/blog/tag/:namespace/:slug` — tag-filtered (reuse `TagsNamespace` pattern)

API:
- `GET /api/blog-posts` (list with facets, q, sort, page)
- `GET /api/blog-posts/:slug` (detail)
- `POST/PATCH/DELETE` — staff-only (per the original spec, blog wasn't a per-user-role CMS)

## laddr-import revival

The existing one-shot importer at `apps/api/scripts/import-laddr.ts` currently skips `blog_posts`. Re-add it as another translator in [`apps/api/scripts/import-laddr/translators.ts`](https://github.com/CodeForPhilly/codeforphilly-ng/blob/main/apps/api/scripts/import-laddr/translators.ts):

- Map `BlogPost.Slug` → `slug` (slugify-with-dedupe if invalid)
- Map `BlogPost.Title` → `title`
- Map `BlogPost.Body` → `body`
- Map `BlogPost.AuthorID` → resolve via the existing `idMaps.personByLegacy`
- Map `BlogPost.Published` (and similar) → `postedAt`
- Preserve `legacyId` so re-runs are idempotent

## Sequencing

- Depends on [#44](https://github.com/CodeForPhilly/codeforphilly-ng/issues/44) (content-typed gitsheets is the substrate) — or stand on its own as the first content-typed sheet in the project. Either order works since blog-posts is a brand-new sheet that doesn't conflict with the existing TOML-only ones.
- Sequenced after `cutover-prep` so existing migration paths stay valid through cutover.

## Spec updates needed

- `specs/deferred.md` — update the "Blog (`/blog`) as a user-facing CMS" entry from "files in code repo" to "content-typed sheet, see this issue."
- New spec files: `specs/api/blog.md`, `specs/screens/blog-index.md`, `specs/screens/blog-detail.md`.
- `specs/data-model.md` — add `BlogPost` entity.
- `specs/behaviors/legacy-id-mapping.md` — note the new `BlogPost.legacyId` axis.

Out of scope: comments, reactions, the multi-author "posts under a topic" workflow — keep it as simple as the original deferral imagined.

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.