# Hwaro Fast and lightweight static site generator built with Crystal Base URL: https://hwaro.hahwul.com This is documentation for Hwaro, an open-source static site generator. Content is provided under the MIT license. --- Title: Hwaro Documentation URL: https://hwaro.hahwul.com/ Source: content/index.md Hwaro(화로) is a fast, lightweight static site generator built with Crystal. --- Title: Deploy URL: https://hwaro.hahwul.com/deploy/ Source: content/deploy/_index.md Deploy your Hwaro site to any static hosting provider. ## Build for Production ```bash hwaro build ``` This generates static files in `public/`. You can optionally minify output: ```bash hwaro build --minify ``` This performs conservative optimization — HTML comments and trailing whitespace are removed, JSON/XML whitespace is compacted. All code blocks and content structure are preserved. ## General Steps 1. Build the site: `hwaro build` 2. Upload `public/` directory to your host (or use `hwaro deploy`) 3. Configure your domain ## Built-in Deploy Command Hwaro includes `hwaro deploy` for deploying to configured targets: ```bash hwaro deploy # Deploy to default target hwaro deploy --target s3 # Deploy to specific target hwaro deploy --dry-run # Preview changes ``` See [Deploy Configuration](/deploy/config/) for full target setup, matchers, and options. ## Platform Guides See the platform-specific guides below for step-by-step deployment instructions. --- Title: Cloudflare Pages URL: https://hwaro.hahwul.com/deploy/cloudflare-pages/ Source: content/deploy/cloudflare-pages/index.md Deploy your Hwaro site to Cloudflare Pages for fast global delivery. ## Quick Start ### Generate Config ```bash hwaro tool platform cloudflare ``` This creates a `wrangler.toml` with project settings and site bucket configuration. ### Deploy via Dashboard 1. Go to [Cloudflare Dashboard](https://dash.cloudflare.com) > **Workers & Pages** 2. Click **Create application** > **Pages** > **Connect to Git** 3. Select your repository 4. Set build configuration: - **Build command**: `hwaro build` - **Build output directory**: `public` 5. Click **Save and Deploy** ### Deploy via Wrangler CLI ```bash # Install Wrangler npm install -g wrangler # Build the site hwaro build # Deploy wrangler pages deploy public --project-name my-site ``` ## Manual Configuration If you prefer to configure manually, set these in the Cloudflare Pages dashboard: | Setting | Value | |---------|-------| | Build command | `hwaro build` | | Build output directory | `public` | Or create `wrangler.toml`: ```toml name = "my-site" compatibility_date = "2024-01-01" # Use current date when deploying [site] bucket = "./public" ``` ## Redirects Cloudflare Pages uses a `_redirects` file in the output directory. Create `static/_redirects` with redirect rules for your page aliases: ``` /old-url/ /posts/new-post/ 301 /legacy/post/ /posts/new-post/ 301 ``` Aliases are defined in page frontmatter: ```markdown --- title: New Post aliases: - /old-url/ - /legacy/post/ --- ``` When using `hwaro tool platform cloudflare`, the generated `wrangler.toml` includes comments listing these redirects so you can copy them into `static/_redirects`. ## Custom Domain 1. Go to **Workers & Pages** > your project > **Custom domains** 2. Click **Set up a custom domain** 3. Follow DNS configuration instructions 4. Update `base_url` in `config.toml`: ```toml base_url = "https://www.yourdomain.com" ``` ## Preview Deployments Cloudflare Pages automatically creates preview deployments for every branch push. Preview URLs follow the pattern: `..pages.dev`. ## See Also - [Platform Config Generator](/start/tools/platform/) — Detailed generator options - [CLI Reference](/start/cli/#tool) — All tool commands - Other platforms: [Netlify](/deploy/netlify/) | [Vercel](/deploy/vercel/) | [GitHub Pages](/deploy/github-pages/) --- Title: Deploy Configuration URL: https://hwaro.hahwul.com/deploy/config/ Source: content/deploy/config.md Configure deployment targets for the `hwaro deploy` command in `config.toml`. ## Global Options ```toml [deployment] target = "prod" source_dir = "public" confirm = false dry_run = false max_deletes = 256 workers = 10 ``` | Key | Type | Default | Description | |-----|------|---------|-------------| | target | string | — | Default target name to deploy to | | source_dir | string | "public" | Directory containing the built site | | confirm | bool | false | Prompt for confirmation before deploying | | dry_run | bool | false | Show what would be deployed without making changes | | force | bool | false | Force deployment even if no changes detected | | max_deletes | int | 256 | Safety limit on file deletions (-1 disables the limit) | | workers | int | 10 | Number of concurrent workers | ## Targets Define one or more deployment targets: ```toml [[deployment.targets]] name = "prod" url = "file:///var/www/mysite" [[deployment.targets]] name = "s3" url = "s3://my-bucket" # Auto-generates: aws s3 sync {source}/ s3://my-bucket --delete [[deployment.targets]] name = "custom" url = "s3://my-bucket" command = "aws s3 sync {source}/ {url} --delete --exclude '.git/*'" # Custom command overrides auto-generation ``` **Auto-generated commands by URL scheme:** | Scheme | Command | Requires | |--------|---------|----------| | `file://` | Built-in directory sync | — | | `s3://` | `aws s3 sync {source}/ {url} --delete` | AWS CLI | | `gs://` | `gsutil -m rsync -r -d {source}/ {url}` | Google Cloud SDK | | `az://` | `az storage blob sync --source {source} --container {url}` | Azure CLI | If a `command` field is set, it always takes priority over auto-generation. | Key | Type | Default | Description | |-----|------|---------|-------------| | name | string | — | Target identifier | | url | string | — | Destination URL (`file://`, `s3://`, `gs://`, `az://`) | | include | string | — | Glob pattern for files to include | | exclude | string | — | Glob pattern for files to exclude | | strip_index_html | bool | false | Remove `index.html` from URLs | | command | string | — | Custom command (overrides auto-generation) | Custom commands support placeholders: | Placeholder | Description | |-------------|-------------| | `{source}` | Source directory (default: `public`) | | `{url}` | Target URL | | `{target}` | Target name | ## Matchers Configure per-file deployment settings using pattern matchers: ```toml [[deployment.matchers]] pattern = "^.+\\.css$" cache_control = "max-age=31536000" gzip = true [[deployment.matchers]] pattern = "^.+\\.html$" cache_control = "max-age=3600" gzip = true ``` | Key | Type | Default | Description | |-----|------|---------|-------------| | pattern | string | — | Regex pattern to match file paths | | cache_control | string | — | Cache-Control header value | | content_type | string | — | Override Content-Type header | | gzip | bool | false | Gzip compress matched files | | force | bool | false | Always upload matched files | ## See Also - [CLI Reference](/start/cli/) — All deploy command-line options - [Features: Deployment](/features/deployment/) — Quick overview --- Title: Docker URL: https://hwaro.hahwul.com/deploy/docker/ Source: content/deploy/docker/index.md Deploy your Hwaro site using Docker. ## Official Image The official Docker image is available at `ghcr.io/hahwul/hwaro`. ```bash docker pull ghcr.io/hahwul/hwaro:latest ``` ## Multi-stage Build You can use a multi-stage build to compile your site and serve it with a lightweight web server like Nginx. Create a `Dockerfile` in your project root: ```dockerfile # Stage 1: Build the site FROM ghcr.io/hahwul/hwaro:latest AS builder WORKDIR /site COPY . . # Build the site RUN hwaro build # Stage 2: Serve with Nginx FROM nginx:alpine # Copy built assets from builder stage COPY --from=builder /site/public /usr/share/nginx/html # Expose port 80 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` ### Build and Run ```bash # Build the image docker build -t my-hwaro-site . # Run the container docker run -d -p 8080:80 my-hwaro-site ``` Visit `http://localhost:8080` to see your site. ## CLI Usage You can run Hwaro commands directly using the Docker image without installing Crystal or Hwaro locally. ```bash # Build the site docker run --rm -v $(pwd):/site -w /site ghcr.io/hahwul/hwaro build # Interactive shell docker run --rm -it -v $(pwd):/site -w /site ghcr.io/hahwul/hwaro /bin/sh ``` ## See Also - [Deploy Configuration](/deploy/config/) — Target setup and matchers - [CLI Reference](/start/cli/) — All build/deploy options - Other platforms: [GitHub Pages](/deploy/github-pages/) | [Netlify](/deploy/netlify/) | [Vercel](/deploy/vercel/) --- Title: GitHub Pages URL: https://hwaro.hahwul.com/deploy/github-pages/ Source: content/deploy/github-pages/index.md Deploy your Hwaro site to GitHub Pages for free hosting. ## Prerequisites - GitHub repository - Hwaro site ready to build ## Method 1: GitHub Actions (Recommended) Use the official [`hahwul/hwaro`](https://github.com/hahwul/hwaro) action to build and deploy without installing Hwaro manually. ### Create Workflow You can auto-generate the workflow file using: ```bash hwaro tool platform github-pages ``` Or create `.github/workflows/deploy.yml` manually: ```yaml --- name: Hwaro CI/CD on: push: branches: [main] pull_request: branches: [main] workflow_dispatch: permissions: contents: write jobs: build: runs-on: ubuntu-latest if: github.event_name == 'pull_request' steps: - name: Checkout uses: actions/checkout@v6 - name: Build Only uses: hahwul/hwaro@main with: build_only: true deploy: runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' steps: - name: Checkout uses: actions/checkout@v6 - name: Build and Deploy uses: hahwul/hwaro@main with: token: ${{ secrets.GITHUB_TOKEN }} ``` ### Action Inputs | Input | Description | Default | |-------|-------------|---------| | `build_dir` | Directory containing the Hwaro site | `.` (repository root) | | `build_only` | Only build without deploying | `false` | | `token` | GitHub token for deployment | — | If your Hwaro site is in a subdirectory (e.g., `docs/`), set `build_dir`: ```yaml - name: Build and Deploy uses: hahwul/hwaro@main with: build_dir: "docs" token: ${{ secrets.GITHUB_TOKEN }} ``` ### Configure GitHub Pages 1. Go to repository **Settings** → **Pages** 2. Under "Build and deployment", select **Deploy from a branch** 3. Choose `gh-pages` branch, `/ (root)` folder 4. Push to `main` branch to trigger deployment ### Set Base URL Update `config.toml`: ```toml # For user/org site (username.github.io) base_url = "https://username.github.io" # For project site (username.github.io/repo) base_url = "https://username.github.io/repo" ``` ## Method 2: Deploy via `hwaro deploy` Create a deploy script `scripts/deploy-ghpages.sh`: ```bash #!/bin/bash set -e SOURCE_DIR="${1:?Usage: deploy-ghpages.sh }" REMOTE_URL=$(git remote get-url origin) TMPDIR=$(mktemp -d) cp -r "$SOURCE_DIR"/. "$TMPDIR" touch "$TMPDIR/.nojekyll" cd "$TMPDIR" git init -b gh-pages git add -A git commit -m "Deploy to GitHub Pages" git push --force "$REMOTE_URL" gh-pages rm -rf "$TMPDIR" ``` ```bash chmod +x scripts/deploy-ghpages.sh ``` Add the target to `config.toml`: ```toml [[deployment.targets]] name = "github-pages" command = "scripts/deploy-ghpages.sh {source}" ``` Then build and deploy: ```bash hwaro build hwaro deploy github-pages # Preview without deploying hwaro deploy github-pages --dry-run ``` ### Configure GitHub Pages 1. Go to repository **Settings** → **Pages** 2. Under "Build and deployment", select **Deploy from a branch** 3. Choose `gh-pages` branch, `/ (root)` folder 4. Click **Save** ## Method 3: Manual Branch Deploy ```bash hwaro build # Create orphan branch git checkout --orphan gh-pages # Remove all files git rm -rf . # Copy built site cp -r public/* . # Commit and push git add . git commit -m "Deploy site" git push origin gh-pages --force # Return to main branch git checkout main ``` ## Custom Domain ### Configure DNS Add a CNAME record pointing to `username.github.io`: | Type | Name | Value | |------|------|-------| | CNAME | www | username.github.io | | A | @ | 185.199.108.153 | | A | @ | 185.199.109.153 | | A | @ | 185.199.110.153 | | A | @ | 185.199.111.153 | ### Add CNAME File Create `static/CNAME`: ``` www.yourdomain.com ``` ### Update Config ```toml base_url = "https://www.yourdomain.com" ``` ### Enable HTTPS 1. Go to repository **Settings** → **Pages** 2. Check **Enforce HTTPS** ## Troubleshooting ### 404 Errors - Check `base_url` matches your GitHub Pages URL - Ensure CNAME file is in `static/` directory - Wait a few minutes for deployment to complete ### Assets Not Loading - Verify `base_url` has no trailing slash - Check asset paths use `{{ base_url }}` prefix ### Build Failures - Review Actions logs for error messages - Check that `build_dir` points to the correct directory ## Example Repository Structure ``` my-site/ ├── .github/ │ └── workflows/ │ └── deploy.yml ├── content/ ├── templates/ ├── static/ │ └── CNAME ├── config.toml └── README.md ``` ## See Also - [Deploy Configuration](/deploy/config/) — Target setup and matchers - [CLI Reference](/start/cli/) — All deploy command options - Other platforms: [GitLab CI](/deploy/gitlab-ci/) | [Netlify](/deploy/netlify/) | [Vercel](/deploy/vercel/) --- Title: GitLab CI URL: https://hwaro.hahwul.com/deploy/gitlab-ci/ Source: content/deploy/gitlab-ci/index.md Deploy your Hwaro site using GitLab CI/CD. ## Quick Start Auto-generate the config file: ```bash hwaro tool platform gitlab-ci ``` ## Configuration Or add `.gitlab-ci.yml` to your repository manually: ```yaml image: ghcr.io/hahwul/hwaro:latest pages: script: - hwaro build artifacts: paths: - public only: - main ``` This configuration uses the official Hwaro Docker image to build your site and deploys the `public` directory to GitLab Pages. ## See Also - [Deploy Configuration](/deploy/config/) — Target setup and matchers - [CLI Reference](/start/cli/) — All deploy command options - Other platforms: [GitHub Pages](/deploy/github-pages/) | [Netlify](/deploy/netlify/) | [Vercel](/deploy/vercel/) --- Title: Netlify URL: https://hwaro.hahwul.com/deploy/netlify/ Source: content/deploy/netlify/index.md Deploy your Hwaro site to Netlify with automatic builds and global CDN. ## Quick Start ### Generate Config ```bash hwaro tool platform netlify ``` This creates a `netlify.toml` with build settings, redirects from aliases, and cache headers. ### Deploy via Git 1. Push your repository to GitHub, GitLab, or Bitbucket 2. Go to [Netlify](https://app.netlify.com) and click **Add new site** > **Import an existing project** 3. Connect your repository 4. Netlify will auto-detect `netlify.toml` settings 5. Click **Deploy site** ## Manual Configuration If you prefer to configure manually instead of using the generator, create `netlify.toml`: ```toml [build] command = "hwaro build" publish = "public" [build.environment] # Set environment variables as needed ``` ## Redirects Page aliases defined in frontmatter are automatically included as 301 redirects when using `hwaro tool platform netlify`: ```markdown --- title: New Post aliases: - /old-url/ - /legacy/post/ --- ``` Generates: ```toml [[redirects]] from = "/old-url/" to = "/posts/new-post/" status = 301 [[redirects]] from = "/legacy/post/" to = "/posts/new-post/" status = 301 ``` ## Custom Domain 1. Go to **Site settings** > **Domain management** 2. Click **Add custom domain** 3. Follow the DNS configuration instructions 4. Update `base_url` in `config.toml`: ```toml base_url = "https://www.yourdomain.com" ``` ## Deploy Previews Netlify automatically creates deploy previews for pull requests. Preview builds use a temporary URL, so override the base URL using a deploy context: ```toml [context.deploy-preview] command = "hwaro build --base-url $DEPLOY_PRIME_URL" ``` `$DEPLOY_PRIME_URL` is a Netlify-provided environment variable containing the unique preview URL (e.g., `https://deploy-preview-42--your-site.netlify.app`). ## See Also - [Platform Config Generator](/start/tools/platform/) — Detailed generator options - [CLI Reference](/start/cli/#tool) — All tool commands - Other platforms: [Vercel](/deploy/vercel/) | [Cloudflare Pages](/deploy/cloudflare-pages/) | [GitHub Pages](/deploy/github-pages/) --- Title: Vercel URL: https://hwaro.hahwul.com/deploy/vercel/ Source: content/deploy/vercel/index.md Deploy your Hwaro site to Vercel with zero-config deployments. ## Quick Start ### Generate Config ```bash hwaro tool platform vercel ``` This creates a `vercel.json` with build settings, redirects from aliases, and cache headers. ### Deploy via Git 1. Push your repository to GitHub, GitLab, or Bitbucket 2. Go to [Vercel](https://vercel.com) and click **Add New** > **Project** 3. Import your repository 4. Vercel will auto-detect `vercel.json` settings 5. Click **Deploy** ## Manual Configuration If you prefer to configure manually, create `vercel.json`: ```json { "buildCommand": "hwaro build", "outputDirectory": "public" } ``` ## Redirects Page aliases defined in frontmatter are automatically included as 301 redirects when using `hwaro tool platform vercel`: ```markdown --- title: New Post aliases: - /old-url/ --- ``` Generates: ```json { "redirects": [ { "source": "/old-url/", "destination": "/posts/new-post/", "statusCode": 301 } ] } ``` ## Custom Domain 1. Go to **Settings** > **Domains** 2. Add your custom domain 3. Follow DNS configuration instructions 4. Update `base_url` in `config.toml`: ```toml base_url = "https://www.yourdomain.com" ``` ## Preview Deployments Vercel automatically creates preview deployments for every push to non-production branches. No additional configuration is needed. ## See Also - [Platform Config Generator](/start/tools/platform/) — Detailed generator options - [CLI Reference](/start/cli/#tool) — All tool commands - Other platforms: [Netlify](/deploy/netlify/) | [Cloudflare Pages](/deploy/cloudflare-pages/) | [GitHub Pages](/deploy/github-pages/) --- Title: Features URL: https://hwaro.hahwul.com/features/ Source: content/features/_index.md Hwaro ships with a comprehensive set of built-in features — no plugins required. All features are configured through `config.toml` and work out of the box once enabled. ## At a Glance **SEO & Discovery** — Sitemap, RSS/Atom feeds, robots.txt, OpenGraph, Twitter Cards, structured data (JSON-LD), and auto-generated OG images. **Content** — Syntax highlighting, search index generation, pagination, markdown extensions (footnotes, task lists, math, mermaid), series, and related posts. **Performance** — Incremental builds, streaming builds for large sites, asset pipeline with minification and fingerprinting, image processing with responsive variants and LQIP placeholders, and cache busting. **Files & Environment** — Environment variables, environment-specific config overrides, auto-includes for CSS/JS, and content file publishing. **Platform** — Multilingual support, image processing, PWA, AMP, and built-in deployment to multiple targets. --- Title: AMP URL: https://hwaro.hahwul.com/features/amp/ Source: content/features/amp.md Hwaro can automatically generate AMP (Accelerated Mobile Pages) versions of your content alongside the regular pages. ## How It Works 1. Regular pages are rendered normally 2. After rendering, Hwaro reads each page's HTML and creates an AMP-compliant version 3. AMP pages are written under a configurable path prefix (default: `/amp/`) 4. A `` tag is injected into the canonical page's `` ## Configuration ```toml [amp] enabled = true path_prefix = "amp" sections = ["posts"] ``` | Key | Type | Default | Description | |-----|------|---------|-------------| | enabled | bool | false | Enable AMP page generation | | path_prefix | string | "amp" | URL prefix for AMP pages | | sections | array | [] | Sections to generate AMP for (empty = all) | ## What Gets Converted The AMP converter automatically applies these transformations: | Original | AMP Version | |----------|-------------| | `` | `` | | `` | `` | | `