Skip to content

Commit f4ed76d

Browse files
authored
Merge pull request #131 from arrhes/dashboard-redesign
Dashboard redesign
2 parents 945cded + 0518ab6 commit f4ed76d

554 files changed

Lines changed: 4868 additions & 2254 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.workflows/build/compose.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# ci - Lint + unit tests + build (gate before packaging)
99
# api - Production API image
1010
# website - Production Website image (nginx + static)
11+
# dashboard - Production Dashboard image (nginx + SPA)
1112
# worker - Production Worker image (background job processor)
1213
#
1314
# Usage:
@@ -35,6 +36,17 @@ services:
3536
args:
3637
- VITE_WEBSITE_BASE_URL=${VITE_WEBSITE_BASE_URL:-}
3738
- VITE_API_BASE_URL=${VITE_API_BASE_URL:-}
39+
- VITE_DASHBOARD_BASE_URL=${VITE_DASHBOARD_BASE_URL:-}
40+
41+
dashboard:
42+
image: arrhes-dashboard:${ARRHES_VERSION:-dev}
43+
build:
44+
context: ../..
45+
dockerfile: .workflows/build/packages/dashboard/Dockerfile
46+
args:
47+
- VITE_API_BASE_URL=${VITE_API_BASE_URL:-}
48+
- VITE_WEBSITE_BASE_URL=${VITE_WEBSITE_BASE_URL:-}
49+
3850

3951
worker:
4052
image: arrhes-worker:${ARRHES_VERSION:-dev}

.workflows/build/packages/ci/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ RUN pnpm install
2626
# Build all packages (must run before tests so workspace deps are compiled)
2727
RUN pnpm run build
2828

29-
# Auto-format, then run Biome check (lint)
30-
RUN pnpm format:fix && pnpm check
29+
# Auto-fix formatting + imports, then run Biome check (lint)
30+
RUN pnpm check:fix && pnpm check
3131

