Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/docs-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ jobs:
- run: npm run build
- name: Check internal links
run: node scripts/check-links.mjs
# nginx/default.conf ships straight into the runtime image (see Dockerfile)
# and was never validated anywhere in CI. A syntax error there does not fail
# the build — it fails `nginx -g daemon off;` at container start, i.e. the
# docs go down on deploy. Validate it with the same nginx the image uses.
- name: Validate nginx config
run: |
docker run --rm \
-v "$PWD/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro" \
nginx:stable-alpine nginx -t
22 changes: 22 additions & 0 deletions nginx/default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@ server {
location = /docs/usecases/MCP { return 301 /docs/mcp/mcp-server/; }
location = /docs/usecases/MCP/ { return 301 /docs/mcp/mcp-server/; }

# Legacy Pump.fun paths. These are covered by plugin-client-redirects, which
# emits a real HTML page per old URL: HTTP 200, a meta-refresh, a *relative*
# canonical — and an EMPTY <title>. Verified live on 2026-08-11, all four
# sampled paths returned `200` with `<title></title>`. Nine such URLs exist
# for a four-page cluster, and Google indexed them: on 2026-08-09
# /docs/examples/Solana/Pump-Fun-API/ ranked position 3 for "pumpfun api",
# above the canonical page, which was position 13.4 the same day.
#
# A 200 with no title is an indexable duplicate, so the client-side redirect
# is actively competing with the page it points at. Promote to real 301s;
# the client-side redirects stay as a harmless fallback for direct hits that
# somehow bypass nginx.
#
# No redirect loop: the canonical form is /docs/blockchain/Solana/Pumpfun/<page>,
# and the capture group below matches only the bare <page> names, never a
# "Pumpfun/<page>" segment, so targets cannot re-enter this block. The
# ^~ /docs/blockchain/Solana/PumpFun block above does not shadow these
# either — "PumpFun" is not a prefix of "Pump-Fun-API" or "pump-swap-api".
location ~ ^/docs/(?:examples/Solana|examples/dextrades|blockchain/Solana)/(Pump-Fun-API|Pump-Fun-Marketcap-Bonding-Curve-API|pump-fun-to-pump-swap|pump-swap-api)/?$ {
return 301 /docs/blockchain/Solana/Pumpfun/$1/;
}

# Self-hosted fonts + webpack-hashed /assets (filenames change on update)
location ~* ^/(fonts|assets)/ {
try_files $uri =404;
Expand Down
Loading