akagtag commited on
Commit
0604cf4
·
1 Parent(s): 9cd5561

feat: update frontend to proxy requests to Hugging Face Space API and configure environment variables

Browse files
README.md CHANGED
@@ -17,3 +17,11 @@ This Space runs the FastAPI service from `src/api/main.py` and exposes:
17
  - `GET /health`
18
  - `POST /detect/image`
19
  - `POST /detect/video`
 
 
 
 
 
 
 
 
 
17
  - `GET /health`
18
  - `POST /detect/image`
19
  - `POST /detect/video`
20
+
21
+ ## Frontend -> Hugging Face Space API
22
+
23
+ The Next.js frontend now sends requests to `/api/*` and proxies them to your Hugging Face Space.
24
+
25
+ 1. Copy `frontend/.env.local.example` to `frontend/.env.local`.
26
+ 2. Set `NEXT_PUBLIC_HF_SPACE_ID` (default: `akagtag/deepdetection`).
27
+ 3. Optional: set `NEXT_PUBLIC_API_URL` to override and point to a local backend.
frontend/.env.local.example ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Hugging Face Space used by Next.js /api proxy.
2
+ NEXT_PUBLIC_HF_SPACE_ID=akagtag/deepdetection
3
+
4
+ # Optional direct API override (takes precedence over NEXT_PUBLIC_HF_SPACE_ID).
5
+ # NEXT_PUBLIC_API_URL=http://localhost:8000
6
+ # Local Uvicorn example:
7
+ NEXT_PUBLIC_API_URL=http://127.0.0.1:7860
frontend/lib/api.ts CHANGED
@@ -2,9 +2,7 @@
2
 
3
  import type { DetectionResponse } from '@/types/detection'
4
 
5
- const BASE_URL =
6
- process.env.NEXT_PUBLIC_API_URL ??
7
- 'http://localhost:8000'
8
 
9
  async function _post(endpoint: string, file: File): Promise<DetectionResponse> {
10
  const form = new FormData()
 
2
 
3
  import type { DetectionResponse } from '@/types/detection'
4
 
5
+ const BASE_URL = '/api'
 
 
6
 
7
  async function _post(endpoint: string, file: File): Promise<DetectionResponse> {
8
  const form = new FormData()
frontend/next.config.js CHANGED
@@ -1,5 +1,26 @@
1
  const path = require('path')
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  /** @type {import('next').NextConfig} */
4
  const nextConfig = {
5
  reactStrictMode: true,
@@ -8,7 +29,7 @@ const nextConfig = {
8
  return [
9
  {
10
  source: '/api/:path*',
11
- destination: `${process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:8000'}/:path*`,
12
  },
13
  ]
14
  },
 
1
  const path = require('path')
2
 
3
+ function trimTrailingSlash(value) {
4
+ return value.replace(/\/+$/, '')
5
+ }
6
+
7
+ function resolveApiBaseUrl() {
8
+ const explicitApiUrl = process.env.NEXT_PUBLIC_API_URL?.trim()
9
+ if (explicitApiUrl) {
10
+ return trimTrailingSlash(explicitApiUrl)
11
+ }
12
+
13
+ const hfSpaceId = (process.env.NEXT_PUBLIC_HF_SPACE_ID ?? 'akagtag/deepdetection').trim()
14
+ const [owner, space] = hfSpaceId.split('/')
15
+ if (owner && space) {
16
+ return `https://${owner}-${space}.hf.space`
17
+ }
18
+
19
+ return 'http://localhost:8000'
20
+ }
21
+
22
+ const API_BASE_URL = resolveApiBaseUrl()
23
+
24
  /** @type {import('next').NextConfig} */
25
  const nextConfig = {
26
  reactStrictMode: true,
 
29
  return [
30
  {
31
  source: '/api/:path*',
32
+ destination: `${API_BASE_URL}/:path*`,
33
  },
34
  ]
35
  },