[Astro] Installation and Project Setup

2026-03-25 hit count image

Sharing how to install Astro and set up a blog project. Covers astro.config.mjs configuration, directory structure, SCSS setup, build scripts, and more.

astro

Overview

In the previous post Why I Migrated from Jekyll to Astro, I shared the background behind moving from Jekyll to Astro. In this post, I’ll explain step by step how to actually install Astro and set up a blog project.

Prerequisites

Since Astro is Node.js-based, you need to have Node.js installed first.

Installing Node.js

Install the LTS version from the Node.js official website. Using nvm (Node Version Manager) makes it easy to manage multiple versions.

# Install Node.js with nvm
nvm install --lts
nvm use --lts

# Check versions
node -v
npm -v

Creating a .nvmrc file in the project root lets you keep the Node.js version consistent across team members.

Creating an Astro Project

Astro provides an official CLI tool to quickly create projects.

npm create astro@latest

Follow the CLI prompts to select a project name, template, and more. I recommend starting with an empty project (Empty), since designing the blog structure from scratch helps you better understand the project.

# Navigate to the project after creation
cd my-blog

# Install dependencies
npm install

# Start the development server
npm run dev

Once the dev server starts, you can view the site at http://localhost:4321. Thanks to Vite-based HMR, changes to files are instantly reflected in the browser.

Project Directory Structure

The directory structure of this blog project is as follows:

/
├── public/                  # Static files (images, robots.txt, etc.)
│   ├── assets/
│   │   └── images/
│   ├── robots.txt
│   ├── ads.txt
│   ├── CNAME
│   └── .nojekyll
├── src/
│   ├── components/          # Reusable Astro components
│   │   ├── Head.astro
│   │   ├── Navbar.astro
│   │   ├── Footer.astro
│   │   ├── Breadcrumbs.astro
│   │   ├── Comments.astro
│   │   ├── SearchBar.astro
│   │   ├── SearchPage.astro
│   │   ├── Pagination.astro
│   │   ├── CategoryCard.astro
│   │   ├── PostCard.astro
│   │   └── ads/             # Ad components
│   ├── content/             # Blog posts (Content Collections)
│   │   ├── astro/
│   │   ├── react/
│   │   ├── jekyll/
│   │   └── ...
│   ├── data/                # Static data
│   │   └── categories.ts
│   ├── i18n/                # Multilingual translations
│   │   └── translations.ts
│   ├── layouts/             # Layout templates
│   │   ├── BaseLayout.astro
│   │   └── PostLayout.astro
│   ├── pages/               # Route pages
│   │   ├── [...path].astro  # Japanese (default)
│   │   ├── ko/              # Korean
│   │   └── en/              # English
│   ├── plugins/             # Custom rehype plugins
│   │   ├── rehype-picture.mjs
│   │   └── rehype-in-feed-ads.mjs
│   └── styles/              # Global styles
│       └── global.scss
├── scripts/                 # Build/deploy scripts
│   └── share.mjs
├── astro.config.mjs         # Astro configuration
├── package.json
└── tsconfig.json

Key Directory Descriptions

Here’s a closer look at the key directories:

DirectoryRole
public/Static files copied as-is during build. Images, fonts, verification files, etc.
src/components/Reusable .astro components. Head, Navbar, Footer, etc.
src/content/Markdown blog posts managed by Content Collections
src/data/Static data like category definitions
src/i18n/Multilingual translations and helper functions
src/layouts/Page layout templates
src/pages/File-based routing. Directory structure maps directly to URL structure
src/plugins/Custom rehype/remark markdown processing plugins
src/styles/Global SCSS styles

astro.config.mjs Configuration

This is Astro’s core configuration file. Let’s look at the actual configuration used in this blog.

// @ts-check
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
import rehypeExternalLinks from 'rehype-external-links';
import rehypeCallouts from 'rehype-callouts';
import rehypeInFeedAds from './src/plugins/rehype-in-feed-ads.mjs';
import rehypePicture from './src/plugins/rehype-picture.mjs';

export default defineConfig({
  site: 'https://deku.posstree.com',
  output: 'static',
  build: {
    inlineStylesheets: 'always',
  },
  trailingSlash: 'always',
  integrations: [
    sitemap({
      serialize(item) {
        item.lastmod = new Date();
        return item;
      },
      i18n: {
        defaultLocale: 'ja',
        locales: {
          ja: 'ja',
          ko: 'ko',
          en: 'en',
        },
      },
    }),
  ],
  markdown: {
    shikiConfig: {
      theme: 'material-theme-darker',
    },
    rehypePlugins: [
      [rehypeCallouts, { theme: 'github' }],
      [
        rehypeExternalLinks,
        { target: '_blank', rel: ['nofollow', 'noreferrer'] },
      ],
      rehypeInFeedAds,
      [
        rehypePicture,
        { publicDir: new URL('./public', import.meta.url).pathname },
      ],
    ],
  },
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          silenceDeprecations: ['import', 'global-builtin', 'color-functions'],
        },
      },
    },
  },
});

