What is a JSON feed? Learn more

JSON Feed Viewer

Browse through the showcased feeds, or enter a feed URL below.

Now supporting RSS and Atom feeds thanks to Andrew Chilton's feed2json.org service

CURRENT FEED

Xe's Blog

My blog posts and rants about various technology things.

A feed by Xe

JSON


Xeact Version 0.69.71: JSX support

Permalink - Posted on 2022-08-17 00:00

hero image the-magician-anime

Image generated by MidJourney -- The Magician in the style of an anime as a tarot card

Xeact is the most popular femtoframework for discerning development teams. It has been used in at least 3 production facing web applications and has become well-loved by users. You simply cannot argue with this star count:

A graph of Xeact's star count going up and to the right

No React parody is complete without JSX support, so today we at Xeserv are proud to announce the immediate availability of Xeact 0.69.71.

This monumental release brings in officially sanctioned JSX support to the Xeact ecosystem. JSX has been criticized and called names such as "reverse PHP in JavaScript", but the introduction of this critical feature enables users to have unparalleled freedom in their usage of Xeact technology.

Numa is delet
<Numa> Now with additional Funky Kong mode!

No more complicated build system. No more needless complexity. Xeact has only the needful amounts of complexity to help you focus on keeping things simple. Xeact with JSX allows users to create and maintain applications of limitless scale and complexity without sacrificing the core Xeact values.

Numa is delet
<Numa> Makefiles for the winz0rz!

No longer do you need to write Xeact code that looks like this:


const app = async () => {
    // do something important.
    
    return div({}, [
        h1("hi there friends!"),
        p([t("holy cow these are some WORDS like 'lumbersexual macchiatto'. I don't know what they mean though!")]),
    ]),
};

r(() => {
    let root = g("app");
    let contents = await app();
    x(root);
});

That is so many parentheses and m-expressions, it looks like you are going to make Batman jealous!

No, this won't do at all! We need something simpler. We need the simplicity and ease of understanding that Xeact brings to the table. Here is what you can do with the unrestrained power of Xeact and JSX's unholy matrimony:


const Page = async () => {
    // do something important
    
    return (
        <div>
            <h1>hi there friends!</h1>
            <p>holy cow these are some WORDS like 'lumbersexual macchiatto'. I don't know what they mean though!"</p>
        </div>
    );
};

r(() => {
    let root = g("app");
    let contents = await Page();
    x(root);
});

Much better. Xeact is freed from the yoke of its own grammar and this allows you to transcend the boundaries of the flesh to create anything you can imagine with the unlimited power afforded to you. Imagine what you could create with such limitless potential!

How to use this power

Xeact's JSX support has only been tested with Deno's JSX (and TSX) compilation support. Write your code in what you wish you could write and then use Deno to turn that into what you actually have to write. To get started, first you need to install Deno somehow. If you are using Nix flakes, add pkgs.deno to your devShell or run nix shell nixpkgs#deno. If you are using a lesser operating system, follow Deno's instructions and press enter until the messages go away.

Then make a file called deno.json and copy this into it:


{
    "compilerOptions": {
        "jsx": "react-jsx",
        "jsxImportSource": "xeact",
    },
    "importMap": "./import_map.json",
}

Then make a file called import_map.json and copy this into it:


{
    "imports": {
        "xeact": "https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/xeact.ts",
        "xeact/jsx-runtime": "https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/jsx-runtime.js",
    }
}

Cadey is coffee
<Cadey> I wish you could do this with less files.

Numa is delet
<Numa> Why? This is perfect as it is. Any less would ruin the beautiful vision we have for Xeact and absolutely stymie the ease of use! Once you get your JavaScript environment to fuck off and die then everything becomes so beautifully simple you could eat off of it!

Cadey is facepalm
<Cadey> If you say so...

Finally you can make your src/test.tsx file for your Xeact project:


// src/test.tsx

/** @jsxImportSource xeact */

import { g, r, x } from "xeact";

export const Page = async () => {
    return (
        <div>
            <h1>hi there friends!</h1>
            <p>holy cow these are some WORDS like 'lumbersexual macchiatto'. I don't know what they mean though!"</p>
        </div>
    );
};

r(async () => {
    let root = g("app");
    let contents = await Page();
    x(root);
});

You can test this awesome power with deno bundle:


$ mkdir -p static/js && deno bundle ./src/test.tsx ./static/js/test.js
Download https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/jsx-runtime.js
Download https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/xeact.ts
Download https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/xeact.js
Check file:///home/cadey/code/Xe/Xeact-demo/src/test.tsx
Bundle file:///home/cadey/code/Xe/Xeact-demo/src/test.tsx
Emit "./static/js/test.js" (1.25KB)

