Sign in

Jovi 🐨

@jovidecroock.com
1.5K followers 346 following 1.4K posts

🇧🇪 | Software Engineer @Shopify | Building drydock.org | Preact core team | passionate about DX & web perf | opinions are my own

PostsRepliesMedia
Jovi 🐨 @jovidecroock.com · 30/09/2026
Child reconciliation goes through Element.moveBefore() where supported. Reverse a list of 10 iframes: Preact 10 reloads 9, Preact 11 reloads 0, and the focused input stays focused.
Diagram comparing keyed list reordering behavior in Preact 10.29.8 and Preact 11.0.0. In Preact 11, keyed DOM moves use Element.moveBefore() where supported, preserving iframe state and input focus during reordering. Moving one row, reversing the list, and shuffling the list all reload 0 of 10 iframes and keep focus in Preact 11. In Preact 10, the same operations reload 1, 9, and 6 of 10 iframes respectively, and focus is lost in each case.
2181
Jovi 🐨 @jovidecroock.com · 30/09/2026
preact/compat is now tree-shakeable per feature. A library that only imports memo or forwardRef pulls in ~1.3–1.4 kB of compat instead of ~2.2 kB (−35–40% for single APIs).
Bar chart comparing Preact 10.29.8 and Preact 11.0.0 bundle sizes for preact/compat features. Preact 11 reduces compat code for individual React APIs by roughly 35–40%: memo drops from 2,215 B to 1,418 B, forwardRef from 2,218 B to 1,326 B, useSyncExternalStore from 2,275 B to 1,468 B, Children from 2,190 B to 1,334 B, and createRoot from 2,183 B to 1,316 B. Suspense + lazy drops 13%, from 2,215 B to 1,917 B, while importing everything drops 5.5%, from 3,752 B to 3,547 B. The chart highlights that Preact 11 makes preact/compat tree-shakeable per feature.
1140
Jovi 🐨 @jovidecroock.com · 30/09/2026
Core is 4.5 kB brotli, +75 B over 10.29, while adding Hydration 2.0, minimal-move keyed diffing, moveBefore and createPortal.
Four comparison bars showing Preact 10 vs 11 in terms of published bundle size.

preact +75b at 4459b
hooks +41b at 1419b
compat -177b at 3556b
1130
Jovi 🐨 @jovidecroock.com · 30/09/2026
The npm package went from 1.56 MB to 609 kB (−61%). v11 ships ES modules only, so the CommonJS, UMD and duplicate builds, and most source maps, are gone. The runtime you ship is the same ~40 kB of ESM.
2 bars showing the total package size of Preact, in 10.29.8 it's at 1.56MB and at 11.0.0 609KB which is 61% reduction in size.
1293
Jovi 🐨 @jovidecroock.com · 11/09/2026
Every MCP callTool in TypeScript takes a string and returns unknown, mcp-tada reads the server once and ensures every tool-call has the proper names, input- and output types.
2116
Jovi 🐨 @jovidecroock.com · 08/09/2026
Preact 11 will be tree-shakeable, you pay what you use of preact/compat. Soon you won't pay for createElement when using the jsx method. We're continuously trying to give the smallest bundle size, and 600 bytes saved might not seem like a lot but... to us it is
Side-by-side BundleJS comparison showing preact/compat before and after becoming tree-shakeable. The current version bundles render at 7.06 kB gzip with a 1.56 MB publish size, while the release candidate bundles the same import at 6.49 kB gzip with a 601 kB publish size.
1603
Jovi 🐨 @jovidecroock.com · 29/08/2026
Been playing a bit with WebMCP over the past few days and I kind of like where this is going.
152
Jovi 🐨 @jovidecroock.com · 26/08/2026
Three-panel Scooby-Doo unmasking meme. In the first panel, Fred approaches a masked villain with the caption “Finally a good EU model.” In the second, the masked figure is labeled “Le Chaton Fat.” In the final panel, Fred removes the mask to reveal the villain underneath labeled “GLM 5.2.”
140
Jovi 🐨 @jovidecroock.com · 10/08/2026
Released the first release candidate of Preact 11 and I'm pretty proud that all of the packages combined actually shrunk by 100 bytes while adding A LOT of features!
A screenshot of bundle-js where we export preact, preact/hooks and preact/compat on the release candidate tag. It evaluates to 9.25kb gzip
3565
Jovi 🐨 @jovidecroock.com · 03/08/2026
pracht 0.11 ships the capability graph. Define a typed operation once. pracht projects it to your server code, an HTTP endpoint, a WebMCP page tool, and your HTML form. Humans and agents call the same contract. pracht.resynapse.dev/docs/capabil...
export default defineCapability({
  title: "Search notes",
  input: {
    type: "object",
    properties: { query: { type: "string", minLength: 1 } },
    required: ["query"],
    additionalProperties: false,
  },
  effect: "read",
  middleware: ["auth"],
  expose: { http: true, webmcp: true },
  async run({ input }) {
    return { notes: searchNotes(input.query) };
  },
});
190
Jovi 🐨 @jovidecroock.com · 11/06/2026
Looks to always be erroring out for me, I know that I'm futuristic but this is a bit much eh
Account handle: jovidecroock.com with an error underneath saying that client_assertion failed due to a failed iat claim, timestamp check failed (it should be in the past)
110
Jovi 🐨 @jovidecroock.com · 11/06/2026
I did not expect to see urql on the new react foundation website. Looks like we’re in for big changes in React land and I’m all here for it! What’s next? Signals?!
Supported ecosystems on the new react foundation website, listing: relay, tanstack query, swr, apollo client, trpc, urql and react native firebase
4100
Jovi 🐨 @jovidecroock.com · 09/06/2026
As a spoiler, it's a workbench to vet your release or CI gated publish before releasing. It's been delivering great work for some of my repos already
A workbench showing `@preact/signals-debug` moving from 1.4.2 to 1.4.3. Underneath a green badge showing likely safe with the explanation that no blocking signals were found in the released files.