Key Configuration Items

site

site: 'https://deku.posstree.com',

The final deployment URL of the site. Used for sitemap generation, canonical URLs, OG tags, and more.

output

output: 'static',

Builds as a static site. This must be set to 'static' for deploying to GitHub Pages.

build.inlineStylesheets

build: {
  inlineStylesheets: 'always',
},

Includes all CSS inline in the HTML. This reduces separate CSS file requests and improves initial load speed.

trailingSlash

trailingSlash: 'always',

Ensures all URLs end with /. So it becomes /astro/installation/ instead of /astro/installation. This was configured to maintain the URL format used in Jekyll.

integrations

integrations: [
  sitemap({ ... }),
],

Automatically generates a multilingual sitemap with the @astrojs/sitemap plugin. Details are covered in the SEO Implementation post.

markdown

Configuration for markdown processing.

  • shikiConfig: Uses the material-theme-darker theme for code block syntax highlighting
  • rehypePlugins: Plugins applied when converting markdown to HTML
    • rehype-callouts: Supports GitHub-style callout blocks
    • rehype-external-links: Automatically adds target="_blank", rel="nofollow noreferrer" to external links
    • rehype-in-feed-ads: Converts <!-- ad --> comments in markdown to ad blocks
    • rehype-picture: Automatically converts images to <picture> elements with AVIF/WebP formats

package.json Scripts

Here are the npm scripts used in the blog project.

{
  "name": "deku-blog",
  "type": "module",
  "version": "1.0.0",
  "scripts": {
    "dev": "astro dev",
    "build": "astro build && npx pagefind --site dist",
    "prepreview": "npm run build",
    "preview": "astro preview",
    "predeploy": "npm run share:sync",
    "deploy": "gh-pages -d dist -r git@personal:posstree/deku.posstree.com.git -t"
  },
  "dependencies": {
    "@astrojs/rss": "^4.0.0",
    "@astrojs/sitemap": "^3.3.0",
    "astro": "^5.17.1",
    "rehype-callouts": "^2.1.2",
    "rehype-external-links": "^3.0.0",
    "sass": "^1.80.0",
    "sharp": "^0.33.0"
  },
  "devDependencies": {
    "dotenv": "^16.6.1",
    "gh-pages": "^6.3.0",
    "pagefind": "^1.4.0"
  }
}

Key Script Descriptions

Here are the main functions of each script:

ScriptDescription
npm run devStart dev server. Instantly reflects changes with HMR
npm run buildProduction build + Pagefind search index generation
npm run previewPreview the built site locally
npm run deployDeploy to GitHub Pages

The key point in the build script is running npx pagefind --site dist after astro build. Since Pagefind analyzes the built HTML files to generate search indexes, it must be run after the build.

Key Dependency Descriptions

Here are the main packages used in the Astro project and their roles:

PackageRole
astroCore framework
@astrojs/sitemapAutomatic multilingual sitemap generation
@astrojs/rssRSS feed generation
sassSCSS preprocessor
sharpImage conversion (AVIF/WebP)
rehype-calloutsGitHub-style callouts
rehype-external-linksExternal link handling
gh-pagesGitHub Pages deployment
pagefindStatic search

SCSS Setup

This blog uses SCSS for style management. Since Astro has Vite built in, you can use SCSS with no additional configuration — just install the sass package.

npm install sass

However, if you’re using features deprecated in the latest version of Sass, warnings may occur. You can suppress these in the vite configuration of astro.config.mjs.

vite: {
  css: {
    preprocessorOptions: {
      scss: {
        silenceDeprecations: ['import', 'global-builtin', 'color-functions'],
      },
    },
  },
},

Global styles are managed in src/styles/global.scss and imported in the layout component.

---
// BaseLayout.astro
import '../styles/global.scss';
---

Conclusion

In this post, we looked at installing and setting up an Astro project. To summarize:

  • Create a project with npm create astro@latest
  • Configure site URL, static build, sitemap, and markdown plugins in astro.config.mjs
  • Set up build, dev, and deploy scripts in package.json
  • Configure SCSS and handle deprecation warnings

In the next post Content Collections and Markdown Migration, we’ll cover how to migrate Jekyll’s markdown files to Astro’s Content Collections.

Series Guide

This post is part of the Jekyll to Astro migration series.

  1. Why I Migrated from Jekyll to Astro
  2. Astro Installation and Project Setup
  3. Content Collections and Markdown Migration
  4. Multilingual (i18n) Implementation
  5. SEO Implementation
  6. Image Optimization — Custom rehype Plugin
  7. Comment System (Utterances)
  8. Ad Integration (Google AdSense)
  9. Search Implementation with Pagefind
  10. Layout and Component Architecture
  11. GitHub Pages Deployment
  12. Social Share Automation Script
  13. Troubleshooting and Tips

Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!

App promotion

You can use the applications that are created by this blog writer Deku.
Deku created the applications with Flutter.

If you have interested, please try to download them for free.



SHARE
Twitter Facebook RSS