···8787 |> List.map (fun p -> p.slug)
8888 |> String.concat " "
8989 in
9090- let content = Printf.sprintf "@children_order %s\n\n{0 %s}\n\n"
9191- children (month_name month)
9090+ let post_links =
9191+ month_posts
9292+ |> List.map (fun p -> "- " ^ post_link p)
9393+ |> String.concat "\n"
9494+ in
9595+ let content = Printf.sprintf "@children_order %s\n\n{0 %s}\n\n%s\n"
9696+ children (month_name month) post_links
9297 in
9398 Some content
9499
+2
site/blog/2025/03/index.mld
···2233{0 March}
4455+- {{!//blog/2025/03/page-"module-type-of"}The Road to Odoc 3: Module Type Of}
66+- {{!//blog/2025/03/page-"code-block-metadata"}Code block metadata}
+5
site/blog/2025/04/index.mld
···2233{0 April}
4455+- {{!//blog/2025/04/page-"ocaml-docs-ci-and-odoc-3"}OCaml-Docs-CI and Odoc 3}
66+- {{!//blog/2025/04/page-"odoc-3"}Odoc 3: So what?}
77+- {{!//blog/2025/04/page-"semantic-versioning-is-hard"}Semantic Versioning in OCaml is Hard}
88+- {{!//blog/2025/04/page-"meeting-the-team"}Meeting the Team}
99+- {{!//blog/2025/04/page-"this-site"}This site}
+5
site/blog/2025/05/index.mld
···2233{0 May}
4455+- {{!//blog/2025/05/page-"docs-progress"}Progress in OCaml docs}
66+- {{!//blog/2025/05/page-"lots-of-things"}Lots of things have been happening}
77+- {{!//blog/2025/05/page-"ticks-solved-by-ai"}Solving First-year OCaml exercises with AI}
88+- {{!//blog/2025/05/page-"oxcaml-gets-closer"}OxCaml is getting closer...}
99+- {{!//blog/2025/05/page-"ai-for-climate-and-nature-day"}AI for Climate & Nature Community Day}
···2233{0 July}
4455+- {{!//blog/2025/07/page-retrospective}4 months in, a retrospective}
66+- {{!//blog/2025/07/page-week28}Week 28}
77+- {{!//blog/2025/07/page-"odoc-3-live-on-ocaml-org"}Odoc 3 is live on OCaml.org!}
88+- {{!//blog/2025/07/page-week27}Weeks 24-27}
+3
site/blog/2025/08/index.mld
···2233{0 August}
4455+- {{!//blog/2025/08/page-"ocaml-lsp-mcp"}Using ocaml-lsp-server via an MCP server}
66+- {{!//blog/2025/08/page-"ocaml-mcp-server"}An OCaml MCP server}
77+- {{!//blog/2025/08/page-week33}Week 33}
+5
site/blog/2025/09/index.mld
···2233{0 September}
4455+- {{!//blog/2025/09/page-"caching-opam-solutions2"}Caching opam solutions - part 2}
66+- {{!//blog/2025/09/page-"odoc-bugs"}Odoc bugs}
77+- {{!//blog/2025/09/page-"caching-opam-solutions"}Caching opam solutions}
88+- {{!//blog/2025/09/page-"build-ids-for-day10"}Build IDs for Day10}
99+- {{!//blog/2025/09/page-"giving-hub-cl-an-upgrade"}Giving hub.cl an upgrade}
+1
site/blog/2025/11/index.mld
···2233{0 November}
4455+- {{!//blog/2025/11/page-"foundations-of-computer-science"}Foundations of Computer Science}
+2
site/blog/2025/12/index.mld
···2233{0 December}
4455+- {{!//blog/2025/12/page-"claude-and-dune"}Claude and Dune}
66+- {{!//blog/2025/12/page-"an-svg-is-all-you-need"}An SVG is all you need}
+2
site/blog/2026/01/index.mld
···2233{0 January}
4455+- {{!//blog/2026/01/page-"weeknotes-2026-04-05"}Weeknotes for weeks 4-5}
66+- {{!//blog/2026/01/page-"weeknotes-2026-03"}Weeknotes for week 3}
···1010PR.
11111212I mentioned {{!//blog/2026/03/page-"weeknotes-2026-11"}last week} that the
1313-TESSERA reprojection was causing issues with the overlay alignment. Here's
1414-a standalone test showing the Zarr-based pipeline — fetching embeddings,
1515-running PCA, and overlaying the result on a Leaflet map.
1313+TESSERA reprojection was causing issues with the overlay alignment. Now the original
1414+loading of the patches was taking ages, so I switched to zarr to be more efficient.
1515+Also, the PCA was slow, so I switched that over to tensorflow.js to use the GPU.
1616+1717+With these two optimisations in place, it was now a lot quicker to see if the
1818+misalignment was still there. It seemed likely that the issue was translating
1919+between the UTM grid that TESSERA uses and the WGS84 coordinate system that Leaflet.js
2020+is using. It was quite quick to whip up a {{!/tessera-geotessera/Geotessera.Utm.wgs84_to_utm}conversion routine} (click on 'source' to see the gory details!). With that in
2121+place, the overlay now matches up precisely as you can see on the map below.
2222+Be patient while it runs, you'll see the overlay on the map in a few seconds!
16231724{@ocaml kind=setup[
1825#require "tessera-zarr-jsoo";;
···2431(* Load fzstd (Zstd decompressor) and TensorFlow.js *)
2532let () =
2633 let open Js_of_ocaml in
2727- let import url = Js.Unsafe.fun_call
3434+ let import url : unit = Js.Unsafe.fun_call
2835 (Js.Unsafe.get Js.Unsafe.global (Js.string "importScripts"))
2936 [| Js.Unsafe.inject (Js.string url) |] in
3037 import "https://cdn.jsdelivr.net/npm/fzstd@0.1.1/umd/index.js";
···8491 Tessera_zarr.fetch_region ~progress ~store bbox in
8592 Widget.update ~id:"status"
8693 (status_view (Printf.sprintf "Fetched %d×%d. Downsampling..." h_full w_full));
8787- let (mat, h, w) = downsample mat_full ~h:h_full ~w:w_full ~max_pixels:200_000 in
9494+ let (mat, h, w) = downsample mat_full ~h:h_full ~w:w_full ~max_pixels:500_000 in
8895 let bounds = Leaflet_map.{
8996 south = geo_bounds.Geotessera.min_lat;
9097 north = geo_bounds.Geotessera.max_lat;