Underneath we see a comparison of what changed between the two versions and underneath the lack of changes to the manifest files.
110
Jovi 🐨 @jovidecroock.com · 23/05/2026
Maybe simulating it when a gyp file is found is enough for now, I'll have to test it
010
Jovi 🐨 @jovidecroock.com · 21/05/2026
Work in progress on my workbench to analyze staged releases
Dark-themed package diff review UI comparing version 0.1.0 with staged 0.1.1. The release tree shows modified files including CHANGELOG.md, index.js, and package.json. The main panel displays a diff for index.js where signedReportsPreview changes from false to true. Reviewer notes below show “MEDIUM,” “NO EXTRA REVIEW,” and “REVIEW RECOMMENDED,” with no assistant findings. Manifest changes indicate package @pracht/experiments updating from 0.1.0 to 0.1.1 with no script or dependency changes.
130
Jovi 🐨 @jovidecroock.com · 21/05/2026
Updating all of the repositories I am part of to use npm stage publish, this is important! Don't forget to also update your OIDC environment to only allow stage publish from OIDC
npm package setting showing allowed actions npm publish or npm stage publish.
1131
Jovi 🐨 @jovidecroock.com · 19/05/2026
It indeed marks my newest post for blog.jovidecroock.com as 100% human-written, that's a relief honestly 😅 was scared that my posts were being dismissed cause of it being seen as AI
030
Jovi 🐨 @jovidecroock.com · 19/05/2026
Update I used a different website and they tell me this same text is 0% AI, suspicious
Another website showing this text is 100% human-written
070
Jovi 🐨 @jovidecroock.com · 19/05/2026
I put my writing in an AI detector and turns out even my writing from 2019 is just a big LLM produced mess
An AI detector scan showing a 76% AI generated on a text I've put in
4400
Jovi 🐨 @jovidecroock.com · 26/04/2026
I’m open-sourcing le chien: a Cloudflare-native AI chat workspace built with Workers, Durable Objects, D1, Hono, Preact, Better Auth, Workers AI/OpenAI via AI Gateway, and Polar.
Dark-mode screenshot of the le chien AI chat workspace, featuring its tamagotchi-style dog companion. The top bar shows the le chien logo, a small dog status icon with a green online dot, and navigation links for Memory, Shortcuts, Billing, and Sign out. A row of model cards sits below, with “Flash” selected as the fastest model. In the chat, the user asks “How’s your life as a pupper?” and the assistant replies as the virtual dog, describing its tamagotchi-like stats: hunger at 48%, energy at 50%, and a content mood, before playfully mentioning rubs, walks, and “wag wag wag.”
3130
Jovi 🐨 @jovidecroock.com · 29/03/2026
This will never get old for me, this happens when you use CloudFlare Kimi K2.5
A chat interface, the model Kimi K2.5 is selected. The user asks "Who are you" and Kimi responds with "I'm Claude, an AI assistant made by Anthropic. I can help with writing, analysis, coding, answering questions, and other tasks. I don't have a physical body or personal experiences—I process information to provide useful, accurate responses."
1120
Jovi 🐨 @jovidecroock.com · 10/03/2026
What if your LLM could debug your application like this, well... Signals might be getting a vite-plugin really soon to allow this capability!
Screenshot of a dark-themed terminal output describing a debugging investigation for an AuthForm bug. The text explains that the password input is mistakenly updating the username signal instead of the password signal, causing form validation to fail with “Password must be at least 8 characters long.” Logs show that typing in the password field triggers updates to the username state (alice -> p -> a -> s ... -> 3) while the password signal never updates. The analysis concludes the issue is likely incorrect field bindings in demos/auth-form/index.tsx around lines 5–8. At the bottom, a build indicator reads “Build · gpt-5.4 · 1m 21s.”
190
Jovi 🐨 @jovidecroock.com · 10/02/2026
In case it gets deleted, this is the exact extract I am talking about
Two posts, the first where Tim Neutkens sais

