Proudly debugging the system since 1981

Tag: self-hosted

BookmarkFox: resuscitare Delicious con Firefox e un po’ di AI-assisted coding

C’è un momento, per chi naviga il web da abbastanza tempo, in cui capisci che un servizio chiuso non è mai stato davvero sostituito. Per me quel servizio era Delicious.

Chi se lo ricorda sa di cosa parlo: un modo semplice per salvare i segnalibri, taggarli, e condividerli con altri. Quando Delicious ha chiuso i battenti, ho passato anni a provare alternative — estensioni, servizi cloud, note app riadattate — senza trovare niente che replicasse quel flusso naturale: trovo un sito interessante, lo salvo con un click, lo condivido con chi mi segue. Alla fine ho deciso di risolvere il problema alla vecchia maniera: scrivendomi l’alternativa da solo.

È nato così BookmarkFox, un’estensione per Firefox che comunica con un backend web per pubblicare i segnalibri. Niente di rivoluzionario nell’idea, ma è esattamente quello che mi serviva — e visto che non esisteva, l’ho costruito.

Il problema: nessuna vera alternativa a Delicious

Le opzioni moderne per gestire segnalibri condivisibili sono o troppo pesanti (servizi enterprise di bookmarking/knowledge management) o troppo chiuse in un ecosistema (salvataggi legati a un singolo social o browser). Mancava qualcosa di leggero, personale, e soprattutto self-hosted: un’estensione che facesse una cosa sola, bene, e che mi lasciasse controllo pieno sui dati.

BookmarkFox nasce da questa esigenza precisa: un’estensione Firefox minimale che pubblica i segnalibri su un backend che gestisco io, raggiungibile su bookmarkfox.b0sh.net.

Come ho lavorato: SpecKit invece del solito “vibe coding”

La parte che mi interessa raccontare di più, però, non è il “cosa” ma il “come”. Negli ultimi tempi ho sviluppato diversi progettini con l’aiuto di modelli AI locali o via API, e il pattern tipico è quello del prompt libero seguito da iterazioni a ruota libera. Funziona, ma con progetti che superano una certa complessità il modello perde il filo, e tu perdi tempo a rispiegare il contesto ogni volta.

Per BookmarkFox ho voluto provare un approccio più strutturato, usando GitHub SpecKit insieme a OpenCode. L’idea di SpecKit è semplice ma efficace:

  • Si parte da un prompt utente ad alto livello (l’idea del progetto).
  • SpecKit guida una fase di analisi dettagliata, trasformando l’idea grezza in una specifica vera e propria.
  • C’è una fase di clarification: il sistema pone domande specifiche per chiarire ambiguità prima di scrivere codice, invece di assumere e sbagliare.
  • Solo dopo la specifica viene suddivisa in task ben definiti, ognuno con un perimetro chiaro.

Il vantaggio pratico? Un modello non enorme — nel mio caso DeepSeek V4 Flash, con 250k di contesto — riesce a lavorare bene su singole task senza dover tenere “in mente” tutta l’architettura del progetto contemporaneamente. Ogni task è autoconclusiva, con contesto sufficiente ma non eccessivo. Il risultato è un workflow più prevedibile, meno “allucinazioni” da perdita di contesto, e codice più coerente con l’architettura pensata a monte.

È un cambio di paradigma interessante: non si tratta di usare un modello più potente, ma di strutturare meglio il problema perché anche un modello più leggero possa affrontarlo con efficacia. Per chi lavora con LLM locali o con budget di context window limitati, è una lezione che vale la pena portarsi a casa.

Il risultato

BookmarkFox oggi è operativo:

  • L’estensione è scaricabile dalle release su GitHub.
  • Il backend che gestisce la pubblicazione dei segnalibri è live su bookmarkfox.b0sh.net.
  • Il codice è open source, disponibile per chiunque voglia guardare sotto il cofano, contribuire, o semplicemente farsi un’idea di come è stato strutturato il progetto con SpecKit.

Non è (ancora) Delicious 2.0, ma è già quello che mi serviva: un modo veloce per salvare e condividere i siti interessanti che trovo in giro, senza dipendere da un servizio terzo che può chiudere domani.

Cosa mi porto a casa

Al di là del progetto in sé, l’esperienza con SpecKit mi ha convinto che il futuro dell’AI-assisted coding per progetti non banali passa da qui: meno prompt-e-spera, più analisi-chiarifica-scomponi. È un investimento di tempo iniziale che si ripaga abbondantemente quando il progetto cresce oltre le due-tre funzioni.

