Set Up Astro Tone in Ten Minutes
Clone, edit one config file, write one real post, deploy. The shortest path through the starter.
The starter is a small Astro site. By the end of this post you will have your name on the home page, one real post, and a deploy that points to your domain.
Skip any step that does not apply.
Install#
npm create astro@latest my-blog -- --template hanityx/astro-tonecd my-blognpm run devThe dev server runs at http://localhost:4321. If the port is taken, Astro picks the next free one and prints it.
Edit one config file#
Open astro-theme-config.ts. This is the only file you need to touch for site-wide settings.
site: { url: 'https://your-site.com', base: '', title: 'Your Site', logoLabel: 'Tone', description: 'One short line about the site.', author: 'Your Name', defaultOgImage: '/og.png',}Three rules:
urlis the production origin. Setbaseonly when deploying under a subpath, such as GitHub Pages project sites.titleshows in the browser tab and in social previews.logoLabelis the text in the header next to the home link. Keep it short — it sits in a 52px bar.
The other fields can wait.
Know where things live#
The starter keeps the public surface small. Most changes happen in one of these places:
src/ assets/ Demo images components/ Astro components content/blog/ Markdown and MDX posts layouts/ Shared layouts pages/ Routes scripts/ Client-side behavior styles/ Tokens, prose, page, layout, and shared behavior CSS ui.ts Shared UI labels
LICENSE License and third-party noticesUse astro-theme-config.ts first. Reach into src/styles/ for site-level styles, prose, page layouts, and shared behavior. Reach into src/components/ when component structure or component-owned styles need to change.
Decide what the header shows#
nav is empty by default. The logo links home, the theme toggle sits on the right, and that is it.
If you want header links:
nav: [ { label: 'Blog', href: '/blog' }, { label: 'About', href: '/about' },],Footer links live in footerNav and stay visible regardless. A quiet header with a useful footer is a fine combination.
Write the first post#
Posts live in src/content/blog/. The filename becomes the URL slug.
Create src/content/blog/hello.md:
---title: 'Hello'description: 'A first post to test the layout.'pubDate: '2026-05-01'category: 'Notes'---
This is the first paragraph. Start with a concrete note, a small decision, or one thing you want to remember.Required: title, description, pubDate. Everything else is optional.
draft: truekeeps the post out of the build, the RSS feed, and the search index.categorypowers the filter row on/blog. Pick fromconfig.content.categoryOrderor add a new one.heroImageis a relative path to a file insidesrc/assets/. It feeds cards, social metadata, and structured data; place the image in the Markdown body too when the post should show it inline.homeHeroOrder: 1pins a post into one of the two compact links at the top of the home page. Lower numbers appear first; unpinned posts fill any empty slots by publish date.homeFeatured: truepins one post to the large feature card on the home page.homeOrder: 1pins a post into the home page grid. Lower numbers appear first; unpinned posts fill any empty slots by publish date.focusEffect: 'scroll-dark'enables the optional scroll dark effect for that post. It turns on after the reader passes roughly the first 20% of the article body and restores the previous theme near the top. The trigger point is set by the theme; it is not section-specific.
Replace the samples#
The starter ships with sample posts to exercise the layout. Replace or delete them before you publish.
The fastest path:
- Keep this guide if you find it useful.
- Delete the others from
src/content/blog/. - Add three or four of your own.
The blog index, RSS, related posts, and search update on the next build.
Run the checks#
Before deploying:
npm run checknpm run buildnpm run previewcheck runs Astro’s type checks. build writes the static site and the Pagefind search index to dist/. preview serves the built output so you can click through it once.
If check fails, fix it before deploying. Type errors in the starter usually point at a missing field in astro-theme-config.ts.
Deploy#
Tone builds to dist/. Most hosts only need:
| Setting | Value |
|---|---|
| Build command | npm run build |
| Output directory | dist |
| Node | 22.12 or newer |
Vercel, Netlify, and Cloudflare Pages all detect Astro automatically. Import the repository, accept the defaults, deploy.
After the first live deploy, set site.url in astro-theme-config.ts to the real domain and redeploy. Canonical links, RSS, sitemap, and social previews all depend on it.
If you deploy under a subpath such as username.github.io/repo, set site.base in astro-theme-config.ts before publishing. The Astro config reads that value for you.
The bundled GitHub Pages workflow sets ASTRO_SITE_URL and ASTRO_SITE_BASE automatically for project pages. For example, a repository named my-blog deploys with /my-blog; a user site repository named username.github.io deploys at the domain root.
Enable comments (optional)#
Comments are off by default. To turn on giscus:
- Visit
https://giscus.appand pick a repository with Discussions enabled. - Copy the four values it generates (
repo,repoId,category,categoryId) intoconfig.comments.giscus. - Set
config.comments.modetogiscusfor the original widget, orgiscus-customfor the Tone-styled widget.
The component renders nothing until all four values are present. There is no half-enabled state.
What to read next#
- Markdown You Will Actually Use — the prose styles in one page.
- Change the Look in One File — color, spacing, type.
- When to Reach for MDX — using an Astro component inside a post.