Pagination and Kazakh font
The blog grew to 25 posts across three languages. All loaded on a single page. Google sees one long wall of content instead of structure. Users wait for 25 cards to render. And Kazakh characters (Ә, Ғ, Қ, Ң, Ө) were rendering in a system font - like newspaper clippings next to the clean Inter typeface.

Problem 1: everything on one page
Astro generates static HTML. 25 posts means 25 cards with images, tags, dates. For search engines, /blog/ is a single page with all content. No pagination - no structure - no reason to crawl deeper.
Solution: paginate() + “Show more”
Astro has built-in pagination. A [...page].astro file with paginate() generates /blog/, /blog/2/, /blog/3/ automatically.
export const getStaticPaths = (async ({ paginate }) => {
const posts = (await getCollection('blog', (e) => e.data.locale === 'en'))
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
return paginate(posts, { pageSize: 9 });
}) satisfies GetStaticPaths;
9 posts per page - a clean 3×3 grid. Crawlers follow static pages. Users see a “Show more” button that fetches the next batch via fetch() without a page reload.
fetch(nextUrl)
.then(function (res) { return res.text(); })
.then(function (html) {
var doc = new DOMParser().parseFromString(html, 'text/html');
var newCards = doc.querySelectorAll('#blog-grid > .blog-card');
newCards.forEach(function (card) {
grid.appendChild(document.importNode(card, true));
});
});
The trick - parse the next page’s HTML and extract cards from the DOM. No API, no JSON. Static pages already exist - just grab the elements you need.
For users with JS disabled - <noscript> with “Previous” / “Next” links.
SEO details
Each page gets <link rel="next"> and <link rel="prev"> in the head. Pages 2+ append the number to the title: “Blog - imarch.dev - Page 2”. The sitemap includes all paginated URLs with hreflang for all three locales.
Problem 2: Kazakh characters
Inter is the main font on the site. Two subsets are loaded: latin and cyrillic. Russian text looks great. But the Kazakh Cyrillic alphabet includes characters beyond the basic Cyrillic range: Ә, Ғ, Қ, Ң, Ө, Ұ, Ү, Һ.
These characters live in the Cyrillic Extended Unicode block (U+0460–052F). The browser can’t find them in the loaded woff2 files and falls back to a system font. The result - glyphs from a different typeface in the middle of text.
Solution: one file
Inter already contains all Kazakh glyphs. They just didn’t make it into the base subset. You need a third woff2 file - cyrillic-ext.
// BaseLayout.astro - AstroFont config
{
path: './public/fonts/inter-cyrillic-ext-wght-normal.woff2',
style: 'normal',
weight: '100 900',
}
26 KB. Downloaded from Fontsource CDN, added to the font config. All Kazakh characters now render in the same Inter as everything else.
Summary
Two fixes, one evening:
- Pagination -
paginate()for SEO +fetch()for UX. Static pages for crawlers, lazy loading for humans - Font - one woff2 file (26 KB) covered all Kazakh characters
Both changes - zero dependencies, zero complexity. Sometimes you just need to load what’s already there.
The site source code is open. If you’re building a multilingual blog on Astro - reach out, happy to share details.


