This is the abridged developer documentation for Astro
# Why Astro?
> Astro is the web framework for building content-driven websites like blogs, marketing, and e-commerce. Learn why Astro might be a good choice for your next website.
**Astro** is the web framework for building **content-driven websites** like blogs, marketing, and e-commerce. Astro is best-known for pioneering a new [frontend architecture](/en/concepts/islands/) to reduce JavaScript overhead and complexity compared to other frameworks. If you need a website that loads fast and has great SEO, then Astro is for you. ## Features [Section titled “Features”](#features) **Astro is an all-in-one web framework.** It includes everything you need to create a website, built-in. There are also hundreds of different [integrations](https://astro.build/integrations/) and [API hooks](/en/reference/integrations-reference/) available to customize a project to your exact use case and needs. Some highlights include: * **[Islands](/en/concepts/islands/):** A component-based web architecture optimized for content-driven websites. * **[UI-agnostic](/en/guides/framework-components/):** Supports React, Preact, Svelte, Vue, Solid, HTMX, web components, and more. * **[Server-first](/en/guides/on-demand-rendering/):** Moves expensive rendering off of your visitors’ devices. * **[Zero JS, by default](/en/basics/astro-components/):** Less client-side JavaScript to slow your site down. * **[Content collections](/en/guides/content-collections/):** Organize, validate, and provide TypeScript type-safety for your Markdown content. * **[Customizable](/en/guides/integrations-guide/):** Partytown, MDX, and hundreds of integrations to choose from. ## Design Principles [Section titled “Design Principles”](#design-principles) Here are five core design principles to help explain why we built Astro, the problems that it exists to solve, and why Astro may be the best choice for your project or team. Astro is… 1. **[Content-driven](#content-driven):** Astro was designed to showcase your content. 2. **[Server-first](#server-first):** Websites run faster when they render HTML on the server. 3. **[Fast by default](#fast-by-default):** It should be impossible to build a slow website in Astro. 4. **[Easy to use](#easy-to-use):** You don’t need to be an expert to build something with Astro. 5. **[Developer-focused](#developer-focused):** You should have the resources you need to be successful. ### Content-driven [Section titled “Content-driven”](#content-driven) **Astro was designed for building content-rich websites.** This includes marketing sites, publishing sites, documentation sites, blogs, portfolios, landing pages, community sites, and e-commerce sites. If you have content to show, it needs to reach your reader quickly. By contrast, most modern web frameworks were designed for building *web applications*. These frameworks excel at building more complex, application-like experiences in the browser: logged-in admin dashboards, inboxes, social networks, todo lists, and even native-like applications like [Figma](https://figma.com/) and [Ping](https://ping.gg/). However with that complexity, they can struggle to provide great performance when delivering your content. Astro’s focus on content from its beginnings as a static site builder have allowed Astro to **sensibly scale up to performant, powerful, dynamic web applications** that still respect your content and your audience. Astro’s unique focus on content lets Astro make tradeoffs and deliver unmatched performance features that wouldn’t make sense for more application-focused web frameworks to implement. ### Server-first [Section titled “Server-first”](#server-first) **Astro leverages server rendering over client-side rendering in the browser as much as possible.** This is the same approach that traditional server-side frameworks -- PHP, WordPress, Laravel, Ruby on Rails, etc. -- have been using for decades. But you don’t need to learn a second server-side language to unlock it. With Astro, everything is still just HTML, CSS, and JavaScript (or TypeScript, if you prefer). This approach stands in contrast to other modern JavaScript web frameworks like Next.js, SvelteKit, Nuxt, Remix, and others. These frameworks were built for client-side rendering of your entire website and include server-side rendering mainly to address performance concerns. This approach has been dubbed the **Single-Page App (SPA)**, in contrast with Astro’s **Multi-Page App (MPA)** approach. The SPA model has its benefits. However, these come at the expense of additional complexity and performance tradeoffs. These tradeoffs harm page performance -- critical metrics like [Time to Interactive (TTI)](https://web.dev/interactive/) -- which doesn’t make much sense for content-focused websites where first-load performance is essential. Astro’s server-first approach allows you to opt in to client-side rendering only if, and exactly as, necessary. You can choose to add UI framework components that run on the client. You can take advantage of Astro’s view transitions router for finer control over select page transitions and animations. Astro’s server-first rendering, either pre-rendered or on-demand, provides performant defaults that you can enhance and extend. ### Fast by default [Section titled “Fast by default”](#fast-by-default) Good performance is always important, but it is *especially* critical for websites whose success depends on displaying your content. It has been well-proven that poor performance loses you engagement, conversions, and money. For example: * Every 100ms faster → 1% more conversions ([Mobify](https://web.dev/why-speed-matters/), earning +$380,000/yr) * 50% faster → 12% more sales ([AutoAnything](https://www.digitalcommerce360.com/2010/08/19/web-accelerator-revs-conversion-and-sales-autoanything/)) * 20% faster → 10% more conversions ([Furniture Village](https://www.thinkwithgoogle.com/intl/en-gb/marketing-strategies/app-and-mobile/furniture-village-and-greenlight-slash-page-load-times-boosting-user-experience/)) * 40% faster → 15% more sign-ups ([Pinterest](https://medium.com/pinterest-engineering/driving-user-growth-with-performance-improvements-cfc50dafadd7)) * 850ms faster → 7% more conversions ([COOK](https://web.dev/why-speed-matters/)) * Every 1 second slower → 10% fewer users ([BBC](https://www.creativebloq.com/features/how-the-bbc-builds-websites-that-scale)) In many web frameworks, it is easy to build a website that looks great during development only to load painfully slow once deployed. JavaScript is often the culprit, since many phones and lower-powered devices rarely match the speed of a developer’s laptop. Astro’s magic is in how it combines the two values explained above -- a content focus with a server-first architecture -- to make tradeoffs and deliver features that other frameworks cannot. The result is amazing web performance for every website, out of the box. Our goal: **It should be nearly impossible to build a slow website with Astro.** An Astro website can [load 40% faster with 90% less JavaScript](https://twitter.com/t3dotgg/status/1437195415439360003) than the same site built with the most popular React web framework. But don’t take our word for it: watch Astro’s performance leave Ryan Carniato (creator of Solid.js and Marko) [speechless](https://youtu.be/2ZEMb_H-LYE?t=8163). ### Easy to use [Section titled “Easy to use”](#easy-to-use) **Astro’s goal is to be accessible to every web developer.** Astro was designed to feel familiar and approachable regardless of skill level or past experience with web development. The `.astro` UI language is a superset of HTML: any valid HTML is valid Astro templating syntax! So, if you can write HTML, you can write Astro components! But, it also combines some of our favorite features borrowed from other component languages like JSX expressions (React) and CSS scoping by default (Svelte and Vue). This closeness to HTML also makes it easier to use progressive enhancement and common accessibility patterns without any overhead. We then made sure that you could also use your favorite UI component languages that you already know, and even reuse components you might already have. React, Preact, Svelte, Vue, Solid, and others, including web components, are all supported for authoring UI components in an Astro project. Astro was designed to be less complex than other UI frameworks and languages. One big reason for this is that Astro was designed to render on the server, not in the browser. That means that you don’t need to worry about: hooks (React), stale closures (also React), refs (Vue), observables (Svelte), atoms, selectors, reactions, or derivations. There is no reactivity on the server, so all of that complexity melts away. One of our favorite sayings is: **opt in to complexity.** We designed Astro to remove as much “required complexity” as possible from the developer experience, especially as you onboard for the first time. You can build a “Hello World” example website in Astro with just HTML and CSS. Then, when you need to build something more powerful, you can incrementally reach for new features and APIs as you go. ### Developer-focused [Section titled “Developer-focused”](#developer-focused) We strongly believe that Astro is only a successful project if people love using it. Astro has everything you need to support you as you build with Astro. Astro invests in developer tools like a great CLI experience from the moment you open your terminal, an official VS Code extension for syntax highlighting, TypeScript and Intellisense, and documentation actively maintained by hundreds of community contributors and available in 14 languages. Our welcoming, respectful, inclusive community on Discord is ready to provide support, motivation, and encouragement. Open a `#support` thread to get help with your project. Visit our dedicated `#showcase` channel for sharing your Astro sites, blog posts, videos, and even work-in-progress for safe feedback and constructive criticism. Participate in regular live events such as our weekly community call, “Talking and Doc’ing,” and API/bug bashes. As an open-source project, we welcome contributions of all types and sizes from community members of all experience levels. You are invited to join in roadmap discussions to shape the future of Astro, and we hope you’ll contribute fixes and features to the core codebase, compiler, docs, language tools, websites, and other projects.
# Islands architecture
> Learn about how Astro's islands architecture helps keep sites fast.
Astro helped pioneer and popularize a new frontend architecture pattern called **Islands Architecture.** Islands architecture works by rendering the majority of your page to fast, static HTML with smaller “islands” of JavaScript added when interactivity or personalization is needed on the page (an image carousel, for example). This avoids the monolithic JavaScript payloads that slow down the responsiveness of many other, modern JavaScript web frameworks. ## A brief history [Section titled “A brief history”](#a-brief-history) The term “component island” was first coined by Etsy’s frontend architect [Katie Sylor-Miller](https://sylormiller.com/) in 2019. This idea was then expanded on and documented in [this post](https://jasonformat.com/islands-architecture/) by Preact creator Jason Miller on August 11, 2020. > The general idea of an “Islands” architecture is deceptively simple: render HTML pages on the server, and inject placeholders or slots around highly dynamic regions \[…] that can then be “hydrated” on the client into small self-contained widgets, reusing their server-rendered initial HTML.\ > — Jason Miller, Creator of Preact The technique that this architectural pattern builds on is also known as **partial** or **selective hydration.** In contrast, most JavaScript-based web frameworks hydrate & render an entire website as one large JavaScript application (also known as a single-page application, or SPA). SPAs provide simplicity and power but suffer from page-load performance problems due to heavy client-side JavaScript usage. SPAs have their place, even [embedded inside an Astro page](/en/guides/migrate-to-astro/from-create-react-app/). But, SPAs lack the native ability to selectively and strategically hydrate, making them a heavy-handed choice for most projects on the web today. Astro became popular as the first mainstream JavaScript web framework with selective hydration built-in, using that same component islands pattern first coined by Sylor-Miller. We’ve since expanded and evolved on Sylor-Miller’s original work, which helped to inspire a similar component island approach to dynamically server-rendered content. ## What is an island? [Section titled “What is an island?”](#what-is-an-island) In Astro, an island is an enhanced UI component on an otherwise static page of HTML. A [**client island**](#client-islands) is an interactive JavaScript UI component that is hydrated separately from the rest of the page, while a [**server island**](#server-islands) is a UI component that server-renders its dynamic content separately from the rest of the page. Both islands run expensive or slower processes independently, on a per-component basis, for optimized page loads. ## Island components [Section titled “Island components”](#island-components) Astro components are the building blocks of your page template. They render to static HTML with no client-side runtime. Think of a client island as an interactive widget floating in a sea of otherwise static, lightweight, server-rendered HTML. Server islands can be added for personalized or dynamic server-rendered elements, such as a logged in visitor’s profile picture. Header (interactive island) Sidebar (static HTML) Static content like text, images, etc. Image carousel (interactive island) Footer (static HTML) Source: [Islands Architecture: Jason Miller](https://jasonformat.com/islands-architecture/) An island always runs in isolation from other islands on the page, and multiple islands can exist on a page. Client islands can still share state and communicate with each other, even though they run in different component contexts. This flexibility allows Astro to support multiple UI frameworks like [React](https://react.dev/), [Preact](https://preactjs.com/), [Svelte](https://svelte.dev/), [Vue](https://vuejs.org/), and [SolidJS](https://www.solidjs.com/). Because they are independent, you can even mix several frameworks on each page. ## Client Islands [Section titled “Client Islands”](#client-islands) By default, Astro will automatically render every UI component to just HTML & CSS, **stripping out all client-side JavaScript automatically.** src/pages/index.astro ```astro ``` This may sound strict, but this behavior is what keeps Astro websites fast by default and protects developers from accidentally sending unnecessary or unwanted JavaScript that might slow down their website. Turning any static UI component into an interactive island requires only a `client:*` directive. Astro then automatically builds and bundles your client-side JavaScript for optimized performance. src/pages/index.astro ```astro ``` With islands, client-side JavaScript is only loaded for the explicit interactive components that you mark using `client:*` directives. And because interaction is configured at the component-level, you can handle different loading priorities for each component based on its usage. For example, `client:idle` tells a component to load when the browser becomes idle, and `client:visible` tells a component to load only once it enters the viewport. ### Benefits of client islands The most obvious benefit of building with Astro Islands is performance: the majority of your website is converted to fast, static HTML and JavaScript is only loaded for the individual components that need it. JavaScript is one of the slowest assets that you can load per-byte, so every byte counts. Another benefit is parallel loading. In the example illustration above, the low-priority “image carousel” island doesn’t need to block the high-priority “header” island. The two load in parallel and hydrate in isolation, meaning that the header becomes interactive immediately without having to wait for the heavier carousel lower down the page. Even better, you can tell Astro exactly how and when to render each component. If that image carousel is really expensive to load, you can attach a special [client directive](/en/reference/directives-reference/#client-directives) that tells Astro to only load the carousel when it becomes visible on the page. If the user never sees it, it never loads. In Astro, it’s up to you as the developer to explicitly tell Astro which components on the page need to also run in the browser. Astro will only hydrate exactly what’s needed on the page and leave the rest of your site as static HTML. **Client islands are the secret to Astro’s fast-by-default performance story!** Read more about [using JavaScript framework components](/en/guides/framework-components/) in your project. ## Server islands [Section titled “Server islands”](#server-islands) Server islands are a way to move expensive or slow server-side code out of the way of the main rendering process, making it easy to combine high-performance static HTML and dynamic server-generated components. Add the [`server:defer` directive](/en/reference/directives-reference/#server-directives) to any Astro component on your page to turn it into its own server island: src/pages/index.astro ```astro --- import Avatar from "../components/Avatar.astro"; --- ``` This breaks up your page with smaller areas of server-rendered content that each load in parallel. Your page’s main content can be rendered immediately with placeholder content, such as a generic avatar until your island’s own content is available. With server islands, having small components of personalized content does not delay the rendering of an otherwise static page. This rendering pattern was built to be portable. It does not depend on any server infrastructure so it will work with any host, from a Node.js server in a Docker container to the serverless provider of your choice. ### Benefits of server islands One benefit of server islands is the ability to render the more highly dynamic parts of your page on the fly. This allows the outer shell and main content to be more aggressively cached, providing faster performance. Another benefit is providing a great visitor experience. Server islands are optimized and load quickly, often even before the browser has even painted the page. But in the short time it takes for your islands to render, you can display custom fallback content and prevent any layout shift. An example of a site that benefits from Astro’s server islands is an e-commerce storefront. Although the main content of product pages change infrequently, these pages typically have some dynamic pieces: * The user’s avatar in the header. * Special deals and sales for the product. * User reviews. Using server islands for these elements, your visitor will see the most important part of the page, your product, immediately. Generic avatars, loading spinners, and store announcements can be displayed as fallback content until the personalized parts are available. Read more about [using server islands](/en/guides/server-islands/) in your project.
# Install Astro
> How to install Astro and start a new project.
The [`create astro` CLI command](#install-from-the-cli-wizard) is the fastest way to start a new Astro project from scratch. It will walk you through every step of setting up your new Astro project and allow you to choose from a few different official starter templates. You can also run the CLI command with the `template` flag to begin your project using any existing theme or starter template. Explore our [themes and starters showcase](https://astro.build/themes/) where you can browse themes for blogs, portfolios, documentation sites, landing pages, and more! To install Astro manually instead, see our [step-by-step manual installation guide](#manual-setup). ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * **Node.js** - `v18.20.8` or `v20.3.0`, `v22.0.0` or higher. ( `v19` and `v21` are not supported.) * **Text editor** - We recommend [VS Code](https://code.visualstudio.com/) with our [Official Astro extension](https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode). * **Terminal** - Astro is accessed through its command-line interface (CLI). ## Browser compatibility [Section titled “Browser compatibility”](#browser-compatibility) Astro is built with Vite which targets browsers with modern JavaScript support by default. For a complete reference, you can see the [list of currently supported browser versions in Vite](https://vite.dev/guide/build.html#browser-compatibility). ## Install from the CLI wizard [Section titled “Install from the CLI wizard”](#install-from-the-cli-wizard) You can run `create astro` anywhere on your machine, so there’s no need to create a new empty directory for your project before you begin. If you don’t have an empty directory yet for your new project, the wizard will help create one for you automatically. 1. Run the following command in your terminal to start the install wizard: * npm ```shell # create a new project with npm npm create astro@latest ``` * pnpm ```shell # create a new project with pnpm pnpm create astro@latest ``` * Yarn ```shell # create a new project with yarn yarn create astro ``` If all goes well, you will see a success message followed by some recommended next steps. 2. Now that your project has been created, you can `cd` into your new project directory to begin using Astro. 3. If you skipped the “Install dependencies?” step during the CLI wizard, then be sure to install your dependencies before continuing. * npm ```shell npm install ``` * pnpm ```shell pnpm install ``` * Yarn ```shell yarn install ``` 4. You can now [start the Astro dev server](/en/develop-and-build/#start-the-astro-dev-server) and see a live preview of your project while you build! ## CLI installation flags [Section titled “CLI installation flags”](#cli-installation-flags) You can run the `create astro` command with additional flags to customize the setup process (e.g. answering “yes” to all questions, skipping the Houston animation) or your new project (e.g. install git or not, add integrations). See [all the available `create astro` command flags](https://github.com/withastro/astro/blob/main/packages/create-astro/README.md) ### Add integrations [Section titled “Add integrations”](#add-integrations) You can start a new Astro project and install any [official integrations](/en/guides/integrations-guide/) or community integrations that support the `astro add` command at the same time by passing the `--add` argument to the `create astro` command. Run the following command in your terminal, substituting any integration that supports the `astro add` command: * npm ```shell # create a new project with React and Partytown npm create astro@latest -- --add react --add partytown ``` * pnpm ```shell # create a new project with React and Partytown pnpm create astro@latest --add react --add partytown ``` * Yarn ```shell # create a new project with React and Partytown yarn create astro --add react --add partytown ``` ### Use a theme or starter template [Section titled “Use a theme or starter template”](#use-a-theme-or-starter-template) You can start a new Astro project based on an [official example](https://github.com/withastro/astro/tree/main/examples) or the `main` branch of any GitHub repository by passing a `--template` argument to the `create astro` command. Run the following command in your terminal, substituting the official Astro starter template name, or the GitHub username and repository of the theme you want to use: * npm ```shell # create a new project with an official example npm create astro@latest -- --template # create a new project based on a GitHub repository’s main branch npm create astro@latest -- --template / ``` * pnpm ```shell # create a new project with an official example pnpm create astro@latest --template # create a new project based on a GitHub repository’s main branch pnpm create astro@latest --template / ``` * Yarn ```shell # create a new project with an official example yarn create astro --template # create a new project based on a GitHub repository’s main branch yarn create astro --template / ``` By default, this command will use the template repository’s `main` branch. To use a different branch name, pass it as part of the `--template` argument: `/#`. ## Manual Setup [Section titled “Manual Setup”](#manual-setup) This guide will walk you through the steps to manually install and configure a new Astro project. If you prefer not to use our automatic `create astro` CLI tool, you can set up your project yourself by following the guide below. 1. Create your directory Create an empty directory with the name of your project, and then navigate into it. ```bash mkdir my-astro-project cd my-astro-project ``` Once you are in your new directory, create your project `package.json` file. This is how you will manage your project dependencies, including Astro. If you aren’t familiar with this file format, run the following command to create one. * npm ```shell npm init --yes ``` * pnpm ```shell pnpm init ``` * Yarn ```shell yarn init --yes ``` 2. Install Astro First, install the Astro project dependencies inside your project. * npm ```shell npm install astro ``` * pnpm ```shell pnpm add astro ``` * Yarn ```shell yarn add astro ``` Then, replace any placeholder “scripts” section of your `package.json` with the following: package.json ```diff { "scripts": { -"test": "echo \"Error: no test specified\" && exit 1", +"dev": "astro dev", +"build": "astro build", +"preview": "astro preview" }, } ``` You’ll use these scripts later in the guide to start Astro and run its different commands. 3. Create your first page In your text editor, create a new file in your directory at `src/pages/index.astro`. This will be your first Astro page in the project. For this guide, copy and paste the following code snippet (including `---` dashes) into your new file: src/pages/index.astro ```astro --- // Welcome to Astro! Everything between these triple-dash code fences // is your "component frontmatter". It never runs in the browser. console.log('This runs in your terminal, not the browser!'); ---
Hello, World!
``` 4. Create your first static asset You will also want to create a `public/` directory to store your static assets. Astro will always include these assets in your final build, so you can safely reference them from inside your component templates. In your text editor, create a new file in your directory at `public/robots.txt`. `robots.txt` is a simple file that most sites will include to tell search bots like Google how to treat your site. For this guide, copy and paste the following code snippet into your new file: public/robots.txt ```diff # Example: Allow all bots to scan and index your site. # Full syntax: https://developers.google.com/search/docs/advanced/robots/create-robots-txt User-agent: * Allow: / ``` 5. Create `astro.config.mjs` Astro is configured using `astro.config.mjs`. This file is optional if you do not need to configure Astro, but you may wish to create it now. Create `astro.config.mjs` at the root of your project, and copy the code below into it: astro.config.mjs ```js import { defineConfig } from "astro/config"; // https://astro.build/config export default defineConfig({}); ``` If you want to include [UI framework components](/en/guides/framework-components/) such as React, Svelte, etc. or use other tools such as MDX or Partytown in your project, here is where you will [manually import and configure integrations](/en/guides/integrations-guide/). Read Astro’s [API configuration reference](/en/reference/configuration-reference/) for more information. 6. Add TypeScript support TypeScript is configured using `tsconfig.json`. Even if you don’t write TypeScript code, this file is important so that tools like Astro and VS Code know how to understand your project. Some features (like npm package imports) aren’t fully supported in the editor without a `tsconfig.json` file. If you do intend to write TypeScript code, using Astro’s `strict` or `strictest` template is recommended. You can view and compare the three template configurations at [astro/tsconfigs/](https://github.com/withastro/astro/blob/main/packages/astro/tsconfigs/). Create `tsconfig.json` at the root of your project, and copy the code below into it. (You can use `base`, `strict`, or `strictest` for your TypeScript template): tsconfig.json ```json { "extends": "astro/tsconfigs/base" } ``` Read Astro’s [TypeScript setup guide](/en/guides/typescript/#setup) for more information. 7. Next Steps If you have followed the steps above, your project directory should now look like this: * astro.config.mjs * package-lock.json or `yarn.lock`, `pnpm-lock.yaml`, etc. * package.json * tsconfig.json 8. You can now [start the Astro dev server](/en/develop-and-build/#start-the-astro-dev-server) and see a live preview of your project while you build!
# Project structure
> An introduction to the basic file structure of an Astro project.
Your new Astro project generated from the `create astro` CLI wizard already includes some files and folders. Others, you will create yourself and add to Astro’s existing file structure. Here’s how an Astro project is organized, and some files you will find in your new project. ## Directories and Files [Section titled “Directories and Files”](#directories-and-files) Astro leverages an opinionated folder layout for your project. Every Astro project root should include the following directories and files: * `src/*` - Your project source code (components, pages, styles, images, etc.) * `public/*` - Your non-code, unprocessed assets (fonts, icons, etc.) * `package.json` - A project manifest. * `astro.config.mjs` - An Astro configuration file. (recommended) * `tsconfig.json` - A TypeScript configuration file. (recommended) ### Example Project Tree [Section titled “Example Project Tree”](#example-project-tree) A common Astro project directory might look like this: * astro.config.mjs * package.json * tsconfig.json ### `src/` [Section titled “src/”](#src) The `src/` folder is where most of your project source code lives. This includes: * [Pages](/en/basics/astro-pages/) * [Layouts](/en/basics/layouts/) * [Astro components](/en/basics/astro-components/) * [UI framework components (React, etc.)](/en/guides/framework-components/) * [Styles (CSS, Sass)](/en/guides/styling/) * [Markdown](/en/guides/markdown-content/) * [Images to be optimized and processed by Astro](/en/guides/images/) Astro processes, optimizes, and bundles your `src/` files to create the final website that is shipped to the browser. Unlike the static `public/` directory, your `src/` files are built and handled for you by Astro. Some files (like Astro components) are not even sent to the browser as written but are instead rendered to static HTML. Other files (like CSS) are sent to the browser but may be optimized or bundled with other CSS files for performance. ### `src/pages` [Section titled “src/pages”](#srcpages) Pages routes are created for your site by adding [supported file types](/en/basics/astro-pages/#supported-page-files) to this directory. Caution `src/pages` is a **required** sub-directory in your Astro project. Without it, your site will have no pages or routes! ### `src/components` [Section titled “src/components”](#srccomponents) **Components** are reusable units of code for your HTML pages. These could be [Astro components](/en/basics/astro-components/), or [UI framework components](/en/guides/framework-components/) like React or Vue. It is common to group and organize all of your project components together in this folder. This is a common convention in Astro projects, but it is not required. Feel free to organize your components however you like! ### `src/layouts` [Section titled “src/layouts”](#srclayouts) [Layouts](/en/basics/layouts/) are Astro components that define the UI structure shared by one or more [pages](/en/basics/astro-pages/). Just like `src/components`, this directory is a common convention but not required. ### `src/styles` [Section titled “src/styles”](#srcstyles) It is a common convention to store your CSS or Sass files in a `src/styles` directory, but this is not required. As long as your styles live somewhere in the `src/` directory and are imported correctly, Astro will handle and optimize them. ### `public/` [Section titled “public/”](#public) The `public/` directory is for files and assets in your project that do not need to be processed during Astro’s build process. The files in this folder will be copied into the build folder untouched, and then your site will be built. This behavior makes `public/` ideal for common assets that do not require any processing, like some images and fonts, or special files such as `robots.txt` and `manifest.webmanifest`. You can place CSS and JavaScript in your `public/` directory, but be aware that those files will not be bundled or optimized in your final build. ### `package.json` [Section titled “package.json”](#packagejson) This is a file used by JavaScript package managers to manage your dependencies. It also defines the scripts that are commonly used to run Astro (ex: `npm run dev`, `npm run build`). There are [two kinds of dependencies](https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file) you can specify in a `package.json`: `dependencies` and `devDependencies`. In most cases, these work the same: Astro needs all dependencies at build time, and your package manager will install both. We recommend putting all of your dependencies in `dependencies` to start, and only use `devDependencies` if you find a specific need to do so. For help creating a new `package.json` file for your project, check out the [manual setup](/en/install-and-setup/#manual-setup) instructions. ### `astro.config.mjs` [Section titled “astro.config.mjs”](#astroconfigmjs) This file is generated in every starter template and includes configuration options for your Astro project. Here you can specify integrations to use, build options, server options, and more. Astro supports several file formats for its JavaScript configuration file: `astro.config.js`, `astro.config.mjs`, `astro.config.cjs` and `astro.config.ts`. We recommend using `.mjs` in most cases or `.ts` if you want to write TypeScript in your config file. TypeScript config file loading is handled using [`tsm`](https://github.com/lukeed/tsm) and will respect your project’s `tsconfig` options. See the [configuration reference](/en/reference/configuration-reference/) for complete details. ### `tsconfig.json` [Section titled “tsconfig.json”](#tsconfigjson) This file is generated in every starter template and includes TypeScript configuration options for your Astro project. Some features (like npm package imports) aren’t fully supported in the editor without a `tsconfig.json` file. See the [TypeScript Guide](/en/guides/typescript/) for details on setting configurations.
# Develop and build
> How to start working on a new project.
Once you have an Astro project, now you’re ready to build with Astro! 🚀 ## Edit your project [Section titled “Edit your project”](#edit-your-project) To make changes to your project, open your project folder in your code editor. Working in development mode with the dev server running allows you to see updates to your site as you edit the code. You can also [customize aspects of your development environment](#configure-your-dev-environment) such as configuring TypeScript or installing the official Astro editor extensions. ### Start the Astro dev server [Section titled “Start the Astro dev server”](#start-the-astro-dev-server) Astro comes with a built-in development server that has everything you need for project development. The `astro dev` CLI command will start the local development server so that you can see your new website in action for the very first time. Every starter template comes with a pre-configured script that will run `astro dev` for you. After navigating into your project directory, use your favorite package manager to run this command and start the Astro development server. * npm ```shell npm run dev ``` * pnpm ```shell pnpm run dev ``` * yarn ```shell yarn run dev ``` If all goes well, Astro will now be serving your project on . Visit that link in your browser and see your new site! ### Work in development mode [Section titled “Work in development mode”](#work-in-development-mode) Astro will listen for live file changes in your `src/` directory and update your site preview as you build, so you will not need to restart the server as you make changes during development. You will always be able to see an up-to-date version of your site in your browser when the dev server is running. When viewing your site in the browser, you’ll have access to the [Astro dev toolbar](/en/guides/dev-toolbar/). As you build, it will help you inspect your [islands](/en/concepts/islands/), spot accessibility issues, and more. If you aren’t able to open your project in the browser after starting the dev server, go back to the terminal where you ran the `dev` command and check the message displayed. It should tell you if an error occurred, or if your project is being served at a different URL than . ## Build and preview your site [Section titled “Build and preview your site”](#build-and-preview-your-site) To check the version of your site that will be created at build time, quit the dev server (`Ctrl` + `C`) and run the appropriate build command for your package manager in your terminal: * npm ```shell npm run build ``` * pnpm ```shell pnpm build ``` * yarn ```shell yarn run build ``` Astro will build a deploy-ready version of your site in a separate folder (`dist/` by default) and you can watch its progress in the terminal. This will alert you to any build errors in your project before you deploy to production. If TypeScript is configured to `strict` or `strictest`, the `build` script will also check your project for type errors. When the build is finished, run the appropriate `preview` command (e.g. `npm run preview`) in your terminal and you can view the built version of your site locally in the same browser preview window. Note that this previews your code as it existed when the build command was last run. This is meant to give you a preview of how your site will look when it is deployed to the web. Any later changes you make to your code after building will **not** be reflected while you preview your site until you run the build command again. Use (`Ctrl` + `C`) to quit the preview and run another terminal command, such as restarting the dev server to go back to [working in development mode](#work-in-development-mode) which does update as you edit to show a live preview of your code changes. Read more about [the Astro CLI](/en/reference/cli-reference/) and the terminal commands you will use as you build with Astro. ## Next Steps [Section titled “Next Steps”](#next-steps) Success! You are now ready to start building with Astro! 🥳 Here are a few things that we recommend exploring next. You can read them in any order. You can even leave our documentation for a bit and go play in your new Astro project codebase, coming back here whenever you run into trouble or have a question. ### Configure your dev environment [Section titled “Configure your dev environment”](#configure-your-dev-environment) Explore the guides below to customize your development experience. [Editor Setup ](/en/editor-setup/)Customize your code editor to improve the Astro developer experience and unlock new features. [Dev Toolbar ](/en/guides/dev-toolbar/)Explore the helpful features of the dev toolbar. [TypeScript Configuration ](/en/guides/typescript/)Configure options for type-checking, IntelliSense, and more. ### Explore Astro’s Features [Section titled “Explore Astro’s Features”](#explore-astros-features) [Understand your codebase ](/en/basics/project-structure/)Learn about Astro’s file structure in our Project Structure guide. [Create content collections ](/en/guides/content-collections/)Add content to your new site with frontmatter validation and automatic type-safety. [Add view transitions ](/en/guides/view-transitions/)Create seamless page transitions and animations. [Learn about Islands ](/en/concepts/islands/)Read about Astro's islands architecture. ### Take the introductory tutorial [Section titled “Take the introductory tutorial”](#take-the-introductory-tutorial) Build a fully functional Astro blog starting from a single blank page in our [introductory tutorial](/en/tutorial/0-introduction/). This is a great way to see how Astro works and walks you through the basics of pages, layouts, components, routing, islands, and more. It also includes an optional, beginner-friendly unit for those newer to web development concepts in general, which will guide you through installing the necessary applications on your computer, creating a GitHub account, and deploying your site.
# Configuration overview
> Get to know the ways you can configure and customize your new project and your development experience.
Astro is a flexible, unopinionated framework that allows you to configure your project in many different ways. This means that getting started with a new project might feel overwhelming: there is no “one best way” to set up your Astro project! The guides in this “Configuration” section will help you familiarize yourself with the various files that allow you to configure and customize aspects of your project and development environment. If this is your first Astro project, or if it’s been a while since you’ve set up a new project, use the following guides and reference in the documentation for assistance. ## The Astro config File [Section titled “The Astro config File”](#the-astro-config-file) The [Astro config file](/en/reference/configuration-reference/) is a JavaScript file included at the root of every starter project: astro.config.mjs ```js import { defineConfig } from "astro/config"; export default defineConfig({ // your configuration options here... }); ``` It is only required if you have something to configure, but most projects will use this file. The `defineConfig()` helper provides automatic IntelliSense in your IDE and is where you will add all your configuration options to tell Astro how to build and render your project to HTML. We recommend using the default file format `.mjs` in most cases, or `.ts` if you want to write TypeScript in your config file. However, `astro.config.js` and `astro.config.cjs` are also supported. Read Astro’s [configuration reference](/en/reference/configuration-reference/) for a full overview of all supported configuration options. ## The TypeScript config File [Section titled “The TypeScript config File”](#the-typescript-config-file) Every Astro starter project includes a `tsconfig.json` file in your project. Astro’s [component script](/en/basics/astro-components/#the-component-script) is Typescript, which provides Astro’s editor tooling and allows you to optionally add syntax to your JavaScript for type checking of your own project code. Use the `tsconfig.json` file to configure the TypeScript template that will perform type checks on your code, configure TypeScript plugins, set import aliases, and more. Read Astro’s [TypeScript guide](/en/guides/typescript/) for a full overview of TypeScript options and Astro’s built-in utility types. ## Development Experience [Section titled “Development Experience”](#development-experience) While you work in development mode, you can take advantage of your code editor and other tools to improve the Astro developer experience. Astro provides its own official VS Code extension and is compatible with several other popular editor tools. Astro also provides a customizable toolbar that displays in your browser preview while the dev server is running. You can install and even build your own toolbar apps for additional functionality. Read Astro’s guides to [editor setup options](/en/editor-setup/) and [using the dev toolbar](/en/guides/dev-toolbar/) to learn how to customize your development experience. ## Common new project tasks [Section titled “Common new project tasks”](#common-new-project-tasks) Here are some first steps you might choose to take with a new Astro project. ### Add your deployment domain [Section titled “Add your deployment domain”](#add-your-deployment-domain) For generating your sitemap and creating canonical URLs, configure your deployment URL in the [`site`](/en/reference/configuration-reference/#site) option. If you are deploying to a path (e.g. `www.example.com/docs`), you can also configure a [`base`](/en/reference/configuration-reference/#base) for the root of your project. Additionally, different deployment hosts may have different behavior regarding trailing slashes at the end of your URLs. (e.g. `example.com/about` vs `example.com/about/`). Once your site is deployed, you may need to configure your [`trailingSlash`](/en/reference/configuration-reference/#trailingslash) preference. astro.config.mjs ```js import { defineConfig } from "astro/config"; export default defineConfig({ site: "https://www.example.com", base: "/docs", trailingSlash: "always", }); ``` ### Add site metadata [Section titled “Add site metadata”](#add-site-metadata) Astro does not use its configuration file for common SEO or meta data, only for information required to build your project code and render it to HTML. Instead, this information is added to your page `` using standard HTML `` and `` tags, just as if you were writing plain HTML pages. One common pattern for Astro sites is to create a `` [`.astro` component](/en/basics/astro-components/) that can be added to a common [layout component](/en/basics/layouts/) so it can apply to all your pages. src/components/MainLayout.astro ```astro --- import Head from "./Head.astro"; const { ...props } = Astro.props; --- ``` Because `Head.astro` is just a regular Astro component, you can import files and receive props passed from other components, such as a specific page title. src/components/Head.astro ```astro --- import Favicon from "../assets/Favicon.astro"; import SomeOtherTags from "./SomeOtherTags.astro"; const { title = "My Astro Website", ...props } = Astro.props; --- {title} ```
# Astro Courses
> Learn Astro with out-of-this-world courses and tutorials.
Want to get started learning Astro with a course or tutorial? You can learn the basics of Astro with our [official docs Build a Blog tutorial](/en/tutorial/0-introduction/), or explore our collection of recommended Astro educational content. ## Education Partners [Section titled “Education Partners”](#education-partners) Learn Astro from trusted Astro educators, with video lessons, interactive challenges, and projects! [Learn Astro with Coding in Public ](https://learnastro.dev/?code=ASTRO_PROMO)A premium interactive course with 150+ video lessons that teaches you how to use Astro’s built-in tooling and features. [Learn Astro with James Q Quick ](https://scrimba.com/intro-to-astro-c00ar0fi5u?via=astro)Build your first Astro site with 35 interactive Scrimba lessons, with video and IDE merged into one unique learning platform. ## Community learning resources [Section titled “Community learning resources”](#community-learning-resources) Learn from your fellow astronauts with curated collections of guides, articles, and blog posts. [Astro Tips ](https://astro-tips.dev/)Advanced, unusual, experimental, and community-written recipes, tutorials, and quick tips. [Astro Support Squid ](https://get.supportsquid.ink/)An open, public Astro support forum and knowledge base outside of the Astro Discord.
# Components
> An introduction to Astro components.
**Astro components** are the basic building blocks of any Astro project. They are HTML-only templating components with no client-side runtime and use the `.astro` file extension. Astro components are extremely flexible. An Astro component can be as small as a snippet of HTML, like a collection of common `` tags that make SEO easy to work with. Components can be reusable UI elements, like a header or a profile card. Astro components can even contain an entire page layout or, when located in the special `src/pages/` folder, be an entire page itself. The most important thing to know about Astro components is that they **don’t render on the client**. They render to HTML either at build-time or on-demand. You can include JavaScript code inside of your component frontmatter, and all of it will be stripped from the final page sent to your users’ browsers. The result is a faster site, with zero JavaScript footprint added by default. When your Astro component does need client-side interactivity, you can add [standard HTML `
Target here
``` The `.astro` partial must exist at the corresponding file path, and include an export defining the page as a partial: src/pages/partials/clicked.astro ```astro --- export const partial = true; ---
I was clicked!
``` See the [htmx documentation](https://htmx.org/docs/) for more details on using htmx.
# Layouts
> An introduction to layouts in Astro.
**Layouts** are [Astro components](/en/basics/astro-components/) used to provide a reusable UI structure, such as a page template. We conventionally use the term “layout” for Astro components that provide common UI elements shared across pages such as headers, navigation bars, and footers. A typical Astro layout component provides [Astro, Markdown or MDX pages](/en/basics/astro-pages/) with: * a **page shell** (``, `` and `` tags) * a [**``**](/en/basics/astro-components/#slots) to specify where individual page content should be injected. But, there is nothing special about a layout component! They can [accept props](/en/basics/astro-components/#component-props) and [import and use other components](/en/basics/astro-components/#component-structure) like any other Astro component. They can include [UI frameworks components](/en/guides/framework-components/) and [client-side scripts](/en/guides/client-side-scripts/). They do not even have to provide a full page shell, and can instead be used as partial UI templates. However, if a layout component does contain a page shell, its `` element must be the parent of all other elements in the component. Layout components are commonly placed in a `src/layouts` directory in your project for organization, but this is not a requirement; you can choose to place them anywhere in your project. You can even colocate layout components alongside your pages by [prefixing the layout names with `_`](/en/guides/routing/#excluding-pages). ## Sample Layout [Section titled “Sample Layout”](#sample-layout) src/layouts/MySiteLayout.astro ```astro --- import BaseHead from '../components/BaseHead.astro'; import Footer from '../components/Footer.astro'; const { title } = Astro.props; ---
{title}
``` src/pages/index.astro ```astro --- import MySiteLayout from '../layouts/MySiteLayout.astro'; ---
My page content, wrapped in a layout!
``` Learn more about [slots](/en/basics/astro-components/#slots). ## Using TypeScript with layouts [Section titled “Using TypeScript with layouts”](#using-typescript-with-layouts) Any Astro layout can be modified to introduce type safety & autocompletion by providing the types for your props: src/components/MyLayout.astro ```diff --- +interface Props { + title: string; + description: string; + publishDate: string; + viewCount: number; +} const { title, description, publishDate, viewCount } = Astro.props; --- {title}
Published on {publishDate}
Viewed by {viewCount} folks
``` ## Markdown Layouts [Section titled “Markdown Layouts”](#markdown-layouts) Page layouts are especially useful for individual Markdown pages which otherwise would not have any page formatting. Astro provides a special `layout` frontmatter property intended for [individual `.md` files located within `src/pages/` using file-based routing](/en/guides/markdown-content/#individual-markdown-pages) to specify which `.astro` component to use as the page layout. This component allows you to provide `` content like meta tags (e.g. ``) and styles for the Markdown page. By default, this specified component can automatically access data from the Markdown file. This is not recognized as a special property when using [content collections](/en/guides/content-collections/) to query and render your content. src/pages/page.md ```markdown --- layout: ../layouts/BlogPostLayout.astro title: "Hello, World!" author: "Matthew Phillips" date: "09 Aug 2022" --- All frontmatter properties are available as props to an Astro layout component. The `layout` property is the only special one provided by Astro. You can use it in Markdown files located within `src/pages/`. ``` A typical layout for a Markdown page includes: 1. The `frontmatter` prop to access the Markdown page’s frontmatter and other data. 2. A default [``](/en/basics/astro-components/#slots) to indicate where the page’s Markdown content should be rendered. src/layouts/BlogPostLayout.astro ```astro --- // 1. The frontmatter prop gives access to frontmatter and other data const { frontmatter } = Astro.props; --- {frontmatter.title}
{frontmatter.title} by {frontmatter.author}
Written on: {frontmatter.date}
``` You can set a layout’s [`Props` type](/en/guides/typescript/#component-props) with the `MarkdownLayoutProps` helper: src/layouts/BlogPostLayout.astro ```diff --- +import type { MarkdownLayoutProps } from 'astro'; +type Props = MarkdownLayoutProps<{ +// Define frontmatter props here + title: string; + author: string; + date: string; +}>; // Now, `frontmatter`, `url`, and other Markdown layout properties // are accessible with type safety const { frontmatter, url } = Astro.props; --- {frontmatter.title}
{frontmatter.title} by {frontmatter.author}
Written on: {frontmatter.date}
``` ### Markdown Layout Props [Section titled “Markdown Layout Props”](#markdown-layout-props) A Markdown layout will have access to the following information via `Astro.props`: * **`file`** - The absolute path of this file (e.g. `/home/user/projects/.../file.md`). * **`url`** - The URL of the page (e.g. `/en/guides/markdown-content`). * **`frontmatter`** - All frontmatter from the Markdown or MDX document. * **`frontmatter.file`** - The same as the top-level `file` property. * **`frontmatter.url`** - The same as the top-level `url` property. * **`headings`** - A list of headings (`h1 -> h6`) in the Markdown or MDX document with associated metadata. This list follows the type: `{ depth: number; slug: string; text: string }[]`. * **`rawContent()`** - A function that returns the raw Markdown document as a string. * **`compiledContent()`** - An async function that returns the Markdown document compiled to an HTML string. ### Importing Layouts Manually (MDX) [Section titled “Importing Layouts Manually (MDX)”](#importing-layouts-manually-mdx) You can also use the special Markdown layout property in the frontmatter of MDX files to pass `frontmatter` and `headings` props directly to a specified layout component in the same way. To pass information to your MDX layout that does not (or cannot) exist in your frontmatter, you can instead import and use a `` component. This works like any other Astro component, and will not receive any props automatically. Pass it any necessary props directly: src/pages/posts/first-post.mdx ```diff --- -layout: ../../layouts/BaseLayout.astro title: 'My first MDX post' publishDate: '21 September 2022' --- +import BaseLayout from '../../layouts/BaseLayout.astro'; export function fancyJsHelper() { return "Try doing that with YAML!"; } Welcome to my new Astro blog, using MDX! ``` Then, your values are available to you through `Astro.props` in your layout, and your MDX content will be injected into the page where your `` component is written: src/layouts/BaseLayout.astro ```astro --- const { title, fancyJsHelper } = Astro.props; ---
{title}
{fancyJsHelper()}
``` When using any layout (either through the frontmatter `layout` property or by importing a layout), you must include the `` tag in your layout as Astro will no longer add it automatically to your MDX page. Learn more about Astro’s Markdown and MDX support in our [Markdown guide](/en/guides/markdown-content/). ## Nesting Layouts [Section titled “Nesting Layouts”](#nesting-layouts) Layout components do not need to contain an entire page worth of HTML. You can break your layouts into smaller components, and combine layout components to create even more flexible, page templates. This pattern is useful when you want to share some code across multiple layouts. For example, a `BlogPostLayout.astro` layout component could style a post’s title, date and author. Then, a site-wide `BaseLayout.astro` could handle the rest of your page template, like navigation, footers, SEO meta tags, global styles, and fonts. You can also pass props received from your post to another layout, just like any other nested component. src/layouts/BlogPostLayout.astro ```astro --- import BaseLayout from './BaseLayout.astro'; const { frontmatter } = Astro.props; ---
{frontmatter.title}
Post author: {frontmatter.author}
```
# Editor setup
> Set up your code editor to build with Astro.
Customize your code editor to improve the Astro developer experience and unlock new features. ## VS Code [Section titled “VS Code”](#vs-code) [VS Code](https://code.visualstudio.com/) is a popular code editor for web developers, built by Microsoft. The VS Code engine also powers popular in-browser code editors like [GitHub Codespaces](https://github.com/features/codespaces) and [Gitpod](https://gitpod.io/). Astro works with any code editor. However, VS Code is our recommended editor for Astro projects. We maintain an official [Astro VS Code Extension](https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode) that unlocks several key features and developer experience improvements for Astro projects. * Syntax highlighting for `.astro` files. * TypeScript type information for `.astro` files. * [VS Code Intellisense](https://code.visualstudio.com/docs/editor/intellisense) for code completion, hints and more. To get started, install the [Astro VS Code Extension](https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode) today. See how to [set up TypeScript](/en/guides/typescript/) in your Astro project. ## Zed [Section titled “Zed”](#zed) [Zed](https://zed.dev/) is a high-performance and open-source code editor. You can install the [Astro extension](https://github.com/zed-extensions/astro) in the IDE’s Extensions tab. This extension includes features like syntax highlighting, code completion, and formatting. ## JetBrains IDEs [Section titled “JetBrains IDEs”](#jetbrains-ides) [Webstorm](https://www.jetbrains.com/webstorm/) is a JavaScript and TypeScript IDE that added support for the Astro Language Server in version 2024.2. This update brings features like syntax highlighting, code completion, and formatting. Install the official plugin through [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/20959-astro) or by searching for “Astro” in the IDE’s Plugins tab. You can toggle the language server in `Settings | Languages & Frameworks | TypeScript | Astro`. For more information on Astro support in Webstorm, check out [the official Webstorm Astro Documentation](https://www.jetbrains.com/help/webstorm/astro.html). ## Other Code Editors [Section titled “Other Code Editors”](#other-code-editors) Our amazing community maintains several extensions for other popular editors, including: * [VS Code Extension on Open VSX](https://open-vsx.org/extension/astro-build/astro-vscode) Official - The official Astro VS Code Extension, available on the Open VSX registry for editors like [Cursor](https://cursor.com) or [VSCodium](https://vscodium.com/). * [Vim Plugin](https://github.com/wuelnerdotexe/vim-astro) Community - Provides syntax highlighting, indentation, and code folding support for Astro inside of Vim or Neovim * Neovim [LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md#astro) and [TreeSitter](https://github.com/virchau13/tree-sitter-astro) Plugins Community - Provides syntax highlighting, treesitter parsing, and code completion for Astro inside of Neovim * Emacs - See instructions for [Configuring Emacs and Eglot](https://medium.com/@jrmjrm/configuring-emacs-and-eglot-to-work-with-astro-language-server-9408eb709ab0) Community to work with Astro * [Astro syntax highlighting for Sublime Text](https://packagecontrol.io/packages/Astro) Community - The Astro package for Sublime Text, available on the Sublime Text package manager. * [Nova Extension](https://extensions.panic.com/extensions/sciencefidelity/sciencefidelity.astro/) Community - Provides syntax highlighting and code completion for Astro inside of Nova ## In-Browser Editors [Section titled “In-Browser Editors”](#in-browser-editors) In addition to local editors, Astro also runs well on in-browser hosted editors, including: * [StackBlitz](https://stackblitz.com/) and [CodeSandbox](https://codesandbox.io/) - online editors that run in your browser, with built-in syntax highlighting support for `.astro` files. No installation or configuration required! * [GitHub.dev](https://github.dev/) - allows you to install the Astro VS Code extension as a [web extension](https://code.visualstudio.com/api/extension-guides/web-extensions), which gives you access to only some of the full extension features. Currently, only syntax highlighting is supported. * [IDX](https://idx.dev) and [Gitpod](https://gitpod.io/) - a full dev environment in the cloud that can install the official Astro VS Code Extension from Open VSX. ## Other tools [Section titled “Other tools”](#other-tools) ### ESLint [Section titled “ESLint”](#eslint) [ESLint](https://eslint.org/) is a popular linter for JavaScript and JSX. For Astro support, [a community maintained plugin](https://github.com/ota-meshi/eslint-plugin-astro) can be installed. See [the project’s User Guide](https://ota-meshi.github.io/eslint-plugin-astro/user-guide/) for more information on how to install and set up ESLint for your project. ### Stylelint [Section titled “Stylelint”](#stylelint) [Stylelint](https://stylelint.io/) is a popular linter for CSS. [A community maintained Stylelint configuration](https://github.com/ota-meshi/stylelint-config-html) provides Astro support. Installation instructions, editor integration, and additional information can be found in the project’s README. ### Biome [Section titled “Biome”](#biome) [Biome](https://biomejs.dev/) is an all-in-one linter and formatter for the web. [Biome currently has partial support for `.astro` files](https://biomejs.dev/internals/language-support/#html-super-languages-support), and can be used to lint and format the frontmatter in `.astro` files. ### Prettier [Section titled “Prettier”](#prettier) [Prettier](https://prettier.io/) is a popular formatter for JavaScript, HTML, CSS, and more. If you’re using the [Astro VS Code Extension](https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode), code formatting with Prettier is included. To add support for formatting `.astro` files outside of the editor (e.g. CLI) or inside editors that don’t support our editor tooling, install [the official Astro Prettier plugin](https://github.com/withastro/prettier-plugin-astro). 1. Install `prettier` and `prettier-plugin-astro`. * npm ```shell npm install --save-dev --save-exact prettier prettier-plugin-astro ``` * pnpm ```shell pnpm add --save-dev --save-exact prettier prettier-plugin-astro ``` * Yarn ```shell yarn add --dev --exact prettier prettier-plugin-astro ``` 2. Create a `.prettierrc` configuration file (or `.prettierrc.json`, `.prettierrc.mjs`, or [other supported formats](https://prettier.io/docs/configuration)) in the root of your project and add `prettier-plugin-astro` to it. In this file, also manually specify the parser for Astro files. .prettierrc ```json { "plugins": ["prettier-plugin-astro"], "overrides": [ { "files": "*.astro", "options": { "parser": "astro" } } ] } ``` 3. Optionally, install other Prettier plugins for your project, and add them to the configuration file. These additional plugins may need to be listed in a specific order. For example, if you use Tailwind, `prettier-plugin-tailwindcss` must be [the last Prettier plugin in the plugins array](https://github.com/tailwindlabs/prettier-plugin-tailwindcss#compatibility-with-other-prettier-plugins). .prettierrc ```json { "plugins": [ "prettier-plugin-astro", "prettier-plugin-tailwindcss" // needs to be last ], "overrides": [ { "files": "*.astro", "options": { "parser": "astro" } } ] } ``` 4. Run the following command in your terminal to format your files. * npm ```shell npx prettier . --write ``` * pnpm ```shell pnpm exec prettier . --write ``` * Yarn ```shell yarn exec prettier . --write ``` See the [Prettier plugin’s README](https://github.com/withastro/prettier-plugin-astro/blob/main/README.md) for more information about its supported options, how to set up Prettier inside VS Code, and more. ### dprint [Section titled “dprint”](#dprint) [dprint](https://dprint.dev/) is a highly-configurable code formatter that supports many languages, including JavaScript, TypeScript, CSS, and more. Support for `.astro` files can be added using the [markup\_fmt plugin](https://github.com/g-plane/markup_fmt).
# Actions
> Learn how to create type-safe server functions you can call from anywhere.
**Added in:** `astro@4.15` Astro Actions allow you to define and call backend functions with type-safety. Actions perform data fetching, JSON parsing, and input validation for you. This can greatly reduce the amount of boilerplate needed compared to using an [API endpoint](/en/guides/endpoints/). Use actions instead of API endpoints for seamless communication between your client and server code and to: * Automatically validate JSON and form data inputs using [Zod validation](https://zod.dev/?id=primitives). * Generate type-safe functions to call your backend from the client and even [from HTML form actions](#call-actions-from-an-html-form-action). No need for manual `fetch()` calls. * Standardize backend errors with the [`ActionError`](/en/reference/modules/astro-actions/#actionerror) object. ## Basic usage [Section titled “Basic usage”](#basic-usage) Actions are defined in a `server` object exported from `src/actions/index.ts`: src/actions/index.ts ```ts import { defineAction } from 'astro:actions'; import { z } from 'astro:schema'; export const server = { myAction: defineAction({ /* ... */ }) } ``` Your actions are available as functions from the `astro:actions` module. Import `actions` and call them client-side within a [UI framework component](/en/guides/framework-components/), [a form POST request](#call-actions-from-an-html-form-action), or by using a ` ``` ### Write your first action [Section titled “Write your first action”](#write-your-first-action) Follow these steps to define an action and call it in a `script` tag in your Astro page. 1. Create a `src/actions/index.ts` file and export a `server` object. src/actions/index.ts ```ts export const server = { // action declarations } ``` 2. Import the `defineAction()` utility from `astro:actions`, and the `z` object from `astro:schema`. src/actions/index.ts ```diff +import { defineAction } from 'astro:actions'; +import { z } from 'astro:schema'; export const server = { // action declarations } ``` 3. Use the `defineAction()` utility to define a `getGreeting` action. The `input` property will be used to validate input parameters with a [Zod](https://zod.dev) schema and the `handler()` function includes the backend logic to run on the server. src/actions/index.ts ```diff import { defineAction } from 'astro:actions'; import { z } from 'astro:schema'; export const server = { getGreeting: defineAction({ input: z.object({ name: z.string(), }), +handler: async (input) => { return `Hello, ${input.name}!` } }) } ``` 4. Create an Astro component with a button that will fetch a greeting using your `getGreeting` action when clicked. src/pages/index.astro ```astro --- --- ``` 5. To use your action, import `actions` from `astro:actions` and then call `actions.getGreeting()` in the click handler. The `name` option will be sent to your action’s `handler()` on the server and, if there are no errors, the result will be available as the `data` property. src/pages/index.astro ```diff --- --- ``` See the full Actions API documentation for details on [`defineAction()`](/en/reference/modules/astro-actions/#defineaction) and its properties. ## Organizing actions [Section titled “Organizing actions”](#organizing-actions) All actions in your project must be exported from the `server` object in the `src/actions/index.ts` file. You can define actions inline or you can move action definitions to separate files and import them. You can even group related functions in nested objects. For example, to colocate all of your user actions, you can create a `src/actions/user.ts` file and nest the definitions of both `getUser` and `createUser` inside a single `user` object. src/actions/user.ts ```ts import { defineAction } from 'astro:actions'; export const user = { getUser: defineAction(/* ... */), createUser: defineAction(/* ... */), } ``` Then, you can import this `user` object into your `src/actions/index.ts` file and add it as a top-level key to the `server` object alongside any other actions: src/actions/index.ts ```diff +import { user } from './user'; export const server = { myAction: defineAction({ /* ... */ }), +user, } ``` Now, all of your user actions are callable from the `actions.user` object: * `actions.user.getUser()` * `actions.user.createUser()` ## Handling returned data [Section titled “Handling returned data”](#handling-returned-data) Actions return an object containing either `data` with the type-safe return value of your `handler()`, or an `error` with any backend errors. Errors may come from validation errors on the `input` property or thrown errors within the `handler()`. Actions return a custom data format that can handle Dates, Maps, Sets, and URLs [using the Devalue library](https://github.com/Rich-Harris/devalue). Therefore, you can’t easily inspect the response from the network like you can with regular JSON. For debugging, you can instead inspect the `data` object returned by actions. [See the `handler()` API reference](/en/reference/modules/astro-actions/#handler-property) for full details. ### Checking for errors [Section titled “Checking for errors”](#checking-for-errors) It’s best to check if an `error` is present before using the `data` property. This allows you to handle errors in advance and ensures `data` is defined without an `undefined` check. ```ts const { data, error } = await actions.example(); if (error) { // handle error cases return; } // use `data` ``` ### Accessing `data` directly without an error check [Section titled “Accessing data directly without an error check”](#accessing-data-directly-without-an-error-check) To skip error handling, for example while prototyping or using a library that will catch errors for you, use the `.orThrow()` property on your action call to throw errors instead of returning an `error`. This will return the action’s `data` directly. This example calls a `likePost()` action that returns the updated number of likes as a `number` from the action `handler`: ```ts const updatedLikes = await actions.likePost.orThrow({ postId: 'example' }); // ^ type: number ``` ### Handling backend errors in your action [Section titled “Handling backend errors in your action”](#handling-backend-errors-in-your-action) You can use the provided `ActionError` to throw an error from your action `handler()`, such as “not found” when a database entry is missing, or “unauthorized” when a user is not logged in. This has two main benefits over returning `undefined`: * You can set a status code like `404 - Not found` or `401 - Unauthorized`. This improves debugging errors in both development and in production by letting you see the status code of each request. * In your application code, all errors are passed to the `error` object on an action result. This avoids the need for `undefined` checks on data, and allows you to display targeted feedback to the user depending on what went wrong. #### Creating an `ActionError` [Section titled “Creating an ActionError”](#creating-an-actionerror) To throw an error, import the `ActionError()` class from the `astro:actions` module. Pass it a human-readable status `code` (e.g. `"NOT_FOUND"` or `"BAD_REQUEST"`), and an optional `message` to provide further information about the error. This example throws an error from a `likePost` action when a user is not logged in, after checking a hypothetical “user-session” cookie for authentication: src/actions/index.ts ```diff import { defineAction, ActionError } from "astro:actions"; import { z } from "astro:schema"; export const server = { likePost: defineAction({ input: z.object({ postId: z.string() }), handler: async (input, ctx) => { if (!ctx.cookies.has('user-session')) { throw new ActionError({ code: "UNAUTHORIZED", message: "User must be logged in.", }); } // Otherwise, like the post }, }), }; ``` #### Handling an `ActionError` [Section titled “Handling an ActionError”](#handling-an-actionerror) To handle this error, you can call the action from your application and check whether an `error` property is present. This property will be of type `ActionError` and will contain your `code` and `message`. In the following example, a `LikeButton.tsx` component calls the `likePost()` action when clicked. If an authentication error occurs, the `error.code` attribute is used to determine whether to display a login link: src/components/LikeButton.tsx ```tsx import { actions } from 'astro:actions'; import { useState } from 'preact/hooks'; export function LikeButton({ postId }: { postId: string }) { const [showLogin, setShowLogin] = useState(false); return ( <> { showLogin && Log in to like a post. } > ) } ``` ### Handling client redirects [Section titled “Handling client redirects”](#handling-client-redirects) When calling actions from the client, you can integrate with a client-side library like `react-router`, or you can use Astro’s [`navigate()` function](/en/guides/view-transitions/#trigger-navigation) to redirect to a new page when an action succeeds. This example navigates to the homepage after a `logout` action returns successfully: src/pages/LogoutButton.tsx ```tsx import { actions } from 'astro:actions'; import { navigate } from 'astro:transitions/client'; export function LogoutButton() { return ( ); } ``` ## Accepting form data from an action [Section titled “Accepting form data from an action”](#accepting-form-data-from-an-action) Actions accept JSON data by default. To accept form data from an HTML form, set `accept: 'form'` in your `defineAction()` call: src/actions/index.ts ```diff import { defineAction } from 'astro:actions'; import { z } from 'astro:schema'; export const server = { comment: defineAction({ accept: 'form', input: z.object(/* ... */), handler: async (input) => { /* ... */ }, }) } ``` ### Validating form data [Section titled “Validating form data”](#validating-form-data) Actions will parse submitted form data to an object, using the value of each input’s `name` attribute as the object keys. For example, a form containing `` will be parsed to an object like `{ search: 'user input' }`. Your action’s `input` schema will be used to validate this object. To receive the raw `FormData` object in your action handler instead of a parsed object, omit the `input` property in your action definition. The following example shows a validated newsletter registration form that accepts a user’s email and requires a “terms of service” agreement checkbox. 1. Create an HTML form component with unique `name` attributes on each input: src/components/Newsletter.astro ```astro ``` 2. Define a `newsletter` action to handle the submitted form. Validate the `email` field using the `z.string().email()` validator, and the `terms` checkbox using `z.boolean()`: src/actions/index.ts ```diff import { defineAction } from 'astro:actions'; import { z } from 'astro:schema'; export const server = { newsletter: defineAction({ accept: 'form', input: z.object({ email: z.string().email(), terms: z.boolean(), }), +handler: async ({ email, terms }) => { /* ... */ }, }) } ``` See the [`input` API reference](/en/reference/modules/astro-actions/#input-validator) for all available form validators. 3. Add a ` ``` See [“Call actions from an HTML form action”](#call-actions-from-an-html-form-action) for an alternative way to submit form data. ### Displaying form input errors [Section titled “Displaying form input errors”](#displaying-form-input-errors) You can validate form inputs before submission using [native HTML form validation attributes](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation#using_built-in_form_validation) like `required`, `type="email"`, and `pattern`. For more complex `input` validation on the backend, you can use the provided [`isInputError()`](/en/reference/modules/astro-actions/#isinputerror) utility function. To retrieve input errors, use the `isInputError()` utility to check whether an error was caused by invalid input. Input errors contain a `fields` object with messages for each input name that failed to validate. You can use these messages to prompt your user to correct their submission. The following example checks the error with `isInputError()`, then checks whether the error is in the email field, before finally creating a message from the errors. You can use JavaScript DOM manipulation or your preferred UI framework to display this message to users. ```js import { actions, isInputError } from 'astro:actions'; const form = document.querySelector('form'); const formData = new FormData(form); const { error } = await actions.newsletter(formData); if (isInputError(error)) { // Handle input errors. if (error.fields.email) { const message = error.fields.email.join(', '); } } ``` ## Call actions from an HTML form action [Section titled “Call actions from an HTML form action”](#call-actions-from-an-html-form-action) You can enable zero-JS form submissions with standard attributes on any ` ``` Additional attributes on the ` ``` ### Redirect on action success [Section titled “Redirect on action success”](#redirect-on-action-success) If you need to redirect to a new route on success, you can use an action’s result on the server. A common example is creating a product record and redirecting to the new product’s page, e.g. `/products/[id]`. For example, say you have a `createProduct` action that returns the generated product id: src/actions/index.ts ```ts import { defineAction } from 'astro:actions'; import { z } from 'astro:schema'; export const server = { createProduct: defineAction({ accept: 'form', input: z.object({ /* ... */ }), handler: async (input) => { const product = await persistToDatabase(input); return { id: product.id }; }, }) } ``` You can retrieve the action result from your Astro component by calling `Astro.getActionResult()`. This returns an object containing `data` or `error` properties when an action is called, or `undefined` if the action was not called during this request. Use the `data` property to construct a URL to use with `Astro.redirect()`: src/pages/products/create.astro ```astro --- import { actions } from 'astro:actions'; const result = Astro.getActionResult(actions.createProduct); if (result && !result.error) { return Astro.redirect(`/products/${result.data.id}`); } --- ``` ### Handle form action errors [Section titled “Handle form action errors”](#handle-form-action-errors) Calling `Astro.getActionResult()` in the Astro component containing your form gives you access to the `data` and `error` objects for custom error handling. The following example displays a general failure message when a `newsletter` action fails: src/pages/index.astro ```astro --- import { actions } from 'astro:actions'; const result = Astro.getActionResult(actions.newsletter); --- {result?.error && (
Unable to sign up. Please try again later.
)} ``` For more customization, you can [use the `isInputError()` utility](#displaying-form-input-errors) to check whether an error is caused by invalid input. The following example renders an error banner under the `email` input field when an invalid email is submitted: src/pages/index.astro ```diff --- import { actions, isInputError } from 'astro:actions'; const result = Astro.getActionResult(actions.newsletter); +const inputErrors = isInputError(result?.error) ? result.error.fields : {}; --- ``` #### Preserve input values on error [Section titled “Preserve input values on error”](#preserve-input-values-on-error) Inputs will be cleared whenever a form is submitted. To persist input values, you can [enable view transitions](/en/guides/view-transitions/#enabling-view-transitions-spa-mode) and apply the `transition:persist` directive to each input: ```astro ``` ### Update the UI with a form action result [Section titled “Update the UI with a form action result”](#update-the-ui-with-a-form-action-result) To use an action’s return value to display a notification to the user on success, pass the action to `Astro.getActionResult()`. Use the returned `data` property to render the UI you want to display. This example uses the `productName` property returned by an `addToCart` action to show a success message. src/pages/products/\[slug].astro ```astro --- import { actions } from 'astro:actions'; const result = Astro.getActionResult(actions.addToCart); --- {result && !result.error && (
Added {result.data.productName} to cart
)} ``` ### Advanced: Persist action results with a session [Section titled “Advanced: Persist action results with a session”](#advanced-persist-action-results-with-a-session) **Added in:** `astro@5.0.0` Action results are displayed as a POST submission. This means that the result will be reset to `undefined` when a user closes and revisits the page. The user will also see a “confirm form resubmission?” dialog if they attempt to refresh the page. To customize this behavior, you can add middleware to handle the result of the action manually. You may choose to persist the action result using a cookie or session storage. Start by [creating a middleware file](/en/guides/middleware/) and importing [the `getActionContext()` utility](/en/reference/modules/astro-actions/#getactioncontext) from `astro:actions`. This function returns an `action` object with information about the incoming action request, including the action handler and whether the action was called from an HTML form. `getActionContext()` also returns the `setActionResult()` and `serializeActionResult()` functions to programmatically set the value returned by `Astro.getActionResult()`: src/middleware.ts ```ts import { defineMiddleware } from 'astro:middleware'; import { getActionContext } from 'astro:actions'; export const onRequest = defineMiddleware(async (context, next) => { const { action, setActionResult, serializeActionResult } = getActionContext(context); if (action?.calledFrom === 'form') { const result = await action.handler(); // ... handle the action result setActionResult(action.name, serializeActionResult(result)); } return next(); }); ``` A common practice to persist HTML form results is the [POST / Redirect / GET pattern](https://en.wikipedia.org/wiki/Post/Redirect/Get). This redirect removes the “confirm form resubmission?” dialog when the page is refreshed, and allows action results to be persisted throughout the user’s session. This example applies the POST / Redirect / GET pattern to all form submissions using session storage with the [Netlify server adapter](/en/guides/integrations-guide/netlify/) installed. Action results are written to a session store using [Netlify Blob](https://docs.netlify.com/blobs/overview/), and retrieved after a redirect using a session ID: src/middleware.ts ```ts import { defineMiddleware } from 'astro:middleware'; import { getActionContext } from 'astro:actions'; import { randomUUID } from "node:crypto"; import { getStore } from "@netlify/blobs"; export const onRequest = defineMiddleware(async (context, next) => { // Skip requests for prerendered pages if (context.isPrerendered) return next(); const { action, setActionResult, serializeActionResult } = getActionContext(context); // Create a Blob store to persist action results with Netlify Blob const actionStore = getStore("action-session"); // If an action result was forwarded as a cookie, set the result // to be accessible from `Astro.getActionResult()` const sessionId = context.cookies.get("action-session-id")?.value; const session = sessionId ? await actionStore.get(sessionId, { type: "json", }) : undefined; if (session) { setActionResult(session.actionName, session.actionResult); // Optional: delete the session after the page is rendered. // Feel free to implement your own persistence strategy await actionStore.delete(sessionId); context.cookies.delete("action-session-id"); return next(); } // If an action was called from an HTML form action, // call the action handler and redirect to the destination page if (action?.calledFrom === "form") { const actionResult = await action.handler(); // Persist the action result using session storage const sessionId = randomUUID(); await actionStore.setJSON(sessionId, { actionName: action.name, actionResult: serializeActionResult(actionResult), }); // Pass the session ID as a cookie // to be retrieved after redirecting to the page context.cookies.set("action-session-id", sessionId); // Redirect back to the previous page on error if (actionResult.error) { const referer = context.request.headers.get("Referer"); if (!referer) { throw new Error( "Internal: Referer unexpectedly missing from Action POST request.", ); } return context.redirect(referer); } // Redirect to the destination page on success return context.redirect(context.originPathname); } return next(); }); ``` ## Security when using actions [Section titled “Security when using actions”](#security-when-using-actions) Actions are accessible as public endpoints based on the name of the action. For example, the action `blog.like()` will be accessible from `/_actions/blog.like`. This is useful for unit testing action results and debugging production errors. However, this means you **must** use same authorization checks that you would consider for API endpoints and on-demand rendered pages. ### Authorize users from an action handler [Section titled “Authorize users from an action handler”](#authorize-users-from-an-action-handler) To authorize action requests, add an authentication check to your action handler. You may want to use [an authentication library](/en/guides/authentication/) to handle session management and user information. Actions expose the full `APIContext` object to access properties passed from middleware using `context.locals`. When a user is not authorized, you can raise an `ActionError` with the `UNAUTHORIZED` code: src/actions/index.ts ```ts import { defineAction, ActionError } from 'astro:actions'; export const server = { getUserSettings: defineAction({ handler: async (_input, context) => { if (!context.locals.user) { throw new ActionError({ code: 'UNAUTHORIZED' }); } return { /* data on success */ }; } }) } ``` ### Gate actions from middleware [Section titled “Gate actions from middleware”](#gate-actions-from-middleware) **Added in:** `astro@5.0.0` Astro recommends authorizing user sessions from your action handler to respect permission levels and rate-limiting on a per-action basis. However, you can also gate requests to all actions (or a subset of actions) from middleware. Use the `getActionContext()` function from your middleware to retrieve information about any inbound action requests. This includes the action name and whether that action was called using a client-side remote procedure call (RPC) function (e.g. `actions.blog.like()`) or an HTML form. The following example rejects all action requests that do not have a valid session token. If the check fails, a “Forbidden” response is returned. Note: this method ensures that actions are only accessible when a session is present, but is *not* a substitute for secure authorization. src/middleware.ts ```ts import { defineMiddleware } from 'astro:middleware'; import { getActionContext } from 'astro:actions'; export const onRequest = defineMiddleware(async (context, next) => { const { action } = getActionContext(context); // Check if the action was called from a client-side function if (action?.calledFrom === 'rpc') { // If so, check for a user session token if (!context.cookies.has('user-session')) { return new Response('Forbidden', { status: 403 }); } } context.cookies.set('user-session', /* session token */); return next(); }); ``` ## Call actions from Astro components and server endpoints [Section titled “Call actions from Astro components and server endpoints”](#call-actions-from-astro-components-and-server-endpoints) You can call actions directly from Astro component scripts using the `Astro.callAction()` wrapper (or `context.callAction()` when using a [server endpoint](/en/guides/endpoints/#server-endpoints-api-routes)). This is common to reuse logic from your actions in other server code. Pass the action as the first argument and any input parameters as the second argument. This returns the same `data` and `error` objects you receive when calling actions on the client: src/pages/products.astro ```astro --- import { actions } from 'astro:actions'; const searchQuery = Astro.url.searchParams.get('search'); if (searchQuery) { const { data, error } = await Astro.callAction(actions.findProduct, { query: searchQuery }); // handle result } --- ```
# Astro DB
> Learn how to use Astro DB, a fully-managed SQL database designed exclusively for Astro.
Astro DB is a fully-managed SQL database designed for the Astro ecosystem. Develop locally in Astro and deploy to any libSQL-compatible database. Astro DB is a complete solution to configuring, developing, and querying your data. A local database is created in `.astro/content.db` whenever you run `astro dev` to manage your data without the need for Docker or a network connection. ## Installation [Section titled “Installation”](#installation) Install the [`@astrojs/db` integration](/en/guides/integrations-guide/db/) using the built-in `astro add` command: * npm ```sh npx astro add db ``` * pnpm ```sh pnpm astro add db ``` * Yarn ```sh yarn astro add db ``` ## Define your database [Section titled “Define your database”](#define-your-database) Installing `@astrojs/db` with the `astro add` command will automatically create a `db/config.ts` file in your project where you will define your database tables: db/config.ts ```ts import { defineDb } from 'astro:db'; export default defineDb({ tables: { }, }) ``` ### Tables [Section titled “Tables”](#tables) Data in Astro DB is stored using SQL tables. Tables structure your data into rows and columns, where columns enforce the type of each row value. Define your tables in your `db/config.ts` file by providing the structure of the data in your existing libSQL database, or the data you will collect in a new database. This will allow Astro to generate a TypeScript interface to query that table from your project. The result is full TypeScript support when you access your data with property autocompletion and type-checking. To configure a database table, import and use the `defineTable()` and `column` utilities from `astro:db`. Then, define a name (case-sensitive) for your table and the type of data in each column. This example configures a `Comment` table with required text columns for `author` and `body`. Then, makes it available to your project through the `defineDb()` export. db/config.ts ```ts import { defineDb, defineTable, column } from 'astro:db'; const Comment = defineTable({ columns: { author: column.text(), body: column.text(), } }) export default defineDb({ tables: { Comment }, }) ``` See the [table configuration reference](/en/guides/integrations-guide/db/#table-configuration-reference) for a complete reference of table options. ### Columns [Section titled “Columns”](#columns) Astro DB supports the following column types: db/config.ts ```ts import { defineTable, column } from 'astro:db'; const Comment = defineTable({ columns: { // A string of text. author: column.text(), // A whole integer value. likes: column.number(), // A true or false value. flagged: column.boolean(), // Date/time values queried as JavaScript Date objects. published: column.date(), // An untyped JSON object. metadata: column.json(), } }); ``` See the [table columns reference](/en/guides/integrations-guide/db/#table-configuration-reference) for more details. ### Table References [Section titled “Table References”](#table-references) Relationships between tables are a common pattern in database design. For example, a `Blog` table may be closely related to other tables of `Comment`, `Author`, and `Category`. You can define these relations between tables and save them into your database schema using **reference columns**. To establish a relationship, you will need: * An **identifier column** on the referenced table. This is usually an `id` column with the `primaryKey` property. * A column on the base table to **store the referenced `id`**. This uses the `references` property to establish a relationship. This example shows a `Comment` table’s `authorId` column referencing an `Author` table’s `id` column. db/config.ts ```ts const Author = defineTable({ columns: { id: column.number({ primaryKey: true }), name: column.text(), } }); const Comment = defineTable({ columns: { authorId: column.number({ references: () => Author.columns.id }), body: column.text(), } }); ``` ## Seed your database for development [Section titled “Seed your database for development”](#seed-your-database-for-development) In development, Astro will use your DB config to generate local types according to your schemas. These will be generated fresh from your seed file each time the dev server is started, and will allow you to query and work with the shape of your data with type safety and autocompletion. You will not have access to production data during development unless you [connect to a remote database](#connecting-to-remote-databases) during development. This protects your data while allowing you to test and develop with a working database with type-safety. To seed development data for testing and debugging into your Astro project, create a `db/seed.ts` file. Import both the `db` object and your tables defined in `astro:db`. `insert` some initial data into each table. This development data should match the form of both your database schema and production data. The following example defines two rows of development data for a `Comment` table, and an `Author` table: db/seed.ts ```ts import { db, Comment, Author } from 'astro:db'; export default async function() { await db.insert(Author).values([ { id: 1, name: "Kasim" }, { id: 2, name: "Mina" }, ]); await db.insert(Comment).values([ { authorId: 1, body: 'Hope you like Astro DB!' }, { authorId: 2, body: 'Enjoy!'}, ]) } ``` Your development server will automatically restart your database whenever this file changes, regenerating your types and seeding this development data from `seed.ts` fresh each time. ## Connect a libSQL database for production [Section titled “Connect a libSQL database for production”](#connect-a-libsql-database-for-production) Astro DB can connect to any local libSQL database or to any server that exposes the libSQL remote protocol, whether managed or self-hosted. To connect Astro DB to a libSQL database, set the following environment variables obtained from your database provider: * `ASTRO_DB_REMOTE_URL`: the connection URL to the location of your local or remote libSQL DB. This may include [URL configuration options](#remote-url-configuration-options) such as sync and encryption as parameters. * `ASTRO_DB_APP_TOKEN`: the auth token to your libSQL server. This is required for remote databases, and not needed for [local DBs like files or in-memory](#url-scheme-and-host) databases Depending on your service, you may have access to a CLI or web UI to retrieve these values. The following section will demonstrate connecting to Turso and setting these values as an example, but you are free to use any provider. ### Getting started with Turso [Section titled “Getting started with Turso”](#getting-started-with-turso) Turso is the company behind [libSQL](https://github.com/tursodatabase/libsql), the open-source fork of SQLite that powers Astro DB. They provide a fully managed libSQL database platform and are fully compatible with Astro. The steps below will guide you through the process of installing the Turso CLI, logging in (or signing up), creating a new database, getting the required environmental variables, and pushing the schema to the remote database. 1. Install the [Turso CLI](https://docs.turso.tech/cli/installation). 2. [Log in or sign up](https://docs.turso.tech/cli/authentication) to Turso. 3. Create a new database. In this example the database name is `andromeda`. ```sh turso db create andromeda ``` 4. Run the `show` command to see information about the newly created database: ```sh turso db show andromeda ``` Copy the `URL` value and set it as the value for `ASTRO_DB_REMOTE_URL`. .env ```dotenv ASTRO_DB_REMOTE_URL=libsql://andromeda-houston.turso.io ``` 5. Create a new token to authenticate requests to the database: ```sh turso db tokens create andromeda ``` Copy the output of the command and set it as the value for `ASTRO_DB_APP_TOKEN`. .env ```diff ASTRO_DB_REMOTE_URL=libsql://andromeda-houston.turso.io +ASTRO_DB_APP_TOKEN=eyJhbGciOiJF...3ahJpTkKDw ``` 6. Push your DB schema and metadata to the new Turso database. ```sh astro db push --remote ``` 7. Congratulations, now you have a database connected! Give yourself a break. 👾 ```sh turso relax ``` To explore more features of Turso, check out the [Turso docs](https://docs.turso.tech). ### Connecting to remote databases [Section titled “Connecting to remote databases”](#connecting-to-remote-databases) Astro DB allows you to connect to both local and remote databases. By default, Astro uses a local database file for `dev` and `build` commands, recreating tables and inserting development seed data each time. To connect to a hosted remote database, use the `--remote` flag. This flag enables both readable and writable access to your remote database, allowing you to [accept and persist user data](#insert) in production environments. Configure your build command to use the `--remote` flag: package.json ```json { "scripts": { "build": "astro build --remote" } } ``` You can also use the flag directly in the command line: ```bash # Build with a remote connection astro build --remote # Develop with a remote connection astro dev --remote ``` Caution Be careful when using `--remote` in development. This connects to your live production database, and all changes (inserts, updates, deletions) will be persisted. The `--remote` flag uses the connection to the remote DB both locally during the build and on the server. Ensure you set the necessary environment variables in both your local development environment and your deployment platform. Additionally, you may need to [configure web mode](/en/guides/integrations-guide/db/#mode) for non-Node.js runtimes such as Cloudflare Workers or Deno. When deploying your Astro DB project, make sure your deployment platform’s build command is set to `npm run build` (or the equivalent for your package manager) to utilize the `--remote` flag configured in your `package.json`. ### Remote URL configuration options [Section titled “Remote URL configuration options”](#remote-url-configuration-options) The `ASTRO_DB_REMOTE_URL` environment variable configures the location of your database as well as other options like sync and encryption. #### URL scheme and host [Section titled “URL scheme and host”](#url-scheme-and-host) libSQL supports both HTTP and WebSockets as the transport protocol for a remote server. It also supports using a local file or an in-memory DB. Those can be configured using the following URL schemes in the connection URL: * `memory:` will use an in-memory DB. The host must be empty in this case. * `file:` will use a local file. The host is the path to the file (`file:path/to/file.db`). * `libsql:` will use a remote server through the protocol preferred by the library (this might be different across versions). The host is the address of the server (`libsql://your.server.io`). * `http:` will use a remote server through HTTP. `https:` can be used to enable a secure connection. The host is the same as for `libsql:`. * `ws:` will use a remote server through WebSockets. `wss:` can be used to enable a secure connection. The host is the same as for `libsql:`. Details of the libSQL connection (e.g. encryption key, replication, sync interval) can be configured as query parameters in the remote connection URL. For example, to have an encrypted local file work as an embedded replica to a libSQL server, you can set the following environment variables: .env ```dotenv ASTRO_DB_REMOTE_URL=file://local-copy.db?encryptionKey=your-encryption-key&syncInterval=60&syncUrl=libsql%3A%2F%2Fyour.server.io ASTRO_DB_APP_TOKEN=token-to-your-remote-url ``` Caution Using a database file is an advanced feature, and care should be taken when deploying to prevent overriding your database and losing your production data. Additionally, this method will not work in serverless deployments, as the file system is not persisted in those environments. #### `encryptionKey` [Section titled “encryptionKey”](#encryptionkey) libSQL has native support for encrypted databases. Passing this search parameter will enable encryption using the given key: .env ```dotenv ASTRO_DB_REMOTE_URL=file:path/to/file.db?encryptionKey=your-encryption-key ``` #### `syncUrl` [Section titled “syncUrl”](#syncurl) Embedded replicas are a feature of libSQL clients that creates a full synchronized copy of your database on a local file or in memory for ultra-fast reads. Writes are sent to a remote database defined on the `syncUrl` and synchronized with the local copy. Use this property to pass a separate connection URL to turn the database into an embedded replica of another database. This should only be used with the schemes `file:` and `memory:`. The parameter must be URL encoded. For example, to have an in-memory embedded replica of a database on `libsql://your.server.io`, you can set the connection URL as such: .env ```dotenv ASTRO_DB_REMOTE_URL=memory:?syncUrl=libsql%3A%2F%2Fyour.server.io ``` #### `syncInterval` [Section titled “syncInterval”](#syncinterval) Interval between embedded replica synchronizations in seconds. By default it only synchronizes on startup and after writes. This property is only used when `syncUrl` is also set. For example, to set an in-memory embedded replica to synchronize every minute set the following environment variable: .env ```dotenv ASTRO_DB_REMOTE_URL=memory:?syncUrl=libsql%3A%2F%2Fyour.server.io&syncInterval=60 ``` ## Query your database [Section titled “Query your database”](#query-your-database) You can query your database from any [Astro page](/en/basics/astro-pages/#astro-pages), [endpoint](/en/guides/endpoints/), or [action](/en/guides/actions/) in your project using the provided `db` ORM and query builder. ### Drizzle ORM [Section titled “Drizzle ORM”](#drizzle-orm) ```ts import { db } from 'astro:db'; ``` Astro DB includes a built-in [Drizzle ORM](https://orm.drizzle.team/) client. There is no setup or manual configuration required to use the client. The Astro DB `db` client is automatically configured to communicate with your database (local or remote) when you run Astro. It uses your exact database schema definition for type-safe SQL queries with TypeScript errors when you reference a column or table that doesn’t exist. ### Select [Section titled “Select”](#select) The following example selects all rows of a `Comment` table. This returns the complete array of seeded development data from `db/seed.ts` which is then available for use in your page template: src/pages/index.astro ```astro --- import { db, Comment } from 'astro:db'; const comments = await db.select().from(Comment); ---
Comments
{ comments.map(({ author, body }) => (
Author: {author}
{body}
)) } ``` See the [Drizzle `select()` API reference](https://orm.drizzle.team/docs/select) for a complete overview. ### Insert [Section titled “Insert”](#insert) To accept user input, such as handling form requests and inserting data into your remote hosted database, configure your Astro project for [on-demand rendering](/en/guides/on-demand-rendering/) and [add an adapter](/en/guides/on-demand-rendering/#add-an-adapter) for your deployment environment. This example inserts a row into a `Comment` table based on a parsed form POST request: src/pages/index.astro ```astro --- import { db, Comment } from 'astro:db'; if (Astro.request.method === 'POST') { // Parse form data const formData = await Astro.request.formData(); const author = formData.get('author'); const body = formData.get('body'); if (typeof author === 'string' && typeof body === 'string') { // Insert form data into the Comment table await db.insert(Comment).values({ author, body }); } } // Render the new list of comments on each request const comments = await db.select().from(Comment); --- ``` You can also use [Astro actions](/en/guides/actions/) to insert data into an Astro DB table. The following example inserts a row into a `Comment` table using an action: src/actions/index.ts ```ts import { db, Comment } from 'astro:db'; import { defineAction } from 'astro:actions'; import { z } from 'astro:schema'; export const server = { addComment: defineAction({ // Actions include type safety with Zod, removing the need // to check if typeof {value} === 'string' in your pages input: z.object({ author: z.string(), body: z.string(), }), handler: async (input) => { const updatedComments = await db .insert(Comment) .values(input) .returning(); // Return the updated comments return updatedComments; }, }), }; ``` See the [Drizzle `insert()` API reference](https://orm.drizzle.team/docs/insert) for a complete overview. ### Delete [Section titled “Delete”](#delete) You can also query your database from an API endpoint. This example deletes a row from a `Comment` table by the `id` parameter: src/pages/api/comments/\[id].ts ```ts import type { APIRoute } from "astro"; import { db, Comment, eq } from 'astro:db'; export const DELETE: APIRoute = async (ctx) => { await db.delete(Comment).where(eq(Comment.id, ctx.params.id )); return new Response(null, { status: 204 }); } ``` See the [Drizzle `delete()` API reference](https://orm.drizzle.team/docs/delete) for a complete overview. ### Filtering [Section titled “Filtering”](#filtering) To query for table results by a specific property, use [Drizzle options for partial selects](https://orm.drizzle.team/docs/select#partial-select). For example, add [a `.where()` call](https://orm.drizzle.team/docs/select#filtering) to your `select()` query and pass the comparison you want to make. The following example queries for all rows in a `Comment` table that contain the phrase “Astro DB.” Use [the `like()` operator](https://orm.drizzle.team/docs/operators#like) to check if a phrase is present within the `body`: src/pages/index.astro ```astro --- import { db, Comment, like } from 'astro:db'; const comments = await db.select().from(Comment).where( like(Comment.body, '%Astro DB%') ); --- ``` ### Drizzle utilities [Section titled “Drizzle utilities”](#drizzle-utilities) All Drizzle utilities for building queries are exposed from the `astro:db` module. This includes: * [Filter operators](https://orm.drizzle.team/docs/operators) like `eq()` and `gt()` * [Aggregation helpers](https://orm.drizzle.team/docs/select#aggregations-helpers) like `count()` * [The `sql` helper](https://orm.drizzle.team/docs/sql) for writing raw SQL queries ```ts import { eq, gt, count, sql } from 'astro:db'; ``` ### Relationships [Section titled “Relationships”](#relationships) You can query related data from multiple tables using a SQL join. To create a join query, extend your `db.select()` statement with a join operator. Each function accepts a table to join with and a condition to match rows between the two tables. This example uses an `innerJoin()` function to join `Comment` authors with their related `Author` information based on the `authorId` column. This returns an array of objects with each `Author` and `Comment` row as top-level properties: src/pages/index.astro ```astro --- import { db, eq, Comment, Author } from 'astro:db'; const comments = await db.select() .from(Comment) .innerJoin(Author, eq(Comment.authorId, Author.id)); ---
Comments
{ comments.map(({ Author, Comment }) => (
Author: {Author.name}
{Comment.body}
)) } ``` See the [Drizzle join reference](https://orm.drizzle.team/docs/joins#join-types) for all available join operators and config options. ### Batch Transactions [Section titled “Batch Transactions”](#batch-transactions) All remote database queries are made as a network request. You may need to “batch” queries together into a single transaction when making a large number of queries, or to have automatic rollbacks if any query fails. This example seeds multiple rows in a single request using the `db.batch()` method: db/seed.ts ```ts import { db, Author, Comment } from 'astro:db'; export default async function () { const queries = []; // Seed 100 sample comments into your remote database // with a single network request. for (let i = 0; i < 100; i++) { queries.push(db.insert(Comment).values({ body: `Test comment ${i}` })); } await db.batch(queries); } ``` See the [Drizzle `db.batch()`](https://orm.drizzle.team/docs/batch-api) docs for more details. ## Pushing changes to your database [Section titled “Pushing changes to your database”](#pushing-changes-to-your-database) You can push changes made during development to your database. ### Pushing table schemas [Section titled “Pushing table schemas”](#pushing-table-schemas) Your table schema may change over time as your project grows. You can safely test configuration changes locally and push to your remote database when you deploy. You can push your local schema changes to your remote database via the CLI using the `astro db push --remote` command: * npm ```sh npm run astro db push --remote ``` * pnpm ```sh pnpm astro db push --remote ``` * Yarn ```sh yarn astro db push --remote ``` This command will verify that your local changes can be made without data loss and, if necessary, suggest how to safely make changes to your schema in order to resolve conflicts. #### Pushing breaking schema changes [Section titled “Pushing breaking schema changes”](#pushing-breaking-schema-changes) Caution **This will destroy your database**. Only perform this command if you do not need your production data. If you must change your table schema in a way that is incompatible with your existing data hosted on your remote database, you will need to reset your production database. To push a table schema update that includes a breaking change, add the `--force-reset` flag to reset all production data: * npm ```sh npm run astro db push --remote --force-reset ``` * pnpm ```sh pnpm astro db push --remote --force-reset ``` * Yarn ```sh yarn astro db push --remote --force-reset ``` ### Renaming tables [Section titled “Renaming tables”](#renaming-tables) It is possible to rename a table after pushing your schema to your remote database. If you **do not have any important production data**, then you can [reset your database](#pushing-breaking-schema-changes) using the `--force-reset` flag. This flag will drop all of the tables in the database and create new ones so that it matches your current schema exactly. To rename a table while preserving your production data, you must perform a series of non-breaking changes to push your local schema to your remote database safely. The following example renames a table from `Comment` to `Feedback`: 1. In your database config file, add the `deprecated: true` property to the table you want to rename: db/config.ts ```diff const Comment = defineTable({ deprecated: true, columns: { author: column.text(), body: column.text(), } }); ``` 2. Add a new table schema (matching the existing table’s properties exactly) with the new name: db/config.ts ```diff const Comment = defineTable({ deprecated: true, columns: { author: column.text(), body: column.text(), } }); +const Feedback = defineTable({ columns: { author: column.text(), body: column.text(), } +}); ``` 3. [Push to your remote database](#pushing-table-schemas) with `astro db push --remote`. This will add the new table and mark the old as deprecated. 4. Update any of your local project code to use the new table instead of the old table. You might need to migrate data to the new table as well. 5. Once you are confident that the old table is no longer used in your project, you can remove the schema from your `config.ts`: db/config.ts ```diff -const Comment = defineTable({ deprecated: true, columns: { author: column.text(), body: column.text(), } -}); const Feedback = defineTable({ columns: { author: column.text(), body: column.text(), } }); ``` 6. Push to your remote database again with `astro db push --remote`. The old table will be dropped, leaving only the new, renamed table. ### Pushing table data [Section titled “Pushing table data”](#pushing-table-data) You may need to push data to your remote database for seeding or data migrations. You can author a `.ts` file with the `astro:db` module to write type-safe queries. Then, execute the file against your remote database using the command `astro db execute --remote`: The following Comments can be seeded using the command `astro db execute db/seed.ts --remote`: db/seed.ts ```ts import { Comment } from 'astro:db'; export default async function () { await db.insert(Comment).values([ { authorId: 1, body: 'Hope you like Astro DB!' }, { authorId: 2, body: 'Enjoy!' }, ]) } ``` See the [CLI reference](/en/guides/integrations-guide/db/#astro-db-cli-reference) for a complete list of commands. ## Building Astro DB integrations [Section titled “Building Astro DB integrations”](#building-astro-db-integrations) [Astro integrations](/en/reference/integrations-reference/) can extend user projects with additional Astro DB tables and seed data. Use the `extendDb()` method in the `astro:db:setup` hook to register additional Astro DB config and seed files. The `defineDbIntegration()` helper provides TypeScript support and auto-complete for the `astro:db:setup` hook. my-integration/index.ts ```js import { defineDbIntegration } from '@astrojs/db/utils'; export default function MyIntegration() { return defineDbIntegration({ name: 'my-astro-db-powered-integration', hooks: { 'astro:db:setup': ({ extendDb }) => { extendDb({ configEntrypoint: '@astronaut/my-package/config', seedEntrypoint: '@astronaut/my-package/seed', }); }, // Other integration hooks... }, }); } ``` Integration [config](#define-your-database) and [seed](#seed-your-database-for-development) files follow the same format as their user-defined equivalents. ### Type safe operations in integrations [Section titled “Type safe operations in integrations”](#type-safe-operations-in-integrations) While working on integrations, you may not be able to benefit from Astro’s generated table types exported from `astro:db`. For full type safety, use the `asDrizzleTable()` utility to create a table reference object you can use for database operations. For example, given an integration setting up the following `Pets` database table: my-integration/config.ts ```js import { defineDb, defineTable, column } from 'astro:db'; export const Pets = defineTable({ columns: { name: column.text(), species: column.text(), }, }); export default defineDb({ tables: { Pets } }); ``` The seed file can import `Pets` and use `asDrizzleTable()` to insert rows into your table with type checking: my-integration/seed.ts ```js import { asDrizzleTable } from '@astrojs/db/utils'; import { db } from 'astro:db'; import { Pets } from './config'; export default async function() { const typeSafePets = asDrizzleTable('Pets', Pets); await db.insert(typeSafePets).values([ { name: 'Palomita', species: 'cat' }, { name: 'Pan', species: 'dog' }, ]); } ``` The value returned by `asDrizzleTable('Pets', Pets)` is equivalent to `import { Pets } from 'astro:db'`, but is available even when Astro’s type generation can’t run. You can use it in any integration code that needs to query or insert into the database. ## Migrate from Astro Studio to Turso [Section titled “Migrate from Astro Studio to Turso”](#migrate-from-astro-studio-to-turso) 1. In the [Studio dashboard](https://studio.astro.build/), navigate to the project you wish to migrate. In the settings tab, use the “Export Database” button to download a dump of your database. 2. Follow the official instructions to [install the Turso CLI](https://docs.turso.tech/cli/installation) and [sign up or log in](https://docs.turso.tech/cli/authentication) to your Turso account. 3. Create a new database on Turso using the `turso db create` command. ```sh turso db create [database-name] ``` 4. Fetch the database URL using the Turso CLI, and use it as the environment variable `ASTRO_DB_REMOTE_URL`. ```sh turso db show [database-name] ``` ```dotenv ASTRO_DB_REMOTE_URL=[your-database-url] ``` 5. Create a token to access your database, and use it as the environment variable `ASTRO_DB_APP_TOKEN`. ```sh turso db tokens create [database-name] ``` ```dotenv ASTRO_DB_APP_TOKEN=[your-app-token] ``` 6. Push your DB schema and metadata to the new Turso database. ```sh astro db push --remote ``` 7. Import the database dump from step 1 into your new Turso DB. ```sh turso db shell [database-name] < ./path/to/dump.sql ``` 8. Once you have confirmed your project connects to the new database, you can safely delete the project from Astro Studio.
# Building Astro sites with AI tools
> Resources and tips for building Astro sites with AI assistance
AI-powered editors and agentic coding tools generally have good knowledge of Astro’s core APIs and concepts. However, some may use older APIs and may not be aware of newer features or recent changes to the framework. This guide covers how to enhance AI tools with up-to-date Astro knowledge and provides best practices for building Astro sites with AI assistance. ## Context files [Section titled “Context files”](#context-files) Astro provides [`llms.txt`](https://docs.astro.build/llms.txt) and [`llms-full.txt`](https://docs.astro.build/llms-full.txt) files that contains the full docs content in a format optimized for AI consumption. These are static files of the Astro Docs content in a streamlined Markdown format. Some AI tools can auto-discover these files if you provide `https://docs.astro.build` as a docs source. While these files provide a minimal, easy-to-parse version of Astro’s documentation, they are large files that will use a lot of tokens if used directly in context and will need to be updated regularly to stay current. They are best used as a fallback when the AI tool does not have access to the latest documentation in other ways. [The MCP server](#astro-docs-mcp-server) provides more efficient access to the full documentation with real-time search capabilities, making it the preferred option when available. ## Astro Docs MCP Server [Section titled “Astro Docs MCP Server”](#astro-docs-mcp-server) You can ensure your AI tools have current Astro knowledge through the Astro Docs MCP (Model Context Protocol) server. This provides real-time access to the latest documentation, helping AI tools avoid outdated recommendations and ensuring they understand current best practices. Unlike AI models trained on static data, the MCP server provides access to the latest Astro documentation. The server is free, open-source, and runs remotely with nothing to install locally. The Astro Docs MCP server uses the [kapa.ai](https://www.kapa.ai/) API to maintain an up-to-date index of the Astro documentation. ### Server Details [Section titled “Server Details”](#server-details) * **Name**: Astro Docs * **URL**: `https://mcp.docs.astro.build/mcp` * **Transport**: Streamable HTTP ### Installation [Section titled “Installation”](#installation) The setup process varies depending on your AI development tool. You may see some tools refer to MCP servers as connectors, adapters, extensions, or plugins. #### Manual setup [Section titled “Manual setup”](#manual-setup) Many tools support a common JSON configuration format for MCP servers. If there are not specific instructions for your chosen tool, you may be able to add the Astro Docs MCP server by including the following configuration in your tool’s MCP settings: * Streamable HTTP mcp.json ```json { "mcpServers": { "Astro docs": { "type": "http", "url": "https://mcp.docs.astro.build/mcp" } } } ``` * Local Proxy mcp.json ```json { "mcpServers": { "Astro docs": { "type": "stdio", "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.docs.astro.build/mcp"] } } } ``` #### Claude Code CLI [Section titled “Claude Code CLI”](#claude-code-cli) [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) is an agentic coding tool that runs on the command line. Enabling the Astro Docs MCP server allows it to access the latest documentation while generating Astro code. Install using the terminal command: ```shell claude mcp add --transport http astro-docs https://mcp.docs.astro.build/mcp ``` [More info on using MCP servers with Claude Code](https://docs.anthropic.com/en/docs/claude-code/mcp) #### Claude Code GitHub Action [Section titled “Claude Code GitHub Action”](#claude-code-github-action) Claude Code also provides a GitHub Action that can be used to run commands in response to GitHub events. Enabling the Astro Docs MCP server allows it to access the latest documentation while answering questions in comments or generating Astro code. You can configure it to use the Astro Docs MCP server for documentation access by adding the following to the workflow file: .github/workflows/claude.yml ```yaml # ...rest of your workflow configuration - uses: anthropics/claude-code-action@beta with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} mcp_config: | { "mcpServers": { "astro-docs": { "type": "http", "url": "https://mcp.docs.astro.build/mcp" } } } allowed_tools: "mcp__astro-docs__search_astro_docs" ``` [More info on using MCP servers with the Claude Code GitHub Action](https://github.com/anthropics/claude-code-action?tab=readme-ov-file#using-custom-mcp-configuration) #### Cursor [Section titled “Cursor”](#cursor) [Cursor](https://cursor.com) is an AI code editor. Adding the Astro Docs MCP server allows Cursor to access the latest Astro documentation while performing development tasks. Install by clicking the button below: [Add to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=Astro%20docs\&config=eyJ1cmwiOiJodHRwczovL21jcC5kb2NzLmFzdHJvLmJ1aWxkL21jcCJ9) [More info on using MCP servers with Cursor](https://docs.cursor.com/context/mcp) #### Visual Studio Code [Section titled “Visual Studio Code”](#visual-studio-code) [Visual Studio Code](https://code.visualstudio.com) supports MCP servers when using Copilot Chat. Adding the Astro Docs MCP server allows VS Code to access the latest Astro documentation when answering questions or performing coding tasks. Install by clicking the button below: [Add to VS Code](vscode:mcp/install?%7B%22name%22%3A%22Astro%20docs%22%2C%22url%22%3A%22https%3A%2F%2Fmcp.docs.astro.build%2Fmcp%22%7D) [More info on using MCP servers with VS Code](https://code.visualstudio.com/docs/copilot/chat/mcp-servers#_add-an-mcp-server) #### Warp [Section titled “Warp”](#warp) [Warp](https://warp.dev) (formerly Warp Terminal) is an agent development environment built for coding with multiple AI agents. Adding the Astro Docs MCP server allows Warp to access the latest Astro documentation when answering questions or performing coding tasks. 1. Open your Warp settings and go to AI > MCP Servers > Manage MCP Servers. 2. Click “Add”. 3. Enter the following configuration. You can optionally configure the Astro MCP server to activate on startup using the `start_on_launch` flag: MCP Configuration ```json { "mcpServers": { "Astro docs": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.docs.astro.build/mcp"], "env": {}, "working_directory": null, "start_on_launch": true } } } ``` 4. Click “Save”. [More info on using MCP servers with Warp](https://docs.warp.dev/knowledge-and-collaboration/mcp) #### Claude.ai / Claude Desktop [Section titled “Claude.ai / Claude Desktop”](#claudeai--claude-desktop) [Claude.ai](https://claude.ai) is a general-purpose AI assistant. Adding the Astro Docs MCP server allows it to access the latest documentation when answering Astro questions or generating Astro code. 1. Navigate to the [Claude.ai connector settings](https://claude.ai/settings/connectors). 2. Click “Add custom connector”. You may need to scroll down to find this option. 3. Enter the server URL: `https://mcp.docs.astro.build/mcp`. 4. Set the name to “Astro docs”. [More info on using MCP servers with Claude.ai](https://support.anthropic.com/en/articles/10168395-setting-up-integrations-on-claude-ai#h_cda40ecb32) #### Windsurf [Section titled “Windsurf”](#windsurf) [Windsurf](https://windsurf.com/) is an AI-powered agentic coding tool, available as editor plugins or a standalone editor. It can use the Astro Docs MCP server to access documentation while performing coding tasks. Windsurf doesn’t support streaming HTTP, so it requires a local proxy configuration: 1. Open `~/.codeium/windsurf/mcp_config.json` in your editor. 2. Add the following configuration to your Windsurf MCP settings: MCP Configuration ```json { "mcpServers": { "Astro docs": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.docs.astro.build/mcp"] } } } ``` 3. Save the configuration and restart Windsurf. [More info on using MCP servers with Windsurf](https://docs.windsurf.com/windsurf/cascade/mcp#mcp-config-json) #### Gemini CLI [Section titled “Gemini CLI”](#gemini-cli) Gemini CLI is a command-line AI coding tool that can use the Astro Docs MCP server to access documentation while generating Astro code. You can configure MCP servers at the global level in the `~/.gemini/settings.json` file, or in a `.gemini/settings.json` file in a project root. .gemini/settings.json ```json { "mcpServers": { "Astro docs": { "httpUrl": "https://mcp.docs.astro.build/mcp", } } } ``` [More info on using MCP servers with Gemini CLI](https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md) #### Zed [Section titled “Zed”](#zed) [Zed](https://zed.dev) supports MCP servers when using its AI capabilities. It can use the Astro Docs MCP server to access documentation while performing coding tasks. Zed doesn’t support streaming HTTP, so it requires a local proxy configuration: 1. Open `~/.config/zed/settings.json` in your editor. 2. Add the following configuration to your Zed MCP settings: MCP Configuration ```json { "context_servers": { "Astro docs": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.docs.astro.build/mcp"] } } } ``` 3. Save the configuration. [More info on using MCP servers with Zed](https://zed.dev/docs/ai/mcp) #### ChatGPT [Section titled “ChatGPT”](#chatgpt) Limited availability MCP server integration is only available for ChatGPT Pro, Team, and Enterprise users. The setup process is more complex than other tools. Refer to the [OpenAI MCP documentation](https://platform.openai.com/docs/mcp#test-and-connect-your-mcp-server) for specific setup instructions. #### Raycast [Section titled “Raycast”](#raycast) [Raycast](https://www.raycast.com/) can connect to MCP servers to enhance its AI capabilities. AI features such as MCP require a [Raycast Pro](https://www.raycast.com/pro) account, so ensure you have upgraded before trying to install. Adding the Astro Docs MCP server allows Raycast to access the latest Astro documentation while answering questions. Install by clicking the button below: [Add to Raycast](raycast://mcp/install?%7B%22name%22%3A%22Astro%20docs%22%2C%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%20%22mcp-remote%22%2C%20%22https%3A%2F%2Fmcp.docs.astro.build%2Fmcp%22%5D%7D) [More info on using MCP servers with Raycast](https://manual.raycast.com/model-context-protocol) ### Usage [Section titled “Usage”](#usage) Once configured, you can ask your AI tool questions about Astro, and it will retrieve information directly from the latest docs. Coding agents will be able to consult the latest documentation when performing coding tasks, and chatbots will be able to accurately answer questions about Astro features, APIs, and best practices. ### Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) If you encounter issues: * Verify that your tool supports streamable HTTP transport. * Check that the server URL is correct: `https://mcp.docs.astro.build/mcp`. * Ensure your tool has proper internet access. * Consult your specific tool’s MCP integration documentation. If you are still having problems, open an issue in the [Astro Docs MCP Server repository](https://github.com/withastro/docs-mcp/issues). ## Discord AI Support [Section titled “Discord AI Support”](#discord-ai-support) The same technology that powers Astro’s MCP server is also available as a chatbot in the [Astro Discord](https://astro.build/chat) for self-serve support. Visit the `#support-ai` channel to ask questions about Astro or your project code in natural language. Your conversation is automatically threaded, and you can ask an unlimited number of follow-up questions. **Conversations with the chatbot are public, and are subject to the same server rules for language and behavior as the rest of our channels**, but they are not actively visited by our volunteer support members. For assistance from the community, please create a thread in our regular `#support` channel. ## Tips for AI-Powered Astro Development [Section titled “Tips for AI-Powered Astro Development”](#tips-for-ai-powered-astro-development) * **Start with templates**: Rather than building from scratch, ask AI tools to start with an existing [Astro template](https://astro.build/themes/) or use `npm create astro@latest` with a template option. * **Use `astro add` for integrations**: Ask AI tools to use `astro add` for official integrations (e.g. `astro add tailwind`, `astro add react`). For other packages, install using the command for your preferred package manager rather than editing `package.json` directly. * **Verify current APIs**: AI tools may use outdated patterns. Ask them to check the latest documentation, especially for newer features like sessions and actions. This is also important for features that have seen significant changes since their initial launch, such as content collections, or previously experimental features that may no longer be experimental. * **Use project rules**: If your AI tool supports it, set up project rules to enforce best practices and coding standards, such as the ones listed above.
# Scripts and event handling
> How to add client-side interactivity to Astro components using native browser JavaScript APIs.
You can send JavaScript to the browser and add functionality to your Astro components using ` ``` See [when your scripts will not be processed](#unprocessed-scripts) to troubleshoot script behavior, or to learn how to opt-out of this processing intentionally. ## Script processing [Section titled “Script processing”](#script-processing) By default, Astro processes ` ``` ### Unprocessed scripts [Section titled “Unprocessed scripts”](#unprocessed-scripts) Astro will not process a ` ``` ### Include JavaScript files on your page [Section titled “Include JavaScript files on your page”](#include-javascript-files-on-your-page) You may want to write your scripts as separate `.js`/`.ts` files or need to reference an external script on another server. You can do this by referencing these in a ` ``` #### Load external scripts [Section titled “Load external scripts”](#load-external-scripts) **When to use this:** when your JavaScript file lives inside of `public/` or on a CDN. To load scripts outside of your project’s `src/` folder, include the `is:inline` directive. This approach skips the JavaScript processing, bundling, and optimizations that are provided by Astro when you import scripts as described above. src/components/ExternalScripts.astro ```astro ``` ## Common script patterns [Section titled “Common script patterns”](#common-script-patterns) ### Handle `onclick` and other events [Section titled “Handle onclick and other events”](#handle-onclick-and-other-events) Some UI frameworks use custom syntax for event handling like `onClick={...}` (React/Preact) or `@click="..."` (Vue). Astro follows standard HTML more closely and does not use custom syntax for events. Instead, you can use [`addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) in a ` ``` If you have multiple `` components on a page, Astro will not run the script multiple times. Scripts are bundled and only included once per page. Using `querySelectorAll` ensures that this script attaches the event listener to every button with the `alert` class found on the page. ### Web components with custom elements [Section titled “Web components with custom elements”](#web-components-with-custom-elements) You can create your own HTML elements with custom behavior using the Web Components standard. Defining a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) in a `.astro` component allows you to build interactive components without needing a UI framework library. In this example, we define a new `` HTML element that tracks how many times you click the heart button and updates the `` with the latest count. src/components/AstroHeart.astro ```astro × 0 ``` There are two advantages to using a custom element here: 1. Instead of searching the whole page using `document.querySelector()`, you can use `this.querySelector()`, which only searches within the current custom element instance. This makes it easier to work with only the children of one component instance at a time. 2. Although a ` ``` Now we can use our component multiple times and be greeted by a different message for each one. src/pages/example.astro ```astro --- import AstroGreet from '../components/AstroGreet.astro'; --- ``` ### Combining scripts and UI Frameworks [Section titled “Combining scripts and UI Frameworks”](#combining-scripts-and-ui-frameworks) Elements rendered by a UI framework may not be available yet when a ` ``` ### Variable types [Section titled “Variable types”](#variable-types) There are three kinds of environment variables, determined by the combination of `context` (`"client"` or `"server"`) and `access` (`"secret"` or `"public"`) settings defined in your schema: * **Public client variables**: These variables end up in both your final client and server bundles, and can be accessed from both client and server through the `astro:env/client` module: ```js import { API_URL } from "astro:env/client"; ``` * **Public server variables**: These variables end up in your final server bundle and can be accessed on the server through the `astro:env/server` module: ```js import { PORT } from "astro:env/server"; ``` * **Secret server variables**: These variables are not part of your final bundle and can be accessed on the server through the `astro:env/server` module: ```js import { API_SECRET } from "astro:env/server"; ``` By default, secrets are only validated at runtime. You can enable validating private variables on start by [configuring `validateSecrets: true`](/en/reference/configuration-reference/#envvalidatesecrets). ### Data types [Section titled “Data types”](#data-types) There are currently four data types supported: strings, numbers, enums, and booleans: ```js import { envField } from "astro/config"; envField.string({ // context & access optional: true, default: "foo", }) envField.number({ // context & access optional: true, default: 15, }) envField.boolean({ // context & access optional: true, default: true, }) envField.enum({ // context & access values: ["foo", "bar", "baz"], optional: true, default: "baz", }) ``` For a complete list of validation fields, see the [`envField` API reference](/en/reference/configuration-reference/#envschema). ### Retrieving secrets dynamically [Section titled “Retrieving secrets dynamically”](#retrieving-secrets-dynamically) Despite defining your schema, you may want to retrieve the raw value of a given secret or to retrieve secrets not defined in your schema. In this case, you can use `getSecret()` exported from `astro:env/server`: ```js import { FOO, // boolean getSecret } from "astro:env/server"; getSecret("FOO"); // string | undefined ``` Learn more in [the API reference](/en/reference/modules/astro-env/#getsecret). ### Limitations [Section titled “Limitations”](#limitations) `astro:env` is a virtual module which means it can only be used inside the Astro context. For example, you can use it in: * Middlewares * Astro routes and endpoints * Astro components * Framework components * Modules You cannot use it in the following and will have to resort to `process.env`: * `astro.config.mjs` * Scripts
# Using custom fonts
> Looking to add some custom typefaces to an Astro website? Use Google Fonts with Fontsource or add a font of your choice.
This guide will show you how to add web fonts to your project and use them in your components. ## Using a local font file [Section titled “Using a local font file”](#using-a-local-font-file) This example will demonstrate adding a custom font using the font file `DistantGalaxy.woff`. 1. Add your font file to `public/fonts/`. 2. Add the following `@font-face` statement to your CSS. This could be in a global `.css` file you import, a ` ``` ## Using Fontsource [Section titled “Using Fontsource”](#using-fontsource) The [Fontsource](https://fontsource.org/) project simplifies using Google Fonts and other open-source fonts. It provides npm modules you can install for the fonts you want to use. 1. Find the font you want to use in [Fontsource’s catalog](https://fontsource.org/). This example will use [Twinkle Star](https://fontsource.org/fonts/twinkle-star). 2. Install the package for your chosen font. * npm ```shell npm install @fontsource/twinkle-star ``` * pnpm ```shell pnpm add @fontsource/twinkle-star ``` * Yarn ```shell yarn add @fontsource/twinkle-star ``` 3. Import the font package in the component where you want to use the font. Usually, you will want to do this in a common layout component to make sure the font is available across your site. The import will automatically add the necessary `@font-face` rules needed to set up the font. src/layouts/BaseLayout.astro ```astro --- import '@fontsource/twinkle-star'; --- ``` 4. Use the font’s name as shown in the `body` example on its Fontsource page as the `font-family` value. This will work anywhere you can write CSS in your Astro project. ```css h1 { font-family: "Twinkle Star", cursive; } ``` To optimize your website’s rendering times, you may want to preload fonts that are essential for the initial page display. See the [Fontsource guide to preloading fonts](https://fontsource.org/docs/getting-started/preload) for more information and usage. ## Register fonts in Tailwind [Section titled “Register fonts in Tailwind”](#register-fonts-in-tailwind) If you are using [Tailwind](/en/guides/styling/#tailwind), you can use either of the previous methods on this page to install your font, with some modifications. You can either add an [`@font-face` statement for a local font](#using-a-local-font-file) or use [Fontsource’s `import` strategy](#using-fontsource) to install your font. To register your font in Tailwind: 1. Follow either of the guides above, but skip the final step of adding `font-family` to your CSS. 2. Add the typeface name to `src/styles/global.css`. This example adds `Inter` to the sans-serif font stack. src/styles/global.css ```diff @import 'tailwindcss'; +@theme { +--font-sans: 'Inter', 'sans-serif'; +} ``` Now, all sans-serif text (the default with Tailwind) in your project will use your chosen font and the `font-sans` class will also apply the Inter font. See [Tailwind’s docs on adding custom font families](https://tailwindcss.com/docs/font-family#using-custom-values) for more information. ## More resources [Section titled “More resources”](#more-resources) * Learn how web fonts work in [MDN’s web fonts guide](https://developer.mozilla.org/en-US/docs/Learn/CSS/Styling_text/Web_fonts). * Generate CSS for your font with [Font Squirrel’s Webfont Generator](https://www.fontsquirrel.com/tools/webfont-generator).
# Front-end frameworks
> Build your Astro website with React, Svelte, and more.
Build your Astro website without sacrificing your favorite component framework. Create Astro [islands](/en/concepts/islands/) with the UI frameworks of your choice. ## Official front-end framework integrations [Section titled “Official front-end framework integrations”](#official-front-end-framework-integrations) Astro supports a variety of popular frameworks including [React](https://react.dev/), [Preact](https://preactjs.com/), [Svelte](https://svelte.dev/), [Vue](https://vuejs.org/), [SolidJS](https://www.solidjs.com/), and [AlpineJS](https://alpinejs.dev/) with official integrations. Find even more [community-maintained framework integrations](https://astro.build/integrations/?search=\&categories%5B%5D=frameworks) (e.g. Angular, Qwik, Elm) in our integrations directory. ### Front-end frameworks *  ### [@astrojs/alpinejs](/en/guides/integrations-guide/alpinejs/) *  ### [@astrojs/preact](/en/guides/integrations-guide/preact/) *  ### [@astrojs/react](/en/guides/integrations-guide/react/) *  ### [@astrojs/solid-js](/en/guides/integrations-guide/solid-js/) *  ### [@astrojs/svelte](/en/guides/integrations-guide/svelte/) *  ### [@astrojs/vue](/en/guides/integrations-guide/vue/) ## Installing integrations [Section titled “Installing integrations”](#installing-integrations) One or several of these Astro integrations can be installed and configured in your project. See the [Integrations Guide](/en/guides/integrations-guide/) for more details on installing and configuring Astro integrations. ## Using framework components [Section titled “Using framework components”](#using-framework-components) Use your JavaScript framework components in your Astro pages, layouts and components just like Astro components! All your components can live together in `/src/components`, or can be organized in any way you like. To use a framework component, import it from its relative path in your Astro component script. Then, use the component alongside other components, HTML elements and JSX-like expressions in the component template. src/pages/static-components.astro ```diff --- +import MyReactComponent from '../components/MyReactComponent.jsx'; ---
Use React components directly in Astro!
+ ``` By default, your framework components will only render on the server, as static HTML. This is useful for templating components that are not interactive and avoids sending any unnecessary JavaScript to the client. ## Hydrating interactive components [Section titled “Hydrating interactive components”](#hydrating-interactive-components) A framework component can be made interactive (hydrated) using a [`client:*` directive](/en/reference/directives-reference/#client-directives). These are component attributes that determine when your component’s JavaScript should be sent to the browser. With all client directives except `client:only`, your component will first render on the server to generate static HTML. Component JavaScript will be sent to the browser according to the directive you chose. The component will then hydrate and become interactive. src/pages/interactive-components.astro ```astro --- // Example: hydrating framework components in the browser. import InteractiveButton from '../components/InteractiveButton.jsx'; import InteractiveCounter from '../components/InteractiveCounter.jsx'; import InteractiveModal from '../components/InteractiveModal.svelte'; --- ``` The JavaScript framework (React, Svelte, etc.) needed to render the component will be sent to the browser along with the component’s own JavaScript. If two or more components on a page use the same framework, the framework will only be sent once. ### Available hydration directives [Section titled “Available hydration directives”](#available-hydration-directives) There are several hydration directives available for UI framework components: `client:load`, `client:idle`, `client:visible`, `client:media={QUERY}` and `client:only={FRAMEWORK}`. See our [directives reference](/en/reference/directives-reference/#client-directives) page for a full description of these hydration directives, and their usage. ## Mixing frameworks [Section titled “Mixing frameworks”](#mixing-frameworks) You can import and render components from multiple frameworks in the same Astro component. src/pages/mixing-frameworks.astro ```astro --- // Example: Mixing multiple framework components on the same page. import MyReactComponent from '../components/MyReactComponent.jsx'; import MySvelteComponent from '../components/MySvelteComponent.svelte'; import MyVueComponent from '../components/MyVueComponent.vue'; ---
``` Astro will recognize and render your component based on its file extension. To distinguish between frameworks that use the same file extension, [additional configuration when rendering multiple JSX frameworks](/en/guides/integrations-guide/react/#combining-multiple-jsx-frameworks) (e.g. React and Preact) is required. Caution Only **Astro** components (`.astro`) can contain components from multiple frameworks. ## Passing props to framework components [Section titled “Passing props to framework components”](#passing-props-to-framework-components) You can pass props from Astro components to framework components: src/pages/frameworks-props.astro ```astro --- import TodoList from '../components/TodoList.jsx'; import Counter from '../components/Counter.svelte'; ---
``` Props that are passed to interactive framework components [using a `client:*` directive](/en/reference/directives-reference/#client-directives) must be [serialized](https://developer.mozilla.org/en-US/docs/Glossary/Serialization): translated into a format suitable for transfer over a network, or storage. However, Astro does not serialize every type of data structure. Therefore, there are some limitations on what can be passed as props to hydrated components. The following prop types are supported: plain object, `number`, `string`, `Array`, `Map`, `Set`, `RegExp`, `Date`, `BigInt`, `URL`, `Uint8Array`, `Uint16Array`, `Uint32Array`, and `Infinity` Non-supported data structures passed to components, such as functions, can only be used during the component’s server rendering and cannot be used to provide interactivity. For example, passing functions to hydrated components is not supported because Astro cannot pass functions from the server in a way that makes them executable on the client. ## Passing children to framework components [Section titled “Passing children to framework components”](#passing-children-to-framework-components) Inside of an Astro component, you **can** pass children to framework components. Each framework has its own patterns for how to reference these children: React, Preact, and Solid all use a special prop named `children`, while Svelte and Vue use the `` element. src/pages/component-children.astro ```astro --- import MyReactSidebar from '../components/MyReactSidebar.jsx'; ---
Here is a sidebar with some text and a button.
``` Additionally, you can use [Named Slots](/en/basics/astro-components/#named-slots) to group specific children together. For React, Preact, and Solid, these slots will be converted to a top-level prop. Slot names using `kebab-case` will be converted to `camelCase`. src/pages/named-slots.astro ```astro --- import MySidebar from '../components/MySidebar.jsx'; ---
``` src/components/MySidebar.jsx ```jsx export default function MySidebar(props) { return ( ) } ``` For Svelte and Vue these slots can be referenced using a `` element with the `name` attribute. Slot names using `kebab-case` will be preserved. src/components/MySidebar.svelte ```jsx ``` ## Nesting framework components [Section titled “Nesting framework components”](#nesting-framework-components) Inside of an Astro file, framework component children can also be hydrated components. This means that you can recursively nest components from any of these frameworks. src/pages/nested-components.astro ```astro --- import MyReactSidebar from '../components/MyReactSidebar.jsx'; import MyReactButton from '../components/MyReactButton.jsx'; import MySvelteButton from '../components/MySvelteButton.svelte'; ---
Here is a sidebar with some text and a button.
``` Caution Remember: framework component files themselves (e.g. `.jsx`, `.svelte`) cannot mix multiple frameworks. This allows you to build entire “apps” in your preferred JavaScript framework and render them, via a parent component, to an Astro page. ## Can I use Astro components inside my framework components? [Section titled “Can I use Astro components inside my framework components?”](#can-i-use-astro-components-inside-my-framework-components) Any UI framework component becomes an “island” of that framework. These components must be written entirely as valid code for that framework, using only its own imports and packages. You cannot import `.astro` components in a UI framework component (e.g. `.jsx` or `.svelte`). You can, however, use [the Astro `` pattern](/en/basics/astro-components/#slots) to pass static content generated by Astro components as children to your framework components **inside an `.astro` component**. src/pages/astro-children.astro ```astro --- import MyReactComponent from '../components/MyReactComponent.jsx'; import MyAstroComponent from '../components/MyAstroComponent.astro'; --- ``` ## Can I hydrate Astro components? [Section titled “Can I hydrate Astro components?”](#can-i-hydrate-astro-components) If you try to hydrate an Astro component with a `client:` modifier, you will get an error. [Astro components](/en/basics/astro-components/) are HTML-only templating components with no client-side runtime. But, you can use a ` ``` Astro components (e.g. ``, ``, SVG components) are unavailable inside UI framework components because [a client island must contain only valid code for its own framework](/en/guides/framework-components/#can-i-use-astro-components-inside-my-framework-components). But, you can pass the static content generated by these components to a framework component inside a `.astro` file [as children](/en/guides/framework-components/#passing-children-to-framework-components) or using a [named ``](/en/guides/framework-components/#can-i-use-astro-components-inside-my-framework-components): src/components/ImageWrapper.astro ```astro --- import ReactComponent from './ReactComponent.jsx'; import { Image } from 'astro:assets'; import stars from '~/stars/docline.png'; --- ``` ## Astro components for images [Section titled “Astro components for images”](#astro-components-for-images) Astro provides two built-in Astro components for images (`` and ``) and also allows you to import SVG files and use them as Astro components. These components may be used in any files that can import and render `.astro` components. ### `` [Section titled “\”](#image-) Use the built-in `` Astro component to display optimized versions of: * your local images located within the `src/` folder * [configured remote images](#authorizing-remote-images) from authorized sources `` can transform a local or authorized remote image’s dimensions, file type, and quality for control over your displayed image. This transformation happens at build time for prerendered pages. When your page is rendered on demand, this transformation will occur on the fly when the page is viewed. The resulting `` tag includes `alt`, `loading`, and `decoding` attributes and infers image dimensions to avoid Cumulative Layout Shift (CLS). src/components/MyComponent.astro ```astro --- // import the Image component and the image import { Image } from 'astro:assets'; import myImage from '../assets/my_image.png'; // Image is 1600x900 --- ``` ```html /> ``` The `` component accepts [several component properties](/en/reference/modules/astro-assets/#image-properties) as well as any attributes accepted by the HTML `` tag. The following example provides a `class` to the image component which will apply to the final `` element. src/pages/index.astro ```astro --- import { Image } from 'astro:assets'; import myImage from '../assets/my_image.png'; --- ``` ```html ``` ### `` [Section titled “\”](#picture-) **Added in:** `astro@3.3.0` Use the built-in `` Astro component to generate a `` tag with multiple formats and/or sizes of your image. This allows you to specify preferred file formats to display and at the same time, provide a fallback format. Like the [`` component](#image-), images will be processed at build time for prerendered pages. When your page is rendered on demand, processing will occur on the fly when the page is viewed. The following example uses the `` component to transform a local `.png` file into a web-friendly `avif` and `webp` format as well as the `.png` `` that can be displayed as a fallback when needed: src/pages/index.astro ```astro --- import { Picture } from 'astro:assets'; import myImage from '../assets/my_image.png'; // Image is 1600x900 --- ``` ```html ``` See details about [the `` component properties](/en/reference/modules/astro-assets/#picture-properties) in the `astro:assets` reference. ### Responsive image behavior [Section titled “Responsive image behavior”](#responsive-image-behavior) **Added in:** `astro@5.10.0` Responsive images are images that adjust to improve performance across different devices. These images can resize to fit their container, and can be served in different sizes depending on your visitor’s screen size and resolution. With [responsive image properties](/en/reference/modules/astro-assets/#responsive-image-properties) applied to the `` or `` components, Astro will automatically generate the required `srcset` and `sizes` values for your images, and apply the necessary [styles to ensure they resize correctly](#responsive-image-styles). When this responsive behavior is [configured globally](/en/reference/configuration-reference/#imagelayout), it will apply to all image components and also to any local and remote images using [the Markdown `![]()` syntax](/en/guides/images/#images-in-markdown-files). Images in your `public/` folder are never optimized, and responsive images are not supported. Read more about [responsive images on MDN web docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Responsive_images). #### Generated HTML output for responsive images [Section titled “Generated HTML output for responsive images”](#generated-html-output-for-responsive-images) When a layout is set, either by default or on an individual component, images have automatically generated `srcset` and `sizes` attributes based on the image’s dimensions and the layout type. Images with `constrained` and `full-width` layouts will have styles applied to ensure they resize according to their container. src/components/MyComponent.astro ```astro --- import { Image } from 'astro:assets'; import myImage from '../assets/my_image.png'; --- ``` This `` component will generate the following HTML output on a prerendered page: ```html ``` #### Responsive image styles [Section titled “Responsive image styles”](#responsive-image-styles) Setting [`image.responsiveStyles: true`](/en/reference/configuration-reference/#imageresponsivestyles) applies a small number of global styles to ensure that your images resize correctly. In most cases, you will want to enable these as a default; your images will not be responsive without additional styles. However, if you prefer to handle responsive image styling yourself, or need to [override these defaults when using Tailwind 4](#responsive-images-with-tailwind-4), leave the default `false` value configured. The global styles applied by Astro will depend on the layout type, and are designed to produce the best result for the generated `srcset` and `sizes` attributes. These are the default styles: Responsive Image Styles ```css :where([data-astro-image]) { object-fit: var(--fit); object-position: var(--pos); } :where([data-astro-image='full-width']) { width: 100%; } :where([data-astro-image='constrained']) { max-width: 100%; } ``` The styles use the [`:where()` pseudo-class](https://developer.mozilla.org/en-US/docs/Web/CSS/:where), which has a [specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/Specificity) of 0, meaning that it is easy to override with your own styles. Any CSS selector will have a higher specificity than `:where()`, so you can easily override the styles by adding your own styles to target the image. You can override the `object-fit` and `object-position` styles on a per-image basis by setting the `fit` and `position` props on the `` or `` component. #### Responsive images with Tailwind 4 [Section titled “Responsive images with Tailwind 4”](#responsive-images-with-tailwind-4) Tailwind 4 is compatible with Astro’s default responsive styles. However, Tailwind uses [cascade layers](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer), meaning that its rules are always lower specificity than rules that don’t use layers, including Astro’s responsive styles. Therefore, Astro’s styling will take precedence over Tailwind styling. To use Tailwind rules instead of Astro’s default styling, do not enable [Astro’s default responsive styles](/en/reference/configuration-reference/#imageresponsivestyles). ### SVG components [Section titled “SVG components”](#svg-components) **Added in:** `astro@5.7.0` Astro allows you to import SVG files and use them as Astro components. Astro will inline the SVG content into your HTML output. Reference the default import of any local `.svg` file. Since this import is treated as an Astro component, you must use the same conventions (e.g. capitalization) as when [using dynamic tags](/en/reference/astro-syntax/#dynamic-tags). src/components/MyAstroComponent.astro ```astro --- import Logo from './path/to/svg/file.svg'; --- ``` Your SVG component, like `` or any other Astro component, is unavailable inside UI framework components, but can [be passed to a framework component](#images-in-ui-framework-components) inside a `.astro` component. #### SVG component attributes [Section titled “SVG component attributes”](#svg-component-attributes) You can pass props such as `width`, `height`, `fill`, `stroke`, and any other attribute accepted by the [native `