Se usi Firefox e ti manca un modo semplice per salvare e condividere segnalibri, dai un’occhiata a BookmarkFox. E se sei curioso di provare tu stesso il workflow SpecKit + LLM locale, è un ottimo punto di partenza per progetti di dimensioni simili.

PhotoPrism AI Curator: aggiornamenti, raffinamenti e una web UI

Qualche tempo fa ho scritto di aver costruito un selezionatore AI per PhotoPrism, un piccolo strumento che usa modelli locali per scegliere le foto migliori e creare album automatici. Il post originale raccontava il primo prototipo: ranking estetico puro, clustering semantico, e una CLI minimale.

Da allora ho lavorato molto sul progetto, aggiungendo funzionalità, migliorando la stabilità e rendendo tutto più facile da usare.

Da Ollama a Ollama e LM Studio

Una delle richiesta più comuni che ho visto in giro per progetti simili è la possibilità di usare backend diversi. Nel primo post parlavo solo di Ollama come backend AI. Ora lo strumento supporta anche LM Studio, con API OpenAI-compatibili.

Che significa, in pratica? Se desideri avere più controllo e scelta di modelli, puoi usare LM Studio senza cambiare nulla nel flusso di lavoro. Nell’interfaccia web e nella CLI il passaggio è trasparente: basta cambiare il backend nei parametri e puntare all’URL del server corretto.

Deduplicazione tempo e spazio, non solo semantica

Nel post originale parlavo di clustering semantico: le foto venivano raggruppate per similarità di descrizione e poi selezionate a rotazione per evitare ripetizioni. Funzionava, ma a volte finivo comunque con foto troppo simili, scattate nello stesso istante e nella stessa posizione.

Ho aggiunto un secondo livello di deduplicazione temporale e geografica. Dopo la selezione iniziale, lo strumento rimuove automaticamente le foto che sono entro 30 secondi e 100 metri l’una dall’altra, tenendo sempre quella con il ranking estetico migliore.

Il risultato è un album più vario, con meno “serie di foto quasi identiche” e più momenti distinti.

Logging professionale con Logback

Il primo prototipo scriveva log in modo un po’ artigianale, spesso su stdout o in file senza gestione. Per un tool che può girare automaticamente su grandi archivi, serve qualcosa di più robusto.

Ora il progetto usa Logback con:

  • logging su file (logs/photoprism-ai.log)
  • rotazione giornaliera
  • retention di 7 giorni
  • nessun output su stdout, tranne barre di progresso essenziali

Nel log trovi:

  • prompt di clustering (DEBUG)
  • rimozioni per dedup temporale/spaziale (INFO)
  • nomi dei cluster finali (INFO)

Prompt emozionale e descrizioni più ricche

Uno dei problemi iniziali era che il modello multimodale produceva descrizioni troppo brevi o generiche, il che rendeva il clustering meno efficace.

Ho:

  • aumentato la descrizione a 30 parole per ogni foto
  • introdotto un prompt emozionale più ricco, per spingere il modello a valutare anche composizione, originalità e “atmosfera”, non solo要素 tecnici

Il clustering ne beneficia molto: le categorie sono più pulite e coerenti.

Batch, thread e performance

Nel primo post parlavo di timeout e latenza come principali colli di bottiglia. Ho fatto diversi affini:

  • batch da 30 richieste per il clustering
  • 3 thread per il processing parallelo
  • caching più intelligente di takenAt, titolo, coordinate e luogo
  • retry automatico per le chiamate AI in caso di errore

Questi cambiamenti hanno reso il tool più stabile e veloce, soprattutto su archivi grandi.

Barra di progresso e Web UI

La CLI funziona bene, ma per molti utenti un’interfaccia visuale è più comoda. Ho quindi sviluppato una Web UI leggera con:

  • Javalin come server embedded
  • HTMX per dinamicità senza scrivere JavaScript complesso
  • una barra di progresso per il clustering, con conteggio batch in tempo reale

La Web UI permette di:

  • scegliere mese singolo o anno intero
  • specificare quante foto selezionare
  • personalizzare il prompt di valutazione
  • scegliere il nome dell’album

Il form è semplice, ma copre tutti i casi d’uso principali.

Modalità anno intero

Nel post originale parlavo solo di selezione per mese. Ora c’è anche una modalità anno intero: lo strumento processa tutti i 12 mesi in sequenza, accumulando le foto migliori di ogni mese in un unico album annuale.

