Start an Astro project

Understand the project structure

Know which folders Astro owns and which folders you create as the site grows.

An Astro project has two kinds of files. Files Astro processes, and files it copies as they are. The folder structure reflects that split.

Here is the shape of our small site:

astro-notes/
├── public/
│   └── robots.txt
├── src/
│   ├── components/
│   ├── layouts/
│   ├── pages/
│   └── assets/
├── astro.config.mjs
├── package.json
└── tsconfig.json

The src/ folder

Everything Astro processes lives under src/. Components, layouts, pages, styles, images you import.

src/pages/ is special. Files in there become URLs. It’s the one folder whose name Astro enforces, and we’ll spend a whole module on it.

src/components/ and src/layouts/ are conventions, not rules. You could name them anything. Almost everybody keeps the standard names because every Astro developer recognizes them, and I suggest you do the same.

Because Astro processes these files, it can help you. It bundles scripts and styles. It optimizes imported images. And it reports broken imports. Rename an image in src/assets/ without updating the component that imports it, and the build fails with the exact file and line. The mistake cannot reach production.

The public/ folder

Files in public/ skip all that. Astro copies them unchanged to the root of the output. public/robots.txt is served at /robots.txt.

Use it for files that must keep an exact name and path. robots.txt, a web manifest, a favicon, a PDF you link to.

The trade-off is that a reference to a public file is only a string. Type /robot.txt in a link and the build succeeds anyway. You find out later, as a 404.

The root files

Three files at the root complete the picture.

astro.config.mjs holds project-wide settings, like integrations and build options. package.json lists the dependencies and the dev, build, and preview scripts. tsconfig.json configures TypeScript, which Astro projects support from day one.

The dist/ folder

You don’t see it yet. It appears after the first production build, and it holds the generated site.

Treat dist/ as disposable. Never edit it by hand. The next build overwrites everything in it.

Try this on your own project: put an image in public/ and reference it from a page, then move the same image under src/assets/ and import it instead. Break both references on purpose. Only one of the two mistakes stops the build.

Lesson completed