···11+---
22+title: "Xeact: The femtoframework you've been waiting for"
33+date: 2024-01-25
44+tags:
55+ - js
66+ - react
77+series: xeact
88+image: talks/2024/xeact/001
99+---
1010+1111+## Warning to readers
1212+1313+This talk is about [a shitpost](https://github.com/Xe/Xeact) that got way out of hand. Out of respect for the material, this talk is also a shitpost and a work of satire. In order to help make this talk teach you things, I have included technical deep dives into aspects of how and why Xeact works. I hope you enjoy it and you can learn...something useful.
1414+1515+Please don't repeat any of the absurd acts mentioned here in production. I am not responsible for any damage caused by this talk. You are the one copying and pasting my code samples into production.
1616+1717+Otherwise, kick back, grab a beverage, and enjoy the ride.
1818+1919+## Video
2020+2121+<XeblogVideo path="talks/2024/xeact" />
2222+2323+In case the video from XeDN doesn't load, try the [YouTube
2424+version](https://youtu.be/povkpv-mRKw). Please [let me
2525+know](/contact/) with the contents of
2626+[`cdn.xeiaso.net/cgi-cdn/wtf`](https://cdn.xeiaso.net/cgi-cdn/wtf) so
2727+I can diagnose the problem. Hopefully it's not boltdb acting up again.
2828+2929+## Transcript
3030+3131+<XeblogSlide name="2024/xeact/001" essential />
3232+3333+Hi, I'm Xe. I'm the Philosopher-in-Chief at Techaro. You might know me
3434+from my blog or other hit talks I've given like ["AI, the not-so-good
3535+parts"](/talks/2024/prepare-unforeseen-consequences/), or ["Reaching the Unix philosophy's logical conclusion with WebAssembly"](/talks/unix-philosophy-logical-extreme-wasm/), but today
3636+I'm not going to talk about any of my employers.
3737+3838+Today I'm talking about Xeact. It's the femtoframework that your
3939+editor has been waiting for. As I mentioned, Xeact is a
4040+femtoframework. It's designed to help you make your websites load
4141+faster, work with the script tag, and overall helps you live your life
4242+with love and light. It is the perfect basis for your projects and
4343+should scale infinitely.
4444+4545+Asterisk.
4646+4747+<XeblogSlide name="2024/xeact/003" essential />
4848+4949+React is a framework. It gives you all the goodness of working on the
5050+front end, but sometimes it's a bit too big for what you need. So you
5151+reach for Preact. Preact has a lot of the benefits of React, but it's
5252+smaller, which makes it more adaptable and easier to understand. Xeact
5353+is even smaller. It's a femtoframework, which takes ideas from both
5454+React and Preact to get you the smallest possible bundle that can do
5555+what you need.
5656+5757+Today I'm going to cover the foundations of Xeact, how it works, what
5858+I learned in the process, and then we're going to look into the future
5959+with the help of Techaro.
6060+6161+So our industry is based heavily on design. Design is the heart of our
6262+products and it's what our users crave. When I started working on
6363+Xeact, I just started working right on the design first and foremost.
6464+Here are the core principles that I used for designing Xeact.
6565+6666+I wanted the source code to be understandable because let's face it,
6767+when you're debugging things, knowing what's going on means you know
6868+what's going on. Computer programming is complicated. There's a lot of
6969+indirection and access layers and everything that just makes it
7070+difficult to understand. I want the source code of Xeact to fit inside
7171+your mental model so that you don't have to think about it. It's
7272+beautiful.
7373+7474+Zero compile steps. Two steps is too many. If you have more than a
7575+script tag, you're doing it wrong. That's my hope at least. Less time
7676+spending deploying your product, more time spending disrupting the
7777+burrito delivery industry or whatever.
7878+7979+I want the source code to fit on a t-shirt because open source
8080+maintainer burnout is real and one of the main reasons why it happens
8181+is because people don't get paid adequately for their work. This way,
8282+by having the source code available on the t-shirt, you open up
8383+merchandising possibilities that help people make up for the lost
8484+income spent working on open source.
8585+8686+And the entire thing GZipped should fit inside 500 bytes. Egress
8787+bandwidth? Expensive. One gigabyte through managed NAT gateway? Seven
8888+U.S. pennies. That adds up. The less amount of money you spend per
8989+user, the more money you make per user. Xeact saves you time, grief,
9090+your money, and saves your company from bankruptcy.
9191+9292+So, in the beginning, it started out with a function like this.
9393+9494+```javascript
9595+const mkNode = (name, data = {}, children = []) => {
9696+ let result = Object.assign(document.createElement(name), data);
9797+ result.append(...children);
9898+ return result;
9999+};
100100+```
101101+102102+In the beginning, the make node function was created. This has made a
103103+lot of people very happy and has been widely regarded as a good move.
104104+In this young state, this function is small, nimble, adaptable, and
105105+with it came syntax that only a Haskeller could love. But that's okay
106106+because I love Haskell.
107107+108108+```javascript
109109+const blockQuote = (text) =>
110110+ mkNode(
111111+ "blockquote",
112112+ {
113113+ class: "p-4 border-l-4 border-gray-400 bg-gray-100 text-lg font-semibold",
114114+ },
115115+ [
116116+ mkNode(
117117+ "p",
118118+ {
119119+ class: "text-lg font-semibold",
120120+ },
121121+ [text]
122122+ ),
123123+ ]
124124+ );
125125+```
126126+127127+HTML is just a tree, right? Why should our code hide this? You can
128128+kind of see it, right? That kind of resembles how a tree of elements
129129+is. And if you're in the back and you can't see it, I just want you to
130130+imagine it because it's about as perfect as you think.
131131+132132+With all this in mind, I had to rename this function, this make node
133133+function, because that's like, what, six characters and a shift key?
134134+You're going to be typing that all the time. It needs to be short, it
135135+needs to be rememberable, and most importantly,
136136+137137+It needs to be representative of everything because this is
138138+effectively the one function that gives you anything. It's the
139139+universal source of meaning and meaninglessness in your program.
140140+141141+<XeblogSlide name="2024/xeact/017" essential />
142142+143143+With all this in mind, I had one idea. I looked back into my life, I
144144+thought about everything, and one name stood out. This letter came to
145145+me in a divine vision with eight fantastic sides and eight awesome
146146+angles. This letter is the letter H, and with it came a divine vision
147147+that I will repeat now.
148148+149149+One day on the road to Nazareth, Jesus Christ met with a group of
150150+theologians. The theologians realized who he was and stood with him.
151151+Jesus looked upon them in confusion and said unto them, "Who do you
152152+say that I am?"
153153+154154+All at once they replied, "You are the astrological manifestation of
155155+the ground of our being, the kerygma of which we find the ultimate
156156+meaning in our interpersonal relationships. You are the source of love
157157+and life in the world. The foundation, the savior, the alpha, the
158158+omega, the beginning, the end, all and nothing simultaneously, and we
159159+love you for it all."
160160+161161+Upon hearing this, Jesus was taken back a bit. This was a bit much for
162162+him, and he was confused. After some time, he replied, "What the fuck
163163+are you talking about"? Panic sprung up among the theologians. They
164164+had just confused their savior. They had sullied the thoughts of their
165165+messiah. The silence deafened the field.
166166+167167+After some time, one of the theologians managed to speak up.
168168+And they spoke. "h".
169169+170170+Jesus was enlightened.
171171+172172+```javascript
173173+const blockQuote = (text) =>
174174+ h(
175175+ "blockquote",
176176+ {
177177+ class: "p-4 border-l-4 border-gray-400 bg-gray-100 text-lg font-semibold",
178178+ },
179179+ [
180180+ h(
181181+ "p",
182182+ {
183183+ class: "text-lg font-semibold",
184184+ },
185185+ [text]
186186+ ),
187187+ ]
188188+ );
189189+```
190190+191191+This is the name of the function. Now let me paste that code from
192192+earlier, but with the proper name. It just takes the name of a tag,
193193+the list of attributes to apply, and the list of children. And that's
194194+it. That's the entire thing. That's the entire femto framework.
195195+Everything else is just a bunch of helpers to make things more
196196+convenient, like plain text nodes or removing all the children or
197197+grabbing specific things out of the tree or debouncing or onload
198198+handlers. But, you know, that's just standard JavaScript stuff that I
199199+just remade because you can't stop me.
200200+201201+So, this made everything a lot more easy because I could just assemble
202202+the nodes in the way that I understood, which, because I have back end
203203+brain rot syndrome, I just need to do in functions.
204204+205205+And this made Xeact a success.
206206+207207+With this shitpost, I was finally able to understand how to make
208208+frontend UI stuff work. I finally understood how to get an HTTP fetch,
209209+parse the JSON, crap out a bunch of nodes, and then throw it on the
210210+page for people to understand what's going on. And then this basically
211211+unblocked everything else so that I could use everything else
212212+normally.
213213+214214+However, in the process, there was one small problem. Semantic
215215+satiation. If H is supposed to mean everything and it's everywhere, it
216216+loses its meaning. This cannot stand.
217217+218218+So I ended up creating a library to help with it and I made the
219219+femtomixin Xeact HTML. If you look over the code of a bunch of all the
220220+popular websites, you'll see that they use like 15 HTML tags. And even
221221+then, you can put them into three categories, like stuff that usually
222222+takes attributes and children, stuff that only takes attributes or
223223+stuff that stands bu itself, like the horizontal rule tag.
224224+225225+```javascript
226226+const blockQuote = (text) =>
227227+ blockquote(
228228+ {
229229+ class: "p-4 border-l-4 border-gray-400 bg-gray-100 text-lg font-semibold",
230230+ },
231231+ [p(text)]
232232+ );
233233+```
234234+235235+With this knowledge, you can break this down into a list of things, and then you
236236+can create functions for all of them. So here's that same block quote
237237+function, but with you know the function blockquote to create a
238238+blockquote. Wow, so easy! And this is where things really started
239239+making sense because it was a lot easier for me to look at this token
240240+soup and then imagine what it would look like. Press f5. It shows up. I
241241+feel unstoppable.
242242+243243+It was just a continuous series of golden moments that made me a real
244244+full stack developer: kernel to front end.
245245+246246+```javascript
247247+console.log(`import { h, t } from "./xeact.js";`);
248248+console.log(`const $tl = (kind) => (text, attrs = {}, children = []) => {
249249+ children.unshift(t(text));
250250+ return h(kind, attrs, children);
251251+};`);
252252+253253+[
254254+ "h1",
255255+ "h2",
256256+ "h3",
257257+ "h4",
258258+ "h5",
259259+ "h6",
260260+ "p",
261261+ "b",
262262+ "i",
263263+ "u",
264264+ "dd",
265265+ "dt",
266266+ "del",
267267+ "sub",
268268+ "sup",
269269+ "strong",
270270+ "small",
271271+].forEach((tag) => console.log(`export const ${tag} = $tl("${tag}");`));
272272+```
273273+274274+So in order to make this and not lose whatever shred of sanity I had left, I
275275+made a code generator. This is a JavaScript program that prints JavaScript
276276+code to standard output so that you can include it in your JavaScript code.
277277+It's kind of beautiful. Again, if you're in the back, you can't see it because I'm
278278+very bad at formatting code, just imagine like a bunch of things in a list and then
279279+some small forEach at the bottom with an arrow function to actually generate the
280280+code. It's a lot more beautiful in practice than it looks.
281281+282282+At this point, I feel like I need to clarify something very important. I'll circle back to Xeact, but just trust me where I'm going with this. I have a plan.
283283+284284+I'm not an Arch Linux user (by the way), but do use something else that continues to be a source of wisdom.
285285+286286+I use Emacs rigged to act like Vim. One of the main things about
287287+Emacs that continues to give me inspiration is extensibility in its
288288+own little language called Emacs Lisp.
289289+290290+If you've never used Lisp before, it is a very unique kind of violence
291291+where lists are the core data type of everything where everything is
292292+your code and your data. Yes, you can represent data and code in the
293293+same way. And this allows you to create new code on the fly with while
294294+making it impossible to make something that won't parse.
295295+296296+```lisp
297297+ELISP> (+ 3 4)
298298+7
299299+```
300300+301301+So, by default, when you make a list in Lisp, it's considered a code
302302+list. This is something that just immediately gets evaluated. Like,
303303+for example, adding the numbers 3 and 4 and getting 7.
304304+305305+```lisp
306306+ELISP> '(+ 3 4)
307307+(+ 3 4)
308308+```
309309+310310+This is nice and all, but sometimes you need to make data. So they
311311+have this concept of quoting a list to get the data associated with
312312+it. This is so common that it's considered one of the core functions
313313+in Lisp. I think, like, McCarthy has a paper that's, like, 11
314314+functions that you can use to bootstrap the entire Turing complete
315315+world. It's quite a paper, but it is very old and has some 1970s-isms
316316+in it.
317317+318318+But if you notice, you either get all code or all data. Sometimes you
319319+need to go halfsies.
320320+321321+That's why they have this magic thing called quasi-quoting. When
322322+you're assembling complicated things, you will need to mix code and
323323+data together. Quasi-quoting effectively lets you mix the two. Things
324324+normally get quoted, as in you normally have data, but then you can
325325+use a comma to unquote or inject the code value into it.
326326+327327+```lisp
328328+ELISP> (let ((user-name "Xe")
329329+ (user-email "xeact@xeserv.us"))
330330+ (json-serialize
331331+ `((user . ,user-name)
332332+ (email . ,user-email))))
333333+"{\"user\":\"Xe\",\"email\":\"xeact@xeserv.us\"}"
334334+```
335335+336336+So for example, for the sake of argument, I have this associative
337337+list, which is probably known as a hash map in any sensible language.
338338+And I have some variables with let for the user name and user email.
339339+And I build an associative array and I get it back. And why would you
340340+use this? JSON. That's why you would use it. You mix literal names
341341+with variable code.
342342+343343+So if quasi-quoting lets you mix code and data to tree-like
344344+structures, and we mostly deal with web applications that deal with
345345+elements in a tree, what else could we do with this?
346346+347347+HTML. HTML is a tree and we often need to mix literal data and
348348+variable data. So what if we put this all, what if we add this all up
349349+and put it together?
350350+351351+It turns out there's prior art here. I'm not the first person to come
352352+up with the idea of JSX, but JSX is a compiler for JavaScript that
353353+lets you mix HTML literal code and variable JavaScript data, and it
354354+will just transparently compile to all the right JavaScript things
355355+under the hood. It's really nice because it's impossible to create
356356+invalid HTML syntax trees. Well, normally impossible. Otherwise you
357357+found a bug in the JSX compiler, but that's a different story.
358358+359359+```javascript
360360+export const jsx = (tag, data) => {
361361+ let children = data.children;
362362+ delete data.children;
363363+ const result = h(tag, data, children);
364364+ result.classList.value = result.class;
365365+ return result;
366366+};
367367+```
368368+369369+So I experimented and in the process, I decided to see what would
370370+happen if I broke that core tenant of zero compile steps. The
371371+efficiency gains that you do this are phenomenal because code and data
372372+mixed together is just such a lovely pattern that I thought was a
373373+waste of time until I started doing it. I was wrong initially because
374374+I thought the extra step would just be another layer of annoyance, but
375375+it worked out pretty great.
376376+377377+And yeah, what is this? Didn't you just make a big show about not
378378+needing a compile step?
379379+380380+I never said you need to use JSX with this. It turns out that my H
381381+function is depressingly similar to react createElement function. So
382382+with this five line monster, I'm able to adapt it into the create
383383+element into the JSX signature that it wants. And you know, you're off
384384+to the races. You, if you want, you activate the JSX runtime, you
385385+write your backwards PHP all you want, and you're good to go. Instant
386386+deployment to any cloud, including no cloud. And like I said, don't
387387+want it. Don't turn it on. Do you want it? Do turn it on. It's great.
388388+389389+Also, if you're deploying with Nix, the idiomatic Xeact deployment
390390+process, by the way, you should be able to just have Nix handle it for
391391+you, and then you don't even have to think about thinking about it.
392392+It's really great.
393393+394394+It was really easy to get a basic Xeact JSX runtime created because of
395395+that similar function signature, but there was one key thing that it
396396+missed. Components.
397397+398398+However, components in React are just functions, asterisk. All you
399399+have to do is detect if the HTML tag name argument is a function and
400400+then call it. So I did just that.
401401+402402+```javascript
403403+const h = (name, data = {}, children = []) => {
404404+ const result =
405405+ typeof name == "function"
406406+ ? name(data)
407407+ : Object.assign(document.createElement(name), data);
408408+ if (!Array.isArray(children)) {
409409+ children = [children];
410410+ }
411411+ result.append(...children);
412412+ return result;
413413+};
414414+```
415415+416416+And this is the current `h` function in the open source repo. This
417417+allowed me to have, this allowed with everything else, let me have
418418+modern syntax, compiler handrails, and a minimal JavaScript workflow
419419+at the same time. And not to mention, I had compatibility with
420420+React...
421421+422422+...asterisk.
423423+424424+At this point, I had a very nice situation going on. I'd reached
425425+version 0.69.71. It was all in a private repo, internal to work. And
426426+the world of front end that had eluded me for so long was finally
427427+within my grasp and I was able to understand what the JavaScript runes
428428+did and bend them to my chaotic-good will.
429429+430430+In a moment, I knew where this place could be, this new power could be
431431+used for good. I saw a place where it could fit in, and I saw a
432432+feature gap and jumped to fill it.
433433+434434+It was for an internal tool, as one does, called DAB, data about
435435+business. It was effectively a sidebar for the support UI, so the
436436+support people didn't have to open as many tabs when they were trying
437437+to debug what was going on. It was designed with the kind of UI that
438438+only a terminal hacker could love, yet it was ruthlessly effective
439439+enough that when I deployed it in testing, and then realized that it
440440+showed up for the support people by default, because who would think
441441+about having something that doesn't show up by default for support,
442442+they were like, this is amazing, this has already cut down our ticket
443443+response time in half, so I knew I was onto something, so I just kept
444444+going.
445445+446446+It was a success thanks to Xeact.
447447+448448+It was then that I realized that the world needs this power of Xeact
449449+for their single page applications. Sometimes you only need to view
450450+some stuff that requires poking an API, and Xeact fits that goal,
451451+hackery tools that display simple information.
452452+453453+Xeact remains open source software to this day, where it is used by
454454+thousands of milli-developers.
455455+456456+However, when I got to a certain scale, I realized that I made another
457457+mistake here. I was missing something very important that made it
458458+impossible to scale beyond those simple hackery tools to view web
459459+forms. I was missing the fact that React components are monads.
460460+461461+This isn't gonna be a monad tutorial. There's no burritos here. But
462462+the small reason, the reason why I was missing this is because of a
463463+fifth design principle that is a secret and will now be revealed.
464464+465465+The separation of Church-Turing and state. The idea is that the state
466466+was supposed to be external to your Xeact components. And you know,
467467+the Xeact components were just supposed to render HTML notes. And this
468468+sounds insane, but it does work for very small tools like that. It
469469+just doesn't scale to the levels that I wanted to do something more
470470+complicated, like a form for filling out and creating a server in one
471471+of my other projects.
472472+473473+I kind of regret this in the long run. So I remade it. I remade things
474474+to make it better. React components are monads because they have
475475+effects and they can leech into each other. And there's a whole bunch
476476+of math that you can talk about here. But the important thing is that
477477+they're just monads. The important part is that what I had was not
478478+monads. I needed to have effects and ways to handle state.
479479+480480+So one of the main ways that you handle state in React is with this
481481+thing called useState. It's effectively a container for data. You put
482482+the data in on one end, it triggers re-renders on the other, and you
483483+know, it just works sorta. The only thing is that you need to
484484+implement the hook system and I'm crazy, but I'm not crazy enough to
485485+re-implement React's hook system in a weekend.
486486+487487+```javascript
488488+const useState = (x = undefined) => [() => x, (y) => (x = y)];
489489+```
490490+491491+So I made the Xeact version of useState, which is this golfed
492492+monstrosity. It is a mutable variable that returns a getter and a
493493+setter. This is effectively a burrito around the data. It lets you
494494+change what value X points to so that you can build up state with a
495495+text area and then grab it out when you're submitting it to a fetch
496496+call. It doesn't trigger re-renders because, again, I didn't want to
497497+reinvent React hooks for a very good reason, but the surprising part
498498+is that this works.
499499+500500+Oh, by the way, fun cursed JavaScript fact for you. The reason that
501501+this works is because function arguments are mutable references. You
502502+can redefine what function arguments are in a function, and that just
503503+works. Try it in production with some people that are more junior and
504504+newer to JavaScript. You'll never expect what happens next.
505505+506506+At this point, I thought Xeact was basically perfect. It had all the
507507+features I want, none of the features I didn't, and here's just where
508508+I decided to stop working on it, not because I lost interest or anything.
509509+Xeact made my front end tasks as hard as I wanted to make them. I
510510+could go from thought to photon in seconds and there was no madness
511511+unless I felt like it.
512512+513513+Grug brain make you want dot key work? I added TypeScript types
514514+everywhere, so the dot key worked. Absolutely beautiful. Full
515515+TypeScript for the entire femtoframework.
516516+517517+It has mature and robust integrations with tools like Nix to automate
518518+your production deployments so you can get back to disrupting the
519519+burrito drone delivery industry. Don't think about minutiae. Go back
520520+to innovation. Xeact is the femtoframework that developers love. Don't
521521+believe us? See the testimonials for yourself.
522522+523523+<XeblogSlide name="2024/xeact/067" essential />
524524+525525+> Our engineering team was blown away. This is versatile, powerful, and
526526+> constantly updated. It's everything we've wanted and more.
527527+528528+<XeblogSlide name="2024/xeact/068" essential />
529529+530530+> This software's cloud backend has only been hacked twice so far this
531531+> year.
532532+533533+<XeblogSlide name="2024/xeact/069" essential />
534534+535535+> It shouldn't crash until the heat death of the universe.
536536+537537+<XeblogSlide name="2024/xeact/070" essential />
538538+539539+> Oh God, where are my hands? Why have you taken my hands away from me?
540540+541541+Overall, you can see that Xeact is an obvious choice for your front
542542+end projects. Small, fast, and...small. Xeact scales to your needs or
543543+your money back, and you didn't pay me.
544544+545545+However, Xeact only focuses on the front end. There's a whole other
546546+half of the stack to look at and a whole other half of that stack to
547547+look at. What would Xeact for the backend look like?
548548+549549+<XeblogPicture path="blog/2023/incredible-xeact-journey/our-incredible-journey" />
550550+551551+We think there's room for the Xeact way to be taken to the backend
552552+where it belongs. That's right. At the end of October last year,
553553+Techaro acquired Xeact. All the existing cloud services were shut down
554554+and refunds were issued to all affected customers with only 24 hours
555555+of notice. However, in the process, Xeact has become more and more
556556+popular.
557557+558558+<XeblogSlide name="2024/xeact/074" essential />
559559+560560+In the process, we have a unique opportunity to ideate some more
561561+synergy and really disrupt everything. We're going to revolutionize
562562+the concept of disruption. With Techaro, we are going to make the
563563+Xeact development flow for the backend and the front end at the same
564564+time using PILK, or Putting Individual Lookups in Kubernetes. This
565565+will allow you to make infinitely scalable backend services as easily
566566+as you can make infinitely scalable front end services.
567567+568568+Legacy frameworks like Next.js make it easy to mix front-end and
569569+back-end code, but they have limitations when it comes to scaling it.
570570+What happens when your search route uses too many resources and blocks
571571+your credit card processing route and you just turned off the money
572572+generator and you can't generate money anymore?
573573+574574+We can't stand for this. Why do we accept this as an industry?
575575+576576+<XeblogSlide name="2024/xeact/076" essential />
577577+578578+So we are leveraging the power of PILK to automagically put every
579579+server function into its own auto-scaling group with Kubernetes with
580580+its own URL that changes it every single time. Every deploy, so your
581581+backend is also unscrapable. Take that, ArchiveTeam!
582582+583583+It's infinitely scalable. Everything has its own execution context and
584584+your cloud provider will love you. This makes PILK a win-win-win
585585+scenario for everyone involved. Your front-end logic? Easy. Your
586586+backend logic? Easy. Your SREs, they'll have nothing to do and they'll
587587+be very bored.
588588+589589+Maybe even so bored, they'll invent a sarcastic JavaScript framework
590590+with a bunch of bad jokes.
591591+592592+And this allows the Xeact to advance you towards infinity. Looking
593593+back, we saved developers from the despair of Webpack with the power
594594+of the script tag. We covered the amazing might of naming and how
595595+choosing good names makes the Xeact experience what developers crave.
596596+We covered JSX, quasi-quoting, DAB, and the useState monad. And then
597597+finally, we looked towards the future with the sheer glory of PILK.
598598+599599+It's obvious.
600600+601601+Xeact is the perfect choice for your server applications. If you want
602602+it to happen on the front-end, use Xeact. If you want it to happen on
603603+the backend tomorrow, use PILK.
604604+605605+<XeblogSlide name="2024/xeact/081" essential />
606606+607607+By the way, a little disclaimer, the entire preceding talk was a work
608608+of satire. All characters, companies, or events referenced in this
609609+talk are products of my imagination and thus fictional. Any synergy
610610+with observable realities is purely coincidental. I was not speaking
611611+for any of my employers' past, present, or future, and ha-ha, gottem.
612612+613613+<XeblogSlide name="2024/xeact/082" essential />
614614+615615+Thanks for having me tonight, and I hope you learned some-
616616+617617+(thunderous applause)
618618+619619+Thanks for having me tonight. I hope you learned...something. By the
620620+way, when I was writing this talk, I put at least one joke about the
621621+industry in it. Extra credit if you can tell me what it was. If I
622622+don't get to your questions, email xeact@xeserv.us, and I promise I will reply.
623623+Otherwise, any questions?
624624+625625+## Q&A
626626+627627+<BlockQuote>
628628+ If having small frameworks means you eventually build up all the code that the
629629+ framework has anyways, do you see that happening with Xeact?
630630+</BlockQuote>
631631+632632+Well, yeah. That's going to happen no matter what you do. That's just
633633+kind of how this industry is. And the best way to handle that is to,
634634+like, just find something that you can be at peace with and then cry.
635635+Or laugh. I think laughing is more healthy than crying. I think that's
636636+what my therapist said. Not entirely sure. It was a while ago.
637637+638638+Any more questions?
639639+640640+<BlockQuote>How does it handle "rage clicks"?</BlockQuote>
641641+642642+<XeblogConv name="Mara" mood="hacker">
643643+ Context: one of the talks talked about how you measure "rage clicks", or
644644+ repeated clicks to get the UI to do something when things are slow by
645645+ frustrated users.
646646+</XeblogConv>
647647+648648+It handles rage clicks thanks to the debounce timer built into the
649649+Xeact standard library. And if you forget to debounce it, then you
650650+have problems. So don't forget.
651651+652652+<BlockQuote>Where is the documentation?</BlockQuote>
653653+654654+The documentation for Xeact is at
655655+[github.com/Xe/Xeact](https://github.com/Xe/Xeact). And if you are in
656656+doubt, read the source code. Because the source code is designed to be
657657+readable. Asterisk.
658658+659659+<BlockQuote>Did you actually make the Xeact source code T-shirt?</BlockQuote>
660660+661661+Oh, the T-shirt, right? I was actually going to get a T-shirt as a
662662+bit. But I thought about that idea after the logistics wouldn't work
663663+out.