Deploy Astro site to sub-path
Published: 2021-10-28 07:37:34

---
title: Deploy Astro site to sub-path
published: true
description: How to fix Astro hosted at a subpath
tags: 
---

Astro is a static site generator which enables you to use a familiar javascript component architecture while shipping less client-side Javascript.

### Problem with Sub-Path deployment

When you are not using a custom domain, Gitlab Pages deploys your website to a sub-path, e.g., `http(s)://username.example.io/repository-name/`.
Due to an open bug, Astro ignores the `buildConfig.site` configuration, which is necessary to rewrite all asset paths.

### Solution

This is a small script which manually touches all files in the output directory and rewrites the paths. To use the script, copy it to your project’s root folder and name the file `postbuild.mjs`.

```js
import fs from 'fs'
import path from 'path'
import astroConfig from './astro.config.mjs'


const PUBLIC_DIR = astroConfig.dist || "dist"
const argvs = process.argv.slice(2);

if ((argvs[0] === '--p' || argvs[0] === '-path') && argvs[1]) {
    let files = [];
    const extensions = ['.html', '.css', '.js', '.json']
    const PRODUCTION_URL = argvs[1]


    const replaceUrlsInFiles = function(dirPath, arrayOfFiles) {
        files = fs.readdirSync(dirPath)

        files.forEach(function(file) {
            const current = fs.statSync(dirPath + "/" + file)
            if (current.isDirectory()) {
                replaceUrlsInFiles(dirPath + "/" + file, arrayOfFiles)
            } else {
                const filePath = path.join(
                    path.dirname(
                        (
                            import.meta.url).replace(/file\:/, '')), dirPath, "/", file)
                if (extensions.includes(path.extname(filePath))) {
                    let content = fs.readFileSync(filePath)

                    content = String(content).replace(/src="\//g, `src="${PRODUCTION_URL}`)
                    content = String(content).replace(/href="\//g, `href="${PRODUCTION_URL}`)
                    content = String(content).replace(/url\("\//g, `url("${PRODUCTION_URL}`)

                    content = String(content).replace(/src='\//g, `src='${PRODUCTION_URL}`)
                    content = String(content).replace(/href='\//g, `href='${PRODUCTION_URL}`)
                    content = String(content).replace(/url\('\//g, `url('${PRODUCTION_URL}`)
                    fs.writeFileSync(filePath, content)
                }
            }
        })
    }

    if (PRODUCTION_URL && process.env.NODE_ENV === 'production') {
        replaceUrlsInFiles(PUBLIC_DIR, files)
    } else {
        console.log('skip postbuild')
        process.exit(0)
    }
} else {
    console.error('please provide a path argument "-path", "--p"')
    process.exit(1)
}
```

You can now use the script as a post-build hook via NPM scripts.

```js
{
	"scripts": {
	    "dev": "astro dev",
	    "start": "astro dev",
	    "build": "astro build",
	    "postbuild": "node ./postbuild.mjs -path https://username.example.io/repository-name/",
	    "preview": "astro preview"
	},
}
```

### Conclusion

I hope this script helps you out until the bug in Astro is fixed. If you have some time to spare, please consider contributing to Astro :)

- [https://github.com/snowpackjs/astro/issues/1171](Astro.resolve fails if buildOptions.site includes a path)
- [https://github.com/snowpackjs/astro/issues/968](Built Astro site cannot be hosted at a subpath)