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
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Full wayfinding is in [`MAP.md`](MAP.md). This is a **Bun monorepo** using works

- **apps/frontend** — React 19 + Vite web app → [`apps/frontend/CLAUDE.md`](apps/frontend/CLAUDE.md)
- **apps/demo** — minimal browser SDK integration → [`apps/demo/CLAUDE.md`](apps/demo/CLAUDE.md)
- **apps/gold** — "ouro. by Vortex" gold app served at /gold → [`apps/gold/CLAUDE.md`](apps/gold/CLAUDE.md)
- **apps/gold** — "ouro. by Vortex" gold app served at /pt-br/gold → [`apps/gold/CLAUDE.md`](apps/gold/CLAUDE.md)
- **apps/api** — Express backend (PostgreSQL + Sequelize) → [`apps/api/CLAUDE.md`](apps/api/CLAUDE.md)
- **apps/dashboard** — authenticated React dashboard → [`apps/dashboard/CLAUDE.md`](apps/dashboard/CLAUDE.md)
- **apps/rebalancer** — liquidity rebalancing service → [`apps/rebalancer/CLAUDE.md`](apps/rebalancer/CLAUDE.md)
Expand Down
2 changes: 1 addition & 1 deletion MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ workspace; use [`docs/README.md`](docs/README.md) to locate durable project cont
| `apps/api` | Express API, PostgreSQL/Sequelize models and migrations, block-flow ramp engine, provider integrations, webhooks, and workers. |
| `apps/frontend` | React widget and public web surface. XState ramp/KYC flows, wallets, and partner embedding. |
| `apps/demo` | Minimal browser-only React example for a BRL/PIX to BSC USDC onramp through `@vortexfi/sdk`. |
| `apps/gold` | "ouro. by Vortex" consumer app for BRL/PIX to PAXG through `@vortexfi/sdk`, served by the frontend site at `/gold`. |
| `apps/gold` | "ouro. by Vortex" consumer app for BRL/PIX to PAXG through `@vortexfi/sdk`, served by the frontend site at `/pt-br/gold`. |
| `apps/dashboard` | React account dashboard. Auth, customer entities, onboarding, recipients, history, and self-ramp flows. |
| `apps/rebalancer` | Standalone service for cross-chain liquidity correction and profitability-aware rebalancing. |

Expand Down
10 changes: 4 additions & 6 deletions apps/frontend/_redirects
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@
# Support the lowercase widget alias without turning unknown localized paths into soft 404s.
/pt-br/widget /_shell.html 200