"It's very disappointing that you end up sharing numbers you know are not final yet. They will be misused to create a false narrative."

And the second where Tim Neutkens sais

"I'm expecting the original post will be deleted? Now that you know it's inaccurately showing frameworks performance."
120
Jovi 🐨 @jovidecroock.com · 06/02/2026
The Graph view is cool but... The updates view is pretty awesome as well
Preact Signals DevTools showing a todo app's reactive dependency graph with 23 updates across 9 signals, including new-todo-text input, todos-list state, all-done computed value, and component renders, with signal updates timestamped at 07:04:47.
091
Jovi 🐨 @jovidecroock.com · 05/02/2026
The new update to signals-debug and the devtools now includes highlights of computeds/signals causing component re-renders! Play with it at stackblitz.com/edit/vitejs-...
A component graph, on the left we see 5 different signal nodes, the first and last node link to a Purple node which refers to a component saying TodoItem. The middle 3 link both to the TodoItem nodes as well as to an orange computed node called all-done which in turn links to a component node called Show.
051
Jovi 🐨 @jovidecroock.com · 06/01/2026
Outrageously slow
A terminal window showing 1220 passing tests executed in 15.67 seconds within chromium.
160
Jovi 🐨 @jovidecroock.com · 21/09/2025
Not sure what's been happening to the NPM downloads of Preact but we've been going parabolic these past few weeks. I know that downloads don't indicate much but always fun to look at a project you've been working on for 7 years gain popularity npmtrends.com/@angular/cor...
A chart showing 4 lines, these represent npm libraries and their downloads.

We can see at the bottom angular core have a steady 4m weekly downloads over the last year, then going up we see vue/runtime-dom evolving from 4 million to the current 6million. Going even more up we see the vue library (vue 2) going from 6Million to 8Million and dropping back to 7Million.

At the top we see the Preact library starting the year around 6M and then now at the end going parabolic to 10million weekly downloads
3182
Jovi 🐨 @jovidecroock.com · 09/08/2025
GPT-5 would really help you make the best. web-apps
A chat where in the top right it sais "in one word how should I maange state in my next web-application" and the reply "Signals."
1191
Jovi 🐨 @jovidecroock.com · 22/07/2025
Fuse may not have taken off but it had a pretty amazing video showing the power of gql.tada gql-tada.0no.co
120
Jovi 🐨 @jovidecroock.com · 09/06/2025
I felt like commenting on this, not with regards to AI or NFT's. Just about GraphQL, I agree that when GraphQL initially came out in 2015 that there was a lot of hype and that the community really didn't benefit from the perceived benefit. The hype <--> value was at a weird point
A chart showing three titles, GraphQL Web3/NFTs and AI. Each of the titles have two vertical bars, on the left value and on the right hype.

