Fujimod
Try your camera firmware in the browser and build Fujimod SD boot files.
Gestisci e approfondisci i tuoi veicoli: motore, carrozzeria, assetto, impianto frenante e altro.
Translation pending
LifestyleGitHub @edorebu00OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗App per gestire e approfondire i propri veicoli (auto e moto): schede tecniche per sezione (motore, carrozzeria, assetto, impianto frenante, trasmissione, elettronica), ricerca IA di risorse online (forum, manuali PDF, video, schemi tecnici/esplosi) e chat IA sui documenti caricati (es. libretto uso e manutenzione).
App/
├── web/ App Next.js (App Router) — frontend + backend IA → deploy su Vercel
└── supabase/ Migrazioni SQL (schema DB, RLS, storage buckets)
web/app/api/agent/* per la ricerca web
categorizzata e la chat sui documenti. È l'unico servizio a pagamento a consumo (nessun costo
fisso mensile: paghi solo quando qualcuno usa davvero le funzioni IA).Non c'è nessun backend separato: le API route di Next.js girano come funzioni serverless su Vercel, usano la sessione Supabase dell'utente (quindi le query rispettano automaticamente le policy di Row Level Security) e chiamano l'API Anthropic lato server, senza mai esporre la chiave al browser.
supabase/migrations/0001_init.sql, poi esegui. Questo crea tutte le tabelle, le policy di Row Level Security e i bucket di storage (vehicle-files, vehicle-images), entrambi privati.Project URL → NEXT_PUBLIC_SUPABASE_URLanon public key → NEXT_PUBLIC_SUPABASE_ANON_KEYANTHROPIC_API_KEY.edorebu00/MyVehicle.web.web/.env.example:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYANTHROPIC_API_KEYCLAUDE_MODEL (opzionale, default claude-sonnet-5)cd web
cp .env.example .env.local # compila le variabili
npm install
npm run dev # http://localhost:3000
Nessun costo fisso mensile: paghi solo se e quando l'IA viene effettivamente utilizzata.
L'app si installa dalla schermata Home e si apre a schermo intero, senza barra del browser. Non serve nessuno store: su Android compare l'invito all'installazione, su iPhone si passa da Condividi → «Aggiungi a Home».
Nessuna scelta architetturale è cambiata per ottenerlo — restano componenti server, API route e autenticazione a cookie. Sono stati aggiunti soltanto:
app/manifest.ts — nome, icone, colori e scorciatoie;public/sw.js — service worker volutamente prudente: non mette mai in cache /api/ né
/auth/, e per le pagine va sempre in rete (il contenuto dipende da chi ha fatto l'accesso),
con la pagina /offline come ripiego. Gli unici file messi in cache sono gli asset immutabili
di Next;components/InstallPrompt.tsx — invito all'installazione, con le istruzioni di iOS dove
l'evento di sistema non esiste; si chiude e non ritorna;app/icon.svg con npm run icons (comprese le maskable per Android).Se cambi il logo basta sostituire app/icon.svg: npm run build rigenera tutto. Il nome dei
file contiene l'impronta dell'SVG, quindi cambiando il logo cambia anche il manifest — è l'unico
modo perché Chrome si accorga della modifica e aggiorni l'icona già installata sulla schermata
Home. Su iPhone invece l'icona viene fotografata al momento dell'installazione e iOS non la
rilegge mai: lì serve rimuovere l'app dalla Home e riaggiungerla.
Attenzione al middleware: manifest.webmanifest e sw.js sono esclusi dal matcher. Se ci
passassero dentro verrebbero rimandati al login e l'app non risulterebbe mai installabile — è un
guasto silenzioso, l'app continua a funzionare e sembra solo che «l'installazione non si possa
fare».
La PWA evita i costi e le revisioni degli store, ma non gli obblighi di legge: l'app tratta email, targhe, numeri di telaio e documenti caricati. Mancano ancora un'informativa privacy e la cancellazione dell'account (oggi si cancella un veicolo, non il proprio profilo). Entrambe sono richieste dal GDPR a prescindere da dove l'app viene distribuita.
Il costo è dominato dalla chat: il testo dei documenti caricati viene rispedito al modello a ogni messaggio, e un manuale di medie dimensioni vale da solo ~60.000 token per messaggio, cioè centinaia di volte tutto il resto del prompt. Le scelte sono ordinate per questo.
web/lib/chatPrompt.ts): davanti istruzioni e documenti, con un punto di cache; in coda la
lingua, che l'utente può cambiare. Dal secondo messaggio in poi i documenti si pagano ~un
decimo. Su una conversazione di dieci messaggi sono circa il 75-80% in meno.ORDER BY esplicito (senza, Postgres può restituirli in ordine
diverso e la cache non viene mai riletta) e la finestra della cronologia avanza a blocchi di
sei messaggi invece che scorrere di uno alla volta.web/lib/extractedText.ts): intestazioni e piè
di pagina ricorrenti, numeri di pagina, spaziatura e parole spezzate a fine riga vengono tolti
al momento del caricamento. Quanto si risparmia dipende dal documento — su un manuale con
intestazioni su ogni pagina è dell'ordine del 20-40% — e si risparmia su ogni messaggio futuro.submit_findings, che viene comunque inviato; erano ripetute anche nel prompt di
sistema, e si pagavano due volte. ~36% in meno di testo fisso per chiamata, stesse regole.web_search_20260209): i risultati arrivano ripuliti
dall'impaginazione invece di riversarla nel contesto, dove verrebbe rispedita a ogni giro. Il
ritentativo, quando serve, ha metà delle ricerche a disposizione: deve chiudere, non ricominciare.Notizie e prossime gare sono l'unica funzione IA che gira senza che nessuno la chieda: un
calendario scritto nel codice sarebbe sbagliato entro poche settimane, e date inventate sono
peggio di nessuna data. Il costo è tenuto basso dalla cache (web/lib/motorsport.ts): il
risultato vale 24 ore ed è condiviso da tutti i visitatori, quindi si paga una chiamata al
giorno per lingua effettivamente visitata, non una per visita — nell'ordine di 1 € al mese.
Per cambiare la frequenza si modifica CACHE_SECONDS.
Se la chiave Anthropic manca o la ricerca fallisce, la sezione semplicemente non compare: la
home resta in piedi. Il riquadro è dentro un <Suspense>, così alla scadenza della cache il
resto della pagina non aspetta la ricerca web.
La cache dei prompt non si rompe con un errore: le richieste continuano a funzionare, cambia solo il conto. Le due difese:
cd web && npm run check:cache
verifica le proprietà da cui dipende il riuso (prefisso identico fra turni, blocco volatile in
coda, finestra della cronologia stabile) — da rieseguire dopo ogni modifica a un prompt — e i
log del server, dove ogni chiamata stampa una riga [token] con token riletti dalla cache,
riscritti e nuovi. A regime i riletti devono dominare: se restano a zero, qualcosa a monte del
punto di cache sta cambiando a ogni richiesta.
service_role key, quindi non c'è modo di aggirare le policy: un id di un veicolo o
di un documento altrui semplicemente non restituisce righe.vehicle-files e vehicle-images sono privati e le policy consentono
lettura/scrittura/cancellazione solo sotto il prefisso <user_id>/.... I download avvengono con
link firmati validi 60 secondi.http/https)
sia prima di essere salvati sia prima di essere renderizzati, così uno schema come javascript:
non può diventare codice eseguito al click.frame-ancestors/X-Frame-Options (anti clickjacking), nosniff,
Referrer-Policy, Permissions-Policy e HSTS sono impostati in next.config.mjs.search_results è scrivibile direttamente dal
browser. I risultati ripescati dalla cronologia vengono quindi risanificati anche quando si
rileggono, esattamente come quelli appena arrivati dal modello.pdf-parse 1.1.1 include al suo interno una copia di pdf.js 1.10.100, del 2018, e i PDF
caricati dagli utenti sono l'input non fidato più pesante che l'app elabori lato server.
L'esecuzione di codice nota su quelle versioni di pdf.js (CVE-2024-4367) passa dalla generazione
dei glifi durante il rendering su canvas: qui si chiama solo getTextContent(), quindi quel
percorso non viene attraversato. Resta il rischio generico di un parser vecchio e non più
mantenuto, limitato da maxDuration = 90, dal tetto di 20 MB per file, dal limite di frequenza e
dal tetto di 500 pagine analizzate.
La soluzione è passare a pdf-parse 2.x, che usa pdfjs-dist 5.x (2025). Non è stato fatto
qui perché la 2.x carica @napi-rs/canvas, un binario nativo, anche per la sola estrazione
testo: su Vercel va verificato sul deploy reale (dimensione della funzione, serverExternalPackages,
binari per piattaforma), e non aveva senso rischiare la produzione per chiudere un percorso che
non risulta raggiungibile. È un cambiamento a sé, da fare potendo verificare il deploy.
pgvector su Supabase e un modello di embeddings (es. Voyage AI, partner consigliato da Anthropic).maxDuration = 180, chat e processing documenti maxDuration = 90.