3232
# Run unit tests
3333
RUN pnpm --recursive --if-present --filter='./packages/**' run test:unit
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Include any files or directories that you don't want to be copied to your
2+
# container here (e.g., local build artifacts, temporary files, etc.).
3+
#
4+
# For more help, visit the .dockerignore file reference guide at
5+
# https://docs.docker.com/go/build-context-dockerignore/
6+
7+
**/.dockerignore
8+
**/.env
9+
**/.vscode
10+
**/.git
11+
**/.gitignore
12+
**/docker-compose*
13+
**/compose*
14+
**/Dockerfile*
15+
**/node_modules
16+
**/build
17+
README.md
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Use an official Node.js image to build our image from
2+
FROM node:25.2.1-alpine AS base
3+
RUN npm install -g pnpm@10.26.1
4+
ENV NODE_OPTIONS="--max-old-space-size=4096"
5+
6+
# Build the repo
7+
FROM base AS build
8+
9+
# Build arguments for Vite environment variables
10+
ARG VITE_API_BASE_URL
11+
ARG VITE_WEBSITE_BASE_URL
12+
13+
WORKDIR /root
14+
COPY . .
15+
RUN pnpm install
16+
17+
# Write VITE_* build args to .env so Vite can read them during build.
18+
# Vite reads import.meta.env from .env files, not from process.env.
19+
RUN printf "VITE_API_BASE_URL=%s\nVITE_WEBSITE_BASE_URL=%s\n" \
20+
"$VITE_API_BASE_URL" "$VITE_WEBSITE_BASE_URL" \
21+
> packages/dashboard/.env
22+
23+
RUN pnpm --filter @arrhes/application-dashboard... run build
24+
25+
# Start application
26+
FROM nginx:alpine AS deploy
27+
WORKDIR /
28+
COPY .workflows/build/packages/dashboard/nginx/default.conf /etc/nginx/nginx.conf
29+
RUN rm -rf /usr/share/nginx/html/*
30+
COPY --from=build /root/packages/dashboard/build /usr/share/nginx/html
31+
EXPOSE 80
32+
CMD ["nginx"]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# default.conf
2+
worker_processes auto;
3+
4+
daemon off;
5+
6+
events {
7+
worker_connections 1024;
8+
}
9+
10+
http {
11+
include mime.types;
12+
13+
server {
14+
listen 80;
15+
16+
gzip on;
17+
gzip_http_version 1.1;
18+
gzip_disable "MSIE6";
19+
gzip_min_length 256;
20+
gzip_vary on;
21+
gzip_proxied any;
22+
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript font/woff2;
23+
gzip_comp_level 9;
24+
25+
root /usr/share/nginx/html;
26+
index index.html;
27+
28+
# Immutable hashed assets (JS, CSS, fonts, images) - cache for 1 year
29+
location ~* \.(?:js|css|woff2?|ttf|eot|svg|png|jpg|jpeg|gif|webp|webmanifest)$ {
30+
add_header Cache-Control "public, max-age=31536000, immutable";
31+
try_files $uri =404;
32+
}
33+
34+
# SPA fallback - all routes served by index.html
35+
location / {
36+
add_header Cache-Control "no-cache";
37+
try_files $uri $uri/ /index.html =404;
38+
}
39+
}
40+
}

.workflows/build/packages/website/Dockerfile

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,32 @@ FROM base AS build
99
# Build arguments for Vite environment variables
1010
ARG VITE_WEBSITE_BASE_URL
1111
ARG VITE_API_BASE_URL
12+
ARG VITE_DASHBOARD_BASE_URL
1213

1314
WORKDIR /root
1415
COPY . .
1516
RUN pnpm install
1617

1718
# Write VITE_* build args to .env so Vite can read them during build.
1819
# Vite reads import.meta.env from .env files, not from process.env.
19-
RUN printf "VITE_WEBSITE_BASE_URL=%s\nVITE_API_BASE_URL=%s\n" \
20-
"$VITE_WEBSITE_BASE_URL" "$VITE_API_BASE_URL" \
20+
RUN printf "VITE_WEBSITE_BASE_URL=%s\nVITE_API_BASE_URL=%s\nVITE_DASHBOARD_BASE_URL=%s\n" \
21+
"$VITE_WEBSITE_BASE_URL" "$VITE_API_BASE_URL" "$VITE_DASHBOARD_BASE_URL" \
2122
> packages/website/.env
2223

2324
RUN pnpm --filter @arrhes/application-website... run build
2425

26+
# Stamp CLI files from VERSION
27+
RUN VER=$(cat VERSION | tr -d 'v[:space:]') && \
28+
sed -i "s/^VERSION=\".*\"/VERSION=\"$VER\"/" packages/cli/arrhes.sh && \
29+
printf '%s\n' "$VER" > packages/cli/version
30+
2531
# Start application
2632
FROM nginx:alpine AS deploy
2733
WORKDIR /
2834
COPY .workflows/build/packages/website/nginx/default.conf /etc/nginx/nginx.conf
2935
RUN rm -rf /usr/share/nginx/html/*
3036
COPY --from=build /root/packages/website/build /usr/share/nginx/html
37+
COPY --from=build /root/packages/cli/install.sh /usr/share/nginx/html/cli/install.sh
38+
COPY --from=build /root/packages/cli/version /usr/share/nginx/html/cli/version
3139
EXPOSE 80
3240
CMD ["nginx"]

.workflows/build/packages/website/nginx/default.conf

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ http {
3030
location = /og.png { add_header Cache-Control "public, max-age=86400"; try_files $uri =404; }
3131
location = /og.webp { add_header Cache-Control "public, max-age=86400"; try_files $uri =404; }
3232

33+
# CLI install scripts and version file - serve as plain text, no caching
34+
location ~* ^/cli/(.*\.sh|version)$ {
35+
add_header Cache-Control "no-cache";
36+
add_header Content-Type "text/plain; charset=utf-8";
37+
try_files $uri =404;
38+
}
39+
3340
# Immutable hashed assets (JS, CSS, fonts, images) - cache for 1 year
3441
location ~* \.(?:js|css|woff2?|ttf|eot|svg|png|jpg|jpeg|gif|webp|webmanifest)$ {
3542
add_header Cache-Control "public, max-age=31536000, immutable";
@@ -39,7 +46,11 @@ http {
3946
# HTML and other mutable files - always revalidate
4047
location / {
4148
add_header Cache-Control "no-cache";
42-
try_files $uri $uri/ /index.html =404;
49+
# Use a blank SPA shell (__app.html) as the fallback for routes that
50+
# have no prerendered file (e.g. /dashboard). index.html contains
51+
# the prerendered home page and must not be served as a catch-all,
52+
# otherwise it flashes on every non-home route refresh.
53+
try_files $uri $uri/ /__app.html =404;
4354
}
4455
}
4556
}

.workflows/dev/compose.yml

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,12 @@ services:
128128
ENV: development
129129
VERBOSE: "true"
130130
PORT: "${API_HOST_PORT}"
131-
CORS_ORIGIN: "http://localhost:${WEBSITE_HOST_PORT}"
131+
CORS_ORIGIN: localhost
132132
COOKIES_DOMAIN: localhost
133133
COOKIES_KEY: development-secret-key-change-in-production-min-32-chars
134134
API_BASE_URL: "http://localhost:${API_HOST_PORT}"
135135
WEBSITE_BASE_URL: "http://localhost:${WEBSITE_HOST_PORT}"
136+
DASHBOARD_BASE_URL: "http://localhost:${DASHBOARD_HOST_PORT}"
136137
SQL_DATABASE_URL: "postgres://postgres:admin@localhost:${POSTGRES_HOST_PORT}/default"
137138
STORAGE_ENDPOINT: "http://localhost:${STORAGE_HOST_PORT}"
138139
STORAGE_BUCKET_NAME: arrhes-files
@@ -192,6 +193,32 @@ services:
192193
VITE_ENV: development
193194
VITE_API_BASE_URL: "http://localhost:${API_HOST_PORT}"
194195
VITE_WEBSITE_BASE_URL: "http://localhost:${WEBSITE_HOST_PORT}"
196+
VITE_DASHBOARD_BASE_URL: "http://localhost:${DASHBOARD_HOST_PORT}"
197+
198+
# Dashboard - SPA dashboard interface (React + Vite)
199+
dashboard:
200+
container_name: arrhes-dashboard
201+
image: arrhes-dev-dashboard:latest
202+
build:
203+
context: ../..
204+
dockerfile: .workflows/dev/packages/dashboard/Dockerfile
205+
args:
206+
NODE_VERSION: "25.2.1"
207+
PNPM_VERSION: "10.26.1"
208+
networks:
209+
default:
210+
aliases:
211+
- dashboard.arrhes.localhost
212+
volumes:
213+
- ../..:/workspace:cached
214+
ports:
215+
- "127.0.0.1:${DASHBOARD_HOST_PORT}:5174"
216+
environment:
217+
# Vite reads VITE_* from .env files, not process.env.
218+
# The entrypoint writes these to packages/dashboard/.env at startup.
219+
VITE_ENV: development
220+
VITE_API_BASE_URL: "http://localhost:${API_HOST_PORT}"
221+
VITE_WEBSITE_BASE_URL: "http://localhost:${WEBSITE_HOST_PORT}"
195222

196223
# Worker - Background job processor (Bull queue + Redis pub/sub)
197224
worker:
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# ==============================================================================
2+
# Dashboard Development Dockerfile
3+
# ==============================================================================
4+
# Minimal Node.js + PNPM image for running the dashboard dev server.
5+
# The full workspace (including node_modules) is bind-mounted at runtime.
6+
# Dependencies must be installed on the host before starting.
7+
#
8+
# Environment variables are set in compose.yml and written to .env at startup
9+
# so Vite can read them (Vite reads VITE_* from .env files, not process.env).
10+
# ==============================================================================
11+
12+
ARG NODE_VERSION="25.2.1"
13+
ARG PNPM_VERSION="10.26.1"
14+
15+
FROM node:${NODE_VERSION}-bullseye-slim
16+
17+
ARG PNPM_VERSION
18+
19+
# Install PNPM
20+
RUN npm install -g "pnpm@${PNPM_VERSION}"
21+
22+
WORKDIR /workspace/packages/dashboard
23+
24+
# Generate .env from compose environment variables, run Panda codegen, then start Vite
25+
CMD ["sh", "-c", "printenv | grep '^VITE_' > .env && cd /workspace/packages/ui && pnpm panda codegen && cd /workspace/packages/dashboard && pnpm panda codegen && pnpm dev -- --host 0.0.0.0"]

.workflows/dev/up.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ mailpit_ui_host_port=$(_allocate_port_for_key MAILPIT_UI_HOST_PORT)
7272
mailpit_smtp_host_port=$(_allocate_port_for_key MAILPIT_SMTP_HOST_PORT)
7373
postgres_host_port=$(_allocate_port_for_key POSTGRES_HOST_PORT)
7474
redis_host_port=$(_allocate_port_for_key REDIS_HOST_PORT)
75+
dashboard_host_port=$(_allocate_port_for_key DASHBOARD_HOST_PORT)
7576

7677
cat > "$PORTS_FILE" <<EOF
7778
WEBSITE_HOST_PORT=$website_host_port
@@ -82,6 +83,7 @@ MAILPIT_UI_HOST_PORT=$mailpit_ui_host_port
8283
MAILPIT_SMTP_HOST_PORT=$mailpit_smtp_host_port
8384
POSTGRES_HOST_PORT=$postgres_host_port
8485
REDIS_HOST_PORT=$redis_host_port
86+
DASHBOARD_HOST_PORT=$dashboard_host_port
8587
EOF
8688

8789
if ! WEBSITE_HOST_PORT="$website_host_port" \
@@ -92,6 +94,7 @@ if ! WEBSITE_HOST_PORT="$website_host_port" \
9294
MAILPIT_SMTP_HOST_PORT="$mailpit_smtp_host_port" \
9395
POSTGRES_HOST_PORT="$postgres_host_port" \
9496
REDIS_HOST_PORT="$redis_host_port" \
97+
DASHBOARD_HOST_PORT="$dashboard_host_port" \
9598
"${DC[@]}" up --detach --build --force-recreate --wait; then
9699
echo ""
97100
echo "=============================================="
@@ -113,6 +116,7 @@ echo " Arrhes Development Environment"
113116
echo "=============================================="
114117
echo ""
115118
echo " Services:"
119+
echo " Dashboard: http://localhost:$dashboard_host_port"
116120
echo " Website: http://localhost:$website_host_port"
117121
echo " API: http://localhost:$api_host_port"
118122
echo ""
@@ -134,3 +138,4 @@ echo " Password: admin"
134138
echo ""
135139
echo " Logs: docker compose -f $COMPOSE_FILE logs -f"
136140
echo "=============================================="
141+
echo ""

0 commit comments

Comments
 (0)