diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..502415c
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,8 @@
+# AR Test — Environment Variables
+# Copy this to .env on the droplet and fill in the values
+
+# PocketBase public URL (the Traefik-routed domain)
+VITE_POCKETBASE_URL=https://pb.thob.studio
+
+# Frontend public URL
+VITE_FRONTEND_URL=https://ar.thob.studio
diff --git a/.gitignore b/.gitignore
index 039ee62..af96857 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,11 @@
# React Router
/.react-router/
/build/
+
+# Local PocketBase dev data — never commit to production
+/pocketbase/pb_data/
+/pocketbase/pb_migrations/
+/pocketbase/pocketbase
+
+# Keep the root pb_migrations folder tracked (empty placeholder for production)
+!/pb_migrations/.gitkeep
diff --git a/Dockerfile b/Dockerfile
index 207bf93..c0d311b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,6 +12,11 @@ FROM node:20-alpine AS build-env
COPY . /app/
COPY --from=development-dependencies-env /app/node_modules /app/node_modules
WORKDIR /app
+# VITE_ vars are baked into the bundle at build time — must be passed as ARGs
+ARG VITE_POCKETBASE_URL
+ARG VITE_FRONTEND_URL
+ENV VITE_POCKETBASE_URL=$VITE_POCKETBASE_URL
+ENV VITE_FRONTEND_URL=$VITE_FRONTEND_URL
RUN npm run build
FROM node:20-alpine
diff --git a/app/qr-ar/ar-viewer.tsx b/app/qr-ar/ar-viewer.tsx
index b43847e..72d5cdf 100644
--- a/app/qr-ar/ar-viewer.tsx
+++ b/app/qr-ar/ar-viewer.tsx
@@ -69,8 +69,10 @@ export default function ARViewer() {
useEffect(() => {
if (!id) return;
const loadAsset = async () => {
+ // const response = await fetch(`https://thobapi.bopconsultancy.com/v2/ar-assets/${id}`);
const data = await pb.collection('ar_assets').getOne(id);
- if (data) setAsset(data);
+ // const data = await response.json();
+ setAsset(data);
};
loadAsset();
}, [id]);
@@ -177,12 +179,12 @@ export default function ARViewer() {
{asset?.name && (
-
+
{asset.name}
)}
-
diff --git a/app/root.tsx b/app/root.tsx
index 9fc6636..8e0df69 100644
--- a/app/root.tsx
+++ b/app/root.tsx
@@ -11,6 +11,7 @@ import type { Route } from "./+types/root";
import "./app.css";
export const links: Route.LinksFunction = () => [
+ { rel: "icon", href: "/favicon.svg", type: "image/svg+xml" },
{ rel: "preconnect", href: "https://fonts.googleapis.com" },
{
rel: "preconnect",
diff --git a/app/routes/home.tsx b/app/routes/home.tsx
index 31163c0..c9e26a0 100644
--- a/app/routes/home.tsx
+++ b/app/routes/home.tsx
@@ -142,7 +142,7 @@ export default function Dashboard() {
{assets.map((asset) => (
{asset?.name}
@@ -155,7 +155,13 @@ export default function Dashboard() {
className='mx-auto w-40 rounded-lg'
/>
) : (
-
+ asset?.qr_file ? (
+

+ ) :
No QR Image
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..4d0aca4
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,72 @@
+# =============================================================================
+# AR TEST — Application services
+# Deploy path on droplet: /projects/ar-test/
+#
+# Traefik runs in a separate compose (shared infra project) and owns ports 80/443.
+# This project only joins the shared external network `traefik_public`.
+# =============================================================================
+
+services:
+ app:
+ container_name: ar-test-app
+ image: registry.digitalocean.com/bop/ar-test:latest
+ pull_policy: always
+ restart: unless-stopped
+ build:
+ context: .
+ dockerfile: Dockerfile
+ args:
+ - VITE_POCKETBASE_URL=${VITE_POCKETBASE_URL:-https://pb.thob.studio}
+ expose:
+ - "3000"
+ environment:
+ - VITE_POCKETBASE_URL=${VITE_POCKETBASE_URL:-https://pb.thob.studio}
+ - VITE_FRONTEND_URL=${VITE_FRONTEND_URL:-https://ar.thob.studio}
+ depends_on:
+ - pocketbase
+ networks:
+ - traefik_public
+ labels:
+ - "traefik.enable=true"
+ - "traefik.docker.network=traefik_public"
+ - "traefik.http.routers.ar-test-app.rule=Host(`ar.thob.studio`)"
+ - "traefik.http.routers.ar-test-app.entrypoints=websecure"
+ - "traefik.http.routers.ar-test-app.tls.certresolver=defaultresolver"
+ - "traefik.http.services.ar-test-app.loadbalancer.server.port=3000"
+ - "traefik.http.routers.ar-test-app-http.rule=Host(`ar.thob.studio`)"
+ - "traefik.http.routers.ar-test-app-http.entrypoints=web"
+ - "traefik.http.routers.ar-test-app-http.middlewares=ar-test-app-https-redirect"
+ - "traefik.http.middlewares.ar-test-app-https-redirect.redirectscheme.scheme=https"
+
+ pocketbase:
+ container_name: ar-test-pb
+ image: ghcr.io/muchobien/pocketbase:latest
+ restart: unless-stopped
+ command:
+ - serve
+ - --http=0.0.0.0:8090
+ - --dir=/pb_data
+ - --migrationsDir=/pb_migrations
+ volumes:
+ - pb_data:/pb_data
+ - ./pb_migrations:/pb_migrations
+ networks:
+ - traefik_public
+ labels:
+ - "traefik.enable=true"
+ - "traefik.docker.network=traefik_public"
+ - "traefik.http.routers.ar-test-pb.rule=Host(`pb.thob.studio`)"
+ - "traefik.http.routers.ar-test-pb.entrypoints=websecure"
+ - "traefik.http.routers.ar-test-pb.tls.certresolver=defaultresolver"
+ - "traefik.http.services.ar-test-pb.loadbalancer.server.port=8090"
+ - "traefik.http.routers.ar-test-pb-http.rule=Host(`pb.thob.studio`)"
+ - "traefik.http.routers.ar-test-pb-http.entrypoints=web"
+ - "traefik.http.routers.ar-test-pb-http.middlewares=ar-test-pb-https-redirect"
+ - "traefik.http.middlewares.ar-test-pb-https-redirect.redirectscheme.scheme=https"
+
+networks:
+ traefik_public:
+ external: true
+
+volumes:
+ pb_data:
diff --git a/pb_migrations/.gitkeep b/pb_migrations/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/vite.config.ts b/vite.config.ts
index 4a88d58..6fa6aab 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -5,4 +5,8 @@ import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [tailwindcss(), reactRouter(), tsconfigPaths()],
+ server: {
+ port: 5173,
+ host: true, // allow external access (local dev only)
+ },
});