Skip to content

Development notes

Why a growing article list needs native static pagination

Starting with this site’s regular list of six articles per page, I explain how publication filtering, sorting, static routes, and native pagination links use the same data, and what page numbers cannot guarantee.

林予晴
Published Updated
  • Content engineering
  • Astro
  • Pagination
  • Native HTML

An article list that shows only six cards does not necessarily have pagination. It might send every article to the browser and hide the remaining items with a script. Or it might give the next page its own URL and HTML.

This site takes the second approach. Page 2 is a static page that can be opened directly, and its page-number link points to that page. This fits the way the site builds public notes from local Markdown. Moving between pages does not require another layer of browser state.

Decide which articles belong in the list before counting pages

The regular list currently shows at most six articles per page, with NOTES_PER_PAGE set to 6. That is the current presentation setting, not a standard every website should adopt.

Before the list is split into pages, the data passes through several steps: start with the article sources, select articles in the chosen language that meet the publication conditions, sort by publication time with stableId as the tie-breaker, exclude featured articles, then calculate the regular list’s page count and select the items for the requested page. The following diagram preserves the original Traditional Chinese example:

文章來源
  → 選出該語言已符合發布條件的文章
  → 依發布時間排序,同時間以 stableId 排定順序
  → 排除精選文章
  → 計算一般列表頁數,取出該頁項目

These steps cannot be freely reordered. If the data is divided into groups of six before drafts are excluded, a page might end up with only a few cards. If all three languages are mixed together before pagination, each language’s list loses its own page count.

Featured articles appear in a separate block on every valid page. They do not occupy any of the regular list’s six slots. Pagination follows the existing featured-article rules: its job is to use that collection consistently, not to invent another recommendation order.

A page number has a real route

In the Traditional Chinese route examples, page 1 uses /notes, and later pages use routes such as /notes/page/2 and /notes/page/3. English and Japanese each use their own language prefix and calculate their own total number of pages for regular articles.

In Astro’s static mode, getStaticPaths() lists the URLs a dynamic route should generate. The framework also provides a paginate() helper.[2] This site does not use that helper directly. It uses its own paginateNotes() to share page-count calculations between the list and the sitemap, then returns the route parameters for subsequent pages.

The distinction matters: paginateNotes() is local code for this site, not another Astro API. Native static pagination means using the framework’s static routes and HTML links. It does not mean every detail has to use a built-in helper.

Route generation lists only the subsequent pages that actually exist. paginateNotes() clamps internal page numbers that fall outside the valid range, but that is a safeguard in the data function. It does not mean the site has generated a URL for every arbitrary page number someone might enter.

The pagination component outputs <a href="…"> links. Previous and next links appear only when their destination exists, and the current page number has aria-current="page".

Astro’s regular route navigation uses standard HTML links.[2] For this list, every page number already has a known destination. There is no need to turn it into a button that only updates in-memory state. Readers can copy the URL for page 2 or request that page directly. Its cards are already in the returned HTML; they do not depend on a pagination script to appear.

This describes only the responsibilities of the list and page navigation. Other parts of the website may still use animation, drawers, or local scripts. Pagination that works without JavaScript does not make the whole website JavaScript-free.

Routes, lists, and the sitemap must agree on page counts

If pages are divided using regular articles but the sitemap also counts featured articles, the sitemap may include a last page that was never generated. The reverse is also a problem: generating routes but leaving them out of the sitemap makes the two public URL lists disagree.

The list, subsequent-page routes, and sitemap all start with published articles in the chosen language. Featured articles appear on every valid list page but do not occupy regular-list slots or affect its page count; all three outputs use the same regular-article pagination basis.

Multilingual lists do not need the same number of pages in every language. The original Traditional Chinese record uses the example of an English list with two pages and a Traditional Chinese list with a fifth page. Those counts describe the original recording context, not the page counts after more translations are added. In that situation, the site should not generate an empty English fifth page merely to match the Traditional Chinese one.

The same page number does not guarantee the same content, either. Traditional Chinese page 2 and English page 2 are positions in their respective language lists, not pairs of translated articles. Switching to another language version of the same article still relies on the article pages’ stableId relationship.

A page can be shared, but article positions are not permanent

Publishing a new article changes the order. An article at the end of page 1 may move to page 2. Adding or removing featured status can also change the regular list’s page count.

A page-number URL is therefore useful for identifying a page in a list, but it should not replace an article’s own permanent URL. To share a particular article, use its article route. Page 3 should not be treated as the place that article will always occupy.

Static pagination also has an update cost. When the sources, publication eligibility, or ordering change, the site must be rebuilt and updated before readers receive the new list. It is not live search or cursor-based pagination, and it is not suited to handling continuously changing personal transaction data directly.

The content being organized here is public articles, not frequently updated operational data, so I would keep this approach. Whether six articles per page feel comfortable still depends on title length and reading on a phone. Separate HTML pages do not, by themselves, establish that loading speed, search rankings, or reading completion rates have improved.

Scope of this record

This article describes how the existing regular list, pagination routes, pagination component, and sitemap divide their responsibilities. It does not introduce search, infinite scrolling, or live queries, and it provides no performance comparison before and after pagination.

Further reading: How featured articles and date ordering work together.

Sources

[2] https://docs.astro.build/en/guides/routing — Astro — Routing