feat: replace blog pagination with "Load More" button and optional auto-scroll, improve noscript support by stasadev · Pull Request #557 · ddev/ddev.com
## The Issue Blog post listings used prev/next pagination links requiring full page navigations to browse content. Tables in blog posts also lacked full-width rendering and horizontal scroll on mobile. Search results were capped at 10 with no way to see more, and did not restore when navigating back. ## How This PR Solves The Issue **Infinite scroll for blog listings** Replaces pagination with a fetch-HTML-fragment approach. Each listing page (index, category, author) renders its first 12 posts normally. A `data-next-url` attribute on the grid container points to the next pre-built static page. An `IntersectionObserver` fires when the user scrolls near the bottom, fetches that URL, extracts the post cards via `DOMParser`, and appends them to the current grid. The next `data-next-url` is then read from the fetched page to continue the chain. This keeps every page's initial payload at 12 posts regardless of total post count, preserves full Astro image optimization on all cards (no client-side re-rendering), and leaves all paginated static routes intact as valid URLs and noscript fallbacks. All logic is centralised in a new `BlogPostGrid` component. `Paging.astro` is removed as it is no longer referenced anywhere. **Infinite scroll for search** Search results now load progressively in batches of 10 as the user scrolls, with all matches held in memory after each query. Previously results were hard-capped at 10. The input value is also checked on page initialisation so results are restored correctly after browser back navigation. **Full-width tables with mobile scroll** `overflow-x: auto` on a `<table>` element has no effect because tables are not block containers. The previous workaround (`display: block`) broke the table's natural full-width behaviour. A new rehype plugin (`rehype-wrap-tables.mjs`) wraps each `<table>` in a `<div class="table-wrapper">` at build time, keeping the table as `display: table` (full width via Tailwind Typography) while the block-level wrapper provides the scroll container. ## Manual Testing Instructions - Visit /blog/ and scroll down to verify posts load without page navigation - Visit /blog/category/<category>/ and /blog/author/<author>/ and scroll - Check Network tab: each scroll fetch returns 200, not 301 - Disable JS and confirm the noscript fallback link is visible - Search for a term with many results and scroll to load beyond the first 10 - Navigate to a result, press back, confirm results are restored - Open a blog post with a wide table and verify it is full width on desktop and scrolls horizontally on mobile ## Automated Testing Overview No automated tests added; all changes are client-side JS and build-time HTML transforms. ## Release/Deployment Notes All paginated static routes (/blog/2/, /blog/category/x/2/, etc.) remain valid URLs. No redirects or deployment config changes needed. 🤖 Developed with assistance from [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
## Blog listing - Replace infinite scroll with a "Load More" button, fixing the inaccessible footer problem - Button is hidden by default, shown only when JS is available - Button matches the site's hollow button style with dark mode support ## AnimatedTerminal - Add noscript fallback: pre-render ddev describe output at build time - Use CSS (data-theme attribute set by inline head script) to toggle between animated and static pre elements with zero flash - Deduplicate describeOutput — defined once in frontmatter, passed via data attribute, read by the animation script ## get-started page - Replace noscript message with CSS :has() rules so platform picker works without JS (clicking labels shows the correct platform section) ## global.css - Hide copy buttons for noscript users (html:not([data-theme])) - Add noscript notice for unrendered Mermaid diagrams - Remove noscript dark mode CSS (not supported without JS) 🤖 Developed with assistance from [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
stasadev
changed the title
feat: replace blog pagination with infinite scroll
feat: replace blog pagination with "Load More" and improve noscript support
Adds a persistent "Auto-load on scroll" checkbox to all blog listing pages. Preference is saved to localStorage so it applies across visits. Defaults to "Load More" button mode. Toggle is always visible regardless of whether a next page exists, allowing preference to be set on short category pages. 🤖 Developed with assistance from [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
stasadev
changed the title
feat: replace blog pagination with "Load More" and improve noscript support
feat: replace blog pagination with "Load More" button and optional auto-scroll, improve noscript support
stasadev
deleted the
20260224_stasasdev_infinite_scroll
branch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters