# Appendix B: Astro Cheat Sheet

Course: [Astro](https://www.devtutorials.ai/learn/astro) · Section: Appendix
Source: https://www.devtutorials.ai/learn/astro/appendix/cheat-sheet

> Every command, project file and piece of syntax from the course on one page: components, routing, content, rendering, islands, navigation and server features.

## Appendix B: Astro Cheat Sheet

- One page with the commands, files and syntax from the whole course.
- Keep it open while you build.

## Commands

<div className="tscroll">

| Command | What it does |
|---|---|
| `npm create astro@latest` | Start a new project |
| `npm run dev` | Dev server at `http://localhost:4321` |
| `npm run build` | Build the site into `dist/` |
| `npm run preview` | Serve `dist/` locally |
| `npx astro add <name>` | Add an integration or adapter (`preact`, `node`, `netlify`, `sitemap`...) |
| `npx astro check` | Type-check every file |
| `npx astro sync` | Regenerate types for collections and `astro:env` |

</div>

## Project Files

<div className="tscroll">

| Path | Purpose |
|---|---|
| `src/pages/` | Every file here is a route |
| `src/layouts/` | Page shells with `<slot />` |
| `src/components/` | Reusable `.astro`, `.tsx`, `.jsx` components |
| `src/content.config.ts` | Build-time content collections |
| `src/live.config.ts` | Live collections |
| `src/middleware.ts` | Code that runs before every on-demand request |
| `src/actions/index.ts` | Type-safe server functions |
| `public/` | Files copied as they are (`favicon.svg`, `robots.txt`) |
| `astro.config.mjs` | Site settings, integrations, adapter |

</div>

## Component Syntax

```astro
---
// Component script: runs on the server or at build time.
import Card from "../components/Card.astro";
interface Props { title: string; tags?: string[] }
const { title, tags = [] } = Astro.props;
---

<h1 class:list={["title", { big: tags.length > 2 }]}>{title}</h1>
{tags.length > 0 && <ul>{tags.map((t) => <li>{t}</li>)}</ul>}
<Card title="Hi"><p>Default slot</p><p slot="footer">Named slot</p></Card>
<slot />

<style>
  h1 { color: navy; } /* scoped to this component */
</style>

<script>
  console.log("Runs in the browser, bundled once");
</script>
```

## Routing

<div className="tscroll">

| File | URL |
|---|---|
| `src/pages/index.astro` | `/` |
| `src/pages/about.astro` | `/about` |
| `src/pages/posts/[slug].astro` | `/posts/anything` (needs `getStaticPaths()` when static) |
| `src/pages/docs/[...path].astro` | `/docs/a/b/c` |
| `src/pages/feed.xml.ts` | `/feed.xml` (endpoint) |
| `src/pages/_draft.astro` | No route (starts with `_`) |
| `src/pages/404.astro` | The not-found page |

</div>

## Content

```ts
// src/content.config.ts
import { defineCollection } from "astro:content";
import { glob } from "astro/loaders";
import { z } from "astro/zod";

const posts = defineCollection({
  loader: glob({ pattern: "**/*.md", base: "./src/content/posts" }),
  schema: z.object({ title: z.string(), date: z.coerce.date(), draft: z.boolean().default(false) }),
});
export const collections = { posts };
```

- Read: `getCollection("posts")`, `getEntry("posts", id)`. Render Markdown: `const { Content } = await render(entry)`.
- Live data: `getLiveCollection()`, `getLiveEntry()`. Check `error` first.

## Rendering

<div className="tscroll">

| Setting | Effect |
|---|---|
| Default | Every page static, built once |
| `export const prerender = false` | This page on demand (needs an adapter) |
| `output: "server"` | Every page on demand; opt back with `prerender = true` |
| `<Comp server:defer />` | Server island, rendered after the page |

</div>

## Islands and Navigation

<div className="tscroll">

| Syntax | Meaning |
|---|---|
| `client:load` | Hydrate at once |
| `client:idle` | Hydrate when the browser is free |
| `client:visible` | Hydrate when scrolled into view |
| `client:media="(max-width: 600px)"` | Hydrate when the query matches |
| `client:only="preact"` | Browser only, no server HTML |
| `<ClientRouter />` | Smooth page swaps (in the layout `<head>`) |
| `transition:name="hero"` | Morph matching elements |
| `transition:animate="slide"` | Choose the animation |
| `transition:persist` | Keep the element across pages |
| `data-astro-prefetch` | Prefetch the link |

</div>

## Server

```ts
// Endpoint: src/pages/api/likes.ts
export const prerender = false;
export const GET: APIRoute = () => Response.json({ likes: 3 });

// Middleware: src/middleware.ts
export const onRequest = defineMiddleware(async (context, next) => {
  context.locals.user = await getUser(context.cookies.get("token")?.value);
  return next();
});

// Action: src/actions/index.ts
export const server = {
  like: defineAction({ input: z.object({ id: z.string() }), handler: async ({ id }) => ({ id }) }),
};
```

- Cookies: `Astro.cookies.get/set/delete`. Sessions: `await Astro.session?.get(key)`, `Astro.session?.set(key, value)`.
- Env: `envField` in the config, then `import { X } from "astro:env/server"`.

Not sure where code runs? Frontmatter and endpoints: **server**. `<script>` and `client:*` islands: **browser**.