Finally you can witness your wondrous code with some crappy HTML like this:


<!DOCTYPE html>
<html>
    <head>
        <title>Page Title</title>
        <link rel="stylesheet" href="/static/xess.css">
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    </head>
    <body id="top">
        <main>
            <div id="app">Loading...</div>
            <script src="/static/js/test.js" type ="module"></script>
        </main>
    </body>
</html>

This will do everything you need. You can write all the modern code you want and with the power of Xeact, everything will just work out. Component functions work too!


/** @jsxImportSource xeact */

import { g, r, x, u } from "xeact";

type HipsumProps = {
    type: "hipster-centric" | "hipster-latin";
    sentences: number;
};

const getHipsum = async ({type, sentences}: HipsumProps): Promise<string[]> => {
    const resp = await fetch(u("http://hipsum.co/api/", {
        type, sentences, "start-with-lorem": "1"
    }));

    const text: string[] = await resp.json()
    return text;
}

const Hipsum = ({text}: {text: string[]}) => {
    return (
        <div>
            {text.map(para => <p>{para}</p>)}
        </div>
    );
}

export const Page = async () => {
    let paragraph = await getHipsum({type: "hipster-centric", sentences: 8});
    return (
        <div>
            <h1>Lumbersexual macchiatto</h1>
            <Hipsum text={paragraph} />
        </div>
    );
};

r(async () => {
    let root = g("app");
    let contents = await Page();
    x(root);
    root.appendChild(contents);
});

This gets you art like this:

Lumbersexual macchiatto I'm baby 90's thundercats chia poke tbh occupy humblebrag twee prism butcher whatever taxidermy. Brooklyn master cleanse hashtag beard tumeric twee. Normcore af hexagon gochujang, DSA ascot kitsch taxidermy. Fanny pack letterpress af squid. Tofu coloring book twee praxis meggings. Drinking vinegar skateboard try-hard big mood, DSA prism pok pok shaman. Lyft man bun whatever, fam affogato godard bicycle rights letterpress. Photo booth sustainable VHS DSA, organic hammock everyday carry cornhole migas occupy 8-bit.

If you want to witness the fearsome code that powers this humble demo, check here for your gateway to immortality.

Numa is delet
<Numa> Please be sure to follow the Xeact style guide when writing an app that uses Xeact. This means your default component for each page should be named "Page" and you must use semicolons everywhere to be sure the JavaScript compiler knows you are terminating a statement.

What could you create if the cloud was no longer the limit? What is the logical conclusion of your power if you have nothing holding you back? What can you do with Xeact?


How to look up a Nix package's Nix store path from flake inputs

Permalink - Posted on 2022-08-06 00:00

hero image fall-archons

Image generated by MidJourney -- The fall of the Archons, colored pencil drawing, fireball spell, bright sky, digital art, lake of fire

Sometimes God is dead and you need to figure out what the version of a package in your Nix flake's inputs is. With flakes, you can figure this out using nix eval on a flake reference, but what the hecc is a flake reference?

Every URL has a "fragment", or the thing after the # that mainly tells the browser where to scroll to. Nix flakes uses this to allow you to sub-index on flakes by either name or URL. This allows you to address packages like tmux as:


nixpkgs#legacyPackages.x86_64-linux.tmux

Or my site's code as:


github:Xe/site#packages.x86_64-linux.default

Or even some arbitrary git repo:


git+https://tulpa.dev/cadey/printerfacts.git?ref=main#defaultPackage.x86_64-linux

Mara is hacker
<Mara> The flake reference is what drills down into the flake so that Nix can tell the difference between part of the path to the repository and the path inside the flake. It usually works on the outputs of a flake that you can find out with nix flake show:


$ nix flake show github:Xe/site
github:Xe/site/5a50cacef85c9e3b9695a2749359b27d0530f86a
├───devShell
│   ├───aarch64-linux: development environment 'nix-shell'
│   └───x86_64-linux: development environment 'nix-shell'
├───nixosModules
│   ├───aarch64-linux: NixOS module
│   └───x86_64-linux: NixOS module
└───packages
    ├───aarch64-linux
    │   ├───bin: package 'xesite-2.4.0'
    │   ├───config: package 'xesite-config-2.4.0'
    │   ├───default: package 'xesite-2.4.0'
    │   ├───posts: package 'xesite-posts-2.4.0'
    │   └───static: package 'xesite-static-2.4.0'
    └───x86_64-linux
        ├───bin: package 'xesite-2.4.0'
        ├───config: package 'xesite-config-2.4.0'
        ├───default: package 'xesite-2.4.0'
        ├───posts: package 'xesite-posts-2.4.0'
        └───static: package 'xesite-static-2.4.0'

