diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1feeb08..683e019 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,3 +21,6 @@ jobs: - run: npm run typecheck - run: npm run build + + # Validate preview isolation without deployment credentials or uploads. + - run: npm run build:preview diff --git a/README.md b/README.md index c471c70..e941260 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,16 @@ runtime locally (via miniflare), so behaviour matches production. ## Deployment -Merges to `main` automatically deploy via GitHub Actions. A single worker serves -all environments — the network config (API URL, network label) is derived from -the request hostname at runtime. Custom domains are configured once in the -Cloudflare dashboard. +Merges to `main` automatically deploy via GitHub Actions to `rgstry-testnet` and +`rgstry-stellar`. Each build selects its named environment with +`CLOUDFLARE_ENV`; the generated Worker config contains that network's variables +and custom domain. + +Hosted PR previews use a separate `registry-ui` Worker and Testnet-only config. +Run `npm run build:preview` to build and validate that target. The production +configuration and deployment workflow are unchanged. See +[Hosted previews](docs/hosted-previews.md) for the one-time Cloudflare GitHub +connection, build settings, and where reviewers will find the preview URLs. ## Project structure diff --git a/app/root.module.css b/app/root.module.css index 5466a95..70a14ea 100644 --- a/app/root.module.css +++ b/app/root.module.css @@ -177,6 +177,10 @@ flex-direction: column; } +.previewContent { + min-width: 0; +} + /* ── Scaffold Stellar banner ─────────────────────────── */ .scaffoldBanner { diff --git a/app/root.tsx b/app/root.tsx index 4aaa2cb..bfc2b34 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -15,12 +15,13 @@ import { Scripts, ScrollRestoration, useRouteLoaderData, + useLocation, } from "react-router" import { type Route } from "./+types/root" -import { Logo } from "~/components/logo" import "./app.css" import styles from "./root.module.css" +import { Logo } from "~/components/logo" import { checkHealth } from "~/lib/api" // Runs before hydration to avoid flash of wrong theme. Defaults to dark. @@ -361,8 +362,10 @@ export function useRootData() { export default function App({ loaderData }: Route.ComponentProps) { const { network } = loaderData + const { pathname } = useLocation() const [isDark, setIsDark] = useState(true) const [queryClient] = useState(() => new QueryClient()) + const isExplorerPreview = pathname.startsWith("/explorer-preview") useEffect(() => { setIsDark(document.documentElement.classList.contains("dark")) @@ -377,12 +380,16 @@ export default function App({ loaderData }: Route.ComponentProps) { return ( -
-
+ {!isExplorerPreview && ( +
+ )} +
- -