Astro, Themes, GitHub Pages 배포, 그리고 Plugins
Table of contents
Open Table of contents
Astro
올인원 웹 프레임워크
Content driven (Islands), UI agnostic, Server first, Zero JS, ..
v5.9.2 (2024.12-)
Install
Requirements
- node 18.17.1/20.3.0/22.0.0+
- Astro - VS Code extension, https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode
npm create astro@latest
> Need to install the following packages: create-astro@4.12.1
> Where should we create your new project?
> How would you like to start your new project?
> -- A basic, helpful starter project | Use blog template | Use docs (Starlight) template | Use minimal (empty) template
> Install dependencies?
> Initialize a new git repository?
npm run dev
> http://localhost:4321
Instructions
├── public/
├── src/
│ ├── components/
│ ├── content/
│ ├── layouts/
│ ├── styles/
│ └── pages/
│ └── index.astro
├── astro.config.mjs
├── package-lock.json
├── package.json
└── tsconfig.json
Deploy to GitHub Pages
https://docs.astro.build/en/guides/deploy/github/
- Set the site and base
import { defineConfig } from "astro/config";
export default defineConfig({
site: "https://username.github.io", // 혹은 사용자 정의 도메인
base: "/", // 루트 혹은 username.github.io 경우 비워둔다, 루트를 별도로 처리해야 할 경우 '/repository'
});
astro.config.mjs
- Configure GitHub Actions
https://github.com/withastro/action/blob/main/README.md → repository/ Settings/ Code and automaiton - Pages/ Build and deployment/ GitHub Actions → .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
# Trigger the workflow every time you push to the `main` branch
# Using a different branch name? Replace `main` with your branch’s name
push:
branches: [main]
# Allows you to run this workflow manually from the Actions tab on GitHub.
workflow_dispatch:
# Allow this job to clone the repo and create a page deployment
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout your repository using git
uses: actions/checkout@v4
- name: Install, build, and upload your site output
uses: withastro/action@v4
# with:
# path: . # The root location of your Astro project inside the repository. (optional)
# node-version: 22 # The specific version of Node that should be used to build your site. Defaults to 22. (optional)
# package-manager: pnpm@latest # The Node package manager that should be used to install dependencies and build your site. Automatically detected based on your lockfile. (optional)
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
.github/workflows/deploy.yml
Creating pages and posts
Astro는 파일 기반 라우팅을 한다. src/pages/
의 각 파일은 사이트의 endpoint가 된다.
├── src/
│ └── pages/
│ ├── index.astro
│ ├── about.astro
│ └── posts/
│ └── post.md
.astro 파일
- 페이지, UI 컴포넌트, 레이아웃 등으로 사용할 수 있다.
- frontmatter script는 JavaScript로 작성한다.
- HTML의 상위집합이다.
- 컴포넌트 구문은 React, Svelte, Vue와 같은 유용한 기능도 결합되어 있다. — kebab-case, Template directives, slot 등 차이
.md 파일
- 콘텐츠를 작성한다.
---
title:
description:
pubDate: YYYY-MM-DD
author:
image:
url:
alt:
tags: []
---
<!--- 이하 본문 --->
posts/post.md
Themes
다음 테마들을 추천한다.
Astro Paper
https://github.com/satnaing/astro-paper
Stack : astro, tailwindcss, astro-icon, dayjs, lodash.kebabcase, satori, sharp, pagefind
Install
pnpm create astro@latest --template satnaing/astro-paper
# or
git clone https://github.com/satnaing/astro-paper.git
cd astro-paper
pnpm install
# Warning
# Ignored build scripts: esbuild, sharp.
# Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.
pnpm approve-builds
pnpm run dev
Instructions
astro-paper/
├── .github/workflows/
│ └── ci.yml
├── public/
├── src/
│ ├── assets/
│ │ └── icons/
│ │ └── images/
│ ├── components/
│ ├── data/blog/
│ │ └── some-posts.md
│ ├── layouts/
│ ├── pages/
│ │ └── index.astro
│ ├── styles/
│ ├── utils/
│ ├── config.ts
│ ├── constants.ts
│ └── content.config.ts
├── astro.config.mjs
├── package-lock.json
├── package.json
└── tsconfig.json
Set the SITE and SOCIALS
export const SITE = {
website: "https://username.github.io", // replace this with your deployed domain
author: "Full Name",
profile: "https://github.com/username",
desc: "",
title: "",
ogImage: "", // public/og.jpg
lightAndDarkMode: true,
postPerIndex: 4, // view in Home - Recent section
postPerPage: 10,
scheduledPostMargin: 15 * 60 * 1000, // 15 minutes
showArchives: true,
showBackButton: true, // show back button in post detail
editPost: {
enabled: true, // 게시물 제목아래 편집링크 제공 여부
text: "Suggest Changes",
url: "https://github.com/owner/username.github.io/edit/main/",
},
dynamicOgImage: true,
lang: "ko", // html lang code. Set this empty and default will be "en"
timezone: "Asia/Seoul", // Default global timezone (IANA format) https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
} as const;
src/config.ts
export const SOCIALS = [
{
name: "Github",
href: "https://github.com/username",
linkTitle: ` ${SITE.title} on Github`,
icon: IconGitHub,
},
// ...
] as const;
src/constants.ts
Configure GitHub Actions
name: CI
on:
pull_request:
types:
- opened
- edited
- synchronize
- reopened
workflow_call:
jobs:
build:
name: Code standards & build
runs-on: ubuntu-latest
timeout-minutes: 3
strategy:
matrix:
node-version: [22]
steps:
- name: "☁️ Checkout repository"
uses: actions/checkout@v4
- name: "📦 Install pnpm"
uses: pnpm/action-setup@v4
with:
version: 10
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "pnpm"
- name: "📦 Install dependencies"
run: pnpm install
- name: "🔎 Lint code"
run: pnpm run lint
- name: "📝 Checking code format"
run: pnpm run format:check
- name: "🚀 Build the project"
run: pnpm run build
.github/workflows/ci.yml
https://github.com/withastro/action/blob/main/README.md
# ...
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout your repository using git
uses: actions/checkout@v4
- name: Install, build, and upload your site output
uses: withastro/action@v4
with:
# path: . # The root location of your Astro project inside the repository. (optional)
# node-version: 22 # The specific version of Node that should be used to build your site. Defaults to 22. (optional)
package-manager: pnpm@latest # The Node package manager that should be used to install dependencies and build your site. Automatically detected based on your lockfile. (optional)
# ...
.github/workflows/deploy.yml
Creating posts
src/data/blog/
- 새 글(.md)을 작성한다.
- 하위에
_dir/
를 만들어 글들을 묶어 정리해 둘 수 있다. URL에 반영되지 않는다.
---
title:
description:
pubDate: YYYY-MM-DDThh:mm:ss+09 # (ISO 8601형식 중 구분자(-,:)와 ss 필수)
modDatetime:
slug:
author:
tags: []
draft:
image:
url:
alt:
ogImage:
featured:
canonicalURL:
hideEditPost:
timezone: # 콘텐츠내 시간대 -- new Date().toISOString()
---
<!--- 이하 본문 --->
Update template and dependencies
# Updating AstroPaper template
# 새로운 원격(테마)저장소를 추가하고 업데이트용 로컬브랜치로 이동
git remote add astro-paper https://github.com/satnaing/astro-paper.git
git remote -v
git checkout -b update/astro-paper
# 다음 두가지 방식이 있다.
# 1. merge 방식: 단 한 번의 충돌 해결을 선호할 때 (git config pull.rebase false)
# 원격 테마의 최신 변경사항을 update/astro-paper 브랜치로 가져올 때, 모든 변경사항을 하나의 병합커밋(merge commit)으로 통합한다.
# 다만, 히스토리에 병합 커밋이 자주 생성되어 git log가 다소 복잡해 보일 수 있다.
git pull astro-paper main
# fatal: refusing to merge unrelated histories (최초 병합시)
git pull astro-paper main --allow-unrelated-histories
# fatal: Need to specify how to reconcile divergent branches. Need to specify --no-rebase
git pull astro-paper main --no-rebase
# conflict 해결 후 커밋
git status
> On branch update/astro-paper
> You have unmerged paths.
> Unmerged paths:
> both modified: src/styles/base.css
git add .
git commit -m "Resolve merge conflicts with astro-paper main update"
# 2. rebase + squash: 깔끔한 선형 히스토리를 선호할 때 (git config pull.rebase true)
# 원격 브랜치의 최신 커밋들 위에 로컬 커밋들을 하나씩 순서대로 적용하므로, 충돌은 여러 번일 수 있다.
# 여기에 단 한 번의 충돌 해결을 원한다면, 다음 명령으로 update/astro-paper의 모든 로컬 커밋들을 미리 하나의 커밋으로 합쳐둔(squash)후 진행한다. (main 커밋들은 영향받지 않는다!)
git reset --soft $(git rev-list --max-parents=0 HEAD) && git commit --amend --no-edit
git pull astro-paper main --rebase
# 각 커밋별 변경사항 확인, conflict 해결 후 계속
> Auto-merging .github/workflows/ci.yml
> Auto-merging src/constants.ts
> CONFLICT (content): Merge conflict in src/constants.ts
> error: could not apply 4daa336... Initial commit
> hint: Resolve all conflicts manually, mark them as resolved with
> hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
> hint: You can instead skip this commit: run "git rebase --skip".
> hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
> hint: Disable this message with "git config set advice.mergeConflict false"
git add .
git rebase --continue
> fatal: no rebase in progress
git status
> On branch update/astro-paper
> nothing to commit, working tree clean
# 로컬 main으로 병합
git checkout main
git pull origin main
git merge update/astro-paper
git status
> On branch main
> Your branch is ahead of 'origin/main' by 40 commits.
> (use "git push" to publish your local commits)
git push origin main
# 원격(테마)저장소, 업데이트용 로컬브랜치 삭제
git branch -d update/astro-paper
git remote remove astro-paper
git remote -v
Updating Package Dependencies — 테마의 package, lock을 우선시 하자.
# Updating Package Dependencies
npm install -g npm-check-updates
ncu
ncu -i --target patch
ncu -i
Issues
- 외부 링크에 대해 내부 링크로 처리되는 문제
<body>
<slot />
<script is:inline data-astro-rerun>
/* 외부링크를 _blank로 열도록 처리 */
// DOM이 로드된 후에 스크립트가 실행되도록 보장하고
// astro 파일이라 그런가 -- (X) DOMContentLoaded, (O) data-astro-rerun | astro:page-load
// document.addEventListener("astro:page-load", () => {
// 문서 내의 모든 <a> 태그(링크)를 배열로 변환
Array.from(document.links)
.filter(link => {
const href = link.getAttribute("href");
// 현재 호스트네임과 다르면서 호스트네임이 비어있지 않고,
// href가 없거나 '#'으로 시작하는 앵커 링크가 아닌 경우만 필터링
return (
link.hostname !== window.location.hostname &&
link.hostname !== "" &&
(!href || !href.startsWith("#"))
);
})
// 필터링된 각 외부 링크에 대해 다음 작업을 수행
.forEach(link => {
link.target = "_blank";
link.rel = "noopener noreferrer"; // 보안 취약점(Tabnabbing)을 방지
});
// });
</script>
</body>
src/layouts/Layout.astro
Plugins
Giscus
https://github.com/giscus/giscus/blob/main/README.ko.md
오픈 소스 또는 내부 프로젝트에 대한 커뮤니티를 위한 협업 커뮤니케이션 포럼
- GitHub 공개저장소
- Giscus GitHub App 설치 — https://github.com/apps/giscus
- 저장소내 토론 활성화 (repository/ Settings/ General/ Features - [v] Discussions) 및 새 카테고리 생성 (Discussioins/ Categories/ Edit/ New category/ Comments (Announcement 형식))
- https://giscus.app/ API 설정
<Layout {...layoutProps}>
<main>
<ShareLinks />
<!-- Comments 스크립트 추가 -->
<script
src="https://giscus.app/client.js"
data-repo="owner/username.github.io"
data-repo-id="R_kgDOOrIEX.."
data-category="Comments"
data-category-id="DIC_kwDOOrIEXs4.."
data-mapping="pathname"
data-strict="1"
data-reactions-enabled="1"
data-emit-metadata="1"
data-input-position="bottom"
data-theme="preferred_color_scheme"
data-lang="ko"
data-loading="lazy"
crossorigin="anonymous"
async></script>
</main>
<Footer />
</Layout>
src/layouts/PostDetails.astro
- React component with light/dark theme (테마 토글버튼으로 테마 변경시 Giscus 테마도 변경), https://astro-paper.pages.dev/posts/how-to-integrate-giscus-comments/#react-component-with-lightdark-theme
ref.
- Erison Silva, Update frontend theme using git, 2025.6, https://blog.erison.work/posts/update-frontend-theme-using-git/#convert-all-commits-into-one