biff

2025-12-12T18:23:25.501689Z

@foo did you have a certain project structure in mind i.e. where do you think a business logic module would belong in biff? Or is a clean separation of concerns actually not supposed to be in the scope of biff? (Not that that would stop me , I can easily achieve what I want by just creating a logic namespace and requiring that in e g. App.clj or something, the question is more out of curiosity)

2025-12-13T12:59:08.018559Z

Was just skimming through yakread and got really intrigued by the macros defget / defpost. That looks like these automatically create routes with the functionality defined in the body - is that correct?

2025-12-13T13:01:42.473769Z

Although they still need to be registered in the module map, so I am not entirely sure what these are supposed to do

2025-12-13T19:03:00.214449Z

yeah, they're intended to make defining routes a little more ergonomic without being magical. they basically just expand into a thing like (def my-route ["/my-route" (fn ...)]). besides that they also integrate at experimental effects-handling approach that I described in https://biffweb.com/p/removing-effects/ (I.e. so instead of calling impure functions, you return data that describes the effect you want to happen, like a database transaction). and finally, defpost does a nifty thing where it auto-generates as endpoint url based on the symbol. it's meant for internal routes that the user won't see in their address bar. E.g. given (defpost foo ...), you'll end up with an endpoint like "/_biff/api/com.example/foo".

🥳 1
2025-12-13T19:04:18.327599Z

FYI I've recently done a new iteration on all that stuff which I'm migrating Yakread to while I do the XTDB migration: https://github.com/jacobobryant/yakread/blob/migrate/src/com/yakread/lib/fx.clj

🥰 1
2025-12-12T18:31:01.088219Z

I've started putting code like that under com.example.lib.*, then your Biff modules would remain under com.example.app.* and other places as needed. I have some notes about my approach to code organization in the yakread readme: https://github.com/jacobobryant/yakread (e.g. see the bullet points). Some of that is specific to Pathom, and I haven't figured out yet if I'll ever try to bring Pathom into Biff by default, so the Biff starter project may or may not follow the same file layout in the future.

2025-12-12T18:33:35.217949Z

At work since we're dealing with a large codebase, we also follow the convention of treating the first layer of namespaces under com.example.lib.* as public APIs and any nested namespaces as private implementation namespaces. so you would define a bunch of functions in e.g. com.example.lib.foo.impl.a and com.example.lib.foo.impl.b, and then in com.example.lib.foo we expose some of those functions via com.taoensso/defalias

2025-12-12T18:33:55.282899Z

Ah cool, I totally forgot to check the yakread code out, that will probably answer my question way more precisely

2025-12-12T18:35:35.372719Z

it's a good codebase to peruse 🙂 the idea is to have that be a good example of a non-trivial biff project, precisely for questions etc like this. I'm in the middle of migrating it to xtdb2 and am also changing a few other things along the way, but the overall structure is the same. that work is on the migrate branch for now: https://github.com/jacobobryant/yakread/tree/migrate

🥳 1
2025-12-12T18:36:52.368779Z

Pathom also sounds interesting, though I haven't fully grasped what exactly it is:sweat_smile:

2025-12-12T18:37:33.987839Z

heh I probably should write a blog post about it sometime. I was skeptical at first, but after I "got it" I've become a huge fan.

2025-12-12T18:38:04.696079Z

mostly helpful for projects once you get in the 10k+ LOC range IMO