Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Boxwood – simple templating engine for JavaScript, in JavaScript (github.com/buxlabs)
59 points by emilos 14 days ago | hide | past | favorite | 26 comments
Hey!

A while back, I wrote a templating engine (MIT License), which I mostly use for small side projects, either static or ssr generated. Simplicity is one of the main goals.

I'll be happy to answer any questions. The main goal for sharing it is to simply get some feedback.

Best, Emil




Curious about the motivation for this. It’s basically where we were at right before JSX took over, e.g. mercury [1] and the old hyperscript.

Except it’s missing the ability to hydrate components on the client and re-render.

[1] https://github.com/Raynos/mercury


Not the OP but I’m going to guess that, like me, they prefer to render server side where possible, don’t like Handlebars or Pug etc and don’t want to get lost in the quagmire than it NextJS.

I use htmx for as much of my network requests and UI updating as possible as it’s faster to implement features, faster the render and easier to reason around than a SPA front end and JSON response backend - there’s a chance the OP is in a similar boat.

The downside to a JS SSR driven app is the backend templating situation isn’t as expressive as JSX and can feel a bit limiting.

Hopefully OP will chime in and correct of confirm my assumptions.


Correct, that's part of the reason. I've been wanting to move fast without having to worry about the little quirks of different templating languages, frameworks and just get the job done.

I've been using it for small projects and I didn't want to be bothered with all of the setup required to get jsx/tsx transpilation in place.

Another important reason was that I wanted a tool that would let me reach high results in lighthouse, and that's not something you'd get with other tools quickly. Critical css out of the box seemed to be approach that worked for me in this scenario.


TSX doesn't need that much setup: a couple of tsconfig.json compiler options [0], a JSX function of the right shape, optionally a Fragment function of the right shape, and optionally a good definitions file. JSX in general is only a little bit more effort to support Babel's config file in addition to tsconfig.json. The shape of the JSX function (and Fragment function) is really simple. The type definitions you need to write can be complicated, which is why most of the big projects just copy and paste liberally from the massive (hand-maintained?) @types/react, but if a minimal definitions file is simpler than @types/react looks and I've proven that you can meta-type from the lib.dom.ts types to something quite useful instead of hand-maintaining types, in just a few lines of Typescript. [1] [2] (Butterfloat is my low dependency RxJS Observable-powered, non-Virtual DOM TSX-based view engine. Snabbdom is a low dependency Virtual DOM.)

[0] I documented the compiler options and the reasoning behind them in if you expand the Explanations section of this Getting Started document: https://worldmaker.net/butterfloat/#/getting-started

[1] https://github.com/WorldMaker/butterfloat/blob/main/jsx.ts

[2] https://github.com/snabbdom/snabbdom/blob/master/src/jsx.ts


I say this as a frontend dev--if your goal was to convince backend folks that adopting jsx/tsx is not that complicated, my guess is that your comment won't do that. The setup you described might sound simple to you, but it's not for someone who isn't already familiar with the FE ecosystem. The OP wanted a templating library that is simple to setup and use and would score well with lighthouse, but all of a sudden we're talking about lib.dom.ts files and copy pasting from @types/react.

There was a mention of some familiarity with Typescript and that's all I assumed in my comment. I also said most of the work is optional, especially the type definition work.

lib.dom.ts is one of the many lib files shipped with Typescript itself. I mention @types/react mostly as an example of probably what not to do, but it is a simple Node package maintained by DefinitelyTyped and easy to lookup if you did want to do things the brute force way (as many have, because it is easy to do). I also linked to two different examples of the type definition work, they are small files that are maybe not easy to follow in the way they used advanced concepts of Typescript's type system, but show that you can do a lot without copy and pasting thousands of lines from @types/react. You can replace most of the complex types in either file with `any` and get a quick and dirty minimalist type definition file. (If you go far enough back in the commit history of either the files I posted you can find examples of that, too.)

For what it is worth, I test Butterfloat with JSDOM entirely in Node (after Typescript building) and SSR/SSG/progressive enhancement and other backend support has always been on its roadmap, parts of it exist today and other parts were architected with it in mind, but it just hasn't yet been prioritized (because so far it is admittedly a solo project). I also wanted something that was simple to setup and use, backend or frontend, and would score well on lighthouse but also might score well in Web Components and also make sense replacing old Knockout.JS code from a decade or two ago.


Too true.

Also, for some of us, no client side rendering is a feature not a deficiency.

