trackit / backend /README.md
devZenaight's picture
npm run dev
479f206
|
Raw
History Blame Contribute Delete
3.44 kB
# Slip Scanner Backend (FastAPI)
FastAPI service exposing a /scan endpoint to process receipt images:
- Validates Supabase user via Authorization: Bearer <supabase_jwt>
- Detects edges and crops the receipt (OpenCV, perspective transform)
- Performs OCR via Hugging Face Inference API (TrOCR)
- Uploads the cropped image to Supabase Storage
- Inserts a row into the slips table with extracted metadata
## Prerequisites
- Python 3.11+
- Supabase project with Storage and Postgres
- Hugging Face account and API token
## Environment Variables
Create a .env file in backend/ with:
SUPABASE_URL=...
SUPABASE_ANON_KEY=...
SUPABASE_SERVICE_ROLE_KEY=...
SUPABASE_STORAGE_BUCKET=slips
HUGGINGFACE_API_TOKEN=...
HF_OCR_MODEL=microsoft/trocr-base-printed
FRONTEND_CORS_ORIGIN=http://localhost:3000
Notes:
- Use the Service Role key server-side only. Never expose it to the frontend.
- If you prefer signed URLs, adjust upload_bytes_to_supabase_storage accordingly and do not make the bucket public.
## Install & Run (Windows PowerShell)
cd backend
python -m venv .venv
. .venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
## API
### Health
GET http://localhost:8000/health
### Scan
POST http://localhost:8000/scan
Authorization: Bearer <supabase_jwt>
Content-Type: multipart/form-data
file=@/path/to/receipt.jpg
cURL example:
curl -X POST http://localhost:8000/scan \
-H "Authorization: Bearer $SUPABASE_JWT" \
-F "file=@receipt.jpg"
Response:
{
"ok": true,
"slip": {
"id": "...",
"user_id": "...",
"image_url": "https://...",
"amount": 250.0,
"category": "Food",
"raw_text": "...",
"created_at": "2025-09-15T10:00:00Z",
"crop_confidence": 0.8
}
}
## Supabase Setup
### Storage Bucket (public or signed)
- Create bucket slips.
- For public previews, enable public read on the bucket or a specific folder per user. Alternatively, keep private and generate signed URLs server-side.
### Table
Create table slips (adjust types as desired):
create table if not exists public.slips (
id uuid primary key default gen_random_uuid(),
user_id uuid not null,
image_path text not null,
image_url text,
raw_text text,
amount numeric,
category text,
crop_confidence real,
created_at timestamptz not null default now()
);
alter table public.slips enable row level security;
RLS policies (only owner reads/writes their slips):
create policy "slips select own" on public.slips
for select
using (auth.uid() = user_id);
create policy "slips insert own" on public.slips
for insert
with check (auth.uid() = user_id);
create policy "slips update own" on public.slips
for update
using (auth.uid() = user_id);
### Frontend Config
In Next.js .env.local:
NEXT_PUBLIC_API_URL=http://localhost:8000
NEXT_PUBLIC_SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
From the client, include the Supabase session JWT as the Authorization header when calling /scan.
## Design Notes (rules.md alignment)
- Mobile-first UX is handled in the Next.js app; backend is stateless and fast.
- No sensitive keys in frontend; backend uses Service Role for Storage/DB.
- Performance: edge detection and OCR happen server-side; images are resized and optimized.
- Security: RLS ensures users only see their own slips; Storage access can be scoped.
## Dev Tips
- OpenAPI docs: http://localhost:8000/docs
- If HF model cold-starts and returns 503, retry the request after a few seconds.