Mara is happy
<Mara> Tracing through things, you can see how you can go from the package name default to get github.com:Xe/site#packages.x86_64-linux.default as the full legal name of the package!

You can use the nix eval --raw command to figure out what the nix store path of those packages either is or would be:


$ nix eval --raw nixpkgs#legacyPackages.x86_64-linux.tmux
/nix/store/3mn362yak70vq137wnryi7whgvq2cmn2-tmux-3.3a

$ nix eval --raw github:Xe/site#packages.x86_64-linux.default
/nix/store/v3lwgh6vk03yw3aq3j398g613ff3gja0-xesite-2.4.0

$ nix eval --raw git+https://tulpa.dev/cadey/printerfacts.git'?'ref=main#defaultPackage.x86_64-linux
/nix/store/7df21bqkrx2csazc2s8ji8chaabbpqhs-printerfacts-0.3.1

However, this operates on the latest version by default. It won't operate on the current version in your Nix flake. If you need to find it out from the current flake, pass the --inputs-from flag with the current directory .:


$ nix eval --inputs-from . --raw nixpkgs#legacyPackages.x86_64-linux.tmux
/nix/store/5sz57bwrlwhv1l8h4c4sq1bl1fhmcwfw-tmux-3.3a

This will use the nixpkgs defined in your current directory's flake.lock file. You can then share that store path with people to share in your tale of woe as to why a service is crashing when you try and update it.

Mara is hacker
<Mara> You can also pass in an arbitrary version for a flake URL if you specify it in the URL parameters with ref. You can do it like this: github:Xe/site?ref=5a50cacef85c9e3b9695a2749359b27d0530f86a or by specifying the commit hash as an additional path parameter as in github:Xe/site/5a50cacef85c9e3b9695a2749359b27d0530f86a. Here's an example for this xesite commit:


$ nix flake show github:Xe/site/5a50cacef85c9e3b9695a2749359b27d0530f86a
github:Xe/site/5a50cacef85c9e3b9695a2749359b27d0530f86a
├───devShell
│   ├───aarch64-linux: development environment 'nix-shell'
│   └───x86_64-linux: development environment 'nix-shell'
├───nixosModules
│   ├───aarch64-linux: NixOS module
│   └───x86_64-linux: NixOS module
└───packages
    ├───aarch64-linux
    │   ├───bin: package 'xesite-2.4.0'
    │   ├───config: package 'xesite-config-2.4.0'
    │   ├───default: package 'xesite-2.4.0'
    │   ├───posts: package 'xesite-posts-2.4.0'
    │   └───static: package 'xesite-static-2.4.0'
    └───x86_64-linux
        ├───bin: package 'xesite-2.4.0'
        ├───config: package 'xesite-config-2.4.0'
        ├───default: package 'xesite-2.4.0'
        ├───posts: package 'xesite-posts-2.4.0'
        └───static: package 'xesite-static-2.4.0'

Cadey is coffee
<Cadey> I have reached a point where googling for these questions gets me results on my own blog. Of course they didn't help me in the moment. That's why this post exists. Maybe I'll be able to fix my Matrix server returning that a database migration failed so that I can update my homelab machines because that failing makes the whole deploy rollback. I really hate synapse and I regret setting up my own Matrix homeserver.


Do I need Kubernetes?

Permalink - Posted on 2022-08-04 00:00

hero image space-hexagon

Image generated by DALL-E 2 -- A hexagon comprised of pink, blue, green, yellow, orange and purple colored trangles combining into octarine in space, digital art, 8k uhd, anime style

Cadey is coffee
<Cadey> No.

Mara is hmm
<Mara> But I think I do...

Cadey is coffee
<Cadey> No.

Cadey is percussive-maintenance


Xenoblade Chronicles 3 Streams Announcement

Permalink - Posted on 2022-07-26 00:00

Xenoblade Chronicles 3 is set to come out on this friday, July 29th. I plan to stream the game all weekend on twitch. If you want to come and watch, please join me on Twitch at midnight EDT. I will stream it for an hour or two and then go to bed and proceed to stream more when I wake up, minus life things. Saturday and Sunday should be the days with the most streaming in them.

But yeah I hope this will be fun! Fair warning though, I will be casually talking about Xenoblade series spoilers.


The Stanley Parable: Ultra Deluxe Review

Permalink - Posted on 2022-07-25 00:00

