Documentation

Subpath Hosting

Use these templates when mode is SUBPATH. Replace /articles with your selected base path and set YOUR_TEXTA_UPSTREAM_HOST to the runtime host from integration config.

Required Paths

  • {basePath}
  • {basePath}/:path*
  • /blog-assets/:path*
  • /_blog/:path*
  • /api/blog-request
  • /.well-known/:path*

Keep these rewrites above generic catch-all handlers to avoid accidental interception by app routes.

Vercel

{
  "rewrites": [
    { "source": "/articles", "destination": "https://YOUR_TEXTA_UPSTREAM_HOST/blog" },
    { "source": "/articles/:path*", "destination": "https://YOUR_TEXTA_UPSTREAM_HOST/blog/:path*" },
    { "source": "/blog-assets/:path*", "destination": "https://YOUR_TEXTA_UPSTREAM_HOST/blog-assets/:path*" },
    { "source": "/_blog/:path*", "destination": "https://YOUR_TEXTA_UPSTREAM_HOST/_blog/:path*" },
    { "source": "/api/blog-request", "destination": "https://YOUR_TEXTA_UPSTREAM_HOST/api/blog-request" },
    { "source": "/.well-known/:path*", "destination": "https://YOUR_TEXTA_UPSTREAM_HOST/.well-known/:path*" }
  ],
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Forwarded-Host", "value": "blog.example.com" },
        { "key": "X-Forwarded-Proto", "value": "https" }
      ]
    }
  ]
}

Cloudflare Worker

export default {
  async fetch(request) {
    const url = new URL(request.url);
    const upstream = new URL(request.url);
    upstream.hostname = "YOUR_TEXTA_UPSTREAM_HOST";

    if (url.pathname === "/articles") {
      upstream.pathname = "/blog";
    } else if (url.pathname.startsWith("/articles/")) {
      upstream.pathname = "/blog" + url.pathname.slice("/articles".length);
    } else if (
      url.pathname.startsWith("/blog-assets/") ||
      url.pathname.startsWith("/_blog/") ||
      url.pathname === "/api/blog-request" ||
      url.pathname.startsWith("/.well-known/")
    ) {
      upstream.pathname = url.pathname;
    } else {
      return new Response("Not handled", { status: 404 });
    }

    const headers = new Headers(request.headers);
    headers.set("X-Forwarded-Host", url.host);
    headers.set("X-Forwarded-Proto", url.protocol.replace(":", ""));

    return fetch(upstream.toString(), {
      method: request.method,
      headers,
      body: request.body,
    });
  },
};

Nginx

location = /articles {
  proxy_set_header Host YOUR_TEXTA_UPSTREAM_HOST;
  proxy_set_header X-Forwarded-Host $host;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_pass https://YOUR_TEXTA_UPSTREAM_HOST/blog;
}

location /articles/ {
  proxy_set_header Host YOUR_TEXTA_UPSTREAM_HOST;
  proxy_set_header X-Forwarded-Host $host;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_pass https://YOUR_TEXTA_UPSTREAM_HOST/blog/;
}

location /blog-assets/ {
  proxy_set_header Host YOUR_TEXTA_UPSTREAM_HOST;
  proxy_pass https://YOUR_TEXTA_UPSTREAM_HOST/blog-assets/;
}

location /_blog/ {
  proxy_set_header Host YOUR_TEXTA_UPSTREAM_HOST;
  proxy_pass https://YOUR_TEXTA_UPSTREAM_HOST/_blog/;
}

location = /api/blog-request {
  proxy_set_header Host YOUR_TEXTA_UPSTREAM_HOST;
  proxy_set_header X-Forwarded-Host $host;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_pass https://YOUR_TEXTA_UPSTREAM_HOST/api/blog-request;
}

location /.well-known/ {
  proxy_set_header Host YOUR_TEXTA_UPSTREAM_HOST;
  proxy_set_header X-Forwarded-Host $host;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_pass https://YOUR_TEXTA_UPSTREAM_HOST/.well-known/;
}

AWS CloudFront

  1. Create behavior for {basePath} and {basePath}/*.
  2. Set origin to YOUR_TEXTA_UPSTREAM_HOST.
  3. Include Host, X-Forwarded-Host, X-Forwarded-Proto in origin request policy.
  4. Add separate behaviors for /blog-assets/*, /_blog/*, /api/blog-request, /.well-known/*.
  5. Rewrite {basePath} to /blog and {basePath}/* to /blog/* in viewer-request function.

CSP Checklist

  • Preserve existing script/style/image directives required by the blog runtime.
  • Do not strip nonce/hash-based directives if already applied upstream.
  • Keep upgrade-insecure-requests enabled for HTTPS-only custom hosts.