# Gold lives as plain files under dist/client/gold/ (see netlify.toml), so /gold/ needs no rule.
# The locale-first alias mirrors /pt-BR/widget; Gold's canonical link still points at /gold/.
/pt-BR/gold /gold/index.html 200
/pt-BR/gold/* /gold/:splat 200
/pt-br/gold /gold/index.html 200
/pt-br/gold/* /gold/:splat 200
# Gold's canonical URL is /pt-br/gold/ (plain files under dist/client/pt-BR/gold/, see
# netlify.toml). The unprefixed path redirects until an international Gold landing exists.
/gold /pt-br/gold/ 301
/gold/* /pt-br/gold/:splat 301

# Everything else is a real 404
/* /404.html 404
Expand Down
7 changes: 4 additions & 3 deletions apps/frontend/netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
# Redirect rules live in `_redirects` (copied into dist/client by the build), not here.
# Marketing routes are prerendered to static HTML by TanStack Start, so they are plain files
# under `dist/client`; only the SSR-disabled widget route needs a rewrite.
# Gold (apps/gold) is a separate Vite app built with base /gold/ and copied into the
# published tree, so Netlify serves it as plain files before any redirect rule applies.
# Gold (apps/gold) is a separate Vite app built with base /pt-br/gold/ and copied into the
# published tree next to the prerendered locale pages (the pt-BR directory; Netlify matches
# files case-insensitively), so it is served as plain files before any redirect rule applies.
# Gold's build reads these site variables (set in the Netlify UI for all contexts):
# VITE_PRIVY_APP_ID – the Privy app id (without it Gold renders a config error); the
# original gold.satoshipay.io release used cmtiwhqgf01uu0el8lx3ejr35
Expand All @@ -18,7 +19,7 @@
# own domain; this build does not include it.

[build]
command = "cd ../.. && bun install --frozen-lockfile && bun run build:shared && bun run build:sdk && bun run build:frontend && bun run build:gold && mkdir -p apps/frontend/dist/client/gold && cp -R apps/gold/dist/client/. apps/frontend/dist/client/gold/"
command = "cd ../.. && bun install --frozen-lockfile && bun run build:shared && bun run build:sdk && bun run build:frontend && bun run build:gold && mkdir -p apps/frontend/dist/client/pt-BR/gold && cp -R apps/gold/dist/client/. apps/frontend/dist/client/pt-BR/gold/"
publish = "dist/client"
# Netlify's default ignore check only diffs the base directory, so a commit touching only
# apps/gold or the shared/sdk packages would be skipped as "no content change". Build when
Expand Down
10 changes: 6 additions & 4 deletions apps/frontend/src/tests/netlify-redirects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ const redirects = readFileSync(new URL("../../_redirects", import.meta.url), "ut
});

describe("Netlify redirects", () => {
it("routes only the widget shell and the gold alias through lowercase Portuguese paths", () => {
it("routes only the lowercase Portuguese widget path through the SPA shell", () => {
expect(redirects.filter(rule => rule.from.startsWith("/pt-br"))).toEqual([
{ from: "/pt-br/widget", status: "200", to: "/_shell.html" },
{ from: "/pt-br/gold", status: "200", to: "/gold/index.html" },
{ from: "/pt-br/gold/*", status: "200", to: "/gold/:splat" }
{ from: "/pt-br/widget", status: "200", to: "/_shell.html" }
]);
});

it("redirects the unprefixed gold path to its Brazilian edition", () => {
expect(redirects).toContainEqual({ from: "/gold/*", status: "301", to: "/pt-br/gold/:splat" });
});

it("keeps unknown paths on the real 404 fallback", () => {
expect(redirects).toContainEqual({ from: "/*", status: "404", to: "/404.html" });
});
Expand Down
10 changes: 6 additions & 4 deletions apps/gold/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ Brazil-first consumer app for buying and selling PAX Gold with PIX through `@vor
branded "ouro. by Vortex". Plain JavaScript React 19 + Vite app with Privy embedded wallets;
imported as a snapshot from `pendulum-chain/vortexperiments`, which keeps the pilot history.

- It is served by the frontend Netlify site at `https://www.vortexfinance.co/gold/`:
`apps/frontend/netlify.toml` builds it with Vite `base: "/gold/"` and copies `dist/client`
into the frontend's `dist/client/gold/`. Like `/widget`, the canonical path is unprefixed
and `/pt-BR/gold` is a rewrite alias in `apps/frontend/_redirects`.
- It is served by the frontend Netlify site at `https://www.vortexfinance.co/pt-br/gold/`:
`apps/frontend/netlify.toml` builds it with Vite `base: "/pt-br/gold/"` and copies
`dist/client` into the frontend's `dist/client/pt-BR/gold/`, beside the prerendered locale
pages. The site is locale-first (`/pt-br/business`, `/pt-br/widget`), so future markets go
to `/es-mx/gold/` etc.; the unprefixed `/gold/` 301s to the Brazilian edition until an
international landing exists (`apps/frontend/_redirects`).
Reference public assets through `import.meta.env.BASE_URL`, never as root-relative
`/brand/...` paths.
- The API base comes from `VITE_SIGNING_SERVICE_PATH`, like the frontend: a path such as
Expand Down
2 changes: 1 addition & 1 deletion apps/gold/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ Set `VITE_DEMO_MODE=false` and build with `bun run build`. The browser integrati

The frontend never receives the Privy App Secret or a Vortex server secret. Vortex session tokens remain in session storage; CPF and identity documents are not persisted by the app.

Live deployment: [https://www.vortexfinance.co/gold/](https://www.vortexfinance.co/gold/), built and served by the frontend Netlify site (see `apps/frontend/netlify.toml` and `CLAUDE.md` here). The pilot evidence, deployment notes and production checklist from the standalone `gold.satoshipay.io` release stay in `pendulum-chain/vortexperiments`.
Live deployment: [https://www.vortexfinance.co/pt-br/gold/](https://www.vortexfinance.co/pt-br/gold/), built and served by the frontend Netlify site (see `apps/frontend/netlify.toml` and `CLAUDE.md` here). The pilot evidence, deployment notes and production checklist from the standalone `gold.satoshipay.io` release stay in `pendulum-chain/vortexperiments`.
2 changes: 1 addition & 1 deletion apps/gold/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="theme-color" content="#fbf9f5" />
<meta name="description" content="Compre ouro lastreado com PIX e receba direto na sua carteira." />
<link rel="icon" type="image/png" href="/brand/ouro-app-icon.png" />
<link rel="canonical" href="https://www.vortexfinance.co/gold/" />
<link rel="canonical" href="https://www.vortexfinance.co/pt-br/gold/" />
<title>ouro. by Vortex — Compre ouro com PIX</title>
</head>
<body>
Expand Down
2 changes: 1 addition & 1 deletion apps/gold/vite.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
base: "/gold/",
base: "/pt-br/gold/",
build: {
outDir: "dist/client",
},
Expand Down
Loading