Part 3 of 16
Astro project from scratch
Project scaffold, folder structure, .gitignore and a configurable base.
Time to create the project. Astro has a wizard that sets everything up in a couple of minutes.
Creating the project
From the folder where I want the project to live:
npm create -y astro@latest . -- --template minimal --install --no-git --typescript strict --yes
Important detail: I used --no-git so Astro doesn’t initialize Git for me, because I already had the repository prepared and prefer to control that step.
The structure it generates
/
├── public/ → static files (favicon, images)
├── src/
│ └── pages/ → each .astro file is a page
├── astro.config.mjs → Astro configuration
├── package.json
├── tsconfig.json
└── .gitignore
I later added these folders to src/ as I needed them: components/, layouts/, styles/ and scripts/.
Adjusting the .gitignore
Astro already ships a good .gitignore (node_modules/, dist/, .astro/). I added the environment variables so sensitive data never gets committed:
# environment variables
.env
.env.*
!.env.example
Making the base configurable
This is a trick that later saved the deployment. The site is served from different places depending on the environment: on the custom domain it lives at the root /, but on https://user.github.io/repo/ it lives under a subfolder. I solved it by reading an environment variable in the config:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import { loadEnv } from 'vite';
const env = loadEnv(process.env.NODE_ENV ?? 'production', process.cwd(), '');
export default defineConfig({
site: process.env.SITE_URL ?? env.SITE_URL ?? 'http://localhost:4321',
base: process.env.ASTRO_BASE ?? env.ASTRO_BASE ?? '',
});
That way, depending on the value of ASTRO_BASE (empty for a custom domain, /repo/ for GitHub Pages), all links and assets are generated with the correct path.
Testing that it works
npm run dev
It opens at http://localhost:4321. Any change is visible instantly without reloading. In the next part we give it a visual identity.