Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

docusaurus serve: static assets 404 when baseUrl is not "/" and trailingSlash is true

Open Beginner friendly
#12,476 4 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@Shashank01729 is already working on this.

Since Sep 23, 2026.

  • #12477 by @Shashank01729 — open
  • #12737 by @404kernel — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
node.js, typescript
Domain
cli, tooling

Research direction

The issue is in packages/docusaurus/src/commands/serve.ts, where the regex for asset detection is too restrictive. Start by examining the serve command's logic, particularly the looksLikeAsset check. Use the provided reproduction steps to verify the bug. The fix involves splitting the URL to isolate the pathname before checking the extension, similar to how applyTrailingSlash works. Test by building and serving a site with the described configuration, then verifying static assets with long extensions and query strings are served correctly.

Written by the indexing model from the issue text.

Description

bug status: needs triage
Have you read the Contributing Guidelines on issues?
Prerequisites
  • I'm using the latest version of Docusaurus.
  • I have tried the npm run clear or yarn clear command.
  • I have tried rm -rf node_modules yarn.lock package-lock.json and re-installing packages.
  • I have tried creating a repro with https://new.docusaurus.io.
  • I have read the console error message carefully (if applicable).
Description

With a non-root baseUrl and trailingSlash: true, docusaurus serve returns 404 for two kinds of static assets:

  • extensions longer than 4 characters — .woff2, .webmanifest, .geojson
  • any asset requested with a query string — /img/logo.png?v=1

Both get a 302 to a trailing-slash URL and end up on the 404 page. Web fonts are the most visible casualty, since .woff2 is the standard format.

It comes from the asset check in packages/docusaurus/src/commands/serve.ts:

const looksLikeAsset = !!req.url.match(/\.[a-zA-Z\d]{1,4}$/);

{1,4} is too short for .woff2, and the $ is matched against the raw req.url, so a ?query also prevents the match. applyTrailingSlash(), called right after it, does split the query off first:

// The trailing slash should be handled before the ?search#hash !
const [pathname] = path.split(/[#?]/) as [string, ...string[]];

The asset check just misses that step.

Reproducible demo

No repo needed — the steps below start from a fresh create-docusaurus install and reproduce it in about a minute.

Steps to reproduce
  1. npx create-docusaurus@latest repro-serve classic --javascript && cd repro-serve && npm install
  2. In docusaurus.config.js, set baseUrl: '/mysite/' and trailingSlash: true
  3. Add three static files:
    printf 'FAKEWOFF2'    > static/custom-font.woff2
    printf '{"name":"x"}' > static/site.webmanifest
    printf 'FAKEPNG'      > static/logo-test.png
    
  4. npm run build && npm run serve -- --port 3030
  5. Request them:
    curl -sI "http://localhost:3030/mysite/logo-test.png"
    curl -sI "http://localhost:3030/mysite/logo-test.png?v=1"
    curl -sI "http://localhost:3030/mysite/custom-font.woff2"
    curl -sI "http://localhost:3030/mysite/site.webmanifest"
    
Expected behavior

All four serve the file with status 200 and the correct content type. The trailing slash should only be applied to page URLs, whatever the extension length is and whether or not there is a query string.

Actual behavior

Only the plain .png is served:

/mysite/logo-test.png      -> 200 image/png
/mysite/logo-test.png?v=1  -> 302 .../logo-test.png/?v=1 -> 404 text/html
/mysite/custom-font.woff2  -> 302 .../custom-font.woff2/ -> 404 text/html
/mysite/site.webmanifest   -> 302 .../site.webmanifest/  -> 404 text/html

Following the redirect returns the HTML 404 page instead of the file:

$ curl -sIL "http://localhost:3030/mysite/custom-font.woff2" | grep -E "^HTTP|^Content-Type"
HTTP/1.1 302 Found
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8

Same behavior on main (4.0.0), where the regex is /\.[a-z\d]{1,4}$/i.

Splitting off the query/hash and checking the extension of the pathname fixes all three cases while leaving page redirects untouched:

const [pathname] = req.url.split(/[#?]/) as [string, ...string[]];
const looksLikeAsset = !!path.extname(pathname);

With that change, in the same repro, the three failing URLs return 200 and /mysite/docs/intro still redirects to /mysite/docs/intro/.

Your environment
  • Public source code: N/A — repro steps above, from a fresh create-docusaurus site
  • Public site URL: N/A — local docusaurus serve
  • Docusaurus version used: 3.10.2, also reproduced on main (4.0.0)
  • Environment name and version: Node.js v24.21.0
  • Operating system and version: macOS 15
Self-service
  • I'd be willing to fix this bug myself.
Dominant language
TypeScript
Stars
66.5k
Forks
10.1k
Avg merge
23h 6m
Merged PRs (30d)
159

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from facebook/docusaurus

All issues in facebook/docusaurus

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.