set up an astro blog in 2026


what’s new in astro 7

astro 7 brought some significant changes. if you haven’t looked at astro since v4 or v5, here’s what you missed:

fonts API

astro now has a built-in fonts API. no more manual @font-face or third-party font loading solutions:

// astro.config.mjs
import { defineConfig, fontProviders } from 'astro/config';

export default defineConfig({
  fonts: [
    {
      provider: fontProviders.local(),
      name: 'Atkinson',
      cssVariable: '--font-atkinson',
      options: {
        variants: [
          { src: ['./src/assets/fonts/atkinson-regular.woff'], weight: 400 },
        ],
      },
    },
  ],
});

content collections v3

the content layer API is stable now. loading content is simpler:

import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';

const blog = defineCollection({
  loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
  schema: z.object({
    title: z.string(),
    pubDate: z.coerce.date(),
  }),
});

cloudflare adapter

@astrojs/cloudflare works great with the latest astro. just wire it in:

import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  adapter: cloudflare({ mode: 'directory' }),
});

why i chose this stack

  • zero cost — cloudflare pages free plan covers a lot
  • fast — static-first, CDN-distributed
  • maintainable — markdown content, git-tracked
  • AI-friendly — opencode can manage everything from content to deployment

that’s the stack running this very blog. nothing fancy, just works.