Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/images/sections/projects/duckling.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 75 additions & 0 deletions assets/scripts/features/darkmode/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const PERSISTENCE_KEY = "darkmode:color-scheme";

window.addEventListener("load", async () => {
const menu = document.getElementById("themeMenu");
const $icon = document.getElementById("navbar-theme-icon-svg");
if (menu == null || $icon == null) return;

const btns = menu.getElementsByTagName("a");
const iconMap = Array.from(btns).reduce((map, btn) => {
const $img = btn.getElementsByTagName("img")[0];
map[btn.dataset.scheme] = $img.src;
return map;
}, {});

function loadScheme() {
console.log("Loading theme: ", localStorage.getItem(PERSISTENCE_KEY));
return localStorage.getItem(PERSISTENCE_KEY) || "system";
}

function saveScheme(scheme) {
console.log("Saving theme: ", scheme);
localStorage.setItem(PERSISTENCE_KEY, scheme);
}

function getPreferredColorScheme() {
console.log("Getting system theme preference");
const isDarkMode = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
console.log("System prefers dark mode: ", isDarkMode);
return isDarkMode ? "dark" : "light";
}

function setScheme(newScheme) {
let theme = newScheme;
if (newScheme === "system") {
theme = getPreferredColorScheme();
}
console.log("Setting theme to: ", theme);
// set data-theme attribute on html tag
document.querySelector("html").dataset.theme = theme;

// update icon
$icon.src = iconMap[newScheme];

// save preference to local storage
saveScheme(newScheme);

setImages(theme);
}

setScheme(loadScheme());

Array.from(menu.getElementsByTagName("a")).forEach((btn) => {
btn.addEventListener("click", () => {
const { scheme } = btn.dataset;
setScheme(scheme);
});
});
});

function setImages(newScheme) {
const els = Array.from(document.getElementsByClassName("logo-holder"));
for (const el of els) {
const light = el.querySelector(".light-logo");
const dark = el.querySelector(".dark-logo");
if (newScheme === "dark" && dark !== null) {
if (light !== null) light.style.display = "none";
dark.style.display = "inline";
} else {
if (light !== null) light.style.display = "inline";
if (dark !== null) dark.style.display = "none";
}
}
}
1 change: 1 addition & 0 deletions assets/scripts/features/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
if (process.env.FEATURE_ANALYTICS === "1") {
import("./analytics");
}
import "./darkmode";
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions content/posts/category/open-source/duckling-updates/index.de.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
Title: "Some Big Duckling Updates"
Date: 2026-04-16
Category:
Slug: some-big-duckling-updates
hero: ./images/hero.png
reading_time: 5 minutes
---

