How to create a new page

Every page in src/pages/ becomes a page on your website. See the existing page such as index.mdx for reference.

How page names become URLs

File Website address
src/pages/index.mdx /
src/pages/about.mdx /about
src/pages/services.mdx /services
src/pages/team/alex.mdx /team/alex

Use lowercase filenames with hyphens, such as work-with-me.mdx.

Create an MDX page

Use MDX when your page is mostly text, headings, lists, images, and a few components.

Create src/pages/services.mdx:

---
layout: ../layouts/PageLayout.astro
title: Services
description: Learn about the services I offer.
---

import Button from "../components/Button.astro";

# Services

I help people create simple and useful websites.

## Website design

Add a short description of your service here.

<Button href="/contact">Contact me</Button>

You can now visit /services.

The beginning part between the --- lines is called frontmatter:

  • layout adds the shared header, footer, page styles, and page information.
  • title is the title shown in the browser and search results.
  • description is a short summary of the page.
  • topSpacing is optional. Set it to false when the page’s first component provides its own top spacing.

Imports go below the frontmatter and before the component is used.

Create an Astro page

This template allows you to create all your pages using Markdown / .mdx.

If, for some reason, you do want to create pages using .astro files you can:

For a custom .astro page, wrap the content in BaseLayout and provide one main element with id="main-content" and tabindex="-1":

---
import BaseLayout from "../layouts/BaseLayout.astro";
---

<BaseLayout title="Services" description="Learn about the services I offer.">
    <main
        id="main-content"
        tabindex="-1"
        class="base-layout base-layout-content height-smart-fill-screen padding-top-xl padding-bottom-2xl"
    >
        <h1>Services</h1>
        <p>I help people create simple and useful websites.</p>
    </main>
</BaseLayout>

The shared skip link targets #main-content. The negative tabindex lets the main element receive focus without adding it to the normal Tab order. MDX pages using PageLayout and blog posts using BlogPostLayout already receive this main element from their layouts; do not add another one.

Create a blog post

Regular pages go in src/pages/. Blog posts go in src/content/blog/.

Create a file such as src/content/blog/my-first-post.mdx:

---
title: My first post
description: A short introduction to my first blog post.
pubDate: 2026-08-01
---

## My first section

Write your post here.

The post will appear at /blog/my-first-post. Start blog post sections with ## because the blog layout already shows the post title as the main heading.

Keep blog post files directly inside src/content/blog/.

Blog posts also support two optional frontmatter fields:

updateDate: 2026-08-15
draft: true

updateDate records when the post was last changed and defaults to pubDate. Set draft to true to preview a post during development without including its page, listing entry, RSS entry, or social image in a production build.

Add page-specific head information

The shared layouts include a head slot for unusual page-specific tags:

<Fragment slot="head">
    <meta name="category" content="events" />
</Fragment>

Most pages do not need this. Use the existing title, description, canonical, social image, and robots options before adding tags by hand.

Before you publish

Check that:

  1. The filename creates the URL you want.
  2. The title and description explain the page clearly.
  3. The page has one main # or <h1> heading.
  4. Links do not end with a slash.
  5. The page is in the menu if visitors need it there.
  6. Images have useful alternative text.