Community
Chat Logs
Friday, October 23, 2026 (America/New_York)
- bot[ByteCode.News] Andrew Lombardi: Unit Tests are Not the Enemy - https://bytecode.news/posts/2026/10/andrew-lombardi-unit-tests-are-not-the-enemy
- bot[ByteCode.News] Arcana Reads Everything, and Then Some - https://bytecode.news/posts/2026/10/arcana-reads-everything-and-then-some
- bluedreamreal: good take by Lombardi there
- bluealso, what kind of idiot just deletes unit tests...
- liolocblue: Hey blue ! Just to remember, right now there is no package to help with caching in the browser right? Like for instance if you receive props and you wanted to cache those props for the next time the user visits the page, would there be a way to do this?
- liolocCaching is a topic that's always been a bit tough for me to understand (backend vs browser)
- liolocI usually just use packages like tanstack/query that handles the caching mechanisms for me for the browser, and since now I instead typically make the queries in the route, these are backend fetches right? So I can't cache those unless I use redis or something like that right?
- liolocI'm trying to understand what would be the right mechanisms to use caching in Primate for both use cases:
- lioloc1. You're doing a fetch in a route
- lioloc2. You receive props and maybe you want to cache those (or do you need to instead use a query library on the frontend instead and do the call here instead?)
- bluehi lioloc
- bluecan you describe the use case so it's easier to understand? when do you want to cache props? And if you're fetching in a route, that's already on the server, there you'd probably use a caching server like redis. There are plans for a @primate/kv package: https://repopack.com/project/primate/tasks/10
- bluebut I think it'd be easier for me to offer you paths forward if I understand your actual use case
- dreamrealblue: revamped the primate build's topbar
- dreamrealit was getting gross
- bluegood good
- bluedreamreal: release artifacts landed today in repopack; it turned out a bit more than I'd bargained for, but the model is strong, I think; it has products, channels, and releases; releases draw from job runs; and can be promoted to channels. Channels carry access levels (PUBLIC or PROJECT). products are, well, a single publishable entity
- liolocblue: Let's say in a route I fetch: Races and pass them as a prop to Index.vue, races is an array of objects and maybe it can contain 100 results
- dreamrealNoice!
- blueso the `rp` cli is a "product"; it has channels (stable, unstable); and there are releases, either unassigned to any channel (in which case they are project-private), or assigned to a channel
- liolocblue: This is small enough that it isn't an issue without caching I would assume. But let's say there are like 10000 races and I want the experience of the application to feel extremely rapid when I'm moving from page to page, so that I can come back to a previous tab
- bluelioloc: so you load 10k races at once and want to keep it in the browser tab's memory; and those 10k races never change?
- liolocLet's say we want to control when they change, like maybe we want to refetch only after 5 minutes
- liolocso they won't change for 5 minutes
- bluehow would you feel about `response.page(props, { cache: { ttl: 60 /* seconds */ } })`?
- liolocI'm not sure if keeping it in the browser's memory is the best answer btw, I'm just trying to get the fastest experience for a user
- blueand same for response.view
- liolocthat would be neat
- bluethat would be transparent for you; the primate fetch-client would serialise the path, and cache on the serialised key
- bluethe route itself would likely send something like `Primate-Cache: max-age=60` along the response
- blueas a header
- liolocthis is for browser caching or server side caching btw?
- bluebrowser caching
- blueprops caching
- blueserver side caching is the easier problem there because you can write a small cache yourself fairly easily. @primate/kv could help there but it's relatively trivial to do it yourself first. the client part isn't
- liolochave you used something like tanstack/query? They also have the ability to invalidate a cache on the client, for optimistic updates, it can quickly can get confusing imo
- blueI haven't, but I was going to say that what I just purposed is a streamlined version of tanstack/query, where you don't need to manage the caching keys yourself
- bluefrom the documentation of tanstack/query, it appears terribly overengineered to me
- liolocbut what if you wanted to invalidate the cache once a user presses a button for instance?
- liolocwould be neat to be able to do that too
- bluethen we should expose something on `primate/navigate`, probably
- bluehttps://primate-master.repopack.app/blog/primate-043#navigation-that-says-what-it-does
- nevetPrimate — Primate 0.43: diamond migrations, deferred navigation and direct SQL
- bluemaybe navigate.cache.clear()
- liolocyeah would be neat
- liolocI guess it's also because something like tanstack/query is used client side, not server side
- liolocso you'll have multiple different query calls client side, each with their own cache key
- liolocIn primate's case, if you do the fetch in the route directly, wouldn't that mean that "Time to first paint" would be slower than in an app using tanstack/query to load things after?
- liolocI mean naturally it would right? Cause you're fetching before serving the page. I'm thinking like the case of an app's dashboard for a logged in user for instance.
- blueThat's a real distinction, however primate 0.43 will have response.defer
- bluewhich will allow you to use suspence boundaries or awaits inside clients
- bluesuspense*
- bluehttps://primate-master.repopack.app/blog/primate-043#stream-page-data-during-navigation
- nevetPrimate — Primate 0.43: diamond migrations, deferred navigation and direct SQL
- liolocoh wow
- liolocvery neat
- liolocif we introduce caching then maybe with defer you should also be able to invalidate a specific one?
- bluea specific prop?
- liolocyeah
- lioloccause if you have many props, perhaps you don't want everything to reload if you invalidate the cache
- liolocI mean reload every prop
- liolocwhat do you think?
- bluehm, selective browser updates can be hard
- blueI mean, we could potentially support navigate.cache.clear(key). but the mechanism behind it could turn out complicated
- blueif we have `response.page(props, { cache: { ttl: 60 /* seconds */ } })`, the browser would simply not call the route for 60 seconds
- bluebut if we start breaking it down to props, that's a bit harder: the browser needs to call the route for *some* props, and the route suddenly might need to know not to care about some props. the complexity is higher
- liolocyeah for sure
- bluelioloc: this is complex stuff. however, this could make sense:
- blueactivity: response.defer(() => loadActivity(), { ttl: 600 })
- bluethe lazy form means we can save actual work on the server, *for the particular client*
- bluewithout the lazy form, the gains aren't significant
- liolocin essence what does that lazy call mean? as opposed to without the lazy call
- bluewell, imagine we browse back to the page within the cache's lifetime. since we have a mixture between cached and non-cached prompts, primate has to issue a server request
- blueso it issues it with something like "I want this prop, but this prop is already cached and I don't need it)
- bluehowever, something like on this server:
- blueactivity: response.defer(loadActivity(project)),
- bluewill always do the work. loadActivity is essentially a promise-returning function, so the promise will return anyway on the server, and its output would be discard
- bluesomething like:
- blueresponse.defer(() => loadActivity(project), { ttl: 600 })
- bluecan be prevented from running at all if the cache boundary holds
- blues/prompts/props/
- bluethe question whether page-level caching (so an option on response.page) is enough or whether you want the prop granularity
- blueI'm not sure having both mechanisms makes sense, that's a lot of different combinations needed to be accounted for
- blueif prop granularity is actually what you're looking for, then we should explore extending response.defer to accept a lazy function and a ttl
- blueif caching an entire page (=all its props) is what you're looking for, that's easier
- bluebut I'm a bit hesitant to do both
- bluefwiw, the non-lazy form could still make a revisit *feel faster*. since the server work isn't blocking. but it happens anyway, that's a bit of a waste; maybe it's insignificant; though if we're talking about getting 10k records from a db, it might be
- bluedreamreal: would you also benefit from a client cache?
- bluespecifically I think that if someone has loaded an article before, it might be useful to cache. but I don't know the exact model of how you serve articles. you serve the entire rendered html, no?
- liolocwhat if it wasn't a response.defer function but just a "browserCache(" function (name irrelevant)? That way you can just decide whatever you want cached, whether it is the entire html or a specific portion, like props
- liolocjust spitballing ideas
- dreamrealI mean... maybe, but it would rely on a lot of retention
- blueyeah, but "whatever you want" cache still implies someone has to bookkeep that cache, and that's the complex part
- bluea different approach, lioloc, is a offer a `primate/query` or so
- bluehttps://dpaste.com/7NMKZMRM7
- bluebut I feel this is perhaps more relevant for BCN than what you just described
- dreamrealWell, it presumes retention, still
- bluelioloc: maybe you can create a small example and I can play around with it
- blueyes dreamreal, caching is widely also known as retention
- dreamrealstandard use on BCN is not a lot of interrelated post traffic, which annoys me but is reflected in traffic patterns
- bluethank you for stating the obvious :P
- dreamrealI'm not trying to state the obvious, I'm talking about whether that pattern makes sense for BCN, whose traffic patterns would NOT show a benefit as yet
- blueconst response = await posts.get({ path: { slug }, cache: { ttl: 300 },
- blue});
- dreamrealYou wanted me to look, I looked, damn it
- bluedreamreal: lioloc: what do we think about this?
- bluein one line: `const response = await posts.get({ path: { slug }, cache: { ttl: 300 }});`
- blueidk if any of those ideas seems coherent
- dreamrealsure
- dreamrealI don't have a problem with it at all, it just wouldn't affect BCN :D
- bluewell you know me, I'm loath to add things that are over-engineered, or complicated to understand or use
- dreamrealI don't think it's overengineered or difficult to understand
- dreamrealin fact I think its' really easy to understand
- bluewhich of the five options I offered?
- dreamrealThe one that seemed to make sense to me was https://dpaste.com/7NMKZMRM7
- blueoh
- bluedreamreal: flog is live and installable at https://flog.run
- nevetflog — predictable JavaScript package management
- blue(using repopack release primitives)
- blueI will also publish an sdk for releases at @repopack/release; do you need one for java/kotlin as well?
- dreamrealblue: what would primate's BCN build look like with flog?
- dreamrealshould have a "conversion from those other stupid package managers" section
- dreamrealjava's a much harder climb because of maven repositories
- bluedreamreal: well, flog is currently mostly for npm; but the commands aren't js specific. the question is what do you need / what do you expect the workflow to be; generally, flog works like this:
- blueflog add / remove: adds or removes a dependency
- blueflog upgrade: upgrades dependencies (interactively)
- blueflog lock: create a lockfile
- blueflog install: materialises a lockfile
- blueif those primitives are transferable to maven, then there is no reason flog wouldn't be able to manage maven projects / pom.xml projects
- blue(flog add/remove/upgrade also changes a lockfile)
- dreamrealmaven IS a lockfile, there're analogs but they're not esp applicable in the space
- bluedreamreal: just to be clear, you're looking to replace maven on the kotlin/java app, or pnpm on the primate-ui app, or both?
- dreamrealpnpm mainly, although it actually used npm itself unless you changed it
- blueoh ok, then it's different from what I thought
- blueflog should be able to replace pnpm/npm 1:1 and be much faster
- dreamreal*nod* if you want to, try it on ui-primate
- dreamrealgood real-world-ish project
- blueya