Skip to content

Commit 9a2c326

Browse files
authored
Add optional BASE_PREFIX to serve the site under a sub-directory (#630)
* Add optional BASE_PREFIX to serve the site under a sub-directory Introduce a BASE_PREFIX build option that prepends a path segment to each flavor's BASE_HREF, so the whole multi-network site can be served from a sub-directory (e.g. BASE_PREFIX=preview -> /preview/, /preview/signet/, /preview/liquid/, ...) instead of the domain root. The prefix is applied after the flavor config resolves its per-network BASE_HREF, so the network paths are preserved. API_URL is resolved before the prefix is applied and is left un-prefixed, so a prefixed build keeps talking to the same API backend. Cross-network links that are absolute (the network switcher and the Explorer API tab) are routed through the prefix so they stay within the current deployment root. With no BASE_PREFIX set the output is unchanged. * navbar: make Explorer API link relative like its siblings The Explorer API link was the only absolute navbar link (/explorer-api). The router strips the full BASE_HREF before matching route('/explorer-api'), so under a sub-directory or non-root network the absolute path never matches. Use a relative href, consistent with the Dashboard/Blocks/ Transactions links, so it resolves against BASE_HREF and stays within the current network and deployment root.
1 parent b1fee60 commit 9a2c326

5 files changed

Lines changed: 24 additions & 6 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ All options are optional.
8686

8787
- `NODE_ENV` - set to `production` to enable js minification, or to `development` to disable (defaults to `production`)
8888
- `BASE_HREF` - base href for user interface (defaults to `/`, change if not served from the root directory)
89+
- `BASE_PREFIX` - optional path prefix prepended to each flavor's `BASE_HREF`, to serve the whole multi-network site under a sub-directory (e.g. `BASE_PREFIX=preview` serves `/preview/`, `/preview/signet/`, ...). `API_URL` is left un-prefixed so a prefixed build still uses the same backend
8990
- `STATIC_ROOT` - root for static assets (defaults to `BASE_HREF`, change to load static assets from a different server)
9091
- `API_URL` - URL for HTTP REST API (defaults to `/api`, change if the API is available elsewhere)
9192
- `CANONICAL_URL` - absolute base url for user interface (optional, only required for opensearch and canonical link tags)

build.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ export NODE_ENV=${NODE_ENV:=production}
99
export BASE_HREF=${BASE_HREF:-/}
1010
export API_URL=${API_URL:-"${BASE_HREF}api"}
1111

12+
# Optional path prefix for serving the whole site under a sub-directory (e.g. a preview
13+
# deploy keyed by branch name). Applied *after* the flavor sets its per-network BASE_HREF,
14+
# so the network paths are preserved: / -> /$BASE_PREFIX/, /signet/ -> /$BASE_PREFIX/signet/.
15+
# API_URL is resolved above, before this, so it keeps pointing at the un-prefixed network
16+
# API and a prefixed build still talks to the same backend.
17+
if [ -n "$BASE_PREFIX" ]; then
18+
export BASE_HREF="/${BASE_PREFIX#/}${BASE_HREF}"
19+
export BASE_PREFIX="/${BASE_PREFIX#/}"
20+
fi
21+
1222
mkdir -p $DEST
1323
rm -rf $DEST/*
1424

client/src/views/nav-toggle.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { nativeAssetId } from '../const'
22

33
const staticRoot = process.env.STATIC_ROOT || ''
4+
// Prefix for cross-network links so they stay within the current deployment root when the
5+
// whole site is served under a sub-directory (BASE_PREFIX). Empty for a root deployment.
6+
const siteRoot = process.env.BASE_PREFIX || ''
47
const hasCam = process.browser && navigator.mediaDevices && navigator.mediaDevices.getUserMedia
58

69
export default () =>
@@ -40,10 +43,10 @@ export default () =>
4043
<div className="link-list">
4144
<h4 className="menu-title font-h5">Explorers</h4>
4245
<ul className="font-p3">
43-
<li><a href="/" rel="external">Bitcoin</a></li>
44-
<li><a href="/liquid/" rel="external">Liquid Network</a></li>
45-
<li><a href="/testnet/" rel="external" target="_blank">Bitcoin Testnet</a></li>
46-
<li><a href="/liquidtestnet/" rel="external" target="_blank">Liquid Testnet</a></li>
46+
<li><a href={`${siteRoot}/`} rel="external">Bitcoin</a></li>
47+
<li><a href={`${siteRoot}/liquid/`} rel="external">Liquid Network</a></li>
48+
<li><a href={`${siteRoot}/testnet/`} rel="external" target="_blank">Bitcoin Testnet</a></li>
49+
<li><a href={`${siteRoot}/liquidtestnet/`} rel="external" target="_blank">Liquid Testnet</a></li>
4750
</ul>
4851
<h4 className="menu-title font-h5">Developer Tools</h4>
4952
<ul className="font-p3">

client/src/views/navbar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default S =>
1313
<a href="blocks/recent" class={{ active: S.activeTab == 'recentBlocks' }}>Blocks</a>
1414
<a href="tx/recent" class={{ active: S.activeTab == 'recentTxs' }}>Transactions</a>
1515
{ process.env.IS_ELEMENTS ? <a href="assets" class={{ active: S.activeTab == 'assets' }}>Assets<sup className="highlight"></sup></a> : "" }
16-
<a href="/explorer-api" class={{ active: S.activeTab == 'apiLanding' }}>Explorer API</a>
16+
<a href="explorer-api" class={{ active: S.activeTab == 'apiLanding' }}>Explorer API</a>
1717
</div>
1818
{ menu(S) }
1919
</nav>

client/src/views/network-selection.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ const items = process.env.MENU_ITEMS && JSON.parse(process.env.MENU_ITEMS),
22
active = process.env.MENU_ACTIVE;
33

44
const staticRoot = process.env.STATIC_ROOT || "";
5+
// Keep cross-network links within the current deployment root when the site is served under a
6+
// sub-directory (BASE_PREFIX). No-op for a root deployment (empty prefix).
7+
const siteRoot = process.env.BASE_PREFIX || "";
8+
const withRoot = (url) => (siteRoot && url && url.charAt(0) === "/" ? siteRoot + url : url);
59
const itemEntries = items ? Object.entries(items) : [];
610
const activeName = active || (itemEntries[0] && itemEntries[0][0]);
711
const activeId = activeName && activeName.replace(/ /g, "");
@@ -43,7 +47,7 @@ export default ({ t, page }) => (
4347
return (
4448
<a
4549
id={name.replace(/ /g, "")}
46-
href={url}
50+
href={withRoot(url)}
4751
className={`network-hover-menu-option-container ${name.replace(/ /g, "").toLowerCase()} ${name === activeName ? "active" : ""}`}
4852
rel="external"
4953
>

0 commit comments

Comments
 (0)