Every so often a game comes around that is genuinely hard to review. Especially when you are trying to avoid spoiling the magic of the game in that review. This is a game that is even harder to review than normal because it's an absolute philosophical document. This game absolutely riffs at the games industry super hard and it really shows. I'm going to try to avoid spoilers in this article, except for a few I made up.

Cadey is coffee
<Cadey> I was going to include screenshots in this article, but it's difficult for me to get them without spoiling the subtle comedy at hand, so I'm going to leave this as a text-only review.

The Stanley Parable: Ultra Deluxe is either the second or third game in the series. At first this game was a Half Life 2 mod that came out of nowhere and was one of the most beloved mods ever released. Then they made it a proper game on the Source engine and expanded it a bit. After a while they wanted to continue the parable and expand it even more, but they weren't able to get it on consoles with it still being a Source engine game. So they ported it to Unity and the end result is The Stanley Parable: Ultra Deluxe. It is one of my favorite games of all time.

It is a deeply limited game, you only can move around and interact with things. The story is about an office drone named Stanley that pushes buttons based on instructions from his computer. The big thing that this game does though is make you realize the inherent paradoxes in its own design.

Mara is happy
<Mara> Being mechanically limited like this is not actually a bad thing like the phrasing might imply. This means that the main focus of the gameplay is not on the micro actions the player can take. In this case the main focus is on how the player interacts with the story and not how the player interacts with their controller or puzzles or tactics. Additionally, the mechanical limitations of the gameplay are thematically aligned with the story's premise of being an office drone in ways it can play with. Think dramatic irony taken to its logical conclusion.

Endings that make you look like you had exercised your free will actually boil down to your actions being controlled by following the narrator's voices. This is absolutely taking the piss out of how most modern AAA game design works, guiding you with an invisible hand and making it seem like you had the free will to choose what was going on when in fact you were really just following the invisible guidance the whole time.

However I think one of the best examples of how The Stanley Parable riffs at mainstream game design is via the Adventure Line™️ that shows up in one branch of the game. The Line™️ is an obvious riff on games like Dead Space where you can summon a line to tell you where to go at any time. It shows how boring modern game design is by making you see the consequences of it. If you follow the narrator's voice, you get boring endings.

In many modern AAA games, you have the free will to choose to follow the main story and finish all the quests or whatever, but not much else. Consider Call of Duty or Battlefield. You are John America and you have to kill the enemies to death before they kill you to death by throwing bullets at you. You get to the end of the level and blow up the brown people some more or something and then it's suddenly a victory for America. But what did you really accomplish? You just followed the line. Walk outside of the intended playable area? 10 second timer until the game kills you. Shoot a person with the wrong skin color? The game kills you.

Numa is delet
<Numa> If you manage to clip out of bounds in the escape ending, the screen will fade to black and you will be transported to a temperate climate. Then a t-posing model in terrible armor will tell you that it used to be an adventurer until they took an arrow to the knee. Hope that's not a marriage proposal!

However in The Stanley Parable you can defy the narrator and that's where the game really opens up. It's great to get in the area where the game is unfinished and then have the narrator complain about deadlines, scheduling delays, investor funding and them wanting to avoid having to stuff it to the gills with microtransactions. You can legitimately glitch your way out of bounds and then the game will reward you with a new ending you didn't know was possible. The game takes the concept of the illusion of free will and plays with it.

The game makes you think about what games can be. It makes you wonder if the potted plant soliloquy after the broom closet ending speaks to the mental state of the author more than anything. Of all of the artistic endeavors that games as a medium can have, we end up seeing very few or none of them in mainstream gaming. Sure you get your occasional 4k120fps robot killer waifu with a bow and a whacky stick, but none of it really revolutionizes video games as an art form. It's all just derivative of the generic "unalive bad guy and save earth" trope.

Mara is hacker
<Mara> If you want some games that really revolutionize what games can be, check out Celeste, Secret Little Haven, Baba Is You, and Glittermitten Grove. All of these games really challenge what games can be and experiment with radically different kinds of art. You never will see mainstream games be as risk-taking as this because art is fundamentally risky and capitalism wants line to go up, so they go out of their way to make sure that mainstream games are as safe and likely to sell many copies as possible.

I made up the thing about the potted plant, but if you had played the game then you'd probably have started the game up to look for it just to see what was there. I wonder if I made someone stand at that potted plant for like 5 minutes or something. This game sparks creativity in ways that other mainstream games just fundamentally don't. If you've been looking for something different in your video game diet, I really suggest you give it a try. Go in as blind as possible. I'm not paid in any way to say this, I genuinely think this is really good.