Review blocker A — form error swap and false success:
- Change HTMX contract so forms target their own container (outerHTML)
instead of appending to #comments-list
- Use OOB swaps to append approved comments to the correct target
- Add success/error message display inside form templates
- Remove hx-on::after-request handlers (no longer needed)
Review blocker B — reply rendering shape:
- Create _reply.html partial with compact reply markup
- Approved replies via HTMX now use compact template + OOB swap
into parent's .replies-container
- Reply form errors render inside reply form container
E2E test fixes:
- Update 4 failing tests to wait for inline HTMX messages instead
of redirect-based URL assertions
- Add aria-label='Comment form errors' to form error display
- Rename test_reply_submission_redirects to
test_reply_submission_shows_moderation_message
Mypy internal error workaround:
- Add mypy override for apps.comments.views (django-stubs triggers
internal error on ORM annotate() chain with mypy 1.11.2)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1. Reply HTMX target: server sends HX-Retarget/HX-Reswap headers to
insert replies inside parent comment's .replies-container div
2. Empty thread swap target: always render #comments-list container
even when no approved comments exist
3. Reaction hydration: add _annotate_reaction_counts() helper that
hydrates reaction_counts and user_reacted on comments in
get_context(), comment_poll(), and single-comment responses
4. HTMX error swap: return 200 instead of 422 for form errors since
HTMX 2 doesn't swap 4xx responses by default
5. Vary header: use patch_vary_headers() instead of direct assignment
to avoid overwriting existing Vary directives
Also fixes _get_session_key() to handle missing session attribute
(e.g. from RequestFactory in performance tests).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix article header tag borders: replace broken border-current/20
(Tailwind can't apply opacity to currentColor) with per-tag border
colour classes via new get_tag_border_css filter
- Add calendar icon before article date in article header
- Add clock icon before read time in article header and home featured
- Match article card footer to wireframe (remove extra min-read span)
- Add rounded-md to code block matching wireframe
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace nav inline newsletter form with Subscribe CTA link per wireframe
- Remove newsletter form from footer; add Connect section with social/RSS links
- Fix honeypot inputs using hidden attribute (inline style blocked by CSP)
- Add available_tags to HomePage.get_context for Explore Topics section
- Add data-comment-form attribute to main comment form for reliable locating
- Seed approved comment in E2E content for reply flow testing
- Expand test_comments.py: moderation message, not-immediately-visible,
missing fields, reply form visible, reply submission
- Make COMMENT_RATE_LIMIT_PER_MINUTE configurable; set 100 in dev to prevent
E2E test exhaustion; update rate limit unit test with override_settings
- Update newsletter/home E2E tests to reflect nav form removal
- Update unit test to assert no nav/footer newsletter forms
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- nav: add functional mobile menu panel with JS toggle
- nav: hamburger now shows/hides mobile-menu with aria-expanded state
- about_page: full styled layout (header, prose body, author aside)
- legal_page: full styled layout (header with last-updated, max-w-3xl prose)
- article: fix aside newsletter label to 'Subscribe' for E2E test
- CSS: rebuild after all template changes (4.8KB → 24.3KB)
Committed CSS must match CI build — rebuilt after ALL template edits
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- nav: replace hidden newsletter form + Subscribe link with visible inline form
- nav: fix theme toggle aria-label to 'Toggle theme' (was 'Toggle Dark Mode')
- article_page: wrap share buttons in <section aria-label='Share this article'>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>