Privacy-Friendly Analytics on Astro
Add privacy-friendly analytics to Astro with one script tag in your layout: Cloudflare Web Analytics, Plausible, Fathom or Umami, plus custom events.
Read Article ➔Short answers to specific Astro questions, each with code you can paste into your project.
Add privacy-friendly analytics to Astro with one script tag in your layout: Cloudflare Web Analytics, Plausible, Fathom or Umami, plus custom events.
Read Article ➔Check Astro bundle size with rollup-plugin-visualizer: generate a treemap of your client JavaScript, find heavy islands and dependencies, then cut them down.
Add canonical URLs in Astro with new URL(Astro.url.pathname, Astro.site) in your head component. Handles query strings, trailing slashes, pagination and syndication.
Speed up Astro builds in CI by caching node_modules/.astro (processed images and the content data store), using npm ci with a cache, and tuning image work.
The Astro CLI commands that matter: astro dev, build, preview, check, add, sync and info, with the flags worth knowing in Astro 7 and when to reach for each.
Conditional rendering in Astro uses JavaScript expressions in the template: && for show/hide, ternaries for either/or, and early variables for complex cases.
Create src/pages/404.astro and Astro builds a 404.html that Netlify, Vercel, Cloudflare Pages and GitHub Pages serve for missing URLs. Template and testing.
Set up an Astro custom domain: add it in your host, create the DNS records, pick www or apex, redirect the other, then update site in astro.config.mjs and redeploy.
Astro's define:vars passes frontmatter values into a style or script tag as CSS custom properties or variables. How it works, when to use it, and what it costs.
Use set:html to render an HTML string in Astro, and Fragment to group elements or fill a slot without a wrapper. Examples, escaping rules and safety notes.
Mix static and server-rendered pages in Astro with export const prerender. Keep output static and opt pages out, or use output server and opt pages back in.
Lazy load Astro islands with client:visible so a component's JavaScript downloads only when it scrolls into view. rootMargin, client:idle and when not to defer.
Add a newsletter signup form to Astro: post a plain HTML form to your email provider on a static site, or use an Astro Action to call its API on the server.
Enable Astro prefetch with prefetch: true in astro.config.mjs and data-astro-prefetch on links. The hover, tap, viewport and load strategies, and when to use each.
Add reading time to Astro posts with a small remark plugin that writes minutesRead into frontmatter, then read it from render() in your post layout.
Astro redirects three ways: the redirects option in astro.config.mjs, your host's _redirects file for real 301s on static sites, and Astro.redirect() on demand.
Show related posts in Astro by scoring other entries on shared tags with getCollection(), sorting by score and date, and rendering the top three. No plugin needed.
Make Astro responsive images with the layout prop or explicit widths and sizes on Image and Picture, so phones download small files and retina screens stay sharp.
Add robots.txt to Astro as a static file in public/ or generate it from an endpoint using site. Examples for production, staging and blocking AI crawlers.
Use Sass in Astro by installing the sass package and adding lang="scss" to style tags or importing .scss files. Partials, global variables and when to skip Sass.
Install @astrojs/sitemap, set site in astro.config.mjs, and Astro writes sitemap-index.xml on every build. Setup, excluding pages, lastmod and on-demand routes.
Build a table of contents in Astro from the headings array that render() returns: filter by depth, nest h3 under h2, and link to the auto-generated heading ids.
How Astro's trailingSlash and build.format settings work together, which combination to pick for your host, and how to keep links and canonical URLs consistent.
Fix 'action called from the server without Astro.callAction()': use Astro.callAction(actions.name, input), or move shared logic into a plain function.
Astro Actions need a server. Fix 'Actions must be used with server output' by adding an adapter and an on-demand route, or use a form service on a static site.
Astro's 'Adapter does not support server output' means your adapter only builds static sites while some pages render on demand. Switch adapter or prerender them.
Astro.glob errors after upgrading? Astro.glob() was removed. Replace it with import.meta.glob() for files or getCollection() for Markdown content.
Unavailable Astro global in getStaticPaths(): it runs before any page exists, so Astro.url and Astro.props don't exist. Use imports or the page body.
Astro's 'Missing value for client:media directive' needs a media query, like client:media="(max-width: 768px)". Syntax, examples and when to use it instead of CSS.
Astro's 'Missing hint on client:only directive' needs a framework name: client:only="react", "vue", "svelte", "solid-js" or "preact".
Since Astro 6, every collection needs a loader. Fix 'Content collection is missing a loader definition' with glob() for folders or file() for JSON and YAML.
Astro's 'Could not find Sharp' means the image library isn't installed for your platform. Install sharp, fix CI lockfiles, or use passthrough.
Astro error 'Cannot set both densities and widths': srcset can't mix x and w descriptors. Use widths for fluid images, densities for fixed sizes.
Astro's 'Duplicate content entry slug' means two files in one collection resolve to the same id. Rename one, fix duplicate slug frontmatter, or clean stray copies.
Astro's 'The endpoint did not return a Response' means a GET or POST handler returned nothing or an object. Return Response.json() on every path.
Astro's 'Failed to parse Markdown frontmatter' is a YAML syntax error: unquoted colons, tabs, bad indentation or mismatched quotes. Fix each.
Astro's 'Font family not found' means the Font component's cssVariable doesn't match one in the fonts config. Match the names exactly and restart the dev server.
Astro's 'frontmatter does not match collection schema' names the file and field that failed. Fix the value, or relax the Zod schema with optional() or default().
Astro's 'Invalid use of getDataEntryById or getEntryBySlug' means old content APIs are in use. Replace both with getEntry(collection, id) and check for undefined.
Astro's 'getImage() must be used on the server' means it ran in browser code. Call getImage in frontmatter and pass the resulting src to your island or script.
Astro's 'Missing params property on getStaticPaths() route' means a returned route has no params or an empty object. Add params matching your file name.
Astro throws 'getStaticPaths() function required for dynamic routes' when a [param] page is prerendered without it. Export getStaticPaths or render on demand.
Astro's Image and Picture components require alt. Fix 'Image missing required alt property' with descriptive text, or alt="" for decorative images.
Astro's 'Image not found' means the image path doesn't resolve. Check spelling, letter case, relative paths from the Markdown file, and where the file lives.
Astro's 'Invalid environment variables' lists variables in env.schema that are missing or the wrong type. Set them locally and on your host, or add defaults.
Fix Astro's 'Invalid value returned by a route from getStaticPaths()': params must be an object of strings. Correct shapes for single, multiple and rest params.
Astro's 'Invalid prerender export' means prerender isn't a literal true or false Astro can read at build time. Use export const prerender = false exactly.
Astro's 'Legacy configuration detected' names an astro.config.mjs option that moved or was removed. How to find the new location for common legacy keys.
Astro's 'Legacy content config file found' means src/content/config.ts must move to src/content.config.ts, with a loader on every collection. Steps and gotchas.
Astro's 'Local images must be imported' means Image got a file path string. Import the file, use image() in content collections, or import.meta.glob for many.
Astro's 'locals must not be reassigned' means code replaced context.locals with a new object. Set properties on it instead, and type them in src/env.d.ts.
Astro's 'MDX integration missing' means an .mdx file is rendered without @astrojs/mdx. Run npx astro add mdx, include mdx in glob patterns, and restart dev.
Astro's 'The middleware didn't return a Response' means onRequest ended without returning next(). Return next(), and await it to edit headers.
Astro's 'Missing image dimensions' error hits remote images without width and height. Add both, use inferSize, or import the file if it lives in src.
Astro's 'Module is only available server-side' means client code imported astro:env/server. Read it in frontmatter; pass safe values down.
Astro's 'Cannot use server-side rendering without an adapter' means a page renders on demand but no adapter is set. Add one, or make the page static again.
Astro's 'No matching renderer found' means a React, Vue, Svelte or Solid component is used without its integration. Add it with npx astro add, then restart.
Astro's 'No static path found for requested path' means getStaticPaths() didn't return the URL you visited. Check params, string values and trailing slashes.
Astro's 'Prerendered route generates the same path as another route' means two pages build one URL. Find the overlap, rename or filter getStaticPaths().
Astro's 'Remote image is not allowed' means the image's domain isn't in image.domains or image.remotePatterns. Add the host to astro.config.mjs and rebuild.
Astro's 'Attempted to render an undefined content collection entry' means getEntry() returned nothing. Check the id, guard before render(), and return a 404.
Astro error 'Content schema should not contain slug': slug is reserved for entry ids. Remove it from the Zod schema; keep it in frontmatter.
Astro's 'Cannot use server islands without an adapter' appears when a component uses server:defer on a site with no adapter. Add an adapter or render it statically.