Today I Learned

Short TIL posts

1852 posts latest post 2026-05-13
Publishing rhythm
Apr 2026 | 23 posts
- This is an interesting problem. I want to make a solution for this on htmx [1]-patterns. I would make user specific routes with an hx-get rather than serving the whole page, serve a partial with hx-oobs to fill in user specific data with a no cache on the cdn level. Note This post is a thought [2]. It’s a short note that I make about someone else’s content online #thoughts References: [1]: /htmx/ [2]: /thoughts/
Looking for inspiration? DigitalHarbor [1] by DigitalHarbor7 [2]. No description available. References: [1]: https://github.com/DigitalHarbor7/DigitalHarbor [2]: https://github.com/DigitalHarbor7
I’m really excited about fastapi-observability [1], an amazing project by blueswen [2]. It’s worth exploring! Observe FastAPI [3] app with three pillars of observability: Traces (Tempo), Metrics (Prometheus), Logs (Loki) on Grafana through OpenTelemetry and OpenMetrics. References: [1]: https://github.com/blueswen/fastapi-observability [2]: https://github.com/blueswen [3]: /fastapi/
I am working on a page for htmx-patterns [1] and I ran into a situation with lots of duplication. Especially when i am using tailwind I run into situations where the duplication can get tedious to maintiain. The solution I found is macros. Now I can use the same code for all of my links, and call the macro to use it. {% macro link(id, text, boosted=false) -%} <a class=" {% if id is none %} pointer-events-none bg-terminal-950 text-terminal-900 ring-terminal-900 {% else %} bg-terminal-950 hover:bg-terminal-900 hover:text-terminal-400 text-terminal-500 shadow-lg shadow-terminal-300/20 hover:shadow-terminal-300/30 ring-terminal-300 {% endif %} cursor-pointer block text-center font-bold py-2 px-4 rounded w-full ring-1 " {% if id is not none %} href="{{ url_for('boosted', id=id) }}" {% endif %} {% if boosted %} hx-boost="true" {% endif %}> {{ text }} </a> {%- endmacro %} <h2 class='text-3xl font-light mt-0 max-w-xl text-center prose-xl mt-8 text-terminal-500'> Boosted Links </h2> <div class='flex flex-row gap-4'> {{ link(prev_id, 'Previous', boosted=True) }} {{ link(next_id, 'Next', boosted=True) }} </div> <h2 class='text-3xl font-light mt-0 max-w-xl text-center...
If you’re into interesting projects, don’t miss out on taipy [1], created by Avaiga [2]. Turns Data and AI algorithms into production-ready web applications in no time. References: [1]: https://github.com/Avaiga/taipy [2]: https://github.com/Avaiga
jinja has a loop variable that is very handy to use with htmx [1]. Whether you want to implement a click to load more or an infinite scroll this loop variable is very handy. {% for person in persons %} <li {% if loop.last %} hx-get="{{ url_for('infinite', page=next_page) }}" hx-trigger="intersect once" hx-target="#persons" hx-swap='beforeend' hx-indicator="#persons-loading" {% endif %} {{ person.name.upper() }} - {{ person.phone_number }} </li> {% endfor %} Now for every chunk of contacts that we load we will trigger the infinite scroll by loading more once the last one has intersected the screen. References: [1]: /htmx/
Out of the box FastAPI [1].">Starlette does not support url_for with query params. When trying to use url_for with query params it throws the following error. starlette.routing.NoMatchFound: No route exists for name "infinite" and params "page" In my searching for this I found starlette issue #560 [2] quite helpful, but not complete, as it did not work for me. import jinja2 if hasattr(jinja2, "pass_context"): pass_context = jinja2.pass_context else: pass_context = jinja2.contextfunction @pass_context def url_for_query(context: dict, name: str, **params: dict) -> str: request = context["request"] url = str(request.url_for(name)) if params == {}: return url from urllib.parse import parse_qs, urlencode, urlparse, urlunparse # Parse the URL parsed_url = urlparse(url) # Parse the query parameters query_params = parse_qs(parsed_url.query) # Update the query parameters with the new ones query_params.update(params) # Rebuild the query string updated_query_string = urlencode(query_params, doseq=True) # Rebuild the URL with the updated query string updated_url = urlunparse( ( parsed_url.scheme, parsed_url.netloc, parsed_url.path, parsed_url.params, updated_...
Kind (Kubernetes in Docker) is a tool that makes it easy to create and tear down local clusters quickly. I like to use it to test out new workflows. Argocd is a continuous delivery tool that makes it easy to setup gitops workflows in kubernetes. Here is how you can setup a new kind cluster and install argocd into it using helm, the kubernetes package manager. kind create cluster --name argocd # your first time through you need to add the argocd repo helm repo add argo https://argoproj.github.io/argo-helm helm repo update # install argocd into the cluster helm install argo argo/argo-cd --namespace argocd --create-namespace # deploy the app of apps kubectl apply -f apps/apps.yaml If you want to add repos and apps to your cluster you can use the argo cli to do that, but first you will need forward the argocd port and login. # Wait until Argo CD API server is available echo "Waiting for Argo CD API server to be available..." while ! kubectl wait --for=condition=available --timeout=60s deployment/argo-argocd-server -n argocd; do echo "Waiting for Argo CD API server to be ready..." sleep 10 done kubectl port-forward svc/argo-argocd-server -n argocd 8080:443 & argocd_admin_pa...
External Link dotesports.com [1] Damn this button had me stuck for way too long. It definitely looks like a button once I see it, but I don’t recall coming into contact with many buttons in the game, I tried to set it ablaze, pull it, fly it, nothing. Note This post is a thought [2]. It’s a short note that I make about someone else’s content online #thoughts References: [1]: https://dotesports.com/hp/news/hogwarts-legacy-argyllshire-map-what-does-the-button-do [2]: /thoughts/
How can I add my YouTube videos via RSS? You can share your videos or other people SocialBee Help Documentation Ā· help.socialbee.com [1] YouTube makes finding rss feeds way too hard. Hats off to them for still supporting it, allowing you to find content outside the algorithm, and consuming content you asked for. But i had no idea you had to search the source code to get it. Note This post is a thought [2]. It’s a short note that I make about someone else’s content online #thoughts References: [1]: https://help.socialbee.com/article/129-how-can-i-add-my-youtube-videos-via-rss [2]: /thoughts/
External Link stackoverflow.com [1] Another interesting option for slow count queries in sqlite. If you haven’t DELETEd any records, doing: SELECT MAX(ROWID) FROM "table" LIMIT 1; Note This post is a thought [2]. It’s a short note that I make about someone else’s content online #thoughts References: [1]: https://stackoverflow.com/questions/8988915/sqlite-count-slow-on-big-tables [2]: /thoughts/
Optimizing SQLite for servers SQLite is often misconceived as a "toy database", only good for mobile applications and embedded systems because it's default configuration is optimized for embedded use cases, so most ... Sylvain Kerkour Ā· kerkour.com [1] Very interesting article by Sylvain, suggested by Simon Willison. Definitely some things that I want to come back and try later on. Here is the TLDR of the whole post PRAGMA journal_mode = WAL; PRAGMA busy_timeout = 5000; PRAGMA synchronous = NORMAL; PRAGMA cache_size = 1000000000; PRAGMA foreign_keys = true; PRAGMA temp_store = memory; This is interesting, and something I need to consider. I definitely have an application with slow count queries. I am not sure how to make it better as its not a full count(*) so a count table doesn’t work, nor does counting by index. I might need to have a table of cached results, and if a write matches the counter increase it, or update all counters on write. COUNT queries are slow SQLite doesn’t keep statistics about its indexes, unlike PostgreSQL, so COUNT queries are slow, even when using a WHERE clause on an indexed field: SQLite has to scan for all the matching records. One solution...
- Inspiring story transitioning into tech from nursing. I also came to tech through a set of circumstances that made it difficult for me to excel at my current job. Looking back it is something that I was always interested in and I was just unsure how to get in, I am so glad that I figured it out, it has been such a great benefit to my family. I really enjoyed listening to trshpuppy’s journey in through building projects, and choosing tech not based on what she wanted to learn, but what fit the project the best. Note This post is a thought [1]. It’s a short note that I make about someone else’s content online #thoughts References: [1]: /thoughts/
I’m impressed by til [1] from jbranchaud [2]. šŸ“ Today I Learned References: [1]: https://github.com/jbranchaud/til [2]: https://github.com/jbranchaud
I came across Hexa [1] from wyattbubbylee [2], and it’s packed with great features and ideas. Hexa is a game engine References: [1]: https://github.com/wyattbubbylee/Hexa [2]: https://github.com/wyattbubbylee
Some Git poll results Some Git poll results Julia Evans Ā· jvns.ca [1] great poll of git [2] questions poll: did you know that in a git merge conflict, the order of the code is different when you do a merge/rebase? merge: <<<<<<< HEAD YOUR CODE OTHER BRANCH’S CODE c694cf8aabe rebase: «««< HEAD OTHER BRANCH’S CODE YOUR CODE d945752 (your commit message) This one explains a lot. I think I knew this, I might have seen it somewhere, but I have definitely noticed it go both ways and confuse the crap out of me. Feels very similar to how --ours and --theirs flip flops. Note This post is a thought [3]. It’s a short note that I make about someone else’s content online #thoughts References: [1]: https://jvns.ca/blog/2024/03/28/git-poll-results/ [2]: /glossary/git/ [3]: /thoughts/
External Link sealed-secrets.netlify.app [1] kubeseal is a pretty simple to get started with way to manage secrets such that they can be stored in a git [2] repo and be picked up by your continuous delivery service. Sealed Secrets provides declarative Kubernetes Secret Management in a secure way. Since the Sealed Secrets are encrypted, they can be safely stored in a code repository. This enables an easy to implement GitOps flow that is very popular among the OSS community. Note This post is a thought [3]. It’s a short note that I make about someone else’s content online #thoughts References: [1]: https://sealed-secrets.netlify.app/ [2]: /glossary/git/ [3]: /thoughts/
In my homelab [1] kubernetes cluster I am using kubeseal to encrypt secrets. I have been using it successfully for a few months now wtih great success. It allows me to commit all of my secrets manifests to git [2] with out risk of leaking secrets. You see kubeseal encrypts your secrets with a private key only stored in your cluster, so only the cluster itself can decrypt them using the kubeseal controller. [3] KubeSeal # [4] https://sealed-secrets.netlify.app/ [5] installation # [6] Installation happens in two steps. You need the kubernetes controller and the client side cli to create a sealed secret. For a more complete instruction see the [docs#installation](https://github.com/bitnami-labs/sealed-secrets?tab=readme-ov-file#installation] installation - controller # [7] Warning **context** Make sure that you are in the right context before running any kubectl commands. kubectl config current-context sealed-secrets is installed using the helm package manager. To install sealed-secrets run the following command. helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets helm install sealed-secrets -n kube-system --set-string fullnameOverride=sealed-...
Just starred codemirror-codeium [1] by val-town [2]. It’s an exciting project with a lot to offer. Codeium code completion integration for CodeMirror 6 References: [1]: https://github.com/val-town/codemirror-codeium [2]: https://github.com/val-town