# How the Asset Management System Handles Relative Paths in Astro Big Doc: Development vs Production

> Understand how astro-big-doc asset management handles relative paths in development versus production builds. Learn about zero-copy runtime routes and asset copying.

- Repository: [Micro Web Stacks/astro-big-doc](https://github.com/microwebstacks/astro-big-doc)
- Tags: internals
- Published: 2026-03-07

---

**The astro-big-doc asset pipeline uses a zero-copy runtime route for relative paths during development, but copies and optionally hashes assets into `dist/_astro` during production builds based on the `copy_assets` configuration flag.**

The **astro-big-doc** repository implements a dual-mode asset management system that handles relative paths differently depending on whether you are running a development server or building for production. Understanding how the **asset management system handles relative paths** across these environments is crucial for debugging broken images and optimizing cache strategies. The behavior is controlled primarily through the `copy_assets` flag in [`config.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/config.js) and the resolution logic in [`src/libs/assets.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/libs/assets.js).

## Development Mode: Zero-Copy Asset Serving

### The Runtime Asset Route

In development, `copy_assets` defaults to `false`. When you reference a relative asset path like `images/logo.png` in your Markdown, the system does not copy the file. Instead, the `relAssetToUrl` function in [`src/libs/assets.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/libs/assets.js) returns a URL prefixed with `/assets/`, such as `/assets/images/logo.png`.

This request is handled by the dynamic route at `src/pages/assets/[...path].js`. The route resolves the file directly from the source content directory (`config.content_path`) using the `remove_base` helper to strip any configured base path. No files are duplicated on disk, enabling instant updates when you modify assets during development.

### Path Resolution Without Copying

The `assetToUrl` function serves as the main entry point for all asset references. For relative paths, it delegates to `relAssetToUrl`, which checks the `copy_assets` configuration. When this flag is `false`, the function bypasses the copying logic entirely and returns the runtime route URL, ensuring the browser fetches the file from the source location.

## Production Build: Copied and Hashed Assets

### Enabling Asset Copying

When you set `copy_assets` to `true` (typically via environment variables in CI/CD), the asset management system shifts to a static copying strategy. The `relAssetToUrl` function now invokes `relAssetToUrlCopy` for every relative asset path encountered during the build.

This helper determines the absolute source file path by joining `config.content_path` with the relative directory and filename. It then copies the file into the output directory, defaulting to `dist/_astro`. If the `assets_hash_dir` configuration is `true` (the default), the filename is hashed using its content for cache-busting purposes.

### Hashing for Cache Busting

The `relAssetToUrlCopy` function generates hashed filenames like `logo-a1b2c3d4.png` when `assets_hash_dir` is enabled. This ensures that when you redeploy with modified assets, browsers fetch the new versions rather than using stale cached files.

If you disable hashing by setting `assets_hash_dir` to `false`, the system preserves the original directory structure within `_astro`, resulting in URLs like `/_astro/images/logo.png`. This is useful when you need predictable filenames for external referencing.

## Core Asset Resolution Logic in assets.js

### Key Functions Overview

The [`src/libs/assets.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/libs/assets.js) file contains the primary logic for how the **asset management system handles relative paths**:

- **`assetToUrl(path, dirpath)`**: The universal entry point. Distinguishes between absolute paths (starting with `/`), external URLs, and relative paths.
- **`relAssetToUrl(relpath, dirpath)`**: Handles relative paths specifically. Checks `config.copy_assets` to decide between development-style routing or production copying.
- **`relAssetToUrlCopy(relpath, dirpath)`**: Executes the copy-and-hash logic for production builds. Constructs absolute paths, manages the `dist/_astro` output, and generates hashed filenames when configured.
- **`remove_base(path)`** and **`add_base(path)`**: Utility functions that handle the optional `config.base` path prefix, ensuring URLs remain correct when the site is deployed to a subdirectory.

### Base Path Handling

When your site is deployed to a subdirectory (e.g., `/docs`), the `config.base` setting ensures all asset URLs are prefixed correctly. The `add_base` function prepends this base to generated URLs, while `remove_base` strips it when mapping incoming requests back to filesystem paths in the development asset route.

## Configuration Reference

### config.js Settings

The behavior of the asset pipeline is centralized in [`config.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/config.js):

```js
// config.js
export default {
  copy_assets: false,        // Toggle between dev (false) and production (true) modes
  copy_assets_dir: "_astro", // Output directory for copied assets
  assets_hash_dir: true,     // Enable content hashing for cache busting
  base: "",                  // Optional base path (e.g., "/docs")
  content_path: "content"    // Source directory for content and assets
}

```

To switch to production mode, set the environment variable before building:

```bash
COPY_ASSETS=true npm run build

```

## Practical Examples

### Development Usage

Reference an image in your Markdown content:

```markdown
![Architecture Diagram](diagrams/system-overview.png)

```

During development, this generates:

```html
<img src="/assets/diagrams/system-overview.png" alt="Architecture Diagram">

```

The file is served directly from `content/diagrams/system-overview.png` via the dynamic route at `src/pages/assets/[...path].js`.

### Production Build Commands

Enable asset copying and hashing for deployment:

```bash

# Enable production asset handling

export COPY_ASSETS=true
export ASSETS_HASH_DIR=true

# Build the site

npm run build

```

The build process copies `content/diagrams/system-overview.png` to `dist/_astro/system-overview-a1b2c3d4.png` and updates the HTML to:

```html
<img src="/_astro/system-overview-a1b2c3d4.png" alt="Architecture Diagram">

```

## Summary

- **Development mode** (`copy_assets: false`) keeps assets in place and serves them via a dynamic runtime route (`/assets/...`), enabling instant updates without file copying.
- **Production mode** (`copy_assets: true`) copies assets to `dist/_astro`, optionally hashes filenames for cache busting (`assets_hash_dir: true`), and generates static URLs pointing to the copied files.
- The **asset resolution logic** lives in [`src/libs/assets.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/libs/assets.js), with key functions `relAssetToUrl` and `relAssetToUrlCopy` handling the mode-specific behavior.
- **Base path support** via `config.base` ensures correct URL generation when deploying to subdirectories, managed by `add_base` and `remove_base` helpers.

## Frequently Asked Questions

### How do I enable production asset copying in astro-big-doc?

Set the `COPY_ASSETS` environment variable to `true` before running the build command. This switches the asset management system from runtime serving to static copying mode, placing assets in the `dist/_astro` directory with optional content hashing.

### Why are my images broken in development but work in production?

If images return 404 during development, verify that `copy_assets` remains `false` (the default) and that your files exist in the `content` directory relative to your Markdown files. The development server expects to serve these through the `/assets/` dynamic route, not from the `dist` folder.

### What is the difference between hashed and non-hashed asset filenames?

When `assets_hash_dir` is `true` (default in production), the system appends a content hash to filenames (e.g., `logo-a1b2c3d4.png`), ensuring browsers fetch updated versions when the file changes. When set to `false`, the original directory structure and filenames are preserved inside `_astro`, useful when you need predictable URLs for external systems.

### Where does the asset resolution logic live in the codebase?

The core logic resides in [`src/libs/assets.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/src/libs/assets.js), specifically within the `relAssetToUrl` and `relAssetToUrlCopy` functions. Development-time serving is handled by `src/pages/assets/[...path].js`, while configuration defaults are defined in [`config.js`](https://github.com/microwebstacks/astro-big-doc/blob/main/config.js).