CommunityPro / CommunityPro/community-pro-api
Content: public read endpoints, Meilisearch posts index, ISR revalidation (Phase 4.4)
- Dominant language
- C#
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## Scope
Public read surface + search sync + frontend cache invalidation for the blog.
## Endpoints (anonymous)
| Method | Path | Notes |
|---|---|---|
| GET | `/posts` | **published only**, tag filter, paginated, newest first |
| GET | `/posts/{slug}` | published only; feeds the ISR post page |
| GET | `/posts/featured` | the single featured published post |
## Meilisearch `posts` index
- Follow the `CommunityPro.Search` module patterns exactly (hand-rolled REST client, index+settings ensured at boot, sync-on-write handler that logs failures and never throws).
- Document shape mirrors public card data only: id, slug, title, excerpt, tags, authorId, publishedAt. Searchable: `title, excerpt, tags`; filterable: `tags`; sortable: `publishedAt`. **Never index drafts/submitted/rejected posts — publish adds, unpublish/reject removes.**
- Extend the existing `reindex` command (`dotnet run -- reindex`) to rebuild `posts` alongside `members` in 500-doc batches.
## ISR revalidation
On `PostPublished`: `POST {FRONTEND_URL}/api/revalidate?tag=post-{slug}` with a shared secret header (`REVALIDATE_SECRET` — treat like any credential). Best-effort with logging; never fail the pipeline.
## Error codes
`content.not_found`, `search.unavailable` (degrade like members search does)
## Dependencies
Blocked by #3; consumes the `PostPublished` event emitted by #4.
## Acceptance criteria
- [ ] Unpublished posts are unreachable via every public endpoint and absent from the index (query-level filtering, tested)
- [ ] `PostPublished` handler upserts the search doc; failure is logged, not thrown
- [ ] Revalidation call sends the secret and swallows/logs failures
- [ ] `reindex` rebuilds posts (test via the existing search fakes)
### Conventions (project-wide, non-negotiable)
- .NET 9, records for immutable shapes, file-scoped namespaces, primary constructors where they read well. Minimal-API endpoints grouped per module via `IEndpointModule.MapEndpoints`.
- `Result` (SharedKernel) instead of exception-driven control flow. Endpoint results map failures to ProblemDetails with the stable error codes listed above — the frontend keys off them.
- Module owns its EF Core `DbContext` mapped to its own Postgres schema. Modules never reference each other's internals — cross-module needs go through a public contract interface or an in-process domain event (`IEventPublisher`).
- All external calls (GitHub, Stripe, Brevo, Cloudinary, Meilisearch) behind interfaces owned by the consuming module.
- Every list endpoint paginated (offset is fine). xUnit tests in `tests/CommunityPro.Tests//` following the existing harness patterns (see `Members/MembersTestHarness.cs`).
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the CommunityPro.Search module patterns, the existing reindex command, and tests using the existing search fakes; Members/MembersTestHarness.cs shows the project’s test harness conventions. Trace the PostPublished event emitted by #4 and the public endpoint grouping conventions. Done means all acceptance criteria pass, including filtering unpublished posts, resilient sync and revalidation, stable error codes, and batched reindexing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, postgres
- Domain
- api, backend, databases, frontend, search
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100