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
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ jobs:
file: backend/Dockerfile
push: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}
build-args: |
VITE_API_BASE_URL=/api
GIT_VERSION=${{ steps.git-version.outputs.value }}
tags: ${{ steps.backend-meta.outputs.tags }}
labels: ${{ steps.backend-meta.outputs.labels }}
22 changes: 6 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,16 @@ Minimal portfolio app.

## Frontend backend URL

The frontend reads the backend base URL from `VITE_API_BASE_URL`.
The frontend always calls the backend under the relative `/api` path.

1. Copy [`web/.env.example`](web/.env.example) to `web/.env.local`.
2. Set `VITE_API_BASE_URL` to the backend URL you want the frontend to use.
3. Start the frontend with `npm run dev` from `web/`.

Example:

```bash
cp web/.env.example web/.env.local
echo 'VITE_API_BASE_URL=http://127.0.0.1:3000/api' > web/.env.local
```

For local Vite development, set `VITE_API_BASE_URL` explicitly. If it is not set, the frontend defaults to `/api`, which is the path the backend exposes its API under when it serves the bundled frontend.
- Production: the backend serves both the API and the bundled frontend, so same-origin `/api` requests just work.
- Local development: the Vite dev server proxies `/api` to `http://127.0.0.1:3000` (see [`web/vite.config.ts`](web/vite.config.ts)), so no environment variable is needed. Start the backend with `cargo run` from `backend/`, then `npm run dev` from `web/`.

## Deployment

The backend serves both the API and the bundled Vite frontend from a single container image:

- [`backend/Dockerfile`](backend/Dockerfile) builds the Rust API and bundles the static frontend (built with `VITE_API_BASE_URL=/api`) into `/app/web`
- [`backend/Dockerfile`](backend/Dockerfile) builds the Rust API and bundles the static frontend (which targets `/api`) into `/app/web`
- [`docker-compose.yml`](docker-compose.yml) deploys the prebuilt tagged image
- [`docker-compose.build.yml`](docker-compose.build.yml) adds local build support on top of the base compose file

Expand Down Expand Up @@ -69,7 +59,7 @@ export APP_TAG=dev
docker compose -f docker-compose.yml -f docker-compose.build.yml up --build
```

The base compose file keeps the final image name and tag stable. The build override adds `build:` and `pull_policy: never` so `--build` does not try to pull first. The build sets `VITE_API_BASE_URL=/api` by default.
The base compose file keeps the final image name and tag stable. The build override adds `build:` and `pull_policy: never` so `--build` does not try to pull first.

### Runtime endpoints

Expand All @@ -81,7 +71,7 @@ The compose file uses a named volume for backend SQLite data.

### Frontend URL behavior

The bundled frontend always targets `VITE_API_BASE_URL` as set at build time, defaulting to `/api`. For a deployment where the API is hosted on a separate public origin, rebuild the image with the desired public `VITE_API_BASE_URL`.
The bundled frontend always targets the relative `/api` path on its own origin. To host the API on a separate public origin, place a reverse proxy that forwards `/api` to the backend.

### CI

Expand Down
2 changes: 0 additions & 2 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ WORKDIR /web
COPY web/package.json web/package-lock.json ./
RUN npm ci
COPY web/ ./
ARG VITE_API_BASE_URL=/api
ENV VITE_API_BASE_URL=${VITE_API_BASE_URL}
ARG GIT_VERSION
ENV GIT_VERSION=${GIT_VERSION}
RUN npm run build
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@ services:
build:
context: .
dockerfile: backend/Dockerfile
args:
VITE_API_BASE_URL: ${VITE_API_BASE_URL:-/api}
pull_policy: never
1 change: 0 additions & 1 deletion web/.env.example

This file was deleted.

20 changes: 4 additions & 16 deletions web/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
# siniscalco web

## Set the backend URL
## Backend URL

The frontend uses `VITE_API_BASE_URL` as the backend base URL.
The frontend calls the backend under the relative `/api` path.

For local Vite development, point it directly at the backend:

1. Copy `.env.example` to `.env.local`.
2. Set `VITE_API_BASE_URL`.
3. Run `npm run dev`.

Example:

```bash
cp .env.example .env.local
echo 'VITE_API_BASE_URL=http://127.0.0.1:3000/api' > .env.local
```

If `VITE_API_BASE_URL` is not set, the app defaults to `/api`. That default is intended for the container build, where the backend serves the bundled frontend and exposes its API under `/api`.
- Local development: the Vite dev server proxies `/api` to `http://127.0.0.1:3000` (see `vite.config.ts`). Start the backend with `cargo run` from `backend/`, then run `npm run dev`.
- Production: the backend serves the bundled frontend and exposes its API under `/api`, so same-origin requests work out of the box.
4 changes: 3 additions & 1 deletion web/src/lib/env.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export const API_BASE_URL = "/api";

export function getApiBaseUrl() {
return import.meta.env.VITE_API_BASE_URL?.trim() || "/api";
return API_BASE_URL;
}

export function getHealthApiUrl() {
Expand Down
6 changes: 6 additions & 0 deletions web/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ function getGitVersion(): string {
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), tailwindcss()],
server: {
proxy: {
// Local development only: forward API calls to the backend started with `cargo run`.
"/api": "http://127.0.0.1:3000",
},
},
define: {
__APP_VERSION__: JSON.stringify(getGitVersion()),
},
Expand Down
Loading