chore: CLAUDE.md compliance — relative paths, CORS, README tech stack, .vch-description
- Fix absolute API paths in index.html (/analyze, /move, /preview → relative) - Allow all CORS origins in server.py for reverse-proxy compatibility - Add tech stack section to README.md - Create .vch-description for VCH Showcase Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1
.vch-description
Normal file
1
.vch-description
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Foto-Kurator hilft Fotografen dabei, schlechte Fotos aus einem Shooting schnell auszusortieren. Die App analysiert einen Ordner automatisch auf unscharfe, über- oder unterbelichtete Fotos sowie Duplikate — optional auch mit KI. Bevor Fotos verschoben werden, zeigt die App eine Übersicht zur manuellen Kontrolle an.
|
||||||
@@ -30,3 +30,11 @@ Der Browser öffnet automatisch http://localhost:8000.
|
|||||||
- **KI-Analyse** — Claude Vision API (optional, ca. 0,003 € / Foto)
|
- **KI-Analyse** — Claude Vision API (optional, ca. 0,003 € / Foto)
|
||||||
|
|
||||||
Aussortierte Fotos landen in `_aussortiert/` im analysierten Ordner.
|
Aussortierte Fotos landen in `_aussortiert/` im analysierten Ordner.
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
- **Backend:** Python 3, FastAPI, Uvicorn
|
||||||
|
- **Bildanalyse:** OpenCV (Laplacian Variance), Pillow, ImageHash (pHash/MD5)
|
||||||
|
- **KI-Analyse (optional):** Anthropic Claude Vision API
|
||||||
|
- **Frontend:** Vanilla HTML/CSS/JavaScript (kein Framework)
|
||||||
|
- **Konfiguration:** python-dotenv
|
||||||
|
|||||||
@@ -218,7 +218,7 @@
|
|||||||
// --- Folder picker ---
|
// --- Folder picker ---
|
||||||
el("pick-btn").addEventListener("click", async () => {
|
el("pick-btn").addEventListener("click", async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/pick-folder");
|
const res = await fetch("pick-folder");
|
||||||
if (res.status === 204) return;
|
if (res.status === 204) return;
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
el("folder-input").value = data.folder;
|
el("folder-input").value = data.folder;
|
||||||
@@ -250,7 +250,7 @@
|
|||||||
|
|
||||||
let data;
|
let data;
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/analyze", {
|
const res = await fetch("analyze", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(payload),
|
||||||
@@ -285,7 +285,7 @@
|
|||||||
// --- Review ---
|
// --- Review ---
|
||||||
function makeThumb(path, name) {
|
function makeThumb(path, name) {
|
||||||
const img = document.createElement("img");
|
const img = document.createElement("img");
|
||||||
img.src = "/preview?path=" + encodeURIComponent(path);
|
img.src = "preview?path=" + encodeURIComponent(path);
|
||||||
img.alt = name;
|
img.alt = name;
|
||||||
img.onerror = function() { this.style.display = "none"; };
|
img.onerror = function() { this.style.display = "none"; };
|
||||||
img.addEventListener("click", () => openLightbox(img.src, name));
|
img.addEventListener("click", () => openLightbox(img.src, name));
|
||||||
@@ -380,7 +380,7 @@
|
|||||||
el("progress-label").textContent = "Verschiebe " + toMove.length + " Fotos...";
|
el("progress-label").textContent = "Verschiebe " + toMove.length + " Fotos...";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/move", {
|
const res = await fetch("move", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ paths: toMove, folder: currentFolder }),
|
body: JSON.stringify({ paths: toMove, folder: currentFolder }),
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ app = FastAPI(title="Foto-Kurator")
|
|||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins=["http://localhost:8000"],
|
allow_origins=["*"],
|
||||||
allow_methods=["GET", "POST"],
|
allow_methods=["GET", "POST"],
|
||||||
allow_headers=["Content-Type"],
|
allow_headers=["Content-Type"],
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user