For GraphQL we see low value and high hype.
For Web3, we see low value and even higher hype.
For AI we see high value but even higher hype.
130
Jovi 🐨 @jovidecroock.com · 07/06/2025
I also really love the bindings view, it's so clean
The CloudFlare bindings view, on the left we see a node named personal-assisstant (aka the worker) which branches out into 5 other nodes

- Workers AI
- A workflow named ANALYZE_NEWSLETTER
- Browser rendering called BROWSER
- D1 Database called DB
- An R2 Bucket called newsletter_analyzer
120
Jovi 🐨 @jovidecroock.com · 22/04/2025
It's just fun to build things on @cloudflare.social - I have my domains registered at CloudFlare and I decided to send all of my newsletters to one of them. I added an email worker that ingests the newsletter, visits all links and writes a daily summary to Notion for all of them. What a concept!
A notion page, as the icon it is a crystal ball, the title sais newsletter summaries and it contains three items.

Each one is a newsletter summary for a day, April 18, April 21 and April 22 of 2025.
1100
Jovi 🐨 @jovidecroock.com · 14/02/2025
The doge.gov site should look at their hydration mismatch errors... Also stop logging your data in production 😅
A Browser console showing three console error messages, all three of them are React minified errors pointing to https://react.dev/errors/425 (text mismatch error), https://react.dev/errors/418 (node mismatch) and https://react.dev/errors/423 (unrecoverable hydration error).
150
Jovi 🐨 @jovidecroock.com · 28/01/2025
An example
A modal, showing the analysis of an issue

"Based on the closed issue and current documentation, I recommend updating the "Properties and Attributes" section of the Web Components page. The issue reveals an important edge case regarding null/undefined property handling that could cause unexpected behavior, especially with custom elements that expect non-string values. This information would be valuable to developers working with Web Components in Preact."

And then a title, suggested docs addition, it shows a URL in the top-left "/guide/v10/web-components" and then a diff that looks like

@Properties and Attributes

@JSX does not provide a way to differentiate between properties and attributes. Custom Elements generally rely on custom properties in order to support setting complex values that can't be expressed as attributes. This works well in Preact, because the renderer automatically determines whether to set values using a property or attribute by inspecting the affected DOM element.

+ Important Note: When setting properties to null or undefined values, Preact will coerce these values to an empty string ('') when setting them on the DOM element. This behavior can cause unexpected results with custom elements that expect non-string values or need to handle null/undefined states explicitly. For example:

+

+ ```jsx

+ // If MyComponent expects a numeric value or null/undefined:

+ customElements.define('my-component', class extends HTMLElement {

+ set value(val) {

+ // val will be '' instead of null/undefined

+ this._value = val;

+ }

+ });

+ ```

+

+ To handle this case, you may need to implement additional type checking in your custom element's property setters or consider using attributes for null/undefined states.

@When a Custom Element defines a setter for a given property, Preact detects its existence and will use the setter instead of an attribute.
010
Jovi 🐨 @jovidecroock.com · 19/01/2025
I've been loving this little project I've been working on 👀
A card, it shows two textareas. The first one is titled "Suggested docs additions" and shows some markdown, it tells us that we need to update the getting started section, specifically vite and is followed by a diff view tha tells us to update a line about setting Preact up with vite.

The second textarea is labeled issue analysis, it tells us about the solved issue which is titled "cannot read property __h of undefined" and it appears to be a common error that occurs when setting up a new vite application with Preact.
1121
Jovi 🐨 @jovidecroock.com · 06/01/2025
What I think is happening is that plausible is doing some kind of event when you go from the previous page to the next page. When I disable shield, refresh, enable shield, refresh, it will just work.
The learning environment window, on the top right where a code-editor should be there's an empty screen. On the bottom, in a JS console we see an error "plausible is not defined"
200
Jovi 🐨 @jovidecroock.com · 23/12/2024
It is tree-shakeable, a dist folder does not imply that something is not tree-shakeable in the slightest. I would however encourage you to not bundle in dependencies like graphql.web as that would prevent it from sharing with plugins/...
Only kind being exported coming down to 634 bytes gzip
Only print being exported coming down to 1093 bytes gzip
210
Jovi 🐨 @jovidecroock.com · 21/12/2024
Yes, it does, attached a little example from early testing
A github issue

