Jump to a chapter
What SEO Really Is Now
SEO stopped meaning "Search Engine Optimization" and started meaning Search Everywhere Optimization. Your job is to be the answer wherever people look: Google, Bing, YouTube, Reddit, and increasingly ChatGPT, Perplexity, Claude, and Google's AI Overviews.
The single most useful reframe: you don't have an SEO goal, you have a business goal. More customers, more revenue, more qualified leads. SEO is the most durable way to reach people at the precise moment they're looking for what you sell, and unlike paid ads, the traffic keeps arriving after you stop paying.
The three (now four) jobs of a search engine
- Crawl. Bots follow links and fetch pages across the web.
- Render. A headless browser executes JavaScript to see the final page (this step is why front-end architecture matters, covered in Ch. 2).
- Index. The engine stores what it understood in a giant library. If you're not indexed, you cannot rank. Full stop.
- Rank. When someone searches, it orders results by relevance, quality, and trust.
Strings became things
Old SEO matched strings of text. Modern search is vectorized and entity-based: engines convert your content into mathematical representations of meaning and map the world as a graph of entities (people, places, products, concepts) and their relationships. This is Google's Knowledge Graph. Ranking #1 for a broad topic means convincing that graph that your brand is a definitive entity for it, not that you repeated a keyword 30 times.
Write for a knowledgeable human first. Everything technical in this guide exists to remove obstacles between that human's need and your content. Technical SEO cannot rescue thin content, and great content can't rank from a broken site. You need both.
How Search & AI Engines Work
Two systems now read your site: classic crawlers and AI answer engines. They reward the same foundation (clean, fast, server-rendered HTML) but retrieve and present it differently.
Crawl budget & two-pass indexing
Google assigns each site a crawl budget, a finite amount of attention. Slow servers, redirect loops, endless faceted-filter URLs, and piles of low-value pages burn that budget before your important pages get seen. Google also indexes in two passes: it reads raw HTML first, then queues the page for JavaScript rendering, which can lag by days. Content that only appears after client-side JS runs is seen late, or missed.
A single-page app that renders everything in the browser hands crawlers a near-empty HTML shell on the first pass. Server-rendered or statically generated HTML (Astro's default) gives every reader, Googlebot and Bingbot and AI crawlers alike, the full content immediately, with no render queue and no hydration wait. This is the core reason Astro is a strong SEO substrate, expanded in Part IX.
How AI answer engines retrieve
AI engines don't browse like people. Most use retrieval-augmented generation (RAG) and a technique Google calls query fan-out:
- Fan-out: your question is split into several sub-queries. "Best CRM for small law firms in Kenya" might fan out to "best CRM 2026," "CRM for law firms," and "CRM pricing Kenya."
- Retrieval: the model pulls specific passages from pages it can parse cleanly.
- Synthesis: it combines those passages into one answer.
- Citation: it names a handful of sources. This is where your brand appears, or doesn't.
The practical takeaway: you're no longer optimizing only for the long question a user typed, but for the many sub-queries a model generates. Your content must be extractable from clean HTML, because AI crawlers are far less reliable at executing JavaScript than Googlebot. Chapter 13 covers this in full.
Google indexes the mobile version of your site by default. If content, links, or structured data exist on desktop but are stripped on mobile, Google effectively doesn't have them. Parity between mobile and desktop is non-negotiable.
Search Intent & the Funnel
Google rewards the page that ends the search. If a user clicks your result and immediately bounces back to try another (pogo-sticking), you get demoted. Matching intent is the highest-leverage decision in SEO.
The intent spectrum
| Intent | Funnel stage | Example query | Right page type |
|---|---|---|---|
| Informational | Awareness | "how to reduce cloud costs" | Guide / blog post |
| Investigational | Consideration | "AWS vs Azure pricing" | Comparison |
| Commercial | Decision | "best cost-optimization tools" | Listicle / "best of" |
| Transactional | Action | "buy CloudHealth" | Product / pricing page |
| Navigational | Branded | "Tekzuri contact" | The specific page they want |
How to read intent (the free method)
Google the keyword and study the top 10 results. Whatever format dominates (blog posts, product pages, comparison tables, videos) is what searchers want, because Google has already tested it against billions of clicks. If the SERP is all listicles and you publish a product page, you will not rank there no matter how good the page is. Match the format first, then out-execute on quality.
You almost never rank for a broad head term (e.g. "project management") by targeting it directly. You earn it by dominating the hundreds of specific micro-intents beneath it, which is exactly what the pillar-and-cluster model in Chapter 4 is built to do.
Keyword & Entity Research
Keywords are still the map, but the terrain is topics and entities. Cover a subject completely and clearly and you'll surface for queries you never explicitly wrote.
The keyword sweet-spot framework
Score every candidate on four axes before committing:
- Demand. Are people actually searching this? (Volume matters, but high volume ≠ high conversions.)
- Fit. Does it map to something you sell or to a real step in your funnel?
- Intent. Can you satisfy the need better than the pages currently ranking?
- Difficulty. Can your site realistically outrank them right now? A new site won't beat Amazon for "running shoes."
The bottom-up strategy: money pages first
Most beginners start with broad top-of-funnel posts that never drive revenue. Work backwards instead:
- Money pages first. These are the pages that directly convert: product, service, pricing, feature.
- Build a topic cluster around one money page: a 3,000–4,000-word pillar plus specific cluster articles that each link back to it.
- Finish one cluster completely before starting the next. Depth beats scattered breadth.
Engines use NLP to check whether you've covered a topic the way an expert would. Write about espresso and they expect to see related entities: burr grinder, extraction yield, crema, roast profile. Their absence signals shallow coverage. Tools like Surfer or Clearscope surface these terms, but the goal isn't stuffing them in; it's genuinely covering the subject. Every cluster page linking to the pillar with descriptive anchor text is what builds the topical authority needed to rank the pillar for its broad head term.
Where to find keywords
- Google Search Console. Your #1 source: real queries already bringing you impressions.
- Autosuggest, "People Also Ask," and AlsoAsked. Free, live question data.
- Reddit & niche communities. The exact language your customers use for their problems.
- Competitor sitemaps. Paste one into an AI tool and ask it to find topic gaps you haven't covered.
If two of your pages target the same intent, Google gets confused about which to rank and often demotes both. Audit for overlap, merge the weaker into the stronger, and 301-redirect the retired URL. One intent, one canonical page.
Content That Ranks
AI can generate competent, average content for free, so average content no longer ranks. The bar is now information gain: net-new value that doesn't already exist on the results page.
Beat the slop with things a model can't invent
- First-hand data. "We surveyed 1,000 users," real numbers from your own operations.
- Expert quotes. Interview the specialists in your company or industry.
- Original graphics. Diagrams, flowcharts, annotated screenshots. Not stock photos. (Google Images and Lens drive real traffic.)
- Specific, lived examples. Concrete cases, edge conditions, and the mistakes you actually made.
The four-step blueprint
- Research. Read the top 5 ranking pages. Note what they all cover, then find what they all miss. That gap is your angle.
- Structure. Outline to match the dominant SERP format and the sub-questions in "People Also Ask."
- Write. Add the human layer above. Lead each section with a direct answer, then explain.
- Optimize. Check topical completeness, tighten headings, add internal links.
Experience, Expertise, Authoritativeness, Trust. Critical for anything touching health, finance, safety, or money ("Your Money or Your Life" topics). Google wants to know who stands behind the content. Give every serious article a real byline linking to a detailed author page (credentials, publications, LinkedIn), and mark authors up with Person schema connected to your Organization. Trust is the load-bearing member of the four. A site that users and other sites distrust won't rank on expertise alone.
Format for featured snippets & AI extraction
To win the answer box (and to be quotable by AI engines), put a concise 40–55-word answer immediately under an H2 phrased as the question. Use short paragraphs, definition lists, numbered steps, and comparison tables. This "answer-first" structure is the single most portable technique across Google snippets, voice, and generative engines.
Rankings rot. Every 3–6 months, pull pages losing traffic in Search Console and refresh them with new data, current-year examples, updated screenshots, and a genuine "last updated" date. Pages with zero traffic and zero backlinks should be improved, consolidated, or 301-redirected away. Dead weight drags down the whole domain's quality signal.
On-Page SEO
On-page work is the surgical layer: the signals that tell an engine precisely what a page is about. The mindset shifts from writer to detail-obsessed editor.
| Element | Best practice |
|---|---|
| Title tag | Under ~60 characters, main keyword front-loaded, written to earn the click. This is your headline in the SERP. |
| Meta description | Under ~155 characters. Not a ranking factor; it's ad copy. Sell the click. Google may rewrite it, so make the page itself strong. |
| H1 | Exactly one per page, describing the page. Distinct from the title tag is fine. |
| H2 / H3 | Logical, nested outline. Question-shaped H2s help snippets and AI extraction. |
| URL | Short, lowercase, hyphenated, descriptive: /ransomware-recovery-guide. No dates or IDs you'll regret. |
| Keyword prominence | The main term should appear naturally in the first ~100 words and in a heading. |
| Internal links | The most under-used lever. Link cluster pages to the pillar and to money pages with descriptive anchor text. |
| Image alt / filenames | roasted-coffee-beans.jpg, not IMG_4931.jpg. Write real alt text for accessibility and image search. |
| Semantic HTML | Use <article>, <nav>, <main>, real headings and lists. It helps assistive tech, crawlers, and LLMs equally. |
It passes authority to the pages that matter, teaches Google how your topics relate, and it's entirely within your control, with no outreach required. Most sites leave enormous value on the table here.
Site Architecture & Internal Linking
Architecture is information. A flat, logical structure spreads authority efficiently and helps every page get crawled and understood.
Keep it shallow
Follow the 3-click rule: every important page should be reachable within three clicks of the homepage. Pages buried five levels deep get crawled rarely and rank poorly. Watch for orphan pages, pages with no internal links pointing to them, which crawlers may never find.
Each page holds a share of "link authority" and passes some through its outbound links. Your homepage usually has the most (it attracts the most backlinks), so link directly from it to your highest-value money pages instead of burying them. Use hub-and-spoke clusters, descriptive (not "click here") anchor text, and breadcrumbs to route authority deliberately. Mark breadcrumbs up with BreadcrumbList schema (Ch. 10) so the path shows in search results.
Silos and taxonomy
Group related content under clean, hierarchical paths. /shoes/running/nike-pegasus reads better to both users and engines than a flat slug soup. Keep pagination sane: paginated pages should self-reference canonically and never duplicate title tags.
Technical SEO & Crawl Control
Technical errors quietly sink great content. Most modern stacks handle the basics, but you own the crawl directives, canonicalization, and redirects.
| Lever | What it does |
|---|---|
robots.txt | Tells crawlers which paths to skip (admin, internal search results). It blocks crawling, not indexing, so don't use it to hide pages from search. |
<meta name="robots"> | noindex, follow keeps a low-value page out of the index while still passing link authority through it. This is how you actually deindex. |
rel="canonical" | Points duplicate or parameter URLs (?sort=price) at the master version so signals consolidate on one page. |
| Redirects | 301/308 for permanent moves (passes authority); 302/307 for temporary. Avoid redirect chains; they waste crawl budget and leak authority. |
| XML sitemap | Lists canonical URLs you want indexed. Submit the sitemap index in Search Console. Add image/video sitemaps for media-heavy sites. |
hreflang | Maps language/region variants so the right version serves the right country (Ch. 12). |
| HTTPS | Table stakes. A valid certificate is a baseline ranking and trust signal. |
| Trailing slashes | Pick one convention and enforce it. /page and /page/ as separate live URLs is duplicate content. |
Run Screaming Frog SEO Spider (free up to 500 URLs) periodically to catch 404s, redirect chains, missing titles/H1s, duplicate content, and images without alt text. For large sites, log-file analysis reveals what Googlebot actually crawls, and where it's wasting budget on junk URLs.
Core Web Vitals
Google ranks partly on real-world Chrome user data (the CrUX dataset). Three field metrics define "page experience," and you must pass them on mobile.
How to fix each
- LCP. Serve the hero as a preloaded, correctly sized WebP/AVIF; avoid render-blocking CSS/JS; use a CDN. (Astro's
priorityimage prop does most of this for you, covered in Ch. 18.) - INP. Ship less JavaScript and break up long tasks on the main thread. Offload third-party scripts to a web worker (Ch. 20).
- CLS. Set explicit
widthandheight(or aspect-ratio) on every image, ad slot, and embed so the browser reserves space before they load.
Lighthouse gives you a lab score in a simulated environment; rankings use field data from real users (CrUX), visible in Search Console's Core Web Vitals report and PageSpeed Insights. Optimize for the field numbers. A green lab score with slow real-world INP still fails.
Structured Data / Schema
Schema is machine-readable context in JSON-LD. It won't make a bad page rank, but it unlocks rich results, feeds the Knowledge Graph, and gives LLMs clean facts to extract, increasingly the bigger payoff.
The schema types worth implementing
| Type | Use on | Note |
|---|---|---|
Organization + WebSite | Site-wide | Foundational entity + sitelinks search box. core |
BreadcrumbList | Every deep page | Shows the path in the SERP; reinforces architecture. |
Article / BlogPosting | Content pages | Connect to Person author + Organization publisher. |
Product + AggregateRating | E-commerce | Price, availability, review stars in results. |
FAQPage | Q&A blocks | See the note below. Still valuable, but the visual result changed. changed |
HowTo | Step guides | Structured steps; good for AI extraction. |
LocalBusiness | Physical/local | NAP, hours, geo. Pairs with Google Business Profile (Ch. 12). |
Person | Author pages | The backbone of E-E-A-T signals. |
VideoObject / Event | Media / events | Video thumbnails and event listings in search. |
As of May 2026, Google stopped displaying FAQ rich results in Search for most sites, and is retiring the related reporting and testing tools through mid-2026. The FAQPage schema type itself remains valid, and Google still uses it to understand a page. It's now more of a GEO/LLM signal than a rich-snippet play. Keep it for machine comprehension, but don't expect the old blue expandable results.
Don't scatter disconnected snippets. Link them with @id so your Article references its author (a Person) and publisher (your Organization), forming a single connected graph. This is what helps Google resolve your brand as a coherent entity. Always validate output with Google's Rich Results Test and Schema.org validator, and never mark up content that isn't visible on the page.
Link Building & Authority
Backlinks are votes of confidence, still one of the strongest ranking signals and a major driver of whether AI engines trust and cite you. Quality and relevance beat volume every time.
Don't obsess over links on day one. Publish 10–15 genuinely excellent pages first, because you need something worth linking to. Then pursue links deliberately:
Tactics that actually work
- Be the source. Original surveys, studies, and data are catnip for journalists and bloggers who need something to cite.
- Journalist queries. Answer reporter requests on platforms like Source of Sources (the successor to HARO). 15 focused minutes a day earns high-authority links.
- Linkable assets. Free calculators, templates, and definitive guides accumulate links passively for years.
- Broken-link building. Find dead outbound links on relevant sites, then offer your resource as the replacement.
- Unlinked mentions. Set an alert for your brand; when a site names you without linking, politely ask them to link it.
- Digital PR. Turn your data into a story worth covering, and pitch it.
Buy links, join link schemes, or spam guest posts with keyword-stuffed anchors. These trigger algorithmic and manual penalties that are painful to recover from. Keep anchor text natural and varied. An unnaturally high ratio of exact-match anchors is itself a spam signal.
Local & International SEO
If you serve a place, local SEO is often your highest-ROI channel. If you serve many regions or languages, international signals keep the right version in front of the right user.
Local SEO essentials
- Google Business Profile. Claim it, fill it out completely (categories, services, hours, photos), and keep it current. This single asset drives the map pack more than anything else.
- NAP consistency. Identical Name, Address, Phone across your site, GBP, and every directory. Inconsistency confuses the ranking systems.
- Reviews. Actively collect them and reply to every one. Volume, recency, and rating all feed local rankings and human trust.
- Local citations. Listings in reputable local and industry directories reinforce your existence and location.
- Local schema & landing pages.
LocalBusinessmarkup, plus a genuinely distinct page per location or service area (not thin duplicates).
In markets like Kenya and East Africa, Google Business Profile, strong reviews, and precise service-area pages consistently outperform generic national content for "near me" and city-level queries, and they surface well in AI answers about local providers.
International SEO
Use hreflang tags to declare language/region variants (en-KE, en-GB) and prevent duplicate-content ambiguity. Choose a clear URL strategy: subfolders (/ke/) are usually simpler and consolidate authority better than separate ccTLDs for most small teams. Keep one sitemap per locale and translate real content, not just the UI chrome.
GEO: Generative Engine Optimization
A growing share of searches never reach a blue link. People ask ChatGPT, Perplexity, Gemini, Claude, and Google's AI Overviews and get a synthesized answer. GEO is the discipline of being one of the few sources those engines cite.
GEO is SEO with an extra layer, not a replacement
Generative engines pull from the same indexes that power classic search. If your page isn't crawlable, indexed, and relevant, no AI trick will save it. Classic SEO is now necessary but not sufficient. On top of that foundation, these are the levers with the strongest evidence:
- Answer-first structure. Lead each section with a direct, self-contained answer, then context. Clear H2/H3 hierarchy, bullets, and tables let models extract you cleanly.
- Cite authoritative sources inline. Research (notably the Princeton/Allen "GEO" study) found that pages quoting statistics and citing trustworthy sources earned substantially more visibility in generated answers, with the biggest gains for lower-ranked sites. Signal is symmetric: cite trustworthy sources and LLMs treat you as one.
- Specific statistics and named quotes. Concrete numbers and expert attribution get pulled into answers far more than vague prose.
- Own the "best-of" and comparison queries. Models lean on consensus. If ten roundups name you, the AI will confidently name you too.
- Off-site presence. Reddit and LinkedIn are among the most-cited domains across major AI engines. A real presence where your buyers talk compounds your citation rate.
- Freshness. AI engines favor recently updated sources for anything that changes. Keep a visible update cadence.
AI engines can only cite what they can fetch. Make sure your robots.txt allows the AI user agents you want: GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, PerplexityBot, Google-Extended, and others. A common 2026 trap: some CDNs (Cloudflare among them) began blocking AI bots by default. Check your CDN's bot settings and server logs, because you may be invisible to AI search without realizing it.
llms.txt is useful, but know the nuance
llms.txt is a proposed plain-text file at your domain root offering a curated, AI-friendly index of your key content. Two honest facts to hold at once: (1) Google has stated publicly it does not use llms.txt for Google Search (including AI Overviews), and calls files-just-for-AI unnecessary for ranking there. (2) Other systems may use it, including the emerging wave of autonomous agents that read sites programmatically. It's low-cost and won't hurt, so treat it as optional agent-readability infrastructure, not as a ranking lever.
There's no "position #1" in an LLM. The metric is reference rate or share of voice: how often you're mentioned across many prompts. Google Search Console now surfaces AI-feature performance, and dedicated trackers (Profound, Peec AI, Scrunch, and others) monitor citations across engines. Test it yourself first: ask each engine "who are the best [your category] in [your city]?" and see whether you appear.
Measuring & Iterating
What you don't measure, you can't improve, and vanity metrics quietly waste months. Tie SEO to business outcomes, then let the data pick your next move.
Your core instruments
- Google Search Console. The source of truth: impressions, clicks, CTR, average position, index coverage, Core Web Vitals, and the newer generative-AI performance view. Free and irreplaceable.
- GA4. Segment the Organic Search channel, track conversions and revenue, and see which landing pages actually earn money.
- Rank tracking. Monitor your priority keywords over time to catch drops early.
- Screaming Frog / Sitebulb. Scheduled technical crawls for the errors in Chapter 8.
Know the difference between updates and penalties
- Core updates re-weight how Google assesses quality; recovery comes from being genuinely better, not from a quick fix.
- The Helpful Content system demotes sites made for search engines rather than people: thin, unoriginal, or mass-produced content.
- Manual actions (spammy links, cloaking) appear in Search Console and require a fix plus a reconsideration request.
Publish, then wait for data (SEO is slow; give it weeks), then find pages with impressions but low CTR (fix titles) or good rank on page 2 (add depth and links). Refresh decaying winners, then repeat. Small, compounding improvements beat sporadic rewrites.
Don't over-react to daily fluctuations. Rankings bounce; algorithms wobble. Look at 28-day and 3-month trends before making structural decisions.
Why Astro Is a Great SEO Substrate
Astro's defining choice, to ship zero JavaScript by default and render real HTML, happens to be exactly what crawlers and AI engines want. You start several technical-SEO problems ahead.
The mechanics that matter for SEO
- Static HTML first. Every reader (Googlebot, Bingbot, GPTBot, ClaudeBot) receives the full content immediately: no render queue, no hydration delay, no empty JS shell.
- Islands architecture. Interactive components (React, Vue, Svelte) are isolated "islands" hydrated individually, so the rest of the page stays static and instant.
- Great Core Web Vitals by default. Less JS means faster LCP and lower INP almost for free.
- First-class SEO tooling. Built-in image optimization, official sitemap and RSS integrations, and type-safe content collections.
This section targets Astro 7 (released mid-2026; current line 7.0.x). Every SEO-relevant API here is unchanged from Astro 6, so all of it applies exactly as written: the <Font /> component, the image priority/layout props, <ClientRouter />, the official sitemap/RSS integrations, and the Content Layer.
Astro 7 is a foundations release, not an API shake-up. A new Rust .astro compiler, Vite 8 with the Rolldown bundler, and the Sätteri Markdown pipeline make builds 15–61% faster, which matters most on large content sites and programmatic-SEO catalogs with thousands of pages. Route caching and CDN cache providers are now stable, cutting TTFB on SSR pages (a direct LCP win). It requires Node 22.12+.
Stricter HTML. The new Rust compiler parses markup to standards and now errors on things the old compiler silently fixed (unclosed tags, unterminated attributes). This surfaces latent bugs rather than shipping them, so run a local build after upgrading and fix anything it flags.
Markdown pipeline swapped. Sätteri is now the default Markdown/MDX processor, replacing remark/rehype. If your SEO setup leans on rehype/remark plugins (auto heading anchors, rel attributes on external links, reading-time, table-of-contents), install @astrojs/markdown-remark to keep them working. Plain Markdown needs no changes.
Astro shines for content and marketing sites: blogs, docs, landing pages, city/service pages, programmatic catalogs. For a heavily interactive, authenticated app (a dashboard SaaS) where nearly every view is dynamic and personalized, a full app framework like Next.js is often the better fit. Astro can do SSR, but don't fight its grain.
Astro SEO Setup: The Essentials
Astro gives you a clean canvas but doesn't auto-generate meta tags, canonicals, or schema. Wire them once into a reusable head component and every page inherits correct SEO.
Step 1: set your site
This is the foundation for canonical URLs and sitemaps. Without it, both break silently.
import { defineConfig } from 'astro/config'; import sitemap from '@astrojs/sitemap'; export default defineConfig({ site: 'https://tekzuri.com', // required for canonical + sitemap trailingSlash: 'never', // pick one convention and stick to it integrations: [sitemap()], });
Step 2: a single BaseHead component
Compute the canonical from the current URL, and centralise title, description, Open Graph, and Twitter cards so social shares and search both look right.
--- interface Props { title: string; description: string; image?: string; } const { title, description, image = '/og-default.jpg' } = Astro.props; // Canonical: always absolute, always the current path const canonical = new URL(Astro.url.pathname, Astro.site); const ogImage = new URL(image, Astro.site); --- <title>{title}</title> <meta name="description" content={description} /> <link rel="canonical" href={canonical} /> <!-- Open Graph --> <meta property="og:title" content={title} /> <meta property="og:description" content={description} /> <meta property="og:image" content={ogImage} /> <meta property="og:url" content={canonical} /> <meta property="og:type" content="website" /> <!-- Twitter --> <meta name="twitter:card" content="summary_large_image" />
Prefer a maintained package? The community astro-seo integration exposes a single <SEO /> component covering canonicals, OG, Twitter, and robots directives. Roll your own when you want full control; use the package to move fast.
Step 3: inject JSON-LD
Astro doesn't generate schema, but adding it is trivial: build a plain object and serialize it. Use set:html so Astro doesn't escape the JSON.
--- const schema = { "@context": "https://schema.org", "@type": "Article", "headline": title, "author": { "@type": "Person", "name": "Yash Shah" }, "publisher": { "@type": "Organization", "name": "Tekzuri" } }; --- <script type="application/ld+json" set:html={JSON.stringify(schema)} />
Sitemaps, robots.txt & RSS
Three small files decide whether your pages get discovered. Astro generates the sitemap; you write robots.txt and the feed.
Sitemap with real lastmod
The @astrojs/sitemap defaults produce a single file with no modification dates. Add serialize for lastmod and filter to exclude drafts; entryLimit auto-splits large sites into an index.
sitemap({
filter: (page) => !page.includes('/drafts/'),
changefreq: 'weekly',
priority: 0.7,
entryLimit: 10000, // splits into sitemap-index.xml when large
serialize(item) {
item.lastmod = new Date().toISOString();
return item;
},
})The sitemap integration reads your statically known routes. On-demand (SSR) dynamic routes are not auto-included, a common trap on large catalogs and CMS-driven sites. If you render pages at request time, generate those sitemap entries yourself (a custom sitemap.xml.ts endpoint) and always eyeball the built sitemap before deploying.
robots.txt, and letting the AI crawlers in
Astro does not create this file. Drop it in public/ and point it at your sitemap index. Explicitly allow the AI agents you want citing you (see Ch. 13).
User-agent: * Allow: / # Allow AI answer engines to read and cite you User-agent: GPTBot Allow: / User-agent: OAI-SearchBot Allow: / User-agent: ClaudeBot Allow: / User-agent: PerplexityBot Allow: / User-agent: Google-Extended Allow: / Sitemap: https://tekzuri.com/sitemap-index.xml
RSS for discovery & free syndication
Feeds are still consumed by readers, aggregators, and a growing number of AI agents. Include the full post body, not excerpts, so machines have more to work with.
import rss from '@astrojs/rss'; import { getCollection } from 'astro:content'; export async function GET(context) { const posts = await getCollection('blog'); return rss({ title: 'Tekzuri Blog', description: 'Web, AI & automation for East Africa.', site: context.site, items: posts.map((p) => ({ title: p.data.title, pubDate: p.data.pubDate, description: p.data.description, link: `/blog/${p.id}/`, })), }); }
Image Optimization in Astro
Images are typically 60–70% of a page's weight, the number-one performance killer and usually your LCP element. Astro's astro:assets pipeline fixes most of this at build time, but only if you use the components correctly.
Rule 1: store images in src/, not public/
Images imported from src/ get optimized, compressed, format-converted, and hashed. Files in public/ are copied as-is with zero processing. Keep only truly static assets (favicon, robots.txt) in public/.
Rule 2: use <Image />, never a bare <img> for local assets
The component auto-converts to WebP/AVIF, sets width/height to prevent layout shift (CLS), and adds sensible loading/decoding defaults, all with no config.
--- import { Image } from 'astro:assets'; import hero from '../assets/hero.png'; --- <!-- optimized: WebP, compressed, no layout shift --> <Image src={hero} alt="Dashboard preview" />
Rule 3: mark the hero priority to fix LCP
For above-the-fold images (your hero, the LCP element), add priority. Astro sets loading="eager", fetchpriority="high", and optimal decoding so the browser fetches it immediately. Everything below the fold stays lazy-loaded automatically.
<Image src={hero} alt="..." priority /> <!-- below the fold: default lazy loading is correct, leave it --> <Image src={chart} alt="Revenue by region" />
Rule 4: responsive images with layout, widths & sizes
The layout prop (constrained, full-width, fixed) generates a proper srcset so phones don't download desktop-sized images. Pair with sizes to tell the browser how much space the image occupies at each breakpoint.
<Image src={photo} alt="..." layout="constrained" widths={[400, 800, 1200]} sizes="(max-width: 600px) 100vw, 800px" />
Rule 5: use <Picture /> for modern formats & art direction
When you want AVIF with a WebP fallback (or different crops per breakpoint), reach for <Picture />. List the most modern format first.
import { Picture } from 'astro:assets'; <Picture src={photo} formats={['avif', 'webp']} fallbackFormat="png" alt="..." />
Remote images
To optimize images from a CMS or DAM, allowlist their domains. Remote images need explicit width/height, or use inferSize (which, in current Astro, only fetches dimensions for authorized domains).
image: {
domains: ['images.tekzuri.com'],
remotePatterns: [{ protocol: 'https' }],
}| Do | Don't |
|---|---|
Keep source images in src/assets/ | Dump them in public/ expecting optimization |
Add priority to the LCP/hero image | Lazy-load the hero (delays LCP) |
Always provide meaningful alt | Ship decorative images without alt="" |
| Let below-the-fold images lazy-load | Set every image to eager |
| Use SVG directly for icons/logos | Run vector SVGs through raster optimization |
Convert heavy GIFs to <video> (mp4/webm) | Serve multi-MB animated GIFs |
Fonts, CSS & Asset Performance
Fonts and render-blocking CSS are quiet LCP killers. Astro's newer tooling self-hosts fonts and trims CSS with almost no effort.
The <Font /> component (Astro Fonts API)
Astro can self-host any font provider automatically. It downloads and caches the files, adds font-display: swap, generates size-matched fallbacks (reducing layout shift), and injects the right preload hints. This removes the third-party DNS lookup and round-trip you pay with the Google Fonts CDN.
// astro.config.mjs import { defineConfig, fontProviders } from 'astro/config'; export default defineConfig({ experimental: { fonts: [{ provider: fontProviders.google(), name: 'Inter', cssVariable: '--font-inter', }], }, }); // in your layout <head> import { Font } from 'astro:assets'; <Font cssVariable="--font-inter" preload />
Only preload the fonts actually used above the fold. Preloading everything competes with your LCP image for bandwidth and can make things slower.
CSS & the rest
- Critical CSS. Astro scopes styles per component and inlines small stylesheets, so above-the-fold CSS ships fast without manual extraction.
- Tailwind v4. The old
@astrojs/tailwindintegration is deprecated; use the@tailwindcss/viteplugin, which runs inside Vite 8 (now with the Rolldown bundler) for faster builds and smaller output. - Compression. Ensure your host serves Brotli/Gzip and long cache lifetimes for hashed, immutable assets. Community integrations like
astro-compresscan further minify HTML/CSS/JS at build time.
Islands, Hydration & Core Web Vitals
Every island you hydrate is JavaScript on the main thread, and that's where INP is won or lost. Choose the lightest client directive that still works.
Client directives, ranked by SEO impact
| Directive | Loads when | Use for |
|---|---|---|
client:visible | Scrolled into view | Anything below the fold: carousels, charts, comment widgets. best |
client:idle | Main thread is free | Non-critical above-the-fold interactivity. good |
client:media | A media query matches | Mobile-only menus, responsive-only widgets. |
client:load | Immediately | Only truly critical UI. Use sparingly. costly |
client:only | Client only, no SSR HTML | Last resort. Content isn't in the initial HTML, so crawlers and AI may miss it. SEO risk |
client:only renders nothing on the server, so its content is invisible to the first-pass crawl and to AI engines. Never put SEO-critical content (headings, body copy, links) inside a client:only island.
Server Islands, third-party scripts & prefetch
- Server Islands (
server:defer) render a fast static shell and stream in per-component dynamic content (personalized or request-time data) without turning the whole page into SSR. - Partytown (
@astrojs/partytown) moves heavy third-party scripts (analytics, tag managers) off the main thread into a web worker. This is a direct, measurable INP win. - Prefetch. Enable Astro's built-in
prefetchso linked pages load near-instantly on hover or tap, cutting perceived latency and improving engagement signals.
The Client Router (View Transitions)
Astro's <ClientRouter /> (formerly <ViewTransitions />, imported from astro:transitions) gives SPA-like, animated navigation while keeping server-rendered HTML that crawlers read perfectly. The snappier feel lowers bounce, a positive user signal, without sacrificing indexability.
import { ClientRouter } from 'astro:transitions'; <head> <ClientRouter /> </head>
Content Collections & Programmatic SEO
Type-safe content plus static generation is Astro's superpower for scale, from a disciplined blog to thousands of landing pages generated from a dataset.
Enforce SEO fields with a typed schema
Content Collections validate frontmatter at build time. Make title and description required and a missing meta description becomes a build error instead of a silently un-optimized page in production.
import { defineCollection, z } from 'astro:content'; import { glob } from 'astro/loaders'; const blog = defineCollection({ loader: glob({ pattern: '**/*.md', base: './src/content/blog' }), schema: z.object({ title: z.string().max(60), // title-tag discipline description: z.string().max(160), // meta-description discipline pubDate: z.date(), image: z.string().optional(), }), }); export const collections = { blog };
Programmatic SEO with getStaticPaths()
To capture wide, long-tail demand ("best CRM for [industry] in [city]"), generate a page per data row at build time. Because they pre-render to raw HTML, they're fast and instantly indexable.
--- export async function getStaticPaths() { const res = await fetch('https://api.tekzuri.com/integrations'); const items = await res.json(); return items.map((it) => ({ params: { slug: it.slug }, // 'mpesa', 'kra-etims', ... props: { data: it }, })); } const { data } = Astro.props; --- <h1>Integrate with {data.name}</h1> <p>{data.uniqueDescription}</p>
Do not just swap a keyword across an identical template ("Mad Libs SEO"). Google penalizes near-duplicate doorway pages. Every generated page must carry genuine information gain: unique data, real reviews, distinct images, actual local specifics. If you can't make each page meaningfully different, generate fewer pages.
Rendering strategy per route
Default to static (SSG) for everything crawlers and AI should read. Use SSR only when the HTML must reflect request-time data: live availability, personalization, auth, or regional pricing. Astro lets you mix per route:
--- export const prerender = false; // this page renders on demand (SSR) ---
Rule of thumb: let Astro ship static HTML by default, and pay the SSR cost only where the content genuinely can't be known at build time.
The 60-Day Execution Plan
Stop reading, start shipping. Four two-week sprints that take you from a clean Astro foundation to programmatic scale and authority-building.
Foundation & Intent
- Stand up Astro: set
site, add@astrojs/sitemap, writerobots.txt(allow AI bots). - Connect Google Search Console & GA4.
- Keyword + entity research; pick one wide term and its 20–30 micro-intents.
- Identify your money pages.
Pillar & Cluster
- Publish the money page + a 3,000–4,000-word pillar with original data and graphics.
- Publish 4–5 cluster posts, each linking back to the pillar.
- Author E-E-A-T profiles; wire up BaseHead, canonicals, and JSON-LD.
Programmatic Scale
- Build a dataset (JSON/Airtable) of locations, use-cases, or integrations.
- Generate 100–500 pages via
getStaticPaths(), each with real information gain. - Apply dynamic schema; optimize all imagery with
<Image />+priority.
Authority & AI
- Run Screaming Frog; fix 404s, chains, and canonical errors from the build.
- Launch a digital-PR push using your original data; answer Source-of-Sources daily.
- Seed presence on Reddit/LinkedIn; check AI engines for brand mentions.
The Pre-Launch Checklist
Run this before every launch and after every migration.
Technical
siteset; canonical tags absolute and correct on every page.- Sitemap generated and submitted; robots.txt references it and allows AI crawlers.
- HTTPS enforced; one trailing-slash convention; no redirect chains.
- Core Web Vitals green on mobile field data (LCP < 2.5s, INP < 200ms, CLS < 0.1).
- Hero image uses
priority; all images havealtand reserved dimensions. - No SEO-critical content trapped in
client:onlyislands.
On-page & content
- Unique title (<60c) and meta description (<160c) per page; one H1 each.
- Content matches the dominant SERP intent and format.
- Internal links from clusters to pillar and money pages, with descriptive anchors.
- No two pages competing for the same intent (cannibalization checked).
AI-readiness (GEO)
- Answer-first sections; question-shaped H2s; statistics and inline citations.
- Valid JSON-LD (Organization, Article, Breadcrumb, FAQ where relevant).
- AI crawlers verified reachable (check CDN/bot settings and server logs).
- Visible "last updated" dates; freshness cadence scheduled.
Make your content genuinely the best answer, make it fast and crawlable, structure it so both humans and machines understand it, and earn the trust of other sites. Every chapter here is a way of doing one of those four things.
Related posts
· Yash ShahDigital marketing for Kenyan SMEs, honestly
Digital marketing for small businesses in Kenya, without the hype. Where a founder on a tight budget should actually spend limited time and money.
Read article→
· Yash ShahLead generation for small businesses
Lead generation for small businesses is a different problem than the big-agency playbook solves. Here's what actually brings in qualified leads.
Read article→
· Yash ShahAI in retail and e-commerce for small teams
Most of Amazon's AI playbook doesn't transfer to a ten-person retailer. These four pieces do, including the WhatsApp part everyone underestimates.
Read article→