Es ist ein paar Monate her, seit ich zuletzt über Duckling geschrieben habe (https://davidgs.com/posts/category/open-source/a-fresh-ui-for-docling/), und in dieser Zeit habe ich das Projekt deutlich verbessert. Falls Sie Duckling noch nicht kennen: Es handelt sich um eine Weboberfläche für IBMs Docling-Bibliothek (https://docling.ai/), die leistungsstarke Funktionen zur Dokumentenkonvertierung bietet. Mit Duckling können Sie PDFs problemlos in Text, Word-Dokumente in Markdown konvertieren und sogar OCR auf gescannten Bildern anwenden.

## Was ist neu?

### Verbesserungen der Barrierefreiheit

Zunächst einmal habe ich einige Änderungen zur Verbesserung der Barrierefreiheit vorgenommen, um die App für alle Nutzer benutzerfreundlicher zu gestalten. Es gab Probleme mit Kontrasten, und einige interaktive Elemente waren nicht per Tastatur bedienbar. Außerdem habe ich ARIA-Labels hinzugefügt, um die Unterstützung für Bildschirmlesegeräte zu verbessern. Ich hoffe, dass damit einige der Barrierefreiheitsprobleme der ursprünglichen Version behoben sind.

### Massenverarbeitung vs. Einzeldateiverarbeitung

Was mich an dieser Benutzeroberfläche immer gestört hat, war die Notwendigkeit, zwischen Einzeldatei- und Stapelverarbeitung umzuschalten, um mehrere Dateien zu verarbeiten. Um das zu vereinfachen, habe ich den Stapelverarbeitungs-Schalter in der Kopfzeile entfernt und den Drag-and-Drop-Bereich so angepasst, dass mehrere Dateien gleichzeitig abgelegt werden können. Außerdem kann man jetzt einen ganzen Ordner ablegen (oder im Dateiauswahldialog einen Ordner auswählen), woraufhin alle Dateien im Ordner verarbeitet werden. Nicht unterstützte Dateien werden einfach ignoriert, anstatt eine Fehlermeldung auszugeben.

### Leistungskennzahlen

Ich habe der Seitenleiste einen neuen Tab „Performance“ hinzugefügt, der grundlegende Leistungskennzahlen für die letzte Conversion anzeigt. Dazu gehören die Dauer jedes einzelnen Conversion-Schritts sowie die Gesamtdauer. Dies ist hilfreich, um die Dauer verschiedener Conversion-Typen zu verstehen und Leistungsprobleme zu beheben.

Zunächst haben wir einige grundlegende Zahlen zur Gesamtnutzung usw.

![Das Statistik-Dashboard zeigt die Kennzahlen der Konvertierungsaufträge: Insgesamt 9 Aufträge, davon 9 erfolgreich abgeschlossen, keine Fehler, Erfolgsquote 100 %. Zusätzlich werden eine durchschnittliche Verarbeitungszeit von 0,1 Sekunden und aktuell 0 Aufträge in der Warteschlange angezeigt. Die Benutzeroberfläche hat einen dunkelblauen Hintergrund mit cyanfarbenen und roten Akzenten.](images/stats-1.png)



![](images/hardware-stats.png)



![](images/storage-stats.png)



![](images/input-stats.png)









![](images/generate-chunks.png)



![](images/rag-chunks.png)








62 changes: 62 additions & 0 deletions content/posts/category/open-source/duckling-updates/index.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
Title: "Some Big Duckling Updates"
Date: 2026-04-16
Category:
Slug: some-big-duckling-updates
hero: ./images/hero.png
reading_time: 5 minutes
---

It's been a few months since I [last wrote about Duckling](https://davidgs.com/posts/category/open-source/a-fresh-ui-for-docling/), and in that time, I've made some significant updates to the project. If you haven't heard of Duckling before, it's a web interface for IBM's [Docling](https://docling.ai/) library, which provides powerful document conversion capabilities. With Duckling, you can easily convert PDFs to text, Word documents to Markdown, and even perform OCR on scanned images.

## What's New?

### Accessibility Improvements

Well, first of all I made a bunch of Accessibility changes to make the app more usable for everyone. There were some issues with contrasts, and some of the interactive elements were not keyboard accessible. I also added some ARIA labels to improve screen reader support. Hopefully this addresses some of the accessibility issues that were present in the initial release.

### Bulk vs. Single File Processing

One thing that always bothered me about this interface was the requirement to switch from "single file" to "Batch" processing mode in order to process more than one file. To simplify the process, I removed the "Batch" toggle in the header, and just made the drag-and-drop area able to handle dropping multiple files at once. I also added the ability to drop an entire folder (or select a folder if you're using the file chooser) and have all the files in that folder processed. Oh, and it simply ignores files that are not supported, instead of throwing an error.

### Performance Metrics

I added a new "Performance" tab to the sidebar that shows some basic performance metrics for the most recent conversion. This includes the time taken for each step of the conversion process, as well as the total time taken. This is useful for understanding how long different types of conversions take, and can help with debugging performance issues.

First we have some basic numbers of overall usage, etc.

![Statistics dashboard showing conversion job metrics: 9 total jobs with 9 successes, 0 failures, and 100% success rate. Additional metrics display 0.1 second average processing time and 0 jobs currently in queue. The interface features a dark navy background with cyan and red accent colors](images/stats-1.png)

Next, we we have some details on the performance of the hardware that docling is running on, which is useful for understanding how the performance of the conversion process might vary based on the hardware being used.

![Performance dashboard showing hardware metrics: CPU usage at 15%, Memory usage at 2.5GB, and Disk I/O at 50MB/s. The interface features a dark navy background with cyan and red accent colors](images/hardware-stats.png)

Next we have some overall numbers of the storage used by all the processed documents.

![Storage dashboard showing document storage metrics: 500 total documents processed, 1.2GB total storage used, and 251MB storage used. The interface features a dark navy background with cyan and red accent colors](images/storage-stats.png)

Finally, we have a breakdown of the different types of conversions that have been performed, which can be useful for understanding which types of conversions are most common.

![Conversion breakdown dashboard showing conversion type metrics: 60% PDF to Text, 25% Word to Markdown, and 15% OCR. The interface features a dark navy background with cyan and red accent colors](images/input-stats.png)

At the bottom of that last image you may notice the **Chunking Enabled** section showing that 0 conversions were done with chunking enabled. Here is where the strength of the history comes in handy.

### Chunking History

There is a setting which you can turn on that will generate "chunks" of the document being processed. But what if you've processed a bunch of files without that setting turned on? And now you want to go back and generate those chunks for input into an AI model?

Thanks to having the history of all the conversions you've done stored, you can now select a previously processed document and click a button to generate the chunks for that document.

![Loaded history item showing a previously processed document with a "Generate Chunks" button. The interface features a dark navy background with cyan and red accent colors](images/generate-chunks.png)

A simple click of that button will generate the chunks for that document, and then you can view the chunks in the "Chunks" tab of the sidebar. You can also then save those chunks to a file, or copy them to your clipboard for pasting into an AI model.

![Chunks tab showing the generated chunks for the selected document. The interface features a dark navy background with cyan and red accent colors](images/rag-chunks.png)

### Documentation

Though I still have a long way to go, I have been slowly adding images to the documentation (in the various supported languages) to make it easier to understand how to use the different features of the app.

## Conclusion

These are just a few of the updates I've made to Duckling in the past few months. I'm really excited about the direction this project is going, and I have a lot of ideas for new features and improvements that I want to make in the future. If you haven't tried out Duckling yet, I encourage you to give it a try and let me know what you think! You can find the project on GitHub at [duckling-ui/duckling](https://github.com/duckling-ui/duckling). And yes, I have moved the project out of my own personal GitHub account and into a new organization called "duckling-ui" to make it easier for others to contribute and collaborate on the project. So if you're interested in contributing, please feel free to fork the repo and submit a pull request!
62 changes: 62 additions & 0 deletions content/posts/category/open-source/duckling-updates/index.es.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
Title: "Some Big Duckling Updates"
Date: 2026-04-16
Category:
Slug: some-big-duckling-updates
hero: ./images/hero.png
reading_time: 5 minutes
---

Han pasado algunos meses desde mi última publicación sobre Duckling (https://davidgs.com/posts/category/open-source/a-fresh-ui-for-docling/), y durante este tiempo he realizado importantes actualizaciones al proyecto. Si no conoces Duckling, se trata de una interfaz web para la biblioteca Docling de IBM (https://docling.ai/), que ofrece potentes funciones de conversión de documentos. Con Duckling, puedes convertir fácilmente archivos PDF a texto, documentos de Word a Markdown e incluso realizar reconocimiento óptico de caracteres (OCR) en imágenes escaneadas.

## ¿Qué hay de nuevo?

### Mejoras de accesibilidad

Bueno, antes que nada, hice varios cambios de accesibilidad para que la aplicación sea más fácil de usar para todos. Había algunos problemas con el contraste y algunos elementos interactivos no eran accesibles mediante el teclado. También agregué etiquetas ARIA para mejorar la compatibilidad con lectores de pantalla. Espero que esto solucione algunos de los problemas de accesibilidad que presentaba la versión inicial.

### Procesamiento de archivos en lote frente a procesamiento de archivos individuales

Una cosa que siempre me molestó de esta interfaz fue la necesidad de cambiar del modo de procesamiento de "archivo único" al de "procesamiento por lotes" para procesar más de un archivo. Para simplificar el proceso, eliminé el interruptor de "Procesamiento por lotes" del encabezado y simplemente hice que el área de arrastrar y soltar permitiera soltar varios archivos a la vez. También agregué la opción de soltar una carpeta completa (o seleccionar una carpeta si se usa el selector de archivos) y que se procesen todos los archivos que contiene. Ah, y simplemente ignora los archivos no compatibles, en lugar de mostrar un error.

### Métricas de rendimiento

He añadido una nueva pestaña de "Rendimiento" a la barra lateral que muestra algunas métricas básicas de rendimiento de la conversión más reciente. Esto incluye el tiempo empleado en cada paso del proceso de conversión, así como el tiempo total. Esta información es útil para comprender cuánto tiempo tardan los distintos tipos de conversiones y puede ayudar a solucionar problemas de rendimiento.

Primero tenemos algunas cifras básicas de uso general, etc.

![Panel de estadísticas que muestra las métricas de conversión de trabajos: 9 trabajos en total con 9 éxitos, 0 fallos y una tasa de éxito del 100 %. Las métricas adicionales muestran un tiempo de procesamiento promedio de 0,1 segundos y 0 trabajos actualmente en cola. La interfaz presenta un fondo azul marino oscuro con detalles en cian y rojo.](images/stats-1.png)



![](images/hardware-stats.png)



![](images/storage-stats.png)



![](images/input-stats.png)









![](images/generate-chunks.png)



![](images/rag-chunks.png)








62 changes: 62 additions & 0 deletions content/posts/category/open-source/duckling-updates/index.fr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
Title: "Some Big Duckling Updates"
Date: 2026-04-16
Category:
Slug: some-big-duckling-updates
hero: ./images/hero.png
reading_time: 5 minutes
---

Cela fait quelques mois que je n'ai pas écrit sur Duckling, et depuis, j'ai apporté d'importantes mises à jour au projet. Si vous ne connaissez pas Duckling, il s'agit d'une interface web pour la bibliothèque Docling d'IBM, qui offre de puissantes fonctionnalités de conversion de documents. Avec Duckling, vous pouvez facilement convertir des PDF en texte, des documents Word en Markdown, et même effectuer une reconnaissance optique de caractères (OCR) sur des images numérisées.

## Quoi de neuf ?

### Améliorations en matière d'accessibilité

Tout d'abord, j'ai apporté plusieurs modifications d'accessibilité afin de rendre l'application plus utilisable par tous. Il y avait des problèmes de contraste et certains éléments interactifs n'étaient pas accessibles au clavier. J'ai également ajouté des balises ARIA pour améliorer la compatibilité avec les lecteurs d'écran. J'espère que cela résout certains problèmes d'accessibilité présents dans la version initiale.

### Traitement par lots vs. traitement de fichiers individuels

Ce qui m'a toujours gêné avec cette interface, c'est l'obligation de passer du mode de traitement « fichier unique » au mode « traitement par lots » pour traiter plusieurs fichiers. Pour simplifier la procédure, j'ai supprimé l'option « traitement par lots » dans l'en-tête et j'ai directement intégré la possibilité de glisser-déposer plusieurs fichiers simultanément. J'ai également ajouté la possibilité de glisser-déposer un dossier entier (ou d'en sélectionner un via l'explorateur de fichiers) pour que tous les fichiers qu'il contient soient traités. Enfin, le logiciel ignore simplement les fichiers non pris en charge, au lieu de générer une erreur.

### Indicateurs de performance

J'ai ajouté un nouvel onglet « Performances » à la barre latérale. Il affiche des indicateurs de performance de base pour la dernière conversion, notamment le temps d'exécution de chaque étape et le temps total. Ces informations permettent de mieux comprendre la durée des différents types de conversions et facilitent le dépannage des problèmes de performance.

Nous avons d'abord quelques chiffres de base concernant l'utilisation globale, etc.

![Tableau de bord statistique affichant les indicateurs de conversion : 9 tâches au total, 9 réussies, 0 échec, soit un taux de réussite de 100 %. D'autres indicateurs indiquent un temps de traitement moyen de 0,1 seconde et 0 tâche en attente. L'interface présente un fond bleu marine foncé avec des touches de cyan et de rouge.](images/stats-1.png)



![](images/hardware-stats.png)



![](images/storage-stats.png)



![](images/input-stats.png)









![](images/generate-chunks.png)



![](images/rag-chunks.png)








Loading
Loading