Question: I just opened my vite application and it crashes with the message "cannot read property __h of undefined"

A bot reply:
Summary
The user's Vite application crashes with a "cannot read property __h of undefined" message when opened in the browser.

Response
When an application like Vite crashes with a cryptic "cannot read property __h of undefined" error, it's often a sign that there's an issue with the bundling of dependencies. Try checking your vite.config.ts file and ensure that there aren't any duplicate versions of Preact being added to your bundle. You can do this by adding preact and preact/hooks to your optimizeDeps configuration in vite.config.ts. If you're using a package manager like npm or yarn, you can also try running a deduplication command like npm dedupe or yarn dedupe to remove any duplicate dependencies. This might resolve the issue and allow your application to run smoothly.

Confidence: 80

Sources
Error when I boot my application
100
Jovi 🐨 @jovidecroock.com · 19/12/2024
Looks like there's a theme in when I am not contributing, the yearly music festivals hit hard 😅
A GitHub contribution graph for JoviDeCroock, it shows 2024 with 3668 commits, 348 days contributed and longest streak of 170 days. What stands out is that during June there's often a gap.
181
Jovi 🐨 @jovidecroock.com · 18/12/2024
I'll never not appreciate the people who go through the effort of leaving a comment in State of JS. These are the ones for Preact and as a maintainer I'm forever grateful given the time commitment these things are.
7 pieces of feedback for Preact

- Used it, with all the new additions to React I'd feel uncomfortable with Preact in the future
- Used it, postitive, It's a better React
- Used it, negative, Just doesn't feel neccessary and is too hard to supplement for React.
- Used it, positive, Preact is nice to work with
- Used it, positive, the best of react + the best of Solid - bundle size = I feel as if Preact suffers a branding problem, seen as a Diet React, with people saying "why would i use Preact when I can just use full fat React", ignoring the features that make it stand out from React, like Signals, which lets you use it like React when you need, and use like Solid when you need that
- Used it, positive, Love it. One of my favorite things is embedding it in a userscript or extension to power a UI, since its size is so small. These days, if I need any component framework library, I use Preact
= Used it, postive, the main problem though is that most package support Reaact and fewer support Preact
4364
Jovi 🐨 @jovidecroock.com · 07/12/2024
The rule was export *, also where is your hooks implementation 😇 Jokes aside, huge fan of solid!
A code editor on the left which serves as the input, we see export * from solid-js and export * from solid-js/web in there. On the right we see the built output being 37.2kb and 14.3 kb minzipped.
110
Jovi 🐨 @jovidecroock.com · 07/12/2024
Fear not, you can have VDOM, hooks and signals for 8.35kb minzipped!
A bundle JS page on the left we see a code editor, the code exports all from preact, preact/hooks and @preact/signals. On the right we see the build output which sais "Bundle size 21.9kb -> 8.34kb gzipped"
66311
Jovi 🐨 @jovidecroock.com · 07/12/2024
For the record, the latest bench results
Picture showing the benchmarks of graphql.web vs GraphQL 15/16/17

In parsing GraphQL 15 is the fastest, 1% faster than GraphQL.web, 59% faster than GraphQL 17 and 84% faster than GraphQL 16.

In printing GraphQL.web is the fastest 20 times faster than v15, 63 times faster than v16 and 94 times faster than v17.

In visiting GraphQL v15 is the fastest with 14% improvement over GraphQL.web, 2.2x improvement over GraphQL v17 and 2.9x improvement over v16.
010
Jovi 🐨 @jovidecroock.com · 01/12/2024
Not sure where they got the humour thing from, I am exclusively serious, we're talking GraphQL here. blueskyroast.com/roast/jovide...
The analysis from https://blueskyroast.com/ about JoviDeCroock.com

"Meet Jovi: The GraphQL Whisperer with a Soft Spot for Performance
Jovi's feed is a delightful cocktail of coding wisdom and existential musings, expertly shaken with a twist of humor.

A blend of geeky insights and relatable coder struggles—like reading the GraphQL spec while figuring out the last pizza slice."
030