Project structure
my-site/
├── data/
│ ├── site.json site settings: name, url, locale, schema, navigation...
│ └── *.json any other JSON, available as data.<filename>
├── layouts/
│ └── default.vue the shell around every page
├── pages/ .vue and .md pages; folders become URLs
├── components/ Vue components, auto-registered
├── content/
│ └── <collection>/ Markdown entries (posts, notes)
│ └── media/ images belonging to those entries
├── styles/
│ └── main.css Tailwind CSS 4 entry
├── images/ images processed into AVIF/WebP
├── public/ copied unchanged to the site root
└── .env .env.* environment variables (build time only)
| path | purpose |
|---|---|
data/site.json | Required. Site-wide settings, see Configuration. |
data/*.json | Optional data, e.g. data/products.json is data.products in templates. |
layouts/default.vue | Optional. Wraps every page; a bare <slot /> is used if missing. Add layouts/<name>.vue for alternatives. |
pages/ | One page per file. pages/about.vue becomes /about. Files starting with _ are ignored. |
components/ | .vue files available everywhere by PascalCase name. |
content/<name>/ | A collection: one Markdown file per entry. |
styles/main.css | The stylesheet entry. With @import "tailwindcss" it is compiled with Tailwind 4. |
images/ | Images that get optimised variants. Use them with <Image src="photo.jpg">. |
public/ | Files copied verbatim to the site root: favicon.ico, robots.txt, social images. |
Build output
static build writes the finished site to .build/ inside the project. That folder is what gets deployed. It is replaced only when a build succeeds, so a failed build never overwrites a good one. Add .build, .build.tmp and .build-cache to .gitignore (new projects already do).