I fully understand how to do everything the parent poster said, I just don’t want to do it and don’t think it’s the best dev experience in my use cases.


You can support TSX and not support client side rendering. I never said anything about client-side rendering. There's no client-side dependencies to TSX at all. Even optionally depending on `lib.dom.d.ts` for a nice Types experience from a .d.ts file doesn't really mean a client-side dependency as a types-only dependency.

The functions in Boxwood are so close already to the necessary shape for a JSX function (it's just `jsx(tagNameOrComponentFunction, properties, children)`) there's not a lot you actually need to do to get nearly "free" JSX support even if you didn't want to put the work into a .d.ts file to get nice Types back out and just did `export type JSX.InternalElements = any`.

That said, the point about `lib.dom.d.ts` is that building the types can be a lot easier than it seems and need only a couple dozen lines to support a lot of rich typechecking including MDN documentation links in hover tooltips.

From personal experience, with multiple libraries, it is a really nice developer experience to have good TSX type checking and type documentation. Auto-complete along speeds up template development and the number of times I've used the MDN link in a property (attribute) hover to check support statistics or edge case notes in the documentation is surprisingly high.


It's funny because this syntax is basically non-JSX JSX/React anyway. I'm sure you could write a JSX transform for this.


That was exactly my thought looking at the example. But that’s great! Both because people finding it useful have the flexibility to use it with JSX if they prefer, and because it helps demystify JSX to see what a potential compile target looks like without the scary angle brackets.

As per the op: “simplicity is one of the goals”

Not every webapp needs client side hydration. It’s very often wasted CPU cycles on a page that’ll be unloaded three seconds later. Personally I’m happy to see projects like this that live outside the monoculture.


At this point with the web I'm more then content to browse the web with the server serving Content-type as text/text for the page.

I don't really need a library like this, but I want to comment to say how much I like the way you made it. Very minimal in itself and also in its dependencies. Very clear documentation in the readme. I wish more libraries and tools were distributed like this.


why not just use es6 template strings?

(I do that for my framework mininext https://github.com/spirobel/mininext would be happy to receive feedback, other view points on this :-)


I wonder if it has an intermediary step that concerts the template to AST?

I like my tools to have as much types generated from context as possible (types from OpenApi, from graphql or from sql queries) and was looking to build a tool like that for handlebars. Idea being that it would tell you which types the template variables used so you could avoid stupid errors at compile time.

It seamed handlebars could provide an AST, but it was kinda hard to used so I scrapped the effort.

Maybe this would be more condusive?


Having a type system wasn't really the goal here (there's enough great tools that handle that), but there's plenty of options that could work for you, if you're willing to build it. Some quick ideas:

1. You could add a jsdoc comment per component, let your tool read it and treat it as the source of truth 2. The template is just a js file, so you could parse it, get the params of the fn and try to deduce the types based on the usage 3. You could use typescript and export types 4. Serialize/normalize data before passing to the templating engine


Reminds me of Smarty, a famous templating language written in templating language.

If I understand this correctly, it seems similar to one use-case for NanoJSX.


Sweet, I have been looking into Node for my Python SSR webapps, but Pug and Handlebars are just not cutting it. Jinja templating language is just soooo good.

This looks like what I wanted in a templating language


Try edge: https://edgejs.dev/

It is mature and feature rich. I like that the expressions can be plain js and it is not coupled with html.


We are using this as a standalone templating engine. It's easy, fast and has good error reporting. This is the main templating engine of AdonisJS.

Fwiw, you can use JSX without React.

Another project on the HN homepage at the moment happens to do this: https://www.val.town/v/maxm/staticChess

    const { renderToString } = require('react-dom/server')

    renderToString(<ul>{[1, 2, 3].map(n => <li>{n}</ul>)}</div>)
Granted, you have to configure it so that JSX is allowed in your JS. For example, by running your code as `tsx server.js`, but I find it so much better than Pug/Nunjucks of yore that it makes up for that downside.

There’s https://mozilla.github.io/nunjucks/ although it hasn’t been maintained for quite some time.


Reminds me a little of https://github.com/ohanhi/hyperscript-helpers

Could this also work in the browser?


You could get a simple version with little modifications, but it wouldn't really be super useful unless you potentially start adding things like lifecycle events (like mount, unmount), reactivity (state, effects).

Otherwise you might end up reimplementing those.

The intentions of the tool were the server side and static use cases and I didn't plan to use it on the client side.


JSX kind of won, no?



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: