Prompt file imported from dthompsonfl/eccb.app (
.github/prompts/old/CMS_UPDATE_COMPLETE.prompt.md). Fill in{{page_slug}}before use. Copyright stays with the author.
--- /dev/null
Autonomous Agent Instructions: CMS Fixes & Production Readiness (Extended)
Background & Current Errors
The CMS is a Next.js 16.1.6 application using the app router and Turbopack. Two blockers have been reported:
-
Hydration error on
/admin/pages/newIn HTML, <li> cannot be a descendant of <li>. This will cause a hydration error.- Trace: Browser console points to
src/components/ui/breadcrumb.tsxat line 71. - Hierarchy:
Breadcrumbs→BreadcrumbItem(renders<li>) →BreadcrumbSeparator(renders<li>). - Usage: the breadcrumb appears in
src/app/(admin)/admin/pages/new/page.tsx(line 14).
- Trace: Browser console points to
-
Page creation hangs indefinitely
- Submitting the form on
/admin/pages/newshows no network activity or client‑side error. - The server action invoked by the form never resolves nor returns data.
- Submitting the form on
These two issues block CMS operation and must be fixed. In addition, the CMS codebase should be audited end‑to‑end to ensure full CRUD functionality, data validation, slug uniqueness, caching, error handling and general production readiness.
1. Fix Breadcrumb Hydration Error (Invalid HTML Nesting)
Problem
BreadcrumbSeparator renders an <li> element. When used inside a BreadcrumbItem component (which itself renders an <li>), the resulting DOM is <li><li>…</li></li>, violating HTML rules and triggering a hydration error.
Steps to Resolve
- Open
src/components/ui/breadcrumb.tsx. - Locate the
BreadcrumbSeparatorcomponent definition. - Update the component to:
- Render a
<span>(or<div role="presentation">) instead of<li>. - Change its props type from
React.ComponentProps<"li">toReact.ComponentProps<"span">. - Preserve the current attributes used for styling and accessibility (
role="presentation"andaria-hidden="true").
- Render a
- Run the app and verify that
src/components/shared/breadcrumbs.tsxno longer outputs nested<li>tags. Inspect the DOM via browser devtools. - Confirm visual styling remains identical – adjust Tailwind classes if necessary.
- Add a unit test if one exists for breadcrumbs (optional but encouraged).
2. Fix Page Creation "Hanging" Issue
Investigation
- Open
src/app/(admin)/admin/pages/new/page.tsx. Identify theonSubmithandler orformaction. Note which server action is invoked; it should referencecreatePagefromsrc/app/(admin)/admin/pages/actions.tsbut there may also be a legacy/alternatesrc/app/actions/cms.tsfile elsewhere in the repo – locate both and determine which one the UI actually uses. - Open the referenced action(s). In the current repo the
createPageaction looks like this:export async function createPage(formData: FormData) { // permission check, parse FormData, validate via Zod const page = await prisma.page.create({ ... }); await auditLog(...); await invalidatePageCache(page.slug); revalidatePath('/admin/pages'); revalidatePath(`/{{page_slug}}`); return { success: true, pageId: page.id }; } - Examine for the following anti‑patterns or omissions:
- Catching but not re‑throwing redirects/errors. Although these actions currently don't call
redirect, check any other server actions (e.g. delete handlers) for this pattern. - Missing
awaitkeywords on Prisma calls, audit logs, or cache invalidation; ensure no promise is forgotten. - Failure to return a value; every branch (success or catch) should return an object so the client promise resolves.
- Unused session variables – this file previously imported
getSessionand assignedsession; lint warnings indicate they were unused. Confirm that permission checks userequirePermissionand drop dead code.
- Catching but not re‑throwing redirects/errors. Although these actions currently don't call
- Also verify the corresponding client component (
PageForminsrc/components/admin/pages/page-form.tsx) handles the action result, togglesisSubmitting, and displays toast messages on error. If the form doesn't processresult.success, the UI may hang even though the action completed.
Fixes to Apply
- Confirm server actions always return a value and do not swallow redirects or errors in catch blocks. If any action does perform a
redirect(), ensure the redirect error is re‑thrown or executed outside the catch. - Ensure all asynchronous database operations (Prisma, service calls, audit logs, cache invalidations) are preceded by
awaitand that the function is declaredasync. - After successful creation/update/delete, return an object such as
{ success: true, pageId?: string }so clients can react. - In catch blocks, convert known errors (Zod validation, Prisma unique constraint) into user-friendly messages and return them rather than letting the action abort silently.
- Update the client form component (
PageForm): toggleisSubmitting, display a toast on error, and redirect the user client‑side based on the returnedpageIdinstead of relying on server‑side redirects.
Additional Diagnostics
- Run
npm devand reproduce the hang while watching the terminal for server errors; unhandled promise rejections will surface there. - Add temporary
console.logstatements if necessary to trace execution flow.
3. CMS Codebase Review & Completeness Checklist
For each file listed below, conduct a thorough review. The goal is to ensure the admin UI can fully manage public pages without developer intervention.
Files To Audit
src/app/(admin)/admin/pages/page.tsx– listing page with links to edit/deletesrc/app/(admin)/admin/pages/new/page.tsx– create form pagesrc/app/(admin)/admin/pages/[id]/page.tsx– edit form pagesrc/app/(admin)/admin/pages/actions.ts– server actions used by formssrc/app/actions/cms.ts(and any othersrc/app/actions/*) – legacy/general CMS actions; decide whether they are still needed or should be removed/merged and fix any type/any warningssrc/lib/services/cms.service.ts– service layer interacting with Prisma and cache- any additional API routes under
src/app/api(e.g.src/app/api/cms/pages/…)
Review Checklist
- Create
- Form fields: title, slug, content (rich text/markdown)
- Zod schema validating input before database call
- Slug uniqueness check (try/catch Prisma known error or explicit
findUnique/findFirst)
- Read
- List view fetches pages from the database
- Pagination or sorting? Ensure it functions
- Update
- Edit page pre-populates fields from DB
- Changes are validated and persisted
- After update, redirect back to list or show success message
- Delete
- Delete button with confirmation
- Server action deletes record and invalidates cache
- Slug Handling
- Database schema may have a unique index. Ensure code catches duplicates and presents a user-friendly message.
- Consider lowercasing/sluggifying the input.
- Validation
- Use Zod schemas in actions or service layer.
- On validation failure, throw an error the client can display.
- Error Handling
- Catch Prisma errors (e.g.
P2002uniqueness) and convert to readable messages. - If a service call fails, the error should propagate to the form and display a toast.
- Catch Prisma errors (e.g.
- Caching
cms.service.tsshould have functions such asgetPage,getPages,createPage,updatePage,deletePage.- After
create,update, ordelete, ensure any in‑memory or redis cache is invalidated (e.g.revalidatePath('/pages')).
- Permissions
- Actions should call
requirePermission('cms.pages.manage')or similar. sessionorgetSessionmay have been imported but not used — remove or leverage correctly.
- Actions should call
- API Routes
- If the UI uses API routes instead of server actions, ensure the routes exist and return appropriate HTTP statuses.
- Styling & UX
- Ensure the admin pages are responsive and accessible.
- Use loading spinners or optimistic UI where appropriate.
- Tests
- Add or update unit/feature tests (
*.test.tsx) for page actions.
- Add or update unit/feature tests (
- Static/Public Page Rendering
- Verify that pages created in the CMS are rendered on the public site (
/pages/[slug]). - Check caching/ISR behavior if implemented.
- Verify that pages created in the CMS are rendered on the public site (
Production Readiness Items
- Run
npm run lintand fix any warnings/errors from the reviewed files, paying particular attention tosrc/app/(admin)/admin/pages/actions.ts(unused vars) andsrc/app/actions/cms.ts(any-type warnings). - Run
npm run buildto ensure the project compiles cleanly. - Type‑check (
npm run typecheckornpm tsc --noEmit). - Review
prisma/schema.prismafor appropriate constraints (slug unique, required fields) and verify migrations have been generated and applied. - Confirm
seed.tsor migrations include initial CMS pages and that they load without errors. - Search for
CmsServiceusage and ensure the public route (src/app/(public)/[...slug]/page.tsx) correctly handles reserved slugs, scheduled publishing, and sanitizes HTML. - Check that there are tests covering page actions or add them if missing; the existing
cms.servicetests should be expanded to include action-level behaviour if possible.
4. Linting Cleanup in actions.ts
The linter reports:
/home/dylan/eccb.app/src/app/(admin)/admin/pages/actions.ts
5:29 warning 'getSession' is defined but never used
182:9 warning 'session' is assigned a value but never used
270:9 warning 'session' is assigned a value but never used
322:9 warning 'session' is assigned a value but never used
Steps
- Remove the unused import of
getSessionat the top of the file. - Remove or utilize the
sessionvariables. If they were meant to enforce permissions, userequirePermissionor check user role and document this in comments. - Additionally review
src/app/actions/cms.tsfor lint warnings (theanytypes) and either tighten its TypeScript signatures or remove the file if it is no longer in use. - After edits, run the linter again to ensure no unused variables or
anywarnings remain.
5. Implementation Plan (Order of Operations)
- Refactor
src/components/ui/breadcrumb.tsxand verify the hydration error is resolved. - Examine and fix the server action used by the new page form (likely in
src/app/(admin)/admin/pages/actions.ts).- Correct redirect placement, awaits, return values, and error handling.
- Clean up lint warnings in
actions.ts(remove unused variables). - Conduct the comprehensive CMS review described in section 3.
- Fix any missing API routes, validation, caching, or CRUD holes.
- Address any additional issues that surface during testing (missing imports, typos, broken links).
- Run full build, typecheck, and lint to validate readiness.
- Add or update tests to cover the new fixes and CRUD flows.
6. Verification
- Breadcrumbs: navigate to any admin route that renders breadcrumbs (e.g.
/admin/pages/new,/admin/events/123/edit) and confirm no hydration warnings. - Create Page: fill out and submit the form at
/admin/pages/new; ensure page is created, list view updates, and the browser navigates back to/admin/pageswith a success message. If the UI still hangs, inspect the network/devtools and server logs to determine if the action response is missing or the client code is broken. - Edit/Delete Page: modify a page, save, delete; observe expected behavior and no hangs. Verify
isSubmittingtoggles properly and toasts show error messages. - Legacy Actions: confirm whether
src/app/actions/cms.tsis used; if it is unused, remove or refactor it so it doesn’t confuse developers. - Slug Uniqueness: attempt to create two pages with the same slug and verify a friendly error is shown.
- Reserved & Scheduled Pages: on the public site, reserved slugs (e.g.
admin,login) should return 404. Create a page with a futurescheduledFordate and confirm it isn’t accessible until the scheduled time. - Public Rendering: visit a slug generated by the CMS and confirm the page displays correctly; content should sanitize HTML and render markdown appropriately.
- Cache Invalidation: after editing or deleting a page, reload the public page or run
npm run previewto see changes reflected immediately; if possible inspect cache keys. - Lint/Build: no lint warnings/errors and
npm run buildsucceeds.
Follow these instructions step by step and make sure the CMS is fully operational and production ready for a non-technical user to manage publicly visible pages via the /admin portal.