È utile per creare album tipo “Best of 2025” o “Viaggi 2025” senza dover lanciare manualmente 12 selezioni separate.

Cache arricchita e pool temporaneo

La cache (ai-cache.json) ora conserva per ogni foto:

  • score estetico
  • descrizione generata dall’AI
  • cluster assegnato
  • titolo, coordinate, takenAt, placeLabel, placeCity, placeState, placeCountry

Il pool temporaneo pre-dedup viene salvato in {albumName}.json, utile per debug e analisi.

CLI più flessibile

Oltre alla Web UI, la CLI è più potente:

bash# Mese singolo
java -jar target/photoprism-ai-curator-1.0.1.jar \
  --no-web --mode month --month 1 --year 2026 \
  --count 20 --album "Mia Selezione"

# Anno intero
java -jar target/photoprism-ai-curator-1.0.1.jar \
  --no-web --mode year --year 2026 \
  --count 20 --album "Best of 2026"

# Prompt personalizzato
java -jar target/photoprism-ai-curator-1.0.1.jar \
  --no-web --mode month --month 1 --year 2026 \
  --count 20 \
  --prompt "Rate composition and originality"

Sono disponibili flag per:

  • percorso del config file
  • forzatura modalità CLI
  • modalità mese/anno
  • mese, anno, conteggio foto
  • nome album
  • prompt di valutazione

Struttura del progetto

Il progetto è ora più maturo e meglio organizzato:

  • AiBackend come interfaccia comune per rating e clustering
  • OllamaClient e LmStudioClient come implementazioni separate
  • PhotoFetcher, AISelector, AlbumManager, ImageHasher come servizi puliti
  • WebServer con Javalin + HTMX
  • JobContext per lo stato thread-safe dei job

Tutto il codice è in Java 17+, con Maven, JUnit 5 e Mockito per i test.

Perché questi aggiornamenti contano

Per me, il punto non è solo automatizzare una classifica di bellezza. Il vero valore sta nel:

  • combinare giudizio estetico, varietà narrativa e vincoli pratici
  • gestire cache, timeout e costi computazionali in modo intelligente
  • offrire un’alternativa locale e controllabile ai servizi cloud per la selezione foto

Con LM Studio, dedup tempo/spazio, Logback, Web UI e modalità anno intero, ritengo che il progetto sia oggi molto più pronto per l’uso quotidiano.


Tutti i dettagli tecnici, commit e modifiche sono disponibili su GitHub.
La commit history è qui: https://github.com/b0sh-net/photoprism-ai-curator/commits/master/.

Ho costruito un selezionatore AI per scegliere le foto migliori da PhotoPrism

Tornare da un viaggio significa quasi sempre ritrovarsi con una quantità ingestibile di foto. Nel caso di Lisbona, il problema non era tanto archiviare gli scatti, quanto riuscire a estrarne una ventina davvero condivisibile: belle, sì, ma anche varie e capaci di raccontare l’esperienza nel suo insieme. PhotoPrism offriva già un’ottima base grazie a geolocalizzazione, riconoscimento facciale, label e strumenti di organizzazione, ma non aveva ancora un modo per comporre automaticamente un album con “le foto più belle” e soprattutto con sufficiente varietà.

Da qui è nata l’idea di un selezionatore AI: una piccola applicazione Java che usa PhotoPrism per recuperare le miniature delle immagini e Ollama per far lavorare due modelli AI, uno multimodale per assegnare un punteggio estetico e produrre una descrizione oggettiva, e un secondo modello testuale per raggruppare semanticamente le foto e selezionarle con più equilibrio.

Il problema vero non era la qualità

Il primo prototipo faceva una cosa molto semplice: prendere le foto da PhotoPrism, inviarle a un modello multimodale su Ollama e chiedere un voto estetico da 1 a 100 insieme a una breve descrizione. Sulla carta sembrava sufficiente, ma in pratica produceva una selezione monotona: immagini molto belle singolarmente, ma spesso troppo simili tra loro.

Era il classico caso in cui un ranking puro ottimizza la qualità locale ma non la copertura narrativa. Se cinque foto dello stesso scorcio o dello stesso momento ricevono voti alti, un algoritmo ingenuo tende a sceglierle tutte. Per costruire un album da condividere, invece, non basta premiare le immagini migliori: bisogna anche evitare la ripetizione.

Continua a leggere

© 2026 b0sh.net

Tema di Anders NorenSu ↑