home.social

Search

1000 results for “my_actual_brain”

  1. Biological computation and the nature of software

    A new paper is been getting some attention. It makes the case for biological computation. (This is a link to a summary, but there’s a link to the actual paper at the bottom of that article.)

    Characterizing the debate between computational functionalism and biological naturalism as camps that are hopelessly dug in, the authors propose that the brain does do computation, but that it’s a very different kind from the type done in the device you’re using to read this, which they call “biological computation.”

    The differences are that biological computation is a hybrid between digital (discrete) and analog (continuous) computing, there is no clean division between software and hardware, between algorithms and implementation, and that metabolism and energy constraints shape the processing that happens. They sum it up as, in the brain, the algorithm is the substrate.

    The authors argue that to build artificially conscious systems, it may be necessary to go with a different physical ontology, one that is closer to the way biology works.

    Let me start by saying that this paper is a big improvement over the usual arguments about the distinctions between computers and biology. The authors are making a real effort to identify what supposedly makes biology unique. Most of what they’re saying already accords with my own understanding of how the brain works, and what’s different about its computation. There are a few points where they try to pass off speculation as established fact, but those are nits.

    That said, I think they oversell some of their points. For example, the distinction between analog and digital is often less than it appears. We listen to music and watch movies all the time in digital formats that were originally recorded in analog. Yes, something can be lost in the translation from continuous to discrete signaling, but in an analog system there is always variance noise, variations between a system’s processing, both with other systems of the same type, and between runs in the same system. The trick is for the translation to reduce the quantization noise, the distortions from moving to a discrete format, so that they’re less than the variance noise in the original.

    Another is the aspect they call scale inseparability, the idea that the brain doesn’t use the layers of abstraction that technology uses. These layers exist in technology to make the engineering easier to understand and maintain, for engineers. Evolution doesn’t care about understanding so it’s not a factor in how biological systems are organized. The authors use this to imply that the software / hardware divide may be something the technology side will have to give up. That the algorithm may need to be in the substrate as it is with biology.

    I think this represents confusion about what software actually is. We usually talk about software as a set of instructions that a processor follows. In most cases, it’s convenient to think about it that way. But at a more physical level, it makes more sense to think of software as a configuration of hardware. So when software is running on hardware, the algorithm is always the substrate.

    The real distinction here is that technological computers are designed to be reconfigured on the fly. This is actually an amazing achievement when you stop and think about it. I often see articles marveling at the brain’s plasticity, its ability to rewire itself. But your computer’s memory can undergo wholesale reconfiguration on demand by loading a new software package, something brain’s can’t do, at least not quickly.

    Of course, this comes with vulnerabilities brains are far less susceptible to. One reason computers can be hacked is this ability to massively reconfigure. Not that brains are completely immune. Ant brains can be hacked by a fungal infection, and cat owners can be infected with a parasite that makes them like their cats more, and that’s aside from the ability of advertisers and propagandists to hijack our brain’s reasoning to introduce notions we might otherwise resist. But it’s a harder thing to do effectively in biological systems.

    What’s important to realize is that anything that can be done in hardware can, in principle, be done in software, at least once a minimal general computing platform is in place. You can run software that emulates other hardware platforms so you can run their software. It is true that doing it in hardware is often far more efficient in terms of performance and energy, but that comes with reduced flexibility. It’s why we now run word processors on our general purpose computers instead of the old word processing machines that once existed.

    So I don’t think the fact that current AI runs on software neural networks, in and of itself, is a showstopper. Another difference is that the brain operates with massive parallelization, far more than any current technological system. These systems can still perform something like the brain’s processing in software because they operate millions of times faster. Although the addition of GPUs, designed with parallelization in mind, help a great deal.

    But that, I think, gets to a valid concern the authors make about energy constraints. Discrete processing, and doing things with software instead of hardware, come at a cost in terms of energy and performance. This is something I do think AI researchers should be paying more attention to. All we need to do to understand how far current AI is from animal intelligence, much less human level, is look at the vast amounts of data and energy it requires to do what it does. Datacenters are sucking the power grid dry to meet their energy demands. All of which speaks to how crude the technology remains in comparison to biological intelligence.

    But this energy constraint issue is broader than just trying to reproduce biological processes. I think it’s a problem for all technological computing. And it will likely eventually result in architecture changes. Understanding how biology does it may be important, but I tend to doubt the solution will be doing it exactly like those systems.

    And this gets to a sentiment that I detect in the paper and write ups about it. It’s the idea that consciousness is a ghost in the machine, one we need to find the magic ingredients for so we can generate it. I think this is fundamentally the wrong way to think about it. Neuroscientist Hawan Lau, I think, in a Bluesky post, sums up the issue. Why do we think this might be true for consciousness when it isn’t for so many other things the body does, like motor control?

    All that said, I do like the term “biological computation.” It admits that the computation in brains is different while still acknowledging the important ways it’s the same. I suspect that won’t be enough for those strongly convinced computationalism is wrong, but it still feels like useful progress.

    What do you think about the points the authors make? Or my take on them? Are they right that a new hardware architecture is required? Or would even that be enough? Does the “biological computation” term strike the right balance?

    #AI #ArtificialIntelligence #BiologicalComputation #ComputationalFunctionalism #Consciousness #functionalism #Neuroscience #Philosophy #PhilosophyOfMind

  2. Good morning. 🦆🪿🦢

    11 December 2025

    I’m having a portion of my driveway redone. They started yesterday and are supposed to pour this morning. I’m a little on edge—I hired the company through Angi. So far, their work is adequate, but I can’t help feeling that this kind of decision-making is part of what makes me, me.

    I did my research into concrete—it’s not all the same, you know. The contractor initially proposed pouring 3,000 psi concrete, which is the minimum standard. No doubt he was trying to keep costs low to secure the job. I simply told him to go with 4,000 psi, which is the recommended strength for driveways, and that I’d cover the extra cost.

    What frustrates me with contractors is that they often default to the lowest option to win the bid, rarely presenting alternatives. It’s as if they assume all the customer cares about is cost. And yes, cost matters—but so does quality. I understand that cost and quality can be in tension, but I’d rather be given the full picture and make the decision myself. Wouldn’t you?

    The contractor got back to me and said the difference between 3,000 psi and 4,000 psi concrete is only $10 per cubic yard. He estimated the job at 12 yards, so the upgrade adds just $120. I paced it off yesterday and suspect it’s closer to 15 cubic yards. We’ll see. I agreed to pay the actual cost of the concrete rather than the estimate baked into his price. Life goes on.

    “A man who works with his hands is a laborer; a man who works with his hands and his brain is a craftsman; but a man who works with his hands and his brain and his heart is an artist.” - Louis Nizer

    #photo #photography #photographer #photographylovers #wildlife #nature #bird #birds #birding #birdwatching #birdphotography #morning #ducks #concrete #driveway #contractors

  3. Biohazard – Divided We Fall Review

    By Steel Druhm

    Biohazard are one of those bands that held my interest and affection, but only for a small window of my life (1992 through 1996). While their mean street NYC tough guy hardcore-meets-metal sound resonated with me as a dumb, loud 21-year-old, by the time I was approaching 26, it all started to feel too “try hard” and adolescent, like something I should move beyond. After that, I would still enjoy the hits from Urban Discipline and State of the World Address on gym playlists, but I rarely went back to the actual albums or sought out their new stuff. When it was announced that Biohazard had reformed the original lineup for a new album, some 13 years since the last release, I had more than a few reservations. The NYC badass schtick is a perishable one with a definite shelf life, and the idea of a bunch of dudes in their 50s shouting about curb stomping me just wasn’t a selling point. Still, the Cro-Mags pulled it off, so maybe these guys could too. I sampled the early singles, and to my surprise, they were quite entertaining. And here I am reviewing Divided We Fall against my better judgment. Can these Brooklyn goons deliver the burly goods all these years later?

    The short answer is…yes. Divided We Fall is a shockingly spry, punchy outing with catchy writing and enough testosterone to power 4 Cam Skattebos. It’s basically the album that could have followed Urban Discipline, with a collection of short, angry anthems about staying hard no matter what life throws at you. Opener “Fuck the System” sounds exactly like you’d expect. It’s enough like classic NYHC to conjure memories of Madball, Agnostic Front and crossover acts like Pro-Pain. They keep that rowdy, pissed-off tone going on bruisers like “Forsaken,” and the uber rugged “Eyes on Six,” which is one of their most catchy and entertaining tracks ever. This one stinks of BO and malt liquor, and it will hit you a pipe and dump you in the Gowanus Canal.

    Slower cuts like “Death of Me” blend well with the bouncy, classic hardcore urgency of “Words to the Wise” and “The Fight to Be Free,” and at no point does the machismo drop below mega-toxic levels. There are a few missteps though. “S.I.T.F.O.A” is too rap-centric and ends up sounding like a cross between Anthrax’s “I Am the Man” and one of the godawful raps by SNL in-house comedy act The Lonely Island. Closer “Warriors” mostly works and has cool parts, but Evan Seinfeld singing “the warriors” oh so seriously doesn’t really help. Still, 9 out of 11 tracks landing and delivering more or less vintage Bio-sounds is quite a shocker. And the band smartly keeps every song in the 3-minute window so everything motors by in a sweaty fury. The sound is what you’d expect from this kind of band, and production is credited to Jonathan DeMaio. I’ll assume that’s actually Joey DeMaio from Manowar because that’s way too fucking funny.

    Both Billy and Evan sound fine vocally. I’ve always preferred Billy’s rough bellowing, and he still sounds like he could beat your ass. On tracks like “Eyes on Six,” he sounds angry, mean, and murderous, and that’s essential for this kind of music to get over. Evan sounds like Evan, not better or worse, and he only irritates me when he tries that rappy-metal bullshit or tries to sing too much. The guitar work from Billy and Bobby Hambel is sharp and recalls the glory days quite clearly. You get a collection of very NYHC-inspired riffs designed to get you pumped up and into the pit leaping over pizza-rats and comatose hobos. The minimal embellishments work well in the songs, and I even hear traces of Prong at times, so that’s a win. This ain’t prog, folks. It’s simple, fugly noise for the mouth breathers and lunkheads, and that works just fine for me since I’m both.

    Divided We Fall has no business being as good as it is, and it’s on close to the stuff Biohazard were churning out during their peak. That means you get rough, confrontational meathead metal for those with fatty beef in their brain, and there’s a demographic for that. I can’t say I will be blasting this one way into the future, but I already moved select cuts to the gym playlist for maximum gainz. Maybe I still needed a few good curb stomps. Maybe you do too. If so, Biohazard want to say hello from the gutter.

    Rating: 3.0/5.0
    DR: NA | Format Reviewed: Fucking STREAM!
    Label: BLKIIBLK
    Websites: facebook.com/Biohazarddfl | instagram.com/biohazarddfl
    Releases Worldwide: October 17th, 2025

    #2025 #30 #AgnosticFront #AmericanHardcore #AmericanMetal #Biohazard #BLKIIBLK #CroMags #Crossover #DividedWeFall #Madball #Oct25 #ProPain #Prong #Review #Reviews

  4. What if using AI to write fiction isn’t an evil act?

    🌸 P.S. Follow the guide on my experiment writing fiction with AI—it includes a list of all the posts about it.

    When AI first came out, like all other writers, I was pissed off that our work was used to train an LLM model that would replace what made us valuable and special.

    Despite all the arguments that LLMs won’t replace actual writers, you bet your socks that some companies and individuals would try.

    However, I am a realist, and also a tech nerd, so I began pushing buttons to see what the fuss was all about.

    What I found for myself was that AI (LLMs, anyway) gave me relief.

    A lot of it.

    And it may have also solved a decades-old problem that I’ve had with writing fiction.

    The struggle

    I have a habit of writing stories just to entertain myself. I have zero interest to sell or even distribute these stories for others to read.

    I do this because I am tired of searching or waiting for people to write stories I want to read. So, I thought the most efficient way was to write the story myself.

    But I’ve always had this one big problem when it comes to writing fiction.

    My brain just outruns my hands.

    As a neurodivergent person, you do not understand how quickly my mind can generate story ideas. And how bloody exhausting that can get.

    I can generate the plot of an entire story in minutes, but from then on it’s a race against my brain. If I could write fast enough before my brain gets bored, it’s a success.

    But most of the time, my brain just gets bored before I could complete the story, yanking away the precious dopamine I need to finish said story.

    Instead of dropping the story, however, I force myself to continue. And fellow neurodivergent people would know what will happen next: Burnout.

    So, to save myself, I often drop the story until that next elusive moment when my brain is interested enough to throw scraps of dopamine my way. But that rarely happens.

    Yes, wrangling with an ADHD brain is very much like dealing with a rebellious toddler. You tell said toddler not to play with the toy that you can’t afford, but it wants to play with it whether you like it or not. If you direct said toddler to better activities, it will throw a massive fit.

    Over the years, I’ve found ways to manage the toddler and have built a professional writing career for myself.

    But not with fiction.

    Getting analytical

    The problem: I could never find the motivation or cognitive energy to write fast enough to complete a story before my speedy brain grows bored and moves on to the next thing.

    Okay, so you’re probably wondering: If you have succeeded building a writing career for yourself, why couldn’t you succeed with fiction?

    Easy:

    1. Work is a very powerful motivator and I often use anxiety/adrenaline as a dopamine substitute. Fail at finishing work writing stuff = fired. Fired = no food on the table.
    2. I have limited resources to manage activities that require executive function, and it has been prioritised for work and life.
    3. Non-fiction is just easier to write than fiction.
    4. Fiction, in terms of life priorities, is at the lowest rung for me, so it typically only gets scraps of dopamine and executive functioning energy.

    Now, you need to understand something about me as a writer: It’s not that I don’t want to write the story, I just couldn’t. I was just so mentally tired and drained.

    I know the entire arc that I want to write. But my brain is so bored, tired, and demotivated. I have to write so many sentences to get to the end of the story that it refuses to obey my request to write a word. It’s very odd, isn’t it?

    Well, the key was to trick my brain.

    The experiment: Using AI as a creative scaffold

    I have a story that my brain has been nagging at me to finish for months. Let’s call it Forever, At Last.

    The nagging has gotten so bad that at night, when I usually curl up in bed to read, my brain says: Now wouldn’t it be great if Forever, At Last was finished and you can read it?

    So, at last, I decided to use AI to write it for me just to shut this nagging voice up.

    I was mostly inspired by this article written by Natalie Cote-Munoz, The Accidental Pioneers: How Neurodivergent Users Are Discovering AI’s True Potential.

    There has been so much shaming and cancelling when it comes to writing and AI that I never thought there was any other way to think about the subject.

    Natalie’s essay made me realise that not only do we need more nuanced conversations around this topic, there needs to be more understanding. (Also, that I’ve been unknowingly using AI in a way to support my executive functioning all along!)

    Still, what I did felt like a dangerous, naughty act. A traitorous act worthy of excommunication from the Writing Profession. But I didn’t care. I wanted my brain to stop hassling me when I’m trying to sleep, filling up my dreams with plots and keeping me up at night. Besides, I was not going to sell the story, I wanted to read a story for my amusement. Those Judgy Mcjudgy people on the Internet can go fly kites. Pooh!

    Here’s what I did:

    1. I uploaded two chapters I’d already written.
    2. I used this prompt: “Please write in the same style as this author. Continue where this story left off by adding a chapter where:”
    3. Then, I proceeded to write a bloody awful draft. I aimed to be as detailed as possible, with every plot point being mine.
    4. I click enter and wait.

    My bloody awful draft was a combination of story beats and dialogues. It is basically a stream-of-consciousness chaotic brain dump of what my brain wanted to say about the story.

    Here’s an example:

    7. tang hua said that when her body formed, the hope became a desperation that wouldn't leave. and as each month passed without her waking up, he thought that yuan zhong would just lose his life completely but fortunately she woke up. he gave her a faint smile. but now ... well, fortunately you managed to heal him. 8. tanyin was silent for a while and then said, "when i was dying, and i knew my time was near. i thought my words would leave him hope and keep him stronger. i'm afraid that my promise that i'll always be with him became a cruel joke." a tear falls down her cheek. and when i held his body, and i could feel his life ebb away. i finally understood what pain he must have been in when i finally left. she looke down and cried. 9. tanghua could only look on awkwardly. he tells her - but now that you're back. you can finally fulfil your promise. 10. she looks up, determined. yes. this time i will never leave him. i will always be by his side. always.

    What came out was quite interesting and dare I say, impressive:

    For a long moment, Tang Hua didn’t answer. He stared at the ground, his shoulders tense, as if weighing his words.

    She touched his arm. “I need to know.”

    Tang Hua exhaled sharply. “He never got over you leaving. For the longest time, he truly believed he’d never see you again.” A pause. “Then the envoy came. Told him there was a chance you might return.” A bitter laugh escaped him. “Sometimes I think that was the cruelest thing he could’ve said. Yuan Zhong was finally starting to accept that you were gone. But that little hope—it undid everything.”

    Tanyin’s chest ached.

    “He started talking to the dragonflies,” Tang Hua continued, his voice quieter now. “To the air. As if you might answer. I thought he’d lost his mind.”

    A memory flickered in Tanyin’s mind—dragonflies brushing against Yuan Zhong’s cheeks, whispers on the wind. Had those been her? Fragments of her spirit, reaching out without form? Or had it only been his longing, shaping the world into something bearable?

    Tang Hua rubbed his face. “When your body formed from the lotus… that hope turned into desperation. Every day you didn’t wake, it was like watching him die by inches.” He gave her a faint, tired smile. “But you did wake. And now you’ve healed him.”

    Tanyin was silent for a long time. The wind rustled the leaves overhead.

    “When I was dying,” she said at last, “I thought my words would give him strength. That my promise—that I’d always be with him—would comfort him.” Her voice broke. “I didn’t realize it would become a chain.”

    A tear slipped down her cheek.

    “And when I held him as his life faded,” she whispered, “I finally understood the pain he must have felt when I left.”

    She bowed her head, shoulders shaking.

    Tang Hua shifted awkwardly, then cleared his throat. “But you’re back now. You can finally keep your promise.”

    Tanyin lifted her face. The tears still glistened on her lashes, but her gaze was steady.

    “Yes,” she said. “This time, I will never leave him.”

    She looked back toward the house, where Yuan Zhong slept.

    Always.

    When I first started using AI to do this, just out of curiosity to see how it writes fiction, it was really, really laughably bad.

    I am actually quite stunned that the technology has improved a lot. For one, DeepSeek emulated my writing style quite closely. It was like watching myself write.

    Almost.

    As a lark, I continued.

    I decided to go one chapter, then the next, and in just an hour, I completed the story that had been in my head for months but I had no cognitive energy or will to complete.

    AI as a motivational tool

    I write stories mostly to amuse myself. But even then, it has not been easy to write these stories. Photo by Alessia C_Jpg on Unsplash

    And it finally occurred to me: I could actually use AI to finally focus on what I really want to do with fiction.

    You see, I have no problem coming up with stories. However, I have a lot of issues writing effective prose.

    But I’ve never had enough energy to focus on improving that skill because all of my executive functioning has been taken up by work, daily life and trying to force myself to the point of burnout to complete stories.

    Now, you may think that I am just going to generate my prose with AI from now on.

    No bloody way.

    Because I could write better, damn it.

    As I lay in bed that night reading the completed story DeepSeek generated, I twitched, my fingers curling in preparation to rewrite the sentences.

    While my toddler brain was finally happy it got its toy, my writerly side is annoyed at the writing and already dreaming up ways to improve it.

    The sentences were coherent, but the writing was still not stylistically good enough for me.

    It had a lot of clichés, the plot could be refined, the dialogue was definitely very American which is tonally off for my story as it is based in ancient China.

    Like I said, the LLM-generated prose just wasn’t good enough for me. But it provided what I needed: Motivation.

    That elusive desire to continue improving the story by focusing on writing better prose.

    Exactly the skill I want to improve with fiction writing!

    I can actually now focus on improving my storytelling prose without having to worry about all the other things in the front end that used to torment me so much.

    It also got rid of the tyranny of the white page.

    My brain goes, “Hey, I’m not starting with an empty page. I can work on this.”

    It provides me the dopamine boost I need to continue. It tricks my brain to think that the task is not as overwhelming as it seems.

    What was happening?

    I realised I was using AI the same way I used books and Google search in the past.

    In the before-AI-times, when I was stuck writing a scene, I would often jump onto the Internet or grab a book to inspire my brain to write. I’m not sure what to call this process. Is it mirroring? Emulation? Feedback? But the result was never very satisfying as it didn’t mirror what I was trying to write.

    So I asked AI (lol):

    You’re engaging in:

    • Creative priming (using external input to jumpstart your brain)
    • Cognitive offloading (letting an external system handle the “blank page” paralysis)
    • Iterative emulation (taking bits of inspiration and reshaping them into your voice)

    This is how many writers work—they just use different tools:

    • Some read poetry before writing prose to “tune” their rhythm.
    • Others keep a “swipe file” of lines they love for inspiration.
    • You used Google searches; now you use AI.

    Thanks, DeepSeek! (I’ll probably explore these concepts in the future as I didn’t realise it was a thing to do what I did.)

    What I’ll do in the future

    My experiment in completing the story with AI gave me massive hope that I can finally have the cognitive support I need to finally complete stories that I couldn’t and maybe publish them.

    You see, I have a 300,000-word novel I wrote back in 2012 (without AI!) that I couldn’t seem to push out to the world. It’s complete, but the thought of editing it, putting it online, paralyses me.

    I’ve come to accept that it’s my brain seizing up at the thought of the executive functioning required, and also the knowledge that I’m the sort that would burn herself out trying anyway.

    This experiment gives me hope that I can finally share this work to the world.

    This also gives me hope to finish the numerous unfinished stories I’ve left hanging that my brain had gotten bored of but I’m desperate to finish.

    But the danger is real. For one, there’s recent research that says AI can cause cognitive decline. I want to improve my fiction writing muscles, not lose it.

    Here are the rules I’m setting up for myself:

    1. Only use AI to help me when I’m burnt out, cognitively stuck due to mental exhaustion, or in despair at finishing a story.
    2. Always create first. For example, always have a rough, terrible draft first, with pieces of dialogue at least, before using it on AI.
    3. Do not ever let AI do the act of creation before you do.
    4. Do not ever use AI copy wholesale. Rewrite AI output or come up with another spin.
    5. For new stories/chapters where I’m extremely inspired to write – do not AI use at all!

    The truth is, I am able to do this due to my pride as a working writer and the years of discipline I’ve built as a professional writer but do other people have the same will?

    That’s the problem, unfortunately.

    The temptation to rely completely on AI is very real, like the call of a beautiful siren, especially to those of us struggling with this issue.

    Another narrative

    My use of AI during recovery revealed something unexpected: these tools didn’t just compensate for my limitations—they actively helped rebuild my capabilities. By forcing me to break complex ideas into manageable steps through AI iteration, I gradually rediscovered my logical thinking patterns. The scaffolding effect may have actually accelerated my cognitive recovery. – The Accidental Pioneers: How Neurodivergent Users Are Discovering AI’s True Potential by Natalie Cote-Munoz

    I have a lot of hope that this workflow will help me improve my prose based on what Natalie said above. 👆

    There’s a lot of shaming going on in the writing circles about using AI to write fiction, even from fellow neurodivergent writers.

    I get it, there are some of us afraid that we’re just using ADHD as an excuse to do things that are “not allowed”.

    I’m a moderator of a subreddit, and recently had to deal with reports of a user who used AI to generate her posts (it was very obvious).

    When she said that she generates her copy because she has ADHD, I paused. On the neurospicy spectrum I’m at the mild end, but what if someone out there truly needs it to make her thoughts coherent?

    So, I get it: How much of a crutch can ADHD folks justify?

    This is an important conversation to have in the writing space, but I’m afraid that the general writing community is just not ready for such a nuanced discussion.

    If there’s any hint of AI usage when you’re writing fiction, you’re basically toast as a writer.

    I suppose it’s a good thing I’m only writing fiction for my own consumption and amusement, eh?

    #AI #BeingAWriter #Fiction #FictionWritingWithAI #tech #Technology #writing

  5. What if using AI to write fiction isn’t an evil act?

    🌸 P.S. Follow the guide on my experiment writing fiction with AI—it includes a list of all the posts about it.

    When AI first came out, like all other writers, I was pissed off that our work was used to train an LLM model that would replace what made us valuable and special.

    Despite all the arguments that LLMs won’t replace actual writers, you bet your socks that some companies and individuals would try.

    However, I am a realist, and also a tech nerd, so I began pushing buttons to see what the fuss was all about.

    What I found for myself was that AI (LLMs, anyway) gave me relief.

    A lot of it.

    And it may have also solved a decades-old problem that I’ve had with writing fiction.

    The struggle

    I have a habit of writing stories just to entertain myself. I have zero interest to sell or even distribute these stories for others to read.

    I do this because I am tired of searching or waiting for people to write stories I want to read. So, I thought the most efficient way was to write the story myself.

    But I’ve always had this one big problem when it comes to writing fiction.

    My brain just outruns my hands.

    As a neurodivergent person, you do not understand how quickly my mind can generate story ideas. And how bloody exhausting that can get.

    I can generate the plot of an entire story in minutes, but from then on it’s a race against my brain. If I could write fast enough before my brain gets bored, it’s a success.

    But most of the time, my brain just gets bored before I could complete the story, yanking away the precious dopamine I need to finish said story.

    Instead of dropping the story, however, I force myself to continue. And fellow neurodivergent people would know what will happen next: Burnout.

    So, to save myself, I often drop the story until that next elusive moment when my brain is interested enough to throw scraps of dopamine my way. But that rarely happens.

    Yes, wrangling with an ADHD brain is very much like dealing with a rebellious toddler. You tell said toddler not to play with the toy that you can’t afford, but it wants to play with it whether you like it or not. If you direct said toddler to better activities, it will throw a massive fit.

    Over the years, I’ve found ways to manage the toddler and have built a professional writing career for myself.

    But not with fiction.

    Getting analytical

    The problem: I could never find the motivation or cognitive energy to write fast enough to complete a story before my speedy brain grows bored and moves on to the next thing.

    Okay, so you’re probably wondering: If you have succeeded building a writing career for yourself, why couldn’t you succeed with fiction?

    Easy:

    1. Work is a very powerful motivator and I often use anxiety/adrenaline as a dopamine substitute. Fail at finishing work writing stuff = fired. Fired = no food on the table.
    2. I have limited resources to manage activities that require executive function, and it has been prioritised for work and life.
    3. Non-fiction is just easier to write than fiction.
    4. Fiction, in terms of life priorities, is at the lowest rung for me, so it typically only gets scraps of dopamine and executive functioning energy.

    Now, you need to understand something about me as a writer: It’s not that I don’t want to write the story, I just couldn’t. I was just so mentally tired and drained.

    I know the entire arc that I want to write. But my brain is so bored, tired, and demotivated. I have to write so many sentences to get to the end of the story that it refuses to obey my request to write a word. It’s very odd, isn’t it?

    Well, the key was to trick my brain.

    The experiment: Using AI as a creative scaffold

    I have a story that my brain has been nagging at me to finish for months. Let’s call it Forever, At Last.

    The nagging has gotten so bad that at night, when I usually curl up in bed to read, my brain says: Now wouldn’t it be great if Forever, At Last was finished and you can read it?

    So, at last, I decided to use AI to write it for me just to shut this nagging voice up.

    I was mostly inspired by this article written by Natalie Cote-Munoz, The Accidental Pioneers: How Neurodivergent Users Are Discovering AI’s True Potential.

    There has been so much shaming and cancelling when it comes to writing and AI that I never thought there was any other way to think about the subject.

    Natalie’s essay made me realise that not only do we need more nuanced conversations around this topic, there needs to be more understanding. (Also, that I’ve been unknowingly using AI in a way to support my executive functioning all along!)

    Still, what I did felt like a dangerous, naughty act. A traitorous act worthy of excommunication from the Writing Profession. But I didn’t care. I wanted my brain to stop hassling me when I’m trying to sleep, filling up my dreams with plots and keeping me up at night. Besides, I was not going to sell the story, I wanted to read a story for my amusement. Those Judgy Mcjudgy people on the Internet can go fly kites. Pooh!

    Here’s what I did:

    1. I uploaded two chapters I’d already written.
    2. I used this prompt: “Please write in the same style as this author. Continue where this story left off by adding a chapter where:”
    3. Then, I proceeded to write a bloody awful draft. I aimed to be as detailed as possible, with every plot point being mine.
    4. I click enter and wait.

    My bloody awful draft was a combination of story beats and dialogues. It is basically a stream-of-consciousness chaotic brain dump of what my brain wanted to say about the story.

    Here’s an example:

    7. tang hua said that when her body formed, the hope became a desperation that wouldn't leave. and as each month passed without her waking up, he thought that yuan zhong would just lose his life completely but fortunately she woke up. he gave her a faint smile. but now ... well, fortunately you managed to heal him. 8. tanyin was silent for a while and then said, "when i was dying, and i knew my time was near. i thought my words would leave him hope and keep him stronger. i'm afraid that my promise that i'll always be with him became a cruel joke." a tear falls down her cheek. and when i held his body, and i could feel his life ebb away. i finally understood what pain he must have been in when i finally left. she looke down and cried. 9. tanghua could only look on awkwardly. he tells her - but now that you're back. you can finally fulfil your promise. 10. she looks up, determined. yes. this time i will never leave him. i will always be by his side. always.

    What came out was quite interesting and dare I say, impressive:

    For a long moment, Tang Hua didn’t answer. He stared at the ground, his shoulders tense, as if weighing his words.

    She touched his arm. “I need to know.”

    Tang Hua exhaled sharply. “He never got over you leaving. For the longest time, he truly believed he’d never see you again.” A pause. “Then the envoy came. Told him there was a chance you might return.” A bitter laugh escaped him. “Sometimes I think that was the cruelest thing he could’ve said. Yuan Zhong was finally starting to accept that you were gone. But that little hope—it undid everything.”

    Tanyin’s chest ached.

    “He started talking to the dragonflies,” Tang Hua continued, his voice quieter now. “To the air. As if you might answer. I thought he’d lost his mind.”

    A memory flickered in Tanyin’s mind—dragonflies brushing against Yuan Zhong’s cheeks, whispers on the wind. Had those been her? Fragments of her spirit, reaching out without form? Or had it only been his longing, shaping the world into something bearable?

    Tang Hua rubbed his face. “When your body formed from the lotus… that hope turned into desperation. Every day you didn’t wake, it was like watching him die by inches.” He gave her a faint, tired smile. “But you did wake. And now you’ve healed him.”

    Tanyin was silent for a long time. The wind rustled the leaves overhead.

    “When I was dying,” she said at last, “I thought my words would give him strength. That my promise—that I’d always be with him—would comfort him.” Her voice broke. “I didn’t realize it would become a chain.”

    A tear slipped down her cheek.

    “And when I held him as his life faded,” she whispered, “I finally understood the pain he must have felt when I left.”

    She bowed her head, shoulders shaking.

    Tang Hua shifted awkwardly, then cleared his throat. “But you’re back now. You can finally keep your promise.”

    Tanyin lifted her face. The tears still glistened on her lashes, but her gaze was steady.

    “Yes,” she said. “This time, I will never leave him.”

    She looked back toward the house, where Yuan Zhong slept.

    Always.

    When I first started using AI to do this, just out of curiosity to see how it writes fiction, it was really, really laughably bad.

    I am actually quite stunned that the technology has improved a lot. For one, DeepSeek emulated my writing style quite closely. It was like watching myself write.

    Almost.

    As a lark, I continued.

    I decided to go one chapter, then the next, and in just an hour, I completed the story that had been in my head for months but I had no cognitive energy or will to complete.

    AI as a motivational tool

    I write stories mostly to amuse myself. But even then, it has not been easy to write these stories. Photo by Alessia C_Jpg on Unsplash

    And it finally occurred to me: I could actually use AI to finally focus on what I really want to do with fiction.

    You see, I have no problem coming up with stories. However, I have a lot of issues writing effective prose.

    But I’ve never had enough energy to focus on improving that skill because all of my executive functioning has been taken up by work, daily life and trying to force myself to the point of burnout to complete stories.

    Now, you may think that I am just going to generate my prose with AI from now on.

    No bloody way.

    Because I could write better, damn it.

    As I lay in bed that night reading the completed story DeepSeek generated, I twitched, my fingers curling in preparation to rewrite the sentences.

    While my toddler brain was finally happy it got its toy, my writerly side is annoyed at the writing and already dreaming up ways to improve it.

    The sentences were coherent, but the writing was still not stylistically good enough for me.

    It had a lot of clichés, the plot could be refined, the dialogue was definitely very American which is tonally off for my story as it is based in ancient China.

    Like I said, the LLM-generated prose just wasn’t good enough for me. But it provided what I needed: Motivation.

    That elusive desire to continue improving the story by focusing on writing better prose.

    Exactly the skill I want to improve with fiction writing!

    I can actually now focus on improving my storytelling prose without having to worry about all the other things in the front end that used to torment me so much.

    It also got rid of the tyranny of the white page.

    My brain goes, “Hey, I’m not starting with an empty page. I can work on this.”

    It provides me the dopamine boost I need to continue. It tricks my brain to think that the task is not as overwhelming as it seems.

    What was happening?

    I realised I was using AI the same way I used books and Google search in the past.

    In the before-AI-times, when I was stuck writing a scene, I would often jump onto the Internet or grab a book to inspire my brain to write. I’m not sure what to call this process. Is it mirroring? Emulation? Feedback? But the result was never very satisfying as it didn’t mirror what I was trying to write.

    So I asked AI (lol):

    You’re engaging in:

    • Creative priming (using external input to jumpstart your brain)
    • Cognitive offloading (letting an external system handle the “blank page” paralysis)
    • Iterative emulation (taking bits of inspiration and reshaping them into your voice)

    This is how many writers work—they just use different tools:

    • Some read poetry before writing prose to “tune” their rhythm.
    • Others keep a “swipe file” of lines they love for inspiration.
    • You used Google searches; now you use AI.

    Thanks, DeepSeek! (I’ll probably explore these concepts in the future as I didn’t realise it was a thing to do what I did.)

    What I’ll do in the future

    My experiment in completing the story with AI gave me massive hope that I can finally have the cognitive support I need to finally complete stories that I couldn’t and maybe publish them.

    You see, I have a 300,000-word novel I wrote back in 2012 (without AI!) that I couldn’t seem to push out to the world. It’s complete, but the thought of editing it, putting it online, paralyses me.

    I’ve come to accept that it’s my brain seizing up at the thought of the executive functioning required, and also the knowledge that I’m the sort that would burn herself out trying anyway.

    This experiment gives me hope that I can finally share this work to the world.

    This also gives me hope to finish the numerous unfinished stories I’ve left hanging that my brain had gotten bored of but I’m desperate to finish.

    But the danger is real. For one, there’s recent research that says AI can cause cognitive decline. I want to improve my fiction writing muscles, not lose it.

    Here are the rules I’m setting up for myself:

    1. Only use AI to help me when I’m burnt out, cognitively stuck due to mental exhaustion, or in despair at finishing a story.
    2. Always create first. For example, always have a rough, terrible draft first, with pieces of dialogue at least, before using it on AI.
    3. Do not ever let AI do the act of creation before you do.
    4. Do not ever use AI copy wholesale. Rewrite AI output or come up with another spin.
    5. For new stories/chapters where I’m extremely inspired to write – do not AI use at all!

    The truth is, I am able to do this due to my pride as a working writer and the years of discipline I’ve built as a professional writer but do other people have the same will?

    That’s the problem, unfortunately.

    The temptation to rely completely on AI is very real, like the call of a beautiful siren, especially to those of us struggling with this issue.

    Another narrative

    My use of AI during recovery revealed something unexpected: these tools didn’t just compensate for my limitations—they actively helped rebuild my capabilities. By forcing me to break complex ideas into manageable steps through AI iteration, I gradually rediscovered my logical thinking patterns. The scaffolding effect may have actually accelerated my cognitive recovery. – The Accidental Pioneers: How Neurodivergent Users Are Discovering AI’s True Potential by Natalie Cote-Munoz

    I have a lot of hope that this workflow will help me improve my prose based on what Natalie said above. 👆

    There’s a lot of shaming going on in the writing circles about using AI to write fiction, even from fellow neurodivergent writers.

    I get it, there are some of us afraid that we’re just using ADHD as an excuse to do things that are “not allowed”.

    I’m a moderator of a subreddit, and recently had to deal with reports of a user who used AI to generate her posts (it was very obvious).

    When she said that she generates her copy because she has ADHD, I paused. On the neurospicy spectrum I’m at the mild end, but what if someone out there truly needs it to make her thoughts coherent?

    So, I get it: How much of a crutch can ADHD folks justify?

    This is an important conversation to have in the writing space, but I’m afraid that the general writing community is just not ready for such a nuanced discussion.

    If there’s any hint of AI usage when you’re writing fiction, you’re basically toast as a writer.

    I suppose it’s a good thing I’m only writing fiction for my own consumption and amusement, eh?

    #AI #BeingAWriter #Fiction #FictionWritingWithAI #tech #Technology #writing

  6. What if using AI to write fiction isn’t an evil act?

    🌸 P.S. Follow the guide on my experiment writing fiction with AI—it includes a list of all the posts about it.

    When AI first came out, like all other writers, I was pissed off that our work was used to train an LLM model that would replace what made us valuable and special.

    Despite all the arguments that LLMs won’t replace actual writers, you bet your socks that some companies and individuals would try.

    However, I am a realist, and also a tech nerd, so I began pushing buttons to see what the fuss was all about.

    What I found for myself was that AI (LLMs, anyway) gave me relief.

    A lot of it.

    And it may have also solved a decades-old problem that I’ve had with writing fiction.

    The struggle

    I have a habit of writing stories just to entertain myself. I have zero interest to sell or even distribute these stories for others to read.

    I do this because I am tired of searching or waiting for people to write stories I want to read. So, I thought the most efficient way was to write the story myself.

    But I’ve always had this one big problem when it comes to writing fiction.

    My brain just outruns my hands.

    As a neurodivergent person, you do not understand how quickly my mind can generate story ideas. And how bloody exhausting that can get.

    I can generate the plot of an entire story in minutes, but from then on it’s a race against my brain. If I could write fast enough before my brain gets bored, it’s a success.

    But most of the time, my brain just gets bored before I could complete the story, yanking away the precious dopamine I need to finish said story.

    Instead of dropping the story, however, I force myself to continue. And fellow neurodivergent people would know what will happen next: Burnout.

    So, to save myself, I often drop the story until that next elusive moment when my brain is interested enough to throw scraps of dopamine my way. But that rarely happens.

    Yes, wrangling with an ADHD brain is very much like dealing with a rebellious toddler. You tell said toddler not to play with the toy that you can’t afford, but it wants to play with it whether you like it or not. If you direct said toddler to better activities, it will throw a massive fit.

    Over the years, I’ve found ways to manage the toddler and have built a professional writing career for myself.

    But not with fiction.

    Getting analytical

    The problem: I could never find the motivation or cognitive energy to write fast enough to complete a story before my speedy brain grows bored and moves on to the next thing.

    Okay, so you’re probably wondering: If you have succeeded building a writing career for yourself, why couldn’t you succeed with fiction?

    Easy:

    1. Work is a very powerful motivator and I often use anxiety/adrenaline as a dopamine substitute. Fail at finishing work writing stuff = fired. Fired = no food on the table.
    2. I have limited resources to manage activities that require executive function, and it has been prioritised for work and life.
    3. Non-fiction is just easier to write than fiction.
    4. Fiction, in terms of life priorities, is at the lowest rung for me, so it typically only gets scraps of dopamine and executive functioning energy.

    Now, you need to understand something about me as a writer: It’s not that I don’t want to write the story, I just couldn’t. I was just so mentally tired and drained.

    I know the entire arc that I want to write. But my brain is so bored, tired, and demotivated. I have to write so many sentences to get to the end of the story that it refuses to obey my request to write a word. It’s very odd, isn’t it?

    Well, the key was to trick my brain.

    The experiment: Using AI as a creative scaffold

    I have a story that my brain has been nagging at me to finish for months. Let’s call it Forever, At Last.

    The nagging has gotten so bad that at night, when I usually curl up in bed to read, my brain says: Now wouldn’t it be great if Forever, At Last was finished and you can read it?

    So, at last, I decided to use AI to write it for me just to shut this nagging voice up.

    I was mostly inspired by this article written by Natalie Cote-Munoz, The Accidental Pioneers: How Neurodivergent Users Are Discovering AI’s True Potential.

    There has been so much shaming and cancelling when it comes to writing and AI that I never thought there was any other way to think about the subject.

    Natalie’s essay made me realise that not only do we need more nuanced conversations around this topic, there needs to be more understanding. (Also, that I’ve been unknowingly using AI in a way to support my executive functioning all along!)

    Still, what I did felt like a dangerous, naughty act. A traitorous act worthy of excommunication from the Writing Profession. But I didn’t care. I wanted my brain to stop hassling me when I’m trying to sleep, filling up my dreams with plots and keeping me up at night. Besides, I was not going to sell the story, I wanted to read a story for my amusement. Those Judgy Mcjudgy people on the Internet can go fly kites. Pooh!

    Here’s what I did:

    1. I uploaded two chapters I’d already written.
    2. I used this prompt: “Please write in the same style as this author. Continue where this story left off by adding a chapter where:”
    3. Then, I proceeded to write a bloody awful draft. I aimed to be as detailed as possible, with every plot point being mine.
    4. I click enter and wait.

    My bloody awful draft was a combination of story beats and dialogues. It is basically a stream-of-consciousness chaotic brain dump of what my brain wanted to say about the story.

    Here’s an example:

    7. tang hua said that when her body formed, the hope became a desperation that wouldn't leave. and as each month passed without her waking up, he thought that yuan zhong would just lose his life completely but fortunately she woke up. he gave her a faint smile. but now ... well, fortunately you managed to heal him. 8. tanyin was silent for a while and then said, "when i was dying, and i knew my time was near. i thought my words would leave him hope and keep him stronger. i'm afraid that my promise that i'll always be with him became a cruel joke." a tear falls down her cheek. and when i held his body, and i could feel his life ebb away. i finally understood what pain he must have been in when i finally left. she looke down and cried. 9. tanghua could only look on awkwardly. he tells her - but now that you're back. you can finally fulfil your promise. 10. she looks up, determined. yes. this time i will never leave him. i will always be by his side. always.

    What came out was quite interesting and dare I say, impressive:

    For a long moment, Tang Hua didn’t answer. He stared at the ground, his shoulders tense, as if weighing his words.

    She touched his arm. “I need to know.”

    Tang Hua exhaled sharply. “He never got over you leaving. For the longest time, he truly believed he’d never see you again.” A pause. “Then the envoy came. Told him there was a chance you might return.” A bitter laugh escaped him. “Sometimes I think that was the cruelest thing he could’ve said. Yuan Zhong was finally starting to accept that you were gone. But that little hope—it undid everything.”

    Tanyin’s chest ached.

    “He started talking to the dragonflies,” Tang Hua continued, his voice quieter now. “To the air. As if you might answer. I thought he’d lost his mind.”

    A memory flickered in Tanyin’s mind—dragonflies brushing against Yuan Zhong’s cheeks, whispers on the wind. Had those been her? Fragments of her spirit, reaching out without form? Or had it only been his longing, shaping the world into something bearable?

    Tang Hua rubbed his face. “When your body formed from the lotus… that hope turned into desperation. Every day you didn’t wake, it was like watching him die by inches.” He gave her a faint, tired smile. “But you did wake. And now you’ve healed him.”

    Tanyin was silent for a long time. The wind rustled the leaves overhead.

    “When I was dying,” she said at last, “I thought my words would give him strength. That my promise—that I’d always be with him—would comfort him.” Her voice broke. “I didn’t realize it would become a chain.”

    A tear slipped down her cheek.

    “And when I held him as his life faded,” she whispered, “I finally understood the pain he must have felt when I left.”

    She bowed her head, shoulders shaking.

    Tang Hua shifted awkwardly, then cleared his throat. “But you’re back now. You can finally keep your promise.”

    Tanyin lifted her face. The tears still glistened on her lashes, but her gaze was steady.

    “Yes,” she said. “This time, I will never leave him.”

    She looked back toward the house, where Yuan Zhong slept.

    Always.

    When I first started using AI to do this, just out of curiosity to see how it writes fiction, it was really, really laughably bad.

    I am actually quite stunned that the technology has improved a lot. For one, DeepSeek emulated my writing style quite closely. It was like watching myself write.

    Almost.

    As a lark, I continued.

    I decided to go one chapter, then the next, and in just an hour, I completed the story that had been in my head for months but I had no cognitive energy or will to complete.

    AI as a motivational tool

    I write stories mostly to amuse myself. But even then, it has not been easy to write these stories. Photo by Alessia C_Jpg on Unsplash

    And it finally occurred to me: I could actually use AI to finally focus on what I really want to do with fiction.

    You see, I have no problem coming up with stories. However, I have a lot of issues writing effective prose.

    But I’ve never had enough energy to focus on improving that skill because all of my executive functioning has been taken up by work, daily life and trying to force myself to the point of burnout to complete stories.

    Now, you may think that I am just going to generate my prose with AI from now on.

    No bloody way.

    Because I could write better, damn it.

    As I lay in bed that night reading the completed story DeepSeek generated, I twitched, my fingers curling in preparation to rewrite the sentences.

    While my toddler brain was finally happy it got its toy, my writerly side is annoyed at the writing and already dreaming up ways to improve it.

    The sentences were coherent, but the writing was still not stylistically good enough for me.

    It had a lot of clichés, the plot could be refined, the dialogue was definitely very American which is tonally off for my story as it is based in ancient China.

    Like I said, the LLM-generated prose just wasn’t good enough for me. But it provided what I needed: Motivation.

    That elusive desire to continue improving the story by focusing on writing better prose.

    Exactly the skill I want to improve with fiction writing!

    I can actually now focus on improving my storytelling prose without having to worry about all the other things in the front end that used to torment me so much.

    It also got rid of the tyranny of the white page.

    My brain goes, “Hey, I’m not starting with an empty page. I can work on this.”

    It provides me the dopamine boost I need to continue. It tricks my brain to think that the task is not as overwhelming as it seems.

    What was happening?

    I realised I was using AI the same way I used books and Google search in the past.

    In the before-AI-times, when I was stuck writing a scene, I would often jump onto the Internet or grab a book to inspire my brain to write. I’m not sure what to call this process. Is it mirroring? Emulation? Feedback? But the result was never very satisfying as it didn’t mirror what I was trying to write.

    So I asked AI (lol):

    You’re engaging in:

    • Creative priming (using external input to jumpstart your brain)
    • Cognitive offloading (letting an external system handle the “blank page” paralysis)
    • Iterative emulation (taking bits of inspiration and reshaping them into your voice)

    This is how many writers work—they just use different tools:

    • Some read poetry before writing prose to “tune” their rhythm.
    • Others keep a “swipe file” of lines they love for inspiration.
    • You used Google searches; now you use AI.

    Thanks, DeepSeek! (I’ll probably explore these concepts in the future as I didn’t realise it was a thing to do what I did.)

    What I’ll do in the future

    My experiment in completing the story with AI gave me massive hope that I can finally have the cognitive support I need to finally complete stories that I couldn’t and maybe publish them.

    You see, I have a 300,000-word novel I wrote back in 2012 (without AI!) that I couldn’t seem to push out to the world. It’s complete, but the thought of editing it, putting it online, paralyses me.

    I’ve come to accept that it’s my brain seizing up at the thought of the executive functioning required, and also the knowledge that I’m the sort that would burn herself out trying anyway.

    This experiment gives me hope that I can finally share this work to the world.

    This also gives me hope to finish the numerous unfinished stories I’ve left hanging that my brain had gotten bored of but I’m desperate to finish.

    But the danger is real. For one, there’s recent research that says AI can cause cognitive decline. I want to improve my fiction writing muscles, not lose it.

    Here are the rules I’m setting up for myself:

    1. Only use AI to help me when I’m burnt out, cognitively stuck due to mental exhaustion, or in despair at finishing a story.
    2. Always create first. For example, always have a rough, terrible draft first, with pieces of dialogue at least, before using it on AI.
    3. Do not ever let AI do the act of creation before you do.
    4. Do not ever use AI copy wholesale. Rewrite AI output or come up with another spin.
    5. For new stories/chapters where I’m extremely inspired to write – do not AI use at all!

    The truth is, I am able to do this due to my pride as a working writer and the years of discipline I’ve built as a professional writer but do other people have the same will?

    That’s the problem, unfortunately.

    The temptation to rely completely on AI is very real, like the call of a beautiful siren, especially to those of us struggling with this issue.

    Another narrative

    My use of AI during recovery revealed something unexpected: these tools didn’t just compensate for my limitations—they actively helped rebuild my capabilities. By forcing me to break complex ideas into manageable steps through AI iteration, I gradually rediscovered my logical thinking patterns. The scaffolding effect may have actually accelerated my cognitive recovery. – The Accidental Pioneers: How Neurodivergent Users Are Discovering AI’s True Potential by Natalie Cote-Munoz

    I have a lot of hope that this workflow will help me improve my prose based on what Natalie said above. 👆

    There’s a lot of shaming going on in the writing circles about using AI to write fiction, even from fellow neurodivergent writers.

    I get it, there are some of us afraid that we’re just using ADHD as an excuse to do things that are “not allowed”.

    I’m a moderator of a subreddit, and recently had to deal with reports of a user who used AI to generate her posts (it was very obvious).

    When she said that she generates her copy because she has ADHD, I paused. On the neurospicy spectrum I’m at the mild end, but what if someone out there truly needs it to make her thoughts coherent?

    So, I get it: How much of a crutch can ADHD folks justify?

    This is an important conversation to have in the writing space, but I’m afraid that the general writing community is just not ready for such a nuanced discussion.

    If there’s any hint of AI usage when you’re writing fiction, you’re basically toast as a writer.

    I suppose it’s a good thing I’m only writing fiction for my own consumption and amusement, eh?

    #AI #BeingAWriter #Fiction #FictionWritingWithAI #tech #Technology #writing

  7. What if using AI to write fiction isn’t an evil act?

    🌸 P.S. Follow the guide on my experiment writing fiction with AI—it includes a list of all the posts about it.

    When AI first came out, like all other writers, I was pissed off that our work was used to train an LLM model that would replace what made us valuable and special.

    Despite all the arguments that LLMs won’t replace actual writers, you bet your socks that some companies and individuals would try.

    However, I am a realist, and also a tech nerd, so I began pushing buttons to see what the fuss was all about.

    What I found for myself was that AI (LLMs, anyway) gave me relief.

    A lot of it.

    And it may have also solved a decades-old problem that I’ve had with writing fiction.

    The struggle

    I have a habit of writing stories just to entertain myself. I have zero interest to sell or even distribute these stories for others to read.

    I do this because I am tired of searching or waiting for people to write stories I want to read. So, I thought the most efficient way was to write the story myself.

    But I’ve always had this one big problem when it comes to writing fiction.

    My brain just outruns my hands.

    As a neurodivergent person, you do not understand how quickly my mind can generate story ideas. And how bloody exhausting that can get.

    I can generate the plot of an entire story in minutes, but from then on it’s a race against my brain. If I could write fast enough before my brain gets bored, it’s a success.

    But most of the time, my brain just gets bored before I could complete the story, yanking away the precious dopamine I need to finish said story.

    Instead of dropping the story, however, I force myself to continue. And fellow neurodivergent people would know what will happen next: Burnout.

    So, to save myself, I often drop the story until that next elusive moment when my brain is interested enough to throw scraps of dopamine my way. But that rarely happens.

    Yes, wrangling with an ADHD brain is very much like dealing with a rebellious toddler. You tell said toddler not to play with the toy that you can’t afford, but it wants to play with it whether you like it or not. If you direct said toddler to better activities, it will throw a massive fit.

    Over the years, I’ve found ways to manage the toddler and have built a professional writing career for myself.

    But not with fiction.

    Getting analytical

    The problem: I could never find the motivation or cognitive energy to write fast enough to complete a story before my speedy brain grows bored and moves on to the next thing.

    Okay, so you’re probably wondering: If you have succeeded building a writing career for yourself, why couldn’t you succeed with fiction?

    Easy:

    1. Work is a very powerful motivator and I often use anxiety/adrenaline as a dopamine substitute. Fail at finishing work writing stuff = fired. Fired = no food on the table.
    2. I have limited resources to manage activities that require executive function, and it has been prioritised for work and life.
    3. Non-fiction is just easier to write than fiction.
    4. Fiction, in terms of life priorities, is at the lowest rung for me, so it typically only gets scraps of dopamine and executive functioning energy.

    Now, you need to understand something about me as a writer: It’s not that I don’t want to write the story, I just couldn’t. I was just so mentally tired and drained.

    I know the entire arc that I want to write. But my brain is so bored, tired, and demotivated. I have to write so many sentences to get to the end of the story that it refuses to obey my request to write a word. It’s very odd, isn’t it?

    Well, the key was to trick my brain.

    The experiment: Using AI as a creative scaffold

    I have a story that my brain has been nagging at me to finish for months. Let’s call it Forever, At Last.

    The nagging has gotten so bad that at night, when I usually curl up in bed to read, my brain says: Now wouldn’t it be great if Forever, At Last was finished and you can read it?

    So, at last, I decided to use AI to write it for me just to shut this nagging voice up.

    I was mostly inspired by this article written by Natalie Cote-Munoz, The Accidental Pioneers: How Neurodivergent Users Are Discovering AI’s True Potential.

    There has been so much shaming and cancelling when it comes to writing and AI that I never thought there was any other way to think about the subject.

    Natalie’s essay made me realise that not only do we need more nuanced conversations around this topic, there needs to be more understanding. (Also, that I’ve been unknowingly using AI in a way to support my executive functioning all along!)

    Still, what I did felt like a dangerous, naughty act. A traitorous act worthy of excommunication from the Writing Profession. But I didn’t care. I wanted my brain to stop hassling me when I’m trying to sleep, filling up my dreams with plots and keeping me up at night. Besides, I was not going to sell the story, I wanted to read a story for my amusement. Those Judgy Mcjudgy people on the Internet can go fly kites. Pooh!

    Here’s what I did:

    1. I uploaded two chapters I’d already written.
    2. I used this prompt: “Please write in the same style as this author. Continue where this story left off by adding a chapter where:”
    3. Then, I proceeded to write a bloody awful draft. I aimed to be as detailed as possible, with every plot point being mine.
    4. I click enter and wait.

    My bloody awful draft was a combination of story beats and dialogues. It is basically a stream-of-consciousness chaotic brain dump of what my brain wanted to say about the story.

    Here’s an example:

    7. tang hua said that when her body formed, the hope became a desperation that wouldn't leave. and as each month passed without her waking up, he thought that yuan zhong would just lose his life completely but fortunately she woke up. he gave her a faint smile. but now ... well, fortunately you managed to heal him. 8. tanyin was silent for a while and then said, "when i was dying, and i knew my time was near. i thought my words would leave him hope and keep him stronger. i'm afraid that my promise that i'll always be with him became a cruel joke." a tear falls down her cheek. and when i held his body, and i could feel his life ebb away. i finally understood what pain he must have been in when i finally left. she looke down and cried. 9. tanghua could only look on awkwardly. he tells her - but now that you're back. you can finally fulfil your promise. 10. she looks up, determined. yes. this time i will never leave him. i will always be by his side. always.

    What came out was quite interesting and dare I say, impressive:

    For a long moment, Tang Hua didn’t answer. He stared at the ground, his shoulders tense, as if weighing his words.

    She touched his arm. “I need to know.”

    Tang Hua exhaled sharply. “He never got over you leaving. For the longest time, he truly believed he’d never see you again.” A pause. “Then the envoy came. Told him there was a chance you might return.” A bitter laugh escaped him. “Sometimes I think that was the cruelest thing he could’ve said. Yuan Zhong was finally starting to accept that you were gone. But that little hope—it undid everything.”

    Tanyin’s chest ached.

    “He started talking to the dragonflies,” Tang Hua continued, his voice quieter now. “To the air. As if you might answer. I thought he’d lost his mind.”

    A memory flickered in Tanyin’s mind—dragonflies brushing against Yuan Zhong’s cheeks, whispers on the wind. Had those been her? Fragments of her spirit, reaching out without form? Or had it only been his longing, shaping the world into something bearable?

    Tang Hua rubbed his face. “When your body formed from the lotus… that hope turned into desperation. Every day you didn’t wake, it was like watching him die by inches.” He gave her a faint, tired smile. “But you did wake. And now you’ve healed him.”

    Tanyin was silent for a long time. The wind rustled the leaves overhead.

    “When I was dying,” she said at last, “I thought my words would give him strength. That my promise—that I’d always be with him—would comfort him.” Her voice broke. “I didn’t realize it would become a chain.”

    A tear slipped down her cheek.

    “And when I held him as his life faded,” she whispered, “I finally understood the pain he must have felt when I left.”

    She bowed her head, shoulders shaking.

    Tang Hua shifted awkwardly, then cleared his throat. “But you’re back now. You can finally keep your promise.”

    Tanyin lifted her face. The tears still glistened on her lashes, but her gaze was steady.

    “Yes,” she said. “This time, I will never leave him.”

    She looked back toward the house, where Yuan Zhong slept.

    Always.

    When I first started using AI to do this, just out of curiosity to see how it writes fiction, it was really, really laughably bad.

    I am actually quite stunned that the technology has improved a lot. For one, DeepSeek emulated my writing style quite closely. It was like watching myself write.

    Almost.

    As a lark, I continued.

    I decided to go one chapter, then the next, and in just an hour, I completed the story that had been in my head for months but I had no cognitive energy or will to complete.

    AI as a motivational tool

    I write stories mostly to amuse myself. But even then, it has not been easy to write these stories. Photo by Alessia C_Jpg on Unsplash

    And it finally occurred to me: I could actually use AI to finally focus on what I really want to do with fiction.

    You see, I have no problem coming up with stories. However, I have a lot of issues writing effective prose.

    But I’ve never had enough energy to focus on improving that skill because all of my executive functioning has been taken up by work, daily life and trying to force myself to the point of burnout to complete stories.

    Now, you may think that I am just going to generate my prose with AI from now on.

    No bloody way.

    Because I could write better, damn it.

    As I lay in bed that night reading the completed story DeepSeek generated, I twitched, my fingers curling in preparation to rewrite the sentences.

    While my toddler brain was finally happy it got its toy, my writerly side is annoyed at the writing and already dreaming up ways to improve it.

    The sentences were coherent, but the writing was still not stylistically good enough for me.

    It had a lot of clichés, the plot could be refined, the dialogue was definitely very American which is tonally off for my story as it is based in ancient China.

    Like I said, the LLM-generated prose just wasn’t good enough for me. But it provided what I needed: Motivation.

    That elusive desire to continue improving the story by focusing on writing better prose.

    Exactly the skill I want to improve with fiction writing!

    I can actually now focus on improving my storytelling prose without having to worry about all the other things in the front end that used to torment me so much.

    It also got rid of the tyranny of the white page.

    My brain goes, “Hey, I’m not starting with an empty page. I can work on this.”

    It provides me the dopamine boost I need to continue. It tricks my brain to think that the task is not as overwhelming as it seems.

    What was happening?

    I realised I was using AI the same way I used books and Google search in the past.

    In the before-AI-times, when I was stuck writing a scene, I would often jump onto the Internet or grab a book to inspire my brain to write. I’m not sure what to call this process. Is it mirroring? Emulation? Feedback? But the result was never very satisfying as it didn’t mirror what I was trying to write.

    So I asked AI (lol):

    You’re engaging in:

    • Creative priming (using external input to jumpstart your brain)
    • Cognitive offloading (letting an external system handle the “blank page” paralysis)
    • Iterative emulation (taking bits of inspiration and reshaping them into your voice)

    This is how many writers work—they just use different tools:

    • Some read poetry before writing prose to “tune” their rhythm.
    • Others keep a “swipe file” of lines they love for inspiration.
    • You used Google searches; now you use AI.

    Thanks, DeepSeek! (I’ll probably explore these concepts in the future as I didn’t realise it was a thing to do what I did.)

    What I’ll do in the future

    My experiment in completing the story with AI gave me massive hope that I can finally have the cognitive support I need to finally complete stories that I couldn’t and maybe publish them.

    You see, I have a 300,000-word novel I wrote back in 2012 (without AI!) that I couldn’t seem to push out to the world. It’s complete, but the thought of editing it, putting it online, paralyses me.

    I’ve come to accept that it’s my brain seizing up at the thought of the executive functioning required, and also the knowledge that I’m the sort that would burn herself out trying anyway.

    This experiment gives me hope that I can finally share this work to the world.

    This also gives me hope to finish the numerous unfinished stories I’ve left hanging that my brain had gotten bored of but I’m desperate to finish.

    But the danger is real. For one, there’s recent research that says AI can cause cognitive decline. I want to improve my fiction writing muscles, not lose it.

    Here are the rules I’m setting up for myself:

    1. Only use AI to help me when I’m burnt out, cognitively stuck due to mental exhaustion, or in despair at finishing a story.
    2. Always create first. For example, always have a rough, terrible draft first, with pieces of dialogue at least, before using it on AI.
    3. Do not ever let AI do the act of creation before you do.
    4. Do not ever use AI copy wholesale. Rewrite AI output or come up with another spin.
    5. For new stories/chapters where I’m extremely inspired to write – do not AI use at all!

    The truth is, I am able to do this due to my pride as a working writer and the years of discipline I’ve built as a professional writer but do other people have the same will?

    That’s the problem, unfortunately.

    The temptation to rely completely on AI is very real, like the call of a beautiful siren, especially to those of us struggling with this issue.

    Another narrative

    My use of AI during recovery revealed something unexpected: these tools didn’t just compensate for my limitations—they actively helped rebuild my capabilities. By forcing me to break complex ideas into manageable steps through AI iteration, I gradually rediscovered my logical thinking patterns. The scaffolding effect may have actually accelerated my cognitive recovery. – The Accidental Pioneers: How Neurodivergent Users Are Discovering AI’s True Potential by Natalie Cote-Munoz

    I have a lot of hope that this workflow will help me improve my prose based on what Natalie said above. 👆

    There’s a lot of shaming going on in the writing circles about using AI to write fiction, even from fellow neurodivergent writers.

    I get it, there are some of us afraid that we’re just using ADHD as an excuse to do things that are “not allowed”.

    I’m a moderator of a subreddit, and recently had to deal with reports of a user who used AI to generate her posts (it was very obvious).

    When she said that she generates her copy because she has ADHD, I paused. On the neurospicy spectrum I’m at the mild end, but what if someone out there truly needs it to make her thoughts coherent?

    So, I get it: How much of a crutch can ADHD folks justify?

    This is an important conversation to have in the writing space, but I’m afraid that the general writing community is just not ready for such a nuanced discussion.

    If there’s any hint of AI usage when you’re writing fiction, you’re basically toast as a writer.

    I suppose it’s a good thing I’m only writing fiction for my own consumption and amusement, eh?

    #AI #BeingAWriter #Fiction #FictionWritingWithAI #tech #Technology #writing

  8. Convert react/redux webapp from saga/axios to RTK query and RTK listener

    Redux saga is a core component of my react/redux applications. Unfortuately Redux Saga has been deprecated and haven’t seen an upgrade in the last year.

    This blog posts covers the replacement of redux saga and axios with RTK query and RTK listener in a react redux webapp.

    Introduction

    The structure of this blog post, is:

    1. First a walk through of how to use RTK query and RTK listener in a React application
    2. Then I’ll sum up the changes made, what was good and what didn’t feel like an improvement to me

    That means if searching on the web for how to use RTK query landed you here, you’ll find the good stuff first and can skip the rest.

    As for why you should use RTK query…?

    If you, like me, is still using redux with axios and saga, then switching to RTK query is a no-brainer, since redux Saga hasn’t seen an update since February 1 2024, and is now deprecated.

    If you’re not using redux because you have heard that it is hard to understand, bloated and require a lot of boilerplate, then you should reconsider. You should reconsider for the same reason I keep using redux: the existence of redux devtools.

    I find what I miss most when dealing with local state and context object is an easy way to examine the application’s current and entire state and trace when the state changes a particular value.

    Writing console.log() to output the data to find what’s in there, is so… I don’t know… 1985…?

    So without further ado, here’s how to use redux with RTK query in a react application (requires knowledge of JavaScript, it is helpful to know React, and knowledge of redux would help even more).

    Using RTK query

    Adding the dependencies

    Go to the directory containing package.json and run the following commands (first scrub existing dependencies and then add new ones):

    npm uninstall react react-dom react-redux "@reduxjs/toolkit"rm package-lock.jsonnpm install react react-dom react-redux "@reduxjs/toolkit"

    After this you should have all of the newest versions of the required dependencies.

    If converting from saga/axios, then remember to scrub unneccessary dependencies after completing the conversion, with:

    npm uninstall redux-saga axiosrm package-lock.jsonnpm install

    Queries and mutations

    With redux-saga and axios, data from a REST API backend is loaded by something like this

    import { takeLatest, call, put } from 'redux-saga/effects';import axios from 'axios';import { ACCOUNTS_REQUEST, ACCOUNTS_RECEIVE, ACCOUNTS_FAILURE } from '../reduxactions';export default function* accountsSaga() {    yield takeLatest(ACCOUNTS_REQUEST, receiveAccountsResult);}function* receiveAccountsResult() {    try {        const response = yield call(getAccounts);        const accountsresult = (response.headers['content-type'] === 'application/json') ? response.data : {};        yield put(ACCOUNTS_RECEIVE(accountsresult));    } catch (error) {        yield put(ACCOUNTS_FAILURE(error));    }}function getAccounts() {    return axios.get('/api/accounts');}

    In addition to the above code a redux reducer to store the data in the frontend is needed, and the redux actions must be defined (not shown here, this blog post is about RTK query and not about redux-saga and axios).

    In RTK query, the above example would be replaced with a one liner (this is what is called “a query” in RTK query terminology):

    getAccounts: builder.query({ query: () => '/accounts' }),

    In addtion to creating the code fetching the data, this one liner also results in redux storage of the fetched data, and redux actions for starting, successful completion and failure.

    To use the results of data fetched by an RTK query in a React component, a hook created from the above one liner is used

    export default function Home() {    const { data: accounts = [] } = useGetAccountsQuery();    return (<p>Number of accounts: ${accounts.length}</p>);}

    When the component is rendered an HTTP request is started to fetch the data, and when the data arrives the component will be re-rendered. There is also considerable logic behind caching data and refetching that decides whether to reload the data or not when navigating in and out of the component.

    My brief experience with RTK query is enough to tell me that RTK query’s reload logic works a lot better than my own home brewed reload logic.

    One difference from the replaced saga/axios code, was that the reducer where the fetched data is stored, has no default value. So without the “= []” in the example above, accounts would be undefined on the first render.

    Since the returned data is in the redux state, it is possible to use the useSelector() hook to access the data, but using a regular selector won’t trigger the fetch and reload logic. So as a rule of thumb: always start with the generated hook.

    It is possible to add arguments to a query

    getAccount: builder.query({ query: (username) => '/account/' + username }),

    The query argument would then added to the hook used in the react component:

    const { data: account = {} } = useGetAccountQuery('steban');

    Default for a query is to use HTTP GET, but using e.g. POST is simple and still an one-liner

    postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),

    The “body” argument needs to be possible to translate into JSON, to be sent as the POST body (and in my experience it is best to make the POSTed JSON a JSON object).

    const { data: adminStatus } = usePostAccountAdminstatusQuery({ username: 'steban' });

    Queries are for fetching data only. Even if a POST is used a query shouldn’t be used on an endpoint that modifies data on the backend.

    To modify data you use a mutation, and a mutation can also be a one-liner

    postAccountModify: builder.mutation({ query: body => ({ url: '/account/modify', method: 'POST', body }) }),

    The usage if the mutation hook is a little bit more complex than the query hook:

    const { data: account = {} } = useGetAccountQuery('steban');const [ postAccountModify ] = usePostAccountModifyMutation();const onSaveButtonClicked = async () => await postAccountModify(account);

    I.e.:

    1. The mutation function is picked out of the hook return value
    2. Then an async lambda is created using that function to post the return value
    3. The account value is used in the form elements
    4. The onSaveButtonClicked is used in

      <button onClick={onSaveButtonClicked}>Save account</button>

    After updating data in the server, you would like the redux data updated with the new values.

    The simplest way to get updated redux data, is to trigger a reload of the query that fetched the data in the first place.

    To trigger a reload, put a tag on the query that should be reloaded:

    getAccounts: builder.query({ query: () => '/accounts', providesTags: ['Accounts'] }),

    and then invalidate that tag after POSTing a mutation:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    invalidatesTags: ['Accounts'],}),

    The getAccounts query will be re-run and components with the useGetAccountsQuery() hook will be re-rendered.

    That if the accounts had already been loaded by a hook in a react component, it isn’t neccessarily reloaded the next time the component is loaded, so without the invalidation, navigating to the component might show the old data.

    But using invalidation of tags makes everything works smoothly and makes the data be updated on visit.

    If the return from the mutation contains the the updated data, there is no need to make an invalidation. Then the redux storage of the query can be updated with the mutation return:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    async onQueryStarted(body, { dispatch, queryFulfilled }) {        try {            const { data: accountsAfterAccountModify } = await queryFulfilled;            dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));        } catch {}    },}),

    The await queryFulfilled in onQueryStarted() waits for a successful mutation return and then then dispatches a redux action that replaces the results of a query

    The tricky bit, when replacing query values in this way, is argument 2 of the updateQueryData() redux action creator, which is undefined in the above example.

    If the query had an argument (e.g. the username), the replacement needs to have the same value. If not, there is no replacement and no error message. In this case the query has no argument, and then undefined is used.

    The queries and mutations in my converted projects all live in a single file api.js on the top and all look a bit like this:

    import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';export const api = createApi({    reducerPath: 'api',    baseQuery: (...args) => {        const api = args[1];        const basename = api.getState().basename;        return fetchBaseQuery({ baseUrl: basename + '/api' })(...args);    },    endpoints: (builder) => ({        getAccounts: builder.query({ query: () => '/accounts' }),        getAccount: builder.query({ query: (username) => '/account/' + username }),        postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),        postAccountModify: builder.mutation({            query: body => ({ url: '/account/modify', method: 'POST', body }),            async onQueryStarted(body, { dispatch, queryFulfilled }) {                try {                    const { data: accountsAfterAccountModify } = await queryFulfilled;                    dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));                } catch {}            },        }),    }),});export const {    useGetAccountsQuery,    useCetAccountQuery,    usePostAccountAdminstatusQuery,    usePostAccountModifyMutation,} = api;

    I.e.

    1. The reducerPath is the top level path of the api’s reducer slice in the redux state
    2. The baseQuery sets the base path prefix for all API calls, in this case it is the value of ‘/api’ prefixed by redux state value basename
    3. The endpoints contains the specification for the queries and mutations
    4. All mutations are exported at the end for ease of use in the

    For those who like looking at example code, here is the “api.js” of some React web applications converted from saga/axios to RTK query:

    applicationdescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Adding RTK query to the redux store

    The api object needs to be added to the reducer:

    import { combineReducers } from 'redux';import { createReducer } from '@reduxjs/toolkit';import { api } from '../api';export default (basename) => combineReducers({    [api.reducerPath]: api.reducer,    basename: createReducer(basename, (builder) => builder),});

    The exported function is a reducer creator that can be used to create a redux store state with two values:

    1. api which is a redux slice containing all state related to network communication and dowloaded results
    2. basename which is a string value holding the react application’s basepath

    The creator function can be used to create a redux store:

    import rootReducer from './reducers';import { api } from './api';import listeners from './listeners';// Calculate the basename based on the URL of the vite assets directoryconst baseUrl = Array.from(document.scripts).map(s => s.src).filter(src => src.includes('assets/'))[0].replace(/\/assets\/.*/, '');const basename = new URL(baseUrl).pathname;const store = configureStore({    reducer: rootReducer(basename),    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware).prepend(listeners.middleware),});

    First we calculate the application’s basepath from the vite artifact the code is loaded from, then a store is created with a reducer consisting of api and basename, and then two middlewares are added: api and listener

    “What is listeners?” you ask at this point.

    I am glad you asked! Check out the next section.

    For those who like looking at example code, some example redux store setups for RTK query and RTK listener:

    appreducersredux store setuphandleregreducers/index.jstop index.jssampleappreducers/index.jstop index.jsoldalbumreducers/index.jstop index.jsukelonnreducers/index.jstop index.jsauthservicereducers/index.jstop index.js

    Using RTK listener to perform actions on REDUX actions

    Listener fills the same role as another useful saga role: the ability to listen for redux actions and act on them:

    import { createListenerMiddleware } from '@reduxjs/toolkit';import { isFailedRequest } from './matchers';const listeners = createListenerMiddleware();listeners.startListening({    matcher: isFailedRequest,    effect: ({ payload }) => {        const { originalStatus } = payload || {};        const statusCode = parseInt(originalStatus);        if (statusCode === 401 || statusCode === 403) {            location.reload(true); // Will return to current location after the login process        }    }})export default listeners;

    This listener listens for failed RTK query HTTP calls to the API and checks the status codes for 401 “Needs Authentication” and 403 “Not Authorized” and reloads the app with the current URL to let apache shiro deal with it (refresh the auth and just open this page, pop up login or redirect to unauthorized page).

    This is “matchers.js” where isFailedRequest is found:

    import { isAnyOf } from '@reduxjs/toolkit';import { api } from './api';export const isFailedRequest = isAnyOf(    api.endpoints.getAccounts.matchRejected,    api.endpoints.getAccount.matchRejected,    api.endpoints.postAccountAdminstatus.matchRejected,    api.endpoints.postAccountModify.matchRejected,);

    For those who prefer looking at example code, example listener.js and matcher.js files can be found here:

    applisteners definitionmatchershandlereglisteners.js sampleapplisteners.js oldalbumlisteners.js ukelonnlisteners.jsmatchers.jsauthservicelisteners.jsmatchers.js

    Using RTK queries’ successful loads in other reducers

    It is possible to use the successful completion of a mutation to clear reducers backing forms:

    import { createReducer } from '@reduxjs/toolkit';import { SELECT_STORE } from '../actiontypes';import { api } from '../api';const defaultState = {    storeId: -1,    storename: '',    gruppe: 2,};export default const storeReducer = createReducer(defaultState, builder => {    builder        .addCase(SELECT_STORE, (state, action) => action.payload)        .addMatcher(api.endpoints.postNewstore.matchFulfilled, () => ({ ...defaultState }))        .addMatcher(api.endpoints.postModifystore.matchFulfilled, () => ({ ...defaultState }));});

    Here both the completion of a successful postNewstore mutation and a successful postModifystore mutation will set the reducer to its default state (and clear the forms backed by the redux state value).

    Note the use of addMatcher() rather than addCase() to matche the actions.

    All matchFulfilled actions have the same redux type, so traditional redux type matching won’t work. But the matchers provided by the api object can be used instead.

    Dependent queries

    A common requirement is that one REST call needs the value of another value before being called. For this “dependent queries” in RTK query can be used:

    export default function Home() {    const { data: overview = {}, isSuccess: overviewIsSuccess } = useGetOverviewQuery();    const { data: purchases = [] } = useGetPurchasesQuery(overview.accountid, { skip: !overviewIsSuccess });    ...

    The above example the getPurchases query needs an account id that can be found in the results of the getOverview query.

    The “skip” property of the query option object to useGetPurchasesQuery() prevents useGetPurchasesQuery() from being executed until useGetOverviewQuery() has completed successfully.

    Converting apps

    For those preferring to look at code, here are the diffs from converting from redux/axios to RTK queries and RTK listeners:

    appDescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Reduction of JavaScript source code size for the various apps (source code line numbers from cloc run before and after the conversion):

    appsize reduction in %size reduction in #lineshandlereg34%674sampleapp32%359oldalbum14%608ukelonn25%1211authservice31%841

    Summing up the numbers from doing the conversion

    1. A 14% to 35% reduction of JavaScript code of the apps (with lots of boilerplate gone). The package with lowest percentage has a number of lines reduction on par with the rest of the “real” applications
    2. No noticable difference in dependencies size even though I was already using RTK and got rid of redux-saga and axios
    3. No significant difference in vite build artifact size (even an increase in one case) (numbers can be provided on request)

    As said at the start, the obsoletion of redux-saga made doing this change a non-brainer for me.

    But losing all of the boiler plate around network requests made the applications easier to read and understand and maintain. And the logic around lazy loading, reloads and caching of data is a lot better than my home-brewed redux-router powered logic.

    I’m not opposed to learning new stuff, but I can be quite reluctant to let go of stuff I like, and I was really happy about redux saga as outlined in Yep, I’m still using redux.

    So did I lose anything in this conversion?

    Downsides are:

    1. Harder to examine data loaded by RTK query in the redux devtools (but still possible)
    2. More complex react components:
      1. prior this change, redux served up data ready for consumption in the components and with defaults, i.e. this

        const butikker = useSelector(state => state.butikker);

        is simpler than this:

        import { useGetButikkerQuery } from '../services/butikker';...    const { data: butikker = [] } = useGetButikkerQuery();
      2. Prior to this change, gathering the data for a save to the back end took place in a saga, so there was no need to clutter up the component with data not used in the actual render
    3. It’s kinda hard (but not impossible) to use the loaded data as backing storage for the edit form, and then save back from the data. The assumption is that one is to use something like useState() for this, but I don’t wish to do that

    But putting stuff back in the react components makes fewer places to look for stuff and makes my react component look more similar to others’ react components, so maybe this isn’t so bad after all…?

    Where to go next?

    I startet using Redux ToolKit (RTK) back in 2019. I quickly figured that createReducer() and createAction() could make my existing reducers and redux action creation more robust.

    I tried using redux slices at that point in time, but since I had to mix the autocreated redux action with manually created redux actions to trigger REST API operations and handle REST API errors, I figured that redux slices was more work than useful.

    And I later also landed on the “flattened redux state approach” outlined in Yep, I’m still using redux (see that article for the reasoning) that didn’t fit well with slices, so I dropped it back then.

    But with RTK query I no longer have to manually create actions to start API operations or handle errors, since these are created when creating queries or mutations, so maybe it is time to give redux slices a new try…?

    #css #dom #html #lines #react #reactjs #redux #reduxSaga #reduxToolkit #saga

  9. Convert react/redux webapp from saga/axios to RTK query and RTK listener

    Redux saga is a core component of my react/redux applications. Unfortuately Redux Saga has been deprecated and haven’t seen an upgrade in the last year.

    This blog posts covers the replacement of redux saga and axios with RTK query and RTK listener in a react redux webapp.

    Introduction

    The structure of this blog post, is:

    1. First a walk through of how to use RTK query and RTK listener in a React application
    2. Then I’ll sum up the changes made, what was good and what didn’t feel like an improvement to me

    That means if searching on the web for how to use RTK query landed you here, you’ll find the good stuff first and can skip the rest.

    As for why you should use RTK query…?

    If you, like me, is still using redux with axios and saga, then switching to RTK query is a no-brainer, since redux Saga hasn’t seen an update since February 1 2024, and is now deprecated.

    If you’re not using redux because you have heard that it is hard to understand, bloated and require a lot of boilerplate, then you should reconsider. You should reconsider for the same reason I keep using redux: the existence of redux devtools.

    I find what I miss most when dealing with local state and context object is an easy way to examine the application’s current and entire state and trace when the state changes a particular value.

    Writing console.log() to output the data to find what’s in there, is so… I don’t know… 1985…?

    So without further ado, here’s how to use redux with RTK query in a react application (requires knowledge of JavaScript, it is helpful to know React, and knowledge of redux would help even more).

    Using RTK query

    Adding the dependencies

    Go to the directory containing package.json and run the following commands (first scrub existing dependencies and then add new ones):

    npm uninstall react react-dom react-redux "@reduxjs/toolkit"rm package-lock.jsonnpm install react react-dom react-redux "@reduxjs/toolkit"

    After this you should have all of the newest versions of the required dependencies.

    If converting from saga/axios, then remember to scrub unneccessary dependencies after completing the conversion, with:

    npm uninstall redux-saga axiosrm package-lock.jsonnpm install

    Queries and mutations

    With redux-saga and axios, data from a REST API backend is loaded by something like this

    import { takeLatest, call, put } from 'redux-saga/effects';import axios from 'axios';import { ACCOUNTS_REQUEST, ACCOUNTS_RECEIVE, ACCOUNTS_FAILURE } from '../reduxactions';export default function* accountsSaga() {    yield takeLatest(ACCOUNTS_REQUEST, receiveAccountsResult);}function* receiveAccountsResult() {    try {        const response = yield call(getAccounts);        const accountsresult = (response.headers['content-type'] === 'application/json') ? response.data : {};        yield put(ACCOUNTS_RECEIVE(accountsresult));    } catch (error) {        yield put(ACCOUNTS_FAILURE(error));    }}function getAccounts() {    return axios.get('/api/accounts');}

    In addition to the above code a redux reducer to store the data in the frontend is needed, and the redux actions must be defined (not shown here, this blog post is about RTK query and not about redux-saga and axios).

    In RTK query, the above example would be replaced with a one liner (this is what is called “a query” in RTK query terminology):

    getAccounts: builder.query({ query: () => '/accounts' }),

    In addtion to creating the code fetching the data, this one liner also results in redux storage of the fetched data, and redux actions for starting, successful completion and failure.

    To use the results of data fetched by an RTK query in a React component, a hook created from the above one liner is used

    export default function Home() {    const { data: accounts = [] } = useGetAccountsQuery();    return (<p>Number of accounts: ${accounts.length}</p>);}

    When the component is rendered an HTTP request is started to fetch the data, and when the data arrives the component will be re-rendered. There is also considerable logic behind caching data and refetching that decides whether to reload the data or not when navigating in and out of the component.

    My brief experience with RTK query is enough to tell me that RTK query’s reload logic works a lot better than my own home brewed reload logic.

    One difference from the replaced saga/axios code, was that the reducer where the fetched data is stored, has no default value. So without the “= []” in the example above, accounts would be undefined on the first render.

    Since the returned data is in the redux state, it is possible to use the useSelector() hook to access the data, but using a regular selector won’t trigger the fetch and reload logic. So as a rule of thumb: always start with the generated hook.

    It is possible to add arguments to a query

    getAccount: builder.query({ query: (username) => '/account/' + username }),

    The query argument would then added to the hook used in the react component:

    const { data: account = {} } = useGetAccountQuery('steban');

    Default for a query is to use HTTP GET, but using e.g. POST is simple and still an one-liner

    postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),

    The “body” argument needs to be possible to translate into JSON, to be sent as the POST body (and in my experience it is best to make the POSTed JSON a JSON object).

    const { data: adminStatus } = usePostAccountAdminstatusQuery({ username: 'steban' });

    Queries are for fetching data only. Even if a POST is used a query shouldn’t be used on an endpoint that modifies data on the backend.

    To modify data you use a mutation, and a mutation can also be a one-liner

    postAccountModify: builder.mutation({ query: body => ({ url: '/account/modify', method: 'POST', body }) }),

    The usage if the mutation hook is a little bit more complex than the query hook:

    const { data: account = {} } = useGetAccountQuery('steban');const [ postAccountModify ] = usePostAccountModifyMutation();const onSaveButtonClicked = async () => await postAccountModify(account);

    I.e.:

    1. The mutation function is picked out of the hook return value
    2. Then an async lambda is created using that function to post the return value
    3. The account value is used in the form elements
    4. The onSaveButtonClicked is used in

      <button onClick={onSaveButtonClicked}>Save account</button>

    After updating data in the server, you would like the redux data updated with the new values.

    The simplest way to get updated redux data, is to trigger a reload of the query that fetched the data in the first place.

    To trigger a reload, put a tag on the query that should be reloaded:

    getAccounts: builder.query({ query: () => '/accounts', providesTags: ['Accounts'] }),

    and then invalidate that tag after POSTing a mutation:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    invalidatesTags: ['Accounts'],}),

    The getAccounts query will be re-run and components with the useGetAccountsQuery() hook will be re-rendered.

    That if the accounts had already been loaded by a hook in a react component, it isn’t neccessarily reloaded the next time the component is loaded, so without the invalidation, navigating to the component might show the old data.

    But using invalidation of tags makes everything works smoothly and makes the data be updated on visit.

    If the return from the mutation contains the the updated data, there is no need to make an invalidation. Then the redux storage of the query can be updated with the mutation return:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    async onQueryStarted(body, { dispatch, queryFulfilled }) {        try {            const { data: accountsAfterAccountModify } = await queryFulfilled;            dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));        } catch {}    },}),

    The await queryFulfilled in onQueryStarted() waits for a successful mutation return and then then dispatches a redux action that replaces the results of a query

    The tricky bit, when replacing query values in this way, is argument 2 of the updateQueryData() redux action creator, which is undefined in the above example.

    If the query had an argument (e.g. the username), the replacement needs to have the same value. If not, there is no replacement and no error message. In this case the query has no argument, and then undefined is used.

    The queries and mutations in my converted projects all live in a single file api.js on the top and all look a bit like this:

    import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';export const api = createApi({    reducerPath: 'api',    baseQuery: (...args) => {        const api = args[1];        const basename = api.getState().basename;        return fetchBaseQuery({ baseUrl: basename + '/api' })(...args);    },    endpoints: (builder) => ({        getAccounts: builder.query({ query: () => '/accounts' }),        getAccount: builder.query({ query: (username) => '/account/' + username }),        postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),        postAccountModify: builder.mutation({            query: body => ({ url: '/account/modify', method: 'POST', body }),            async onQueryStarted(body, { dispatch, queryFulfilled }) {                try {                    const { data: accountsAfterAccountModify } = await queryFulfilled;                    dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));                } catch {}            },        }),    }),});export const {    useGetAccountsQuery,    useCetAccountQuery,    usePostAccountAdminstatusQuery,    usePostAccountModifyMutation,} = api;

    I.e.

    1. The reducerPath is the top level path of the api’s reducer slice in the redux state
    2. The baseQuery sets the base path prefix for all API calls, in this case it is the value of ‘/api’ prefixed by redux state value basename
    3. The endpoints contains the specification for the queries and mutations
    4. All mutations are exported at the end for ease of use in the

    For those who like looking at example code, here is the “api.js” of some React web applications converted from saga/axios to RTK query:

    applicationdescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Adding RTK query to the redux store

    The api object needs to be added to the reducer:

    import { combineReducers } from 'redux';import { createReducer } from '@reduxjs/toolkit';import { api } from '../api';export default (basename) => combineReducers({    [api.reducerPath]: api.reducer,    basename: createReducer(basename, (builder) => builder),});

    The exported function is a reducer creator that can be used to create a redux store state with two values:

    1. api which is a redux slice containing all state related to network communication and dowloaded results
    2. basename which is a string value holding the react application’s basepath

    The creator function can be used to create a redux store:

    import rootReducer from './reducers';import { api } from './api';import listeners from './listeners';// Calculate the basename based on the URL of the vite assets directoryconst baseUrl = Array.from(document.scripts).map(s => s.src).filter(src => src.includes('assets/'))[0].replace(/\/assets\/.*/, '');const basename = new URL(baseUrl).pathname;const store = configureStore({    reducer: rootReducer(basename),    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware).prepend(listeners.middleware),});

    First we calculate the application’s basepath from the vite artifact the code is loaded from, then a store is created with a reducer consisting of api and basename, and then two middlewares are added: api and listener

    “What is listeners?” you ask at this point.

    I am glad you asked! Check out the next section.

    For those who like looking at example code, some example redux store setups for RTK query and RTK listener:

    appreducersredux store setuphandleregreducers/index.jstop index.jssampleappreducers/index.jstop index.jsoldalbumreducers/index.jstop index.jsukelonnreducers/index.jstop index.jsauthservicereducers/index.jstop index.js

    Using RTK listener to perform actions on REDUX actions

    Listener fills the same role as another useful saga role: the ability to listen for redux actions and act on them:

    import { createListenerMiddleware } from '@reduxjs/toolkit';import { isFailedRequest } from './matchers';const listeners = createListenerMiddleware();listeners.startListening({    matcher: isFailedRequest,    effect: ({ payload }) => {        const { originalStatus } = payload || {};        const statusCode = parseInt(originalStatus);        if (statusCode === 401 || statusCode === 403) {            location.reload(true); // Will return to current location after the login process        }    }})export default listeners;

    This listener listens for failed RTK query HTTP calls to the API and checks the status codes for 401 “Needs Authentication” and 403 “Not Authorized” and reloads the app with the current URL to let apache shiro deal with it (refresh the auth and just open this page, pop up login or redirect to unauthorized page).

    This is “matchers.js” where isFailedRequest is found:

    import { isAnyOf } from '@reduxjs/toolkit';import { api } from './api';export const isFailedRequest = isAnyOf(    api.endpoints.getAccounts.matchRejected,    api.endpoints.getAccount.matchRejected,    api.endpoints.postAccountAdminstatus.matchRejected,    api.endpoints.postAccountModify.matchRejected,);

    For those who prefer looking at example code, example listener.js and matcher.js files can be found here:

    applisteners definitionmatchershandlereglisteners.js sampleapplisteners.js oldalbumlisteners.js ukelonnlisteners.jsmatchers.jsauthservicelisteners.jsmatchers.js

    Using RTK queries’ successful loads in other reducers

    It is possible to use the successful completion of a mutation to clear reducers backing forms:

    import { createReducer } from '@reduxjs/toolkit';import { SELECT_STORE } from '../actiontypes';import { api } from '../api';const defaultState = {    storeId: -1,    storename: '',    gruppe: 2,};export default const storeReducer = createReducer(defaultState, builder => {    builder        .addCase(SELECT_STORE, (state, action) => action.payload)        .addMatcher(api.endpoints.postNewstore.matchFulfilled, () => ({ ...defaultState }))        .addMatcher(api.endpoints.postModifystore.matchFulfilled, () => ({ ...defaultState }));});

    Here both the completion of a successful postNewstore mutation and a successful postModifystore mutation will set the reducer to its default state (and clear the forms backed by the redux state value).

    Note the use of addMatcher() rather than addCase() to matche the actions.

    All matchFulfilled actions have the same redux type, so traditional redux type matching won’t work. But the matchers provided by the api object can be used instead.

    Dependent queries

    A common requirement is that one REST call needs the value of another value before being called. For this “dependent queries” in RTK query can be used:

    export default function Home() {    const { data: overview = {}, isSuccess: overviewIsSuccess } = useGetOverviewQuery();    const { data: purchases = [] } = useGetPurchasesQuery(overview.accountid, { skip: !overviewIsSuccess });    ...

    The above example the getPurchases query needs an account id that can be found in the results of the getOverview query.

    The “skip” property of the query option object to useGetPurchasesQuery() prevents useGetPurchasesQuery() from being executed until useGetOverviewQuery() has completed successfully.

    Converting apps

    For those preferring to look at code, here are the diffs from converting from redux/axios to RTK queries and RTK listeners:

    appDescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Reduction of JavaScript source code size for the various apps (source code line numbers from cloc run before and after the conversion):

    appsize reduction in %size reduction in #lineshandlereg34%674sampleapp32%359oldalbum14%608ukelonn25%1211authservice31%841

    Summing up the numbers from doing the conversion

    1. A 14% to 35% reduction of JavaScript code of the apps (with lots of boilerplate gone). The package with lowest percentage has a number of lines reduction on par with the rest of the “real” applications
    2. No noticable difference in dependencies size even though I was already using RTK and got rid of redux-saga and axios
    3. No significant difference in vite build artifact size (even an increase in one case) (numbers can be provided on request)

    As said at the start, the obsoletion of redux-saga made doing this change a non-brainer for me.

    But losing all of the boiler plate around network requests made the applications easier to read and understand and maintain. And the logic around lazy loading, reloads and caching of data is a lot better than my home-brewed redux-router powered logic.

    I’m not opposed to learning new stuff, but I can be quite reluctant to let go of stuff I like, and I was really happy about redux saga as outlined in Yep, I’m still using redux.

    So did I lose anything in this conversion?

    Downsides are:

    1. Harder to examine data loaded by RTK query in the redux devtools (but still possible)
    2. More complex react components:
      1. prior this change, redux served up data ready for consumption in the components and with defaults, i.e. this

        const butikker = useSelector(state => state.butikker);

        is simpler than this:

        import { useGetButikkerQuery } from '../services/butikker';...    const { data: butikker = [] } = useGetButikkerQuery();
      2. Prior to this change, gathering the data for a save to the back end took place in a saga, so there was no need to clutter up the component with data not used in the actual render
    3. It’s kinda hard (but not impossible) to use the loaded data as backing storage for the edit form, and then save back from the data. The assumption is that one is to use something like useState() for this, but I don’t wish to do that

    But putting stuff back in the react components makes fewer places to look for stuff and makes my react component look more similar to others’ react components, so maybe this isn’t so bad after all…?

    Where to go next?

    I startet using Redux ToolKit (RTK) back in 2019. I quickly figured that createReducer() and createAction() could make my existing reducers and redux action creation more robust.

    I tried using redux slices at that point in time, but since I had to mix the autocreated redux action with manually created redux actions to trigger REST API operations and handle REST API errors, I figured that redux slices was more work than useful.

    And I later also landed on the “flattened redux state approach” outlined in Yep, I’m still using redux (see that article for the reasoning) that didn’t fit well with slices, so I dropped it back then.

    But with RTK query I no longer have to manually create actions to start API operations or handle errors, since these are created when creating queries or mutations, so maybe it is time to give redux slices a new try…?

    #css #dom #html #lines #react #reactjs #redux #reduxSaga #reduxToolkit #saga

  10. Convert react/redux webapp from saga/axios to RTK query and RTK listener

    Redux saga is a core component of my react/redux applications. Unfortuately Redux Saga has been deprecated and haven’t seen an upgrade in the last year.

    This blog posts covers the replacement of redux saga and axios with RTK query and RTK listener in a react redux webapp.

    Introduction

    The structure of this blog post, is:

    1. First a walk through of how to use RTK query and RTK listener in a React application
    2. Then I’ll sum up the changes made, what was good and what didn’t feel like an improvement to me

    That means if searching on the web for how to use RTK query landed you here, you’ll find the good stuff first and can skip the rest.

    As for why you should use RTK query…?

    If you, like me, is still using redux with axios and saga, then switching to RTK query is a no-brainer, since redux Saga hasn’t seen an update since February 1 2024, and is now deprecated.

    If you’re not using redux because you have heard that it is hard to understand, bloated and require a lot of boilerplate, then you should reconsider. You should reconsider for the same reason I keep using redux: the existence of redux devtools.

    I find what I miss most when dealing with local state and context object is an easy way to examine the application’s current and entire state and trace when the state changes a particular value.

    Writing console.log() to output the data to find what’s in there, is so… I don’t know… 1985…?

    So without further ado, here’s how to use redux with RTK query in a react application (requires knowledge of JavaScript, it is helpful to know React, and knowledge of redux would help even more).

    Using RTK query

    Adding the dependencies

    Go to the directory containing package.json and run the following commands (first scrub existing dependencies and then add new ones):

    npm uninstall react react-dom react-redux "@reduxjs/toolkit"rm package-lock.jsonnpm install react react-dom react-redux "@reduxjs/toolkit"

    After this you should have all of the newest versions of the required dependencies.

    If converting from saga/axios, then remember to scrub unneccessary dependencies after completing the conversion, with:

    npm uninstall redux-saga axiosrm package-lock.jsonnpm install

    Queries and mutations

    With redux-saga and axios, data from a REST API backend is loaded by something like this

    import { takeLatest, call, put } from 'redux-saga/effects';import axios from 'axios';import { ACCOUNTS_REQUEST, ACCOUNTS_RECEIVE, ACCOUNTS_FAILURE } from '../reduxactions';export default function* accountsSaga() {    yield takeLatest(ACCOUNTS_REQUEST, receiveAccountsResult);}function* receiveAccountsResult() {    try {        const response = yield call(getAccounts);        const accountsresult = (response.headers['content-type'] === 'application/json') ? response.data : {};        yield put(ACCOUNTS_RECEIVE(accountsresult));    } catch (error) {        yield put(ACCOUNTS_FAILURE(error));    }}function getAccounts() {    return axios.get('/api/accounts');}

    In addition to the above code a redux reducer to store the data in the frontend is needed, and the redux actions must be defined (not shown here, this blog post is about RTK query and not about redux-saga and axios).

    In RTK query, the above example would be replaced with a one liner (this is what is called “a query” in RTK query terminology):

    getAccounts: builder.query({ query: () => '/accounts' }),

    In addtion to creating the code fetching the data, this one liner also results in redux storage of the fetched data, and redux actions for starting, successful completion and failure.

    To use the results of data fetched by an RTK query in a React component, a hook created from the above one liner is used

    export default function Home() {    const { data: accounts = [] } = useGetAccountsQuery();    return (<p>Number of accounts: ${accounts.length}</p>);}

    When the component is rendered an HTTP request is started to fetch the data, and when the data arrives the component will be re-rendered. There is also considerable logic behind caching data and refetching that decides whether to reload the data or not when navigating in and out of the component.

    My brief experience with RTK query is enough to tell me that RTK query’s reload logic works a lot better than my own home brewed reload logic.

    One difference from the replaced saga/axios code, was that the reducer where the fetched data is stored, has no default value. So without the “= []” in the example above, accounts would be undefined on the first render.

    Since the returned data is in the redux state, it is possible to use the useSelector() hook to access the data, but using a regular selector won’t trigger the fetch and reload logic. So as a rule of thumb: always start with the generated hook.

    It is possible to add arguments to a query

    getAccount: builder.query({ query: (username) => '/account/' + username }),

    The query argument would then added to the hook used in the react component:

    const { data: account = {} } = useGetAccountQuery('steban');

    Default for a query is to use HTTP GET, but using e.g. POST is simple and still an one-liner

    postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),

    The “body” argument needs to be possible to translate into JSON, to be sent as the POST body (and in my experience it is best to make the POSTed JSON a JSON object).

    const { data: adminStatus } = usePostAccountAdminstatusQuery({ username: 'steban' });

    Queries are for fetching data only. Even if a POST is used a query shouldn’t be used on an endpoint that modifies data on the backend.

    To modify data you use a mutation, and a mutation can also be a one-liner

    postAccountModify: builder.mutation({ query: body => ({ url: '/account/modify', method: 'POST', body }) }),

    The usage if the mutation hook is a little bit more complex than the query hook:

    const { data: account = {} } = useGetAccountQuery('steban');const [ postAccountModify ] = usePostAccountModifyMutation();const onSaveButtonClicked = async () => await postAccountModify(account);

    I.e.:

    1. The mutation function is picked out of the hook return value
    2. Then an async lambda is created using that function to post the return value
    3. The account value is used in the form elements
    4. The onSaveButtonClicked is used in

      <button onClick={onSaveButtonClicked}>Save account</button>

    After updating data in the server, you would like the redux data updated with the new values.

    The simplest way to get updated redux data, is to trigger a reload of the query that fetched the data in the first place.

    To trigger a reload, put a tag on the query that should be reloaded:

    getAccounts: builder.query({ query: () => '/accounts', providesTags: ['Accounts'] }),

    and then invalidate that tag after POSTing a mutation:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    invalidatesTags: ['Accounts'],}),

    The getAccounts query will be re-run and components with the useGetAccountsQuery() hook will be re-rendered.

    That if the accounts had already been loaded by a hook in a react component, it isn’t neccessarily reloaded the next time the component is loaded, so without the invalidation, navigating to the component might show the old data.

    But using invalidation of tags makes everything works smoothly and makes the data be updated on visit.

    If the return from the mutation contains the the updated data, there is no need to make an invalidation. Then the redux storage of the query can be updated with the mutation return:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    async onQueryStarted(body, { dispatch, queryFulfilled }) {        try {            const { data: accountsAfterAccountModify } = await queryFulfilled;            dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));        } catch {}    },}),

    The await queryFulfilled in onQueryStarted() waits for a successful mutation return and then then dispatches a redux action that replaces the results of a query

    The tricky bit, when replacing query values in this way, is argument 2 of the updateQueryData() redux action creator, which is undefined in the above example.

    If the query had an argument (e.g. the username), the replacement needs to have the same value. If not, there is no replacement and no error message. In this case the query has no argument, and then undefined is used.

    The queries and mutations in my converted projects all live in a single file api.js on the top and all look a bit like this:

    import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';export const api = createApi({    reducerPath: 'api',    baseQuery: (...args) => {        const api = args[1];        const basename = api.getState().basename;        return fetchBaseQuery({ baseUrl: basename + '/api' })(...args);    },    endpoints: (builder) => ({        getAccounts: builder.query({ query: () => '/accounts' }),        getAccount: builder.query({ query: (username) => '/account/' + username }),        postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),        postAccountModify: builder.mutation({            query: body => ({ url: '/account/modify', method: 'POST', body }),            async onQueryStarted(body, { dispatch, queryFulfilled }) {                try {                    const { data: accountsAfterAccountModify } = await queryFulfilled;                    dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));                } catch {}            },        }),    }),});export const {    useGetAccountsQuery,    useCetAccountQuery,    usePostAccountAdminstatusQuery,    usePostAccountModifyMutation,} = api;

    I.e.

    1. The reducerPath is the top level path of the api’s reducer slice in the redux state
    2. The baseQuery sets the base path prefix for all API calls, in this case it is the value of ‘/api’ prefixed by redux state value basename
    3. The endpoints contains the specification for the queries and mutations
    4. All mutations are exported at the end for ease of use in the

    For those who like looking at example code, here is the “api.js” of some React web applications converted from saga/axios to RTK query:

    applicationdescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Adding RTK query to the redux store

    The api object needs to be added to the reducer:

    import { combineReducers } from 'redux';import { createReducer } from '@reduxjs/toolkit';import { api } from '../api';export default (basename) => combineReducers({    [api.reducerPath]: api.reducer,    basename: createReducer(basename, (builder) => builder),});

    The exported function is a reducer creator that can be used to create a redux store state with two values:

    1. api which is a redux slice containing all state related to network communication and dowloaded results
    2. basename which is a string value holding the react application’s basepath

    The creator function can be used to create a redux store:

    import rootReducer from './reducers';import { api } from './api';import listeners from './listeners';// Calculate the basename based on the URL of the vite assets directoryconst baseUrl = Array.from(document.scripts).map(s => s.src).filter(src => src.includes('assets/'))[0].replace(/\/assets\/.*/, '');const basename = new URL(baseUrl).pathname;const store = configureStore({    reducer: rootReducer(basename),    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware).prepend(listeners.middleware),});

    First we calculate the application’s basepath from the vite artifact the code is loaded from, then a store is created with a reducer consisting of api and basename, and then two middlewares are added: api and listener

    “What is listeners?” you ask at this point.

    I am glad you asked! Check out the next section.

    For those who like looking at example code, some example redux store setups for RTK query and RTK listener:

    appreducersredux store setuphandleregreducers/index.jstop index.jssampleappreducers/index.jstop index.jsoldalbumreducers/index.jstop index.jsukelonnreducers/index.jstop index.jsauthservicereducers/index.jstop index.js

    Using RTK listener to perform actions on REDUX actions

    Listener fills the same role as another useful saga role: the ability to listen for redux actions and act on them:

    import { createListenerMiddleware } from '@reduxjs/toolkit';import { isFailedRequest } from './matchers';const listeners = createListenerMiddleware();listeners.startListening({    matcher: isFailedRequest,    effect: ({ payload }) => {        const { originalStatus } = payload || {};        const statusCode = parseInt(originalStatus);        if (statusCode === 401 || statusCode === 403) {            location.reload(true); // Will return to current location after the login process        }    }})export default listeners;

    This listener listens for failed RTK query HTTP calls to the API and checks the status codes for 401 “Needs Authentication” and 403 “Not Authorized” and reloads the app with the current URL to let apache shiro deal with it (refresh the auth and just open this page, pop up login or redirect to unauthorized page).

    This is “matchers.js” where isFailedRequest is found:

    import { isAnyOf } from '@reduxjs/toolkit';import { api } from './api';export const isFailedRequest = isAnyOf(    api.endpoints.getAccounts.matchRejected,    api.endpoints.getAccount.matchRejected,    api.endpoints.postAccountAdminstatus.matchRejected,    api.endpoints.postAccountModify.matchRejected,);

    For those who prefer looking at example code, example listener.js and matcher.js files can be found here:

    applisteners definitionmatchershandlereglisteners.js sampleapplisteners.js oldalbumlisteners.js ukelonnlisteners.jsmatchers.jsauthservicelisteners.jsmatchers.js

    Using RTK queries’ successful loads in other reducers

    It is possible to use the successful completion of a mutation to clear reducers backing forms:

    import { createReducer } from '@reduxjs/toolkit';import { SELECT_STORE } from '../actiontypes';import { api } from '../api';const defaultState = {    storeId: -1,    storename: '',    gruppe: 2,};export default const storeReducer = createReducer(defaultState, builder => {    builder        .addCase(SELECT_STORE, (state, action) => action.payload)        .addMatcher(api.endpoints.postNewstore.matchFulfilled, () => ({ ...defaultState }))        .addMatcher(api.endpoints.postModifystore.matchFulfilled, () => ({ ...defaultState }));});

    Here both the completion of a successful postNewstore mutation and a successful postModifystore mutation will set the reducer to its default state (and clear the forms backed by the redux state value).

    Note the use of addMatcher() rather than addCase() to matche the actions.

    All matchFulfilled actions have the same redux type, so traditional redux type matching won’t work. But the matchers provided by the api object can be used instead.

    Dependent queries

    A common requirement is that one REST call needs the value of another value before being called. For this “dependent queries” in RTK query can be used:

    export default function Home() {    const { data: overview = {}, isSuccess: overviewIsSuccess } = useGetOverviewQuery();    const { data: purchases = [] } = useGetPurchasesQuery(overview.accountid, { skip: !overviewIsSuccess });    ...

    The above example the getPurchases query needs an account id that can be found in the results of the getOverview query.

    The “skip” property of the query option object to useGetPurchasesQuery() prevents useGetPurchasesQuery() from being executed until useGetOverviewQuery() has completed successfully.

    Converting apps

    For those preferring to look at code, here are the diffs from converting from redux/axios to RTK queries and RTK listeners:

    appDescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Reduction of JavaScript source code size for the various apps (source code line numbers from cloc run before and after the conversion):

    appsize reduction in %size reduction in #lineshandlereg34%674sampleapp32%359oldalbum14%608ukelonn25%1211authservice31%841

    Summing up the numbers from doing the conversion

    1. A 14% to 35% reduction of JavaScript code of the apps (with lots of boilerplate gone). The package with lowest percentage has a number of lines reduction on par with the rest of the “real” applications
    2. No noticable difference in dependencies size even though I was already using RTK and got rid of redux-saga and axios
    3. No significant difference in vite build artifact size (even an increase in one case) (numbers can be provided on request)

    As said at the start, the obsoletion of redux-saga made doing this change a non-brainer for me.

    But losing all of the boiler plate around network requests made the applications easier to read and understand and maintain. And the logic around lazy loading, reloads and caching of data is a lot better than my home-brewed redux-router powered logic.

    I’m not opposed to learning new stuff, but I can be quite reluctant to let go of stuff I like, and I was really happy about redux saga as outlined in Yep, I’m still using redux.

    So did I lose anything in this conversion?

    Downsides are:

    1. Harder to examine data loaded by RTK query in the redux devtools (but still possible)
    2. More complex react components:
      1. prior this change, redux served up data ready for consumption in the components and with defaults, i.e. this

        const butikker = useSelector(state => state.butikker);

        is simpler than this:

        import { useGetButikkerQuery } from '../services/butikker';...    const { data: butikker = [] } = useGetButikkerQuery();
      2. Prior to this change, gathering the data for a save to the back end took place in a saga, so there was no need to clutter up the component with data not used in the actual render
    3. It’s kinda hard (but not impossible) to use the loaded data as backing storage for the edit form, and then save back from the data. The assumption is that one is to use something like useState() for this, but I don’t wish to do that

    But putting stuff back in the react components makes fewer places to look for stuff and makes my react component look more similar to others’ react components, so maybe this isn’t so bad after all…?

    Where to go next?

    I startet using Redux ToolKit (RTK) back in 2019. I quickly figured that createReducer() and createAction() could make my existing reducers and redux action creation more robust.

    I tried using redux slices at that point in time, but since I had to mix the autocreated redux action with manually created redux actions to trigger REST API operations and handle REST API errors, I figured that redux slices was more work than useful.

    And I later also landed on the “flattened redux state approach” outlined in Yep, I’m still using redux (see that article for the reasoning) that didn’t fit well with slices, so I dropped it back then.

    But with RTK query I no longer have to manually create actions to start API operations or handle errors, since these are created when creating queries or mutations, so maybe it is time to give redux slices a new try…?

    #css #dom #html #lines #react #reactjs #redux #reduxSaga #reduxToolkit #saga

  11. Convert react/redux webapp from saga/axios to RTK query and RTK listener

    Redux saga is a core component of my react/redux applications. Unfortuately Redux Saga has been deprecated and haven’t seen an upgrade in the last year.

    This blog posts covers the replacement of redux saga and axios with RTK query and RTK listener in a react redux webapp.

    Introduction

    The structure of this blog post, is:

    1. First a walk through of how to use RTK query and RTK listener in a React application
    2. Then I’ll sum up the changes made, what was good and what didn’t feel like an improvement to me

    That means if searching on the web for how to use RTK query landed you here, you’ll find the good stuff first and can skip the rest.

    As for why you should use RTK query…?

    If you, like me, is still using redux with axios and saga, then switching to RTK query is a no-brainer, since redux Saga hasn’t seen an update since February 1 2024, and is now deprecated.

    If you’re not using redux because you have heard that it is hard to understand, bloated and require a lot of boilerplate, then you should reconsider. You should reconsider for the same reason I keep using redux: the existence of redux devtools.

    I find what I miss most when dealing with local state and context object is an easy way to examine the application’s current and entire state and trace when the state changes a particular value.

    Writing console.log() to output the data to find what’s in there, is so… I don’t know… 1985…?

    So without further ado, here’s how to use redux with RTK query in a react application (requires knowledge of JavaScript, it is helpful to know React, and knowledge of redux would help even more).

    Using RTK query

    Adding the dependencies

    Go to the directory containing package.json and run the following commands (first scrub existing dependencies and then add new ones):

    npm uninstall react react-dom react-redux "@reduxjs/toolkit"rm package-lock.jsonnpm install react react-dom react-redux "@reduxjs/toolkit"

    After this you should have all of the newest versions of the required dependencies.

    If converting from saga/axios, then remember to scrub unneccessary dependencies after completing the conversion, with:

    npm uninstall redux-saga axiosrm package-lock.jsonnpm install

    Queries and mutations

    With redux-saga and axios, data from a REST API backend is loaded by something like this

    import { takeLatest, call, put } from 'redux-saga/effects';import axios from 'axios';import { ACCOUNTS_REQUEST, ACCOUNTS_RECEIVE, ACCOUNTS_FAILURE } from '../reduxactions';export default function* accountsSaga() {    yield takeLatest(ACCOUNTS_REQUEST, receiveAccountsResult);}function* receiveAccountsResult() {    try {        const response = yield call(getAccounts);        const accountsresult = (response.headers['content-type'] === 'application/json') ? response.data : {};        yield put(ACCOUNTS_RECEIVE(accountsresult));    } catch (error) {        yield put(ACCOUNTS_FAILURE(error));    }}function getAccounts() {    return axios.get('/api/accounts');}

    In addition to the above code a redux reducer to store the data in the frontend is needed, and the redux actions must be defined (not shown here, this blog post is about RTK query and not about redux-saga and axios).

    In RTK query, the above example would be replaced with a one liner (this is what is called “a query” in RTK query terminology):

    getAccounts: builder.query({ query: () => '/accounts' }),

    In addtion to creating the code fetching the data, this one liner also results in redux storage of the fetched data, and redux actions for starting, successful completion and failure.

    To use the results of data fetched by an RTK query in a React component, a hook created from the above one liner is used

    export default function Home() {    const { data: accounts = [] } = useGetAccountsQuery();    return (<p>Number of accounts: ${accounts.length}</p>);}

    When the component is rendered an HTTP request is started to fetch the data, and when the data arrives the component will be re-rendered. There is also considerable logic behind caching data and refetching that decides whether to reload the data or not when navigating in and out of the component.

    My brief experience with RTK query is enough to tell me that RTK query’s reload logic works a lot better than my own home brewed reload logic.

    One difference from the replaced saga/axios code, was that the reducer where the fetched data is stored, has no default value. So without the “= []” in the example above, accounts would be undefined on the first render.

    Since the returned data is in the redux state, it is possible to use the useSelector() hook to access the data, but using a regular selector won’t trigger the fetch and reload logic. So as a rule of thumb: always start with the generated hook.

    It is possible to add arguments to a query

    getAccount: builder.query({ query: (username) => '/account/' + username }),

    The query argument would then added to the hook used in the react component:

    const { data: account = {} } = useGetAccountQuery('steban');

    Default for a query is to use HTTP GET, but using e.g. POST is simple and still an one-liner

    postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),

    The “body” argument needs to be possible to translate into JSON, to be sent as the POST body (and in my experience it is best to make the POSTed JSON a JSON object).

    const { data: adminStatus } = usePostAccountAdminstatusQuery({ username: 'steban' });

    Queries are for fetching data only. Even if a POST is used a query shouldn’t be used on an endpoint that modifies data on the backend.

    To modify data you use a mutation, and a mutation can also be a one-liner

    postAccountModify: builder.mutation({ query: body => ({ url: '/account/modify', method: 'POST', body }) }),

    The usage if the mutation hook is a little bit more complex than the query hook:

    const { data: account = {} } = useGetAccountQuery('steban');const [ postAccountModify ] = usePostAccountModifyMutation();const onSaveButtonClicked = async () => await postAccountModify(account);

    I.e.:

    1. The mutation function is picked out of the hook return value
    2. Then an async lambda is created using that function to post the return value
    3. The account value is used in the form elements
    4. The onSaveButtonClicked is used in

      <button onClick={onSaveButtonClicked}>Save account</button>

    After updating data in the server, you would like the redux data updated with the new values.

    The simplest way to get updated redux data, is to trigger a reload of the query that fetched the data in the first place.

    To trigger a reload, put a tag on the query that should be reloaded:

    getAccounts: builder.query({ query: () => '/accounts', providesTags: ['Accounts'] }),

    and then invalidate that tag after POSTing a mutation:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    invalidatesTags: ['Accounts'],}),

    The getAccounts query will be re-run and components with the useGetAccountsQuery() hook will be re-rendered.

    That if the accounts had already been loaded by a hook in a react component, it isn’t neccessarily reloaded the next time the component is loaded, so without the invalidation, navigating to the component might show the old data.

    But using invalidation of tags makes everything works smoothly and makes the data be updated on visit.

    If the return from the mutation contains the the updated data, there is no need to make an invalidation. Then the redux storage of the query can be updated with the mutation return:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    async onQueryStarted(body, { dispatch, queryFulfilled }) {        try {            const { data: accountsAfterAccountModify } = await queryFulfilled;            dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));        } catch {}    },}),

    The await queryFulfilled in onQueryStarted() waits for a successful mutation return and then then dispatches a redux action that replaces the results of a query

    The tricky bit, when replacing query values in this way, is argument 2 of the updateQueryData() redux action creator, which is undefined in the above example.

    If the query had an argument (e.g. the username), the replacement needs to have the same value. If not, there is no replacement and no error message. In this case the query has no argument, and then undefined is used.

    The queries and mutations in my converted projects all live in a single file api.js on the top and all look a bit like this:

    import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';export const api = createApi({    reducerPath: 'api',    baseQuery: (...args) => {        const api = args[1];        const basename = api.getState().basename;        return fetchBaseQuery({ baseUrl: basename + '/api' })(...args);    },    endpoints: (builder) => ({        getAccounts: builder.query({ query: () => '/accounts' }),        getAccount: builder.query({ query: (username) => '/account/' + username }),        postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),        postAccountModify: builder.mutation({            query: body => ({ url: '/account/modify', method: 'POST', body }),            async onQueryStarted(body, { dispatch, queryFulfilled }) {                try {                    const { data: accountsAfterAccountModify } = await queryFulfilled;                    dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));                } catch {}            },        }),    }),});export const {    useGetAccountsQuery,    useCetAccountQuery,    usePostAccountAdminstatusQuery,    usePostAccountModifyMutation,} = api;

    I.e.

    1. The reducerPath is the top level path of the api’s reducer slice in the redux state
    2. The baseQuery sets the base path prefix for all API calls, in this case it is the value of ‘/api’ prefixed by redux state value basename
    3. The endpoints contains the specification for the queries and mutations
    4. All mutations are exported at the end for ease of use in the

    For those who like looking at example code, here is the “api.js” of some React web applications converted from saga/axios to RTK query:

    applicationdescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Adding RTK query to the redux store

    The api object needs to be added to the reducer:

    import { combineReducers } from 'redux';import { createReducer } from '@reduxjs/toolkit';import { api } from '../api';export default (basename) => combineReducers({    [api.reducerPath]: api.reducer,    basename: createReducer(basename, (builder) => builder),});

    The exported function is a reducer creator that can be used to create a redux store state with two values:

    1. api which is a redux slice containing all state related to network communication and dowloaded results
    2. basename which is a string value holding the react application’s basepath

    The creator function can be used to create a redux store:

    import rootReducer from './reducers';import { api } from './api';import listeners from './listeners';// Calculate the basename based on the URL of the vite assets directoryconst baseUrl = Array.from(document.scripts).map(s => s.src).filter(src => src.includes('assets/'))[0].replace(/\/assets\/.*/, '');const basename = new URL(baseUrl).pathname;const store = configureStore({    reducer: rootReducer(basename),    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware).prepend(listeners.middleware),});

    First we calculate the application’s basepath from the vite artifact the code is loaded from, then a store is created with a reducer consisting of api and basename, and then two middlewares are added: api and listener

    “What is listeners?” you ask at this point.

    I am glad you asked! Check out the next section.

    For those who like looking at example code, some example redux store setups for RTK query and RTK listener:

    appreducersredux store setuphandleregreducers/index.jstop index.jssampleappreducers/index.jstop index.jsoldalbumreducers/index.jstop index.jsukelonnreducers/index.jstop index.jsauthservicereducers/index.jstop index.js

    Using RTK listener to perform actions on REDUX actions

    Listener fills the same role as another useful saga role: the ability to listen for redux actions and act on them:

    import { createListenerMiddleware } from '@reduxjs/toolkit';import { isFailedRequest } from './matchers';const listeners = createListenerMiddleware();listeners.startListening({    matcher: isFailedRequest,    effect: ({ payload }) => {        const { originalStatus } = payload || {};        const statusCode = parseInt(originalStatus);        if (statusCode === 401 || statusCode === 403) {            location.reload(true); // Will return to current location after the login process        }    }})export default listeners;

    This listener listens for failed RTK query HTTP calls to the API and checks the status codes for 401 “Needs Authentication” and 403 “Not Authorized” and reloads the app with the current URL to let apache shiro deal with it (refresh the auth and just open this page, pop up login or redirect to unauthorized page).

    This is “matchers.js” where isFailedRequest is found:

    import { isAnyOf } from '@reduxjs/toolkit';import { api } from './api';export const isFailedRequest = isAnyOf(    api.endpoints.getAccounts.matchRejected,    api.endpoints.getAccount.matchRejected,    api.endpoints.postAccountAdminstatus.matchRejected,    api.endpoints.postAccountModify.matchRejected,);

    For those who prefer looking at example code, example listener.js and matcher.js files can be found here:

    applisteners definitionmatchershandlereglisteners.js sampleapplisteners.js oldalbumlisteners.js ukelonnlisteners.jsmatchers.jsauthservicelisteners.jsmatchers.js

    Using RTK queries’ successful loads in other reducers

    It is possible to use the successful completion of a mutation to clear reducers backing forms:

    import { createReducer } from '@reduxjs/toolkit';import { SELECT_STORE } from '../actiontypes';import { api } from '../api';const defaultState = {    storeId: -1,    storename: '',    gruppe: 2,};export default const storeReducer = createReducer(defaultState, builder => {    builder        .addCase(SELECT_STORE, (state, action) => action.payload)        .addMatcher(api.endpoints.postNewstore.matchFulfilled, () => ({ ...defaultState }))        .addMatcher(api.endpoints.postModifystore.matchFulfilled, () => ({ ...defaultState }));});

    Here both the completion of a successful postNewstore mutation and a successful postModifystore mutation will set the reducer to its default state (and clear the forms backed by the redux state value).

    Note the use of addMatcher() rather than addCase() to matche the actions.

    All matchFulfilled actions have the same redux type, so traditional redux type matching won’t work. But the matchers provided by the api object can be used instead.

    Dependent queries

    A common requirement is that one REST call needs the value of another value before being called. For this “dependent queries” in RTK query can be used:

    export default function Home() {    const { data: overview = {}, isSuccess: overviewIsSuccess } = useGetOverviewQuery();    const { data: purchases = [] } = useGetPurchasesQuery(overview.accountid, { skip: !overviewIsSuccess });    ...

    The above example the getPurchases query needs an account id that can be found in the results of the getOverview query.

    The “skip” property of the query option object to useGetPurchasesQuery() prevents useGetPurchasesQuery() from being executed until useGetOverviewQuery() has completed successfully.

    Converting apps

    For those preferring to look at code, here are the diffs from converting from redux/axios to RTK queries and RTK listeners:

    appDescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Reduction of JavaScript source code size for the various apps (source code line numbers from cloc run before and after the conversion):

    appsize reduction in %size reduction in #lineshandlereg34%674sampleapp32%359oldalbum14%608ukelonn25%1211authservice31%841

    Summing up the numbers from doing the conversion

    1. A 14% to 35% reduction of JavaScript code of the apps (with lots of boilerplate gone). The package with lowest percentage has a number of lines reduction on par with the rest of the “real” applications
    2. No noticable difference in dependencies size even though I was already using RTK and got rid of redux-saga and axios
    3. No significant difference in vite build artifact size (even an increase in one case) (numbers can be provided on request)

    As said at the start, the obsoletion of redux-saga made doing this change a non-brainer for me.

    But losing all of the boiler plate around network requests made the applications easier to read and understand and maintain. And the logic around lazy loading, reloads and caching of data is a lot better than my home-brewed redux-router powered logic.

    I’m not opposed to learning new stuff, but I can be quite reluctant to let go of stuff I like, and I was really happy about redux saga as outlined in Yep, I’m still using redux.

    So did I lose anything in this conversion?

    Downsides are:

    1. Harder to examine data loaded by RTK query in the redux devtools (but still possible)
    2. More complex react components:
      1. prior this change, redux served up data ready for consumption in the components and with defaults, i.e. this

        const butikker = useSelector(state => state.butikker);

        is simpler than this:

        import { useGetButikkerQuery } from '../services/butikker';...    const { data: butikker = [] } = useGetButikkerQuery();
      2. Prior to this change, gathering the data for a save to the back end took place in a saga, so there was no need to clutter up the component with data not used in the actual render
    3. It’s kinda hard (but not impossible) to use the loaded data as backing storage for the edit form, and then save back from the data. The assumption is that one is to use something like useState() for this, but I don’t wish to do that

    But putting stuff back in the react components makes fewer places to look for stuff and makes my react component look more similar to others’ react components, so maybe this isn’t so bad after all…?

    Where to go next?

    I startet using Redux ToolKit (RTK) back in 2019. I quickly figured that createReducer() and createAction() could make my existing reducers and redux action creation more robust.

    I tried using redux slices at that point in time, but since I had to mix the autocreated redux action with manually created redux actions to trigger REST API operations and handle REST API errors, I figured that redux slices was more work than useful.

    And I later also landed on the “flattened redux state approach” outlined in Yep, I’m still using redux (see that article for the reasoning) that didn’t fit well with slices, so I dropped it back then.

    But with RTK query I no longer have to manually create actions to start API operations or handle errors, since these are created when creating queries or mutations, so maybe it is time to give redux slices a new try…?

    #css #dom #html #lines #react #reactjs #redux #reduxSaga #reduxToolkit #saga

  12. Convert react/redux webapp from saga/axios to RTK query and RTK listener

    Redux saga is a core component of my react/redux applications. Unfortuately Redux Saga has been deprecated and haven’t seen an upgrade in the last year.

    This blog posts covers the replacement of redux saga and axios with RTK query and RTK listener in a react redux webapp.

    Introduction

    The structure of this blog post, is:

    1. First a walk through of how to use RTK query and RTK listener in a React application
    2. Then I’ll sum up the changes made, what was good and what didn’t feel like an improvement to me

    That means if searching on the web for how to use RTK query landed you here, you’ll find the good stuff first and can skip the rest.

    As for why you should use RTK query…?

    If you, like me, is still using redux with axios and saga, then switching to RTK query is a no-brainer, since redux Saga hasn’t seen an update since February 1 2024, and is now deprecated.

    If you’re not using redux because you have heard that it is hard to understand, bloated and require a lot of boilerplate, then you should reconsider. You should reconsider for the same reason I keep using redux: the existence of redux devtools.

    I find what I miss most when dealing with local state and context object is an easy way to examine the application’s current and entire state and trace when the state changes a particular value.

    Writing console.log() to output the data to find what’s in there, is so… I don’t know… 1985…?

    So without further ado, here’s how to use redux with RTK query in a react application (requires knowledge of JavaScript, it is helpful to know React, and knowledge of redux would help even more).

    Using RTK query

    Adding the dependencies

    Go to the directory containing package.json and run the following commands (first scrub existing dependencies and then add new ones):

    npm uninstall react react-dom react-redux "@reduxjs/toolkit"rm package-lock.jsonnpm install react react-dom react-redux "@reduxjs/toolkit"

    After this you should have all of the newest versions of the required dependencies.

    If converting from saga/axios, then remember to scrub unneccessary dependencies after completing the conversion, with:

    npm uninstall redux-saga axiosrm package-lock.jsonnpm install

    Queries and mutations

    With redux-saga and axios, data from a REST API backend is loaded by something like this

    import { takeLatest, call, put } from 'redux-saga/effects';import axios from 'axios';import { ACCOUNTS_REQUEST, ACCOUNTS_RECEIVE, ACCOUNTS_FAILURE } from '../reduxactions';export default function* accountsSaga() {    yield takeLatest(ACCOUNTS_REQUEST, receiveAccountsResult);}function* receiveAccountsResult() {    try {        const response = yield call(getAccounts);        const accountsresult = (response.headers['content-type'] === 'application/json') ? response.data : {};        yield put(ACCOUNTS_RECEIVE(accountsresult));    } catch (error) {        yield put(ACCOUNTS_FAILURE(error));    }}function getAccounts() {    return axios.get('/api/accounts');}

    In addition to the above code a redux reducer to store the data in the frontend is needed, and the redux actions must be defined (not shown here, this blog post is about RTK query and not about redux-saga and axios).

    In RTK query, the above example would be replaced with a one liner (this is what is called “a query” in RTK query terminology):

    getAccounts: builder.query({ query: () => '/accounts' }),

    In addtion to creating the code fetching the data, this one liner also results in redux storage of the fetched data, and redux actions for starting, successful completion and failure.

    To use the results of data fetched by an RTK query in a React component, a hook created from the above one liner is used

    export default function Home() {    const { data: accounts = [] } = useGetAccountsQuery();    return (<p>Number of accounts: ${accounts.length}</p>);}

    When the component is rendered an HTTP request is started to fetch the data, and when the data arrives the component will be re-rendered. There is also considerable logic behind caching data and refetching that decides whether to reload the data or not when navigating in and out of the component.

    My brief experience with RTK query is enough to tell me that RTK query’s reload logic works a lot better than my own home brewed reload logic.

    One difference from the replaced saga/axios code, was that the reducer where the fetched data is stored, has no default value. So without the “= []” in the example above, accounts would be undefined on the first render.

    Since the returned data is in the redux state, it is possible to use the useSelector() hook to access the data, but using a regular selector won’t trigger the fetch and reload logic. So as a rule of thumb: always start with the generated hook.

    It is possible to add arguments to a query

    getAccount: builder.query({ query: (username) => '/account/' + username }),

    The query argument would then added to the hook used in the react component:

    const { data: account = {} } = useGetAccountQuery('steban');

    Default for a query is to use HTTP GET, but using e.g. POST is simple and still an one-liner

    postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),

    The “body” argument needs to be possible to translate into JSON, to be sent as the POST body (and in my experience it is best to make the POSTed JSON a JSON object).

    const { data: adminStatus } = usePostAccountAdminstatusQuery({ username: 'steban' });

    Queries are for fetching data only. Even if a POST is used a query shouldn’t be used on an endpoint that modifies data on the backend.

    To modify data you use a mutation, and a mutation can also be a one-liner

    postAccountModify: builder.mutation({ query: body => ({ url: '/account/modify', method: 'POST', body }) }),

    The usage if the mutation hook is a little bit more complex than the query hook:

    const { data: account = {} } = useGetAccountQuery('steban');const [ postAccountModify ] = usePostAccountModifyMutation();const onSaveButtonClicked = async () => await postAccountModify(account);

    I.e.:

    1. The mutation function is picked out of the hook return value
    2. Then an async lambda is created using that function to post the return value
    3. The account value is used in the form elements
    4. The onSaveButtonClicked is used in

      <button onClick={onSaveButtonClicked}>Save account</button>

    After updating data in the server, you would like the redux data updated with the new values.

    The simplest way to get updated redux data, is to trigger a reload of the query that fetched the data in the first place.

    To trigger a reload, put a tag on the query that should be reloaded:

    getAccounts: builder.query({ query: () => '/accounts', providesTags: ['Accounts'] }),

    and then invalidate that tag after POSTing a mutation:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    invalidatesTags: ['Accounts'],}),

    The getAccounts query will be re-run and components with the useGetAccountsQuery() hook will be re-rendered.

    That if the accounts had already been loaded by a hook in a react component, it isn’t neccessarily reloaded the next time the component is loaded, so without the invalidation, navigating to the component might show the old data.

    But using invalidation of tags makes everything works smoothly and makes the data be updated on visit.

    If the return from the mutation contains the the updated data, there is no need to make an invalidation. Then the redux storage of the query can be updated with the mutation return:

    postAccountModify: builder.mutation({    query: body => ({ url: '/account/modify', method: 'POST', body }),    async onQueryStarted(body, { dispatch, queryFulfilled }) {        try {            const { data: accountsAfterAccountModify } = await queryFulfilled;            dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));        } catch {}    },}),

    The await queryFulfilled in onQueryStarted() waits for a successful mutation return and then then dispatches a redux action that replaces the results of a query

    The tricky bit, when replacing query values in this way, is argument 2 of the updateQueryData() redux action creator, which is undefined in the above example.

    If the query had an argument (e.g. the username), the replacement needs to have the same value. If not, there is no replacement and no error message. In this case the query has no argument, and then undefined is used.

    The queries and mutations in my converted projects all live in a single file api.js on the top and all look a bit like this:

    import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';export const api = createApi({    reducerPath: 'api',    baseQuery: (...args) => {        const api = args[1];        const basename = api.getState().basename;        return fetchBaseQuery({ baseUrl: basename + '/api' })(...args);    },    endpoints: (builder) => ({        getAccounts: builder.query({ query: () => '/accounts' }),        getAccount: builder.query({ query: (username) => '/account/' + username }),        postAccountAdminstatus: builder.query({ query: body => ({ url: '/account/adminstatus', method: 'POST', body }) }),        postAccountModify: builder.mutation({            query: body => ({ url: '/account/modify', method: 'POST', body }),            async onQueryStarted(body, { dispatch, queryFulfilled }) {                try {                    const { data: accountsAfterAccountModify } = await queryFulfilled;                    dispatch(api.util.updateQueryData('getAccounts',  undefined, () => accountsAfterAccountModify));                } catch {}            },        }),    }),});export const {    useGetAccountsQuery,    useCetAccountQuery,    usePostAccountAdminstatusQuery,    usePostAccountModifyMutation,} = api;

    I.e.

    1. The reducerPath is the top level path of the api’s reducer slice in the redux state
    2. The baseQuery sets the base path prefix for all API calls, in this case it is the value of ‘/api’ prefixed by redux state value basename
    3. The endpoints contains the specification for the queries and mutations
    4. All mutations are exported at the end for ease of use in the

    For those who like looking at example code, here is the “api.js” of some React web applications converted from saga/axios to RTK query:

    applicationdescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Adding RTK query to the redux store

    The api object needs to be added to the reducer:

    import { combineReducers } from 'redux';import { createReducer } from '@reduxjs/toolkit';import { api } from '../api';export default (basename) => combineReducers({    [api.reducerPath]: api.reducer,    basename: createReducer(basename, (builder) => builder),});

    The exported function is a reducer creator that can be used to create a redux store state with two values:

    1. api which is a redux slice containing all state related to network communication and dowloaded results
    2. basename which is a string value holding the react application’s basepath

    The creator function can be used to create a redux store:

    import rootReducer from './reducers';import { api } from './api';import listeners from './listeners';// Calculate the basename based on the URL of the vite assets directoryconst baseUrl = Array.from(document.scripts).map(s => s.src).filter(src => src.includes('assets/'))[0].replace(/\/assets\/.*/, '');const basename = new URL(baseUrl).pathname;const store = configureStore({    reducer: rootReducer(basename),    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware).prepend(listeners.middleware),});

    First we calculate the application’s basepath from the vite artifact the code is loaded from, then a store is created with a reducer consisting of api and basename, and then two middlewares are added: api and listener

    “What is listeners?” you ask at this point.

    I am glad you asked! Check out the next section.

    For those who like looking at example code, some example redux store setups for RTK query and RTK listener:

    appreducersredux store setuphandleregreducers/index.jstop index.jssampleappreducers/index.jstop index.jsoldalbumreducers/index.jstop index.jsukelonnreducers/index.jstop index.jsauthservicereducers/index.jstop index.js

    Using RTK listener to perform actions on REDUX actions

    Listener fills the same role as another useful saga role: the ability to listen for redux actions and act on them:

    import { createListenerMiddleware } from '@reduxjs/toolkit';import { isFailedRequest } from './matchers';const listeners = createListenerMiddleware();listeners.startListening({    matcher: isFailedRequest,    effect: ({ payload }) => {        const { originalStatus } = payload || {};        const statusCode = parseInt(originalStatus);        if (statusCode === 401 || statusCode === 403) {            location.reload(true); // Will return to current location after the login process        }    }})export default listeners;

    This listener listens for failed RTK query HTTP calls to the API and checks the status codes for 401 “Needs Authentication” and 403 “Not Authorized” and reloads the app with the current URL to let apache shiro deal with it (refresh the auth and just open this page, pop up login or redirect to unauthorized page).

    This is “matchers.js” where isFailedRequest is found:

    import { isAnyOf } from '@reduxjs/toolkit';import { api } from './api';export const isFailedRequest = isAnyOf(    api.endpoints.getAccounts.matchRejected,    api.endpoints.getAccount.matchRejected,    api.endpoints.postAccountAdminstatus.matchRejected,    api.endpoints.postAccountModify.matchRejected,);

    For those who prefer looking at example code, example listener.js and matcher.js files can be found here:

    applisteners definitionmatchershandlereglisteners.js sampleapplisteners.js oldalbumlisteners.js ukelonnlisteners.jsmatchers.jsauthservicelisteners.jsmatchers.js

    Using RTK queries’ successful loads in other reducers

    It is possible to use the successful completion of a mutation to clear reducers backing forms:

    import { createReducer } from '@reduxjs/toolkit';import { SELECT_STORE } from '../actiontypes';import { api } from '../api';const defaultState = {    storeId: -1,    storename: '',    gruppe: 2,};export default const storeReducer = createReducer(defaultState, builder => {    builder        .addCase(SELECT_STORE, (state, action) => action.payload)        .addMatcher(api.endpoints.postNewstore.matchFulfilled, () => ({ ...defaultState }))        .addMatcher(api.endpoints.postModifystore.matchFulfilled, () => ({ ...defaultState }));});

    Here both the completion of a successful postNewstore mutation and a successful postModifystore mutation will set the reducer to its default state (and clear the forms backed by the redux state value).

    Note the use of addMatcher() rather than addCase() to matche the actions.

    All matchFulfilled actions have the same redux type, so traditional redux type matching won’t work. But the matchers provided by the api object can be used instead.

    Dependent queries

    A common requirement is that one REST call needs the value of another value before being called. For this “dependent queries” in RTK query can be used:

    export default function Home() {    const { data: overview = {}, isSuccess: overviewIsSuccess } = useGetOverviewQuery();    const { data: purchases = [] } = useGetPurchasesQuery(overview.accountid, { skip: !overviewIsSuccess });    ...

    The above example the getPurchases query needs an account id that can be found in the results of the getOverview query.

    The “skip” property of the query option object to useGetPurchasesQuery() prevents useGetPurchasesQuery() from being executed until useGetOverviewQuery() has completed successfully.

    Converting apps

    For those preferring to look at code, here are the diffs from converting from redux/axios to RTK queries and RTK listeners:

    appDescriptionhandleregA groceries tracker and statistics appsampleappA template application for React web applications with jersey backend and PostgreSQL database set up with liquibaseoldalbumAn app wrapping 90-ies albums in 202x web technologyukelonnA weekly allowance appauthserviceA simple user, role and permission manager for Apache Shiro

    Reduction of JavaScript source code size for the various apps (source code line numbers from cloc run before and after the conversion):

    appsize reduction in %size reduction in #lineshandlereg34%674sampleapp32%359oldalbum14%608ukelonn25%1211authservice31%841

    Summing up the numbers from doing the conversion

    1. A 14% to 35% reduction of JavaScript code of the apps (with lots of boilerplate gone). The package with lowest percentage has a number of lines reduction on par with the rest of the “real” applications
    2. No noticable difference in dependencies size even though I was already using RTK and got rid of redux-saga and axios
    3. No significant difference in vite build artifact size (even an increase in one case) (numbers can be provided on request)

    As said at the start, the obsoletion of redux-saga made doing this change a non-brainer for me.

    But losing all of the boiler plate around network requests made the applications easier to read and understand and maintain. And the logic around lazy loading, reloads and caching of data is a lot better than my home-brewed redux-router powered logic.

    I’m not opposed to learning new stuff, but I can be quite reluctant to let go of stuff I like, and I was really happy about redux saga as outlined in Yep, I’m still using redux.

    So did I lose anything in this conversion?

    Downsides are:

    1. Harder to examine data loaded by RTK query in the redux devtools (but still possible)
    2. More complex react components:
      1. prior this change, redux served up data ready for consumption in the components and with defaults, i.e. this

        const butikker = useSelector(state => state.butikker);

        is simpler than this:

        import { useGetButikkerQuery } from '../services/butikker';...    const { data: butikker = [] } = useGetButikkerQuery();
      2. Prior to this change, gathering the data for a save to the back end took place in a saga, so there was no need to clutter up the component with data not used in the actual render
    3. It’s kinda hard (but not impossible) to use the loaded data as backing storage for the edit form, and then save back from the data. The assumption is that one is to use something like useState() for this, but I don’t wish to do that

    But putting stuff back in the react components makes fewer places to look for stuff and makes my react component look more similar to others’ react components, so maybe this isn’t so bad after all…?

    Where to go next?

    I startet using Redux ToolKit (RTK) back in 2019. I quickly figured that createReducer() and createAction() could make my existing reducers and redux action creation more robust.

    I tried using redux slices at that point in time, but since I had to mix the autocreated redux action with manually created redux actions to trigger REST API operations and handle REST API errors, I figured that redux slices was more work than useful.

    And I later also landed on the “flattened redux state approach” outlined in Yep, I’m still using redux (see that article for the reasoning) that didn’t fit well with slices, so I dropped it back then.

    But with RTK query I no longer have to manually create actions to start API operations or handle errors, since these are created when creating queries or mutations, so maybe it is time to give redux slices a new try…?

    #css #dom #html #lines #react #reactjs #redux #reduxSaga #reduxToolkit #saga

  13. alright, I feel like an idiot for for not fucking realizing that

    [T] is a slice in Rust and not just a shorthand for arrays (which are [T; N] where T is the type and N is the size)

    Yesterday was fucking driving me crazy because I thought this goddamn dynamic dispatch function was asking for an array, so I was doing all this horseshit to send in a fucking array and then getting type errors about expecting
    [T] but receiving [T; 3] and you'd think I would have clued in to the fact that they're actual different types and not just some sort of memory/borrowing shenanigans, but I was already like 7 hours into my day so no, brain wasn't working.

    Makes so much more sense now. Because I was like, how the hell is a dynamic dispatch requesting an array, which is fixed size and known at compile time and placed on the stack (usually).

    blehhhhh.

    #techPosting #rustLang

    Probably would help if Google wasn't so shit nowadays and trying to google errors returns a bunch of unrelated crap. Hey, fuzzy search assholes: if I include some variant of "NOT" or "NO" or "DO NOT", please do return results for doing the thing.

  14. It’s really striking to compare the two big crises of the last two decades. 

    The Global Financial Crisis beginning in 2007 was purely a matter of book entries in computers. 

    No actual physical capital was destroyed, nobody died. 

    By contrast, the COVID-19 pandemic beginning in 2020 was a massive blow to productive capacity
    – millions of people died,
    buildings were rendered unusable. 

    But it was the first of these two crises that led to massive scarring and a prolonged global recession, not the second. 

    Why?

    It might be said that the reason why is that if you consider the world economy as an organism,
    the pandemic attacked its muscles and sinews
    while the financial crisis attacked its brain. 

    The global financial services industry is a crucial part of the distributed decision-making system of the world,
    and its core component is a very old, but still surprisingly poorly understood technology
    called #debt.

    In the strictest, purest sense,
    debt is an “#information #technology

    – it’s one of the mechanisms human beings have invented to handle information. 

    By structuring an investment in someone else’s project as a debt,
    you immediately reduce the space of possible outcomes to two
    – you get paid back, or you don’t. 

    There are a lot of other information-processing techniques that banks and investors use,
    from statistical credit scoring to modern portfolio theory,
    but this is the big one. 

    It allows a modern bank to keep track of vastly more financial investments than would ever have been possible for a medieval merchant in the first days of double-entry book-keeping. 

    Rather than having to preserve face-to-face relationships with every single borrower,
    you can rely on the fact that 99% of mortgage loans get paid back in full and on time,
    and concentrate your attention on managing the 1% of cases where something goes wrong.

    🔥The trouble is that if you build a business on this basis, what happens when it turns out that there’s a small variance❓

    Unfortunately, a small variance in the proportion of good loans from 99% to 97% means a tripling in the number of bad loans❗️

    and consequently a huge excess load on the systems that are meant to deal with them. 

    Faced with this massive cognitive overload,
    the system froze. 

    And even more unfortunately,
    in a world in which trillions of dollars need to be rolled over and refinanced every day,
    the one thing that the financial sector cannot do is stop for a moment to regain its bearings. 

    If information processing was free and the bankruptcy process frictionless,
    the Global Financial Crisis would have been over in a month. 

    As it was, all the information which had been attenuated by the use of multiple layers of secured debt came back,
    suddenly unattenuated and needing to be dealt with.

    That’s the “cybernetic history” of the debt crisis which I outline in my book,
    and I think it’s a useful alternative perspective to the economic one,
    and one which makes it more comprehensible that a relatively small market for synthetic CDOs turned into a continental crisis. 

    But this might not even have been the most pernicious use of debt seen in our lifetimes.

    (2/3)

    profilebooks.com/work/the-unac

    #criminogenic #organisation #Stafford #Beer #Barry #Clemson #accountability #sink #Boeing #737MAX #Boeing #merger #McDonnell #Douglas #engineering #culture #cost #control #Ricardian #Fallacy #hard #data #culture #best #practice

  15. It’s really striking to compare the two big crises of the last two decades. 

    The Global Financial Crisis beginning in 2007 was purely a matter of book entries in computers. 

    No actual physical capital was destroyed, nobody died. 

    By contrast, the COVID-19 pandemic beginning in 2020 was a massive blow to productive capacity
    – millions of people died,
    buildings were rendered unusable. 

    But it was the first of these two crises that led to massive scarring and a prolonged global recession, not the second. 

    Why?

    It might be said that the reason why is that if you consider the world economy as an organism,
    the pandemic attacked its muscles and sinews
    while the financial crisis attacked its brain. 

    The global financial services industry is a crucial part of the distributed decision-making system of the world,
    and its core component is a very old, but still surprisingly poorly understood technology
    called #debt.

    In the strictest, purest sense,
    debt is an “#information #technology

    – it’s one of the mechanisms human beings have invented to handle information. 

    By structuring an investment in someone else’s project as a debt,
    you immediately reduce the space of possible outcomes to two
    – you get paid back, or you don’t. 

    There are a lot of other information-processing techniques that banks and investors use,
    from statistical credit scoring to modern portfolio theory,
    but this is the big one. 

    It allows a modern bank to keep track of vastly more financial investments than would ever have been possible for a medieval merchant in the first days of double-entry book-keeping. 

    Rather than having to preserve face-to-face relationships with every single borrower,
    you can rely on the fact that 99% of mortgage loans get paid back in full and on time,
    and concentrate your attention on managing the 1% of cases where something goes wrong.

    🔥The trouble is that if you build a business on this basis, what happens when it turns out that there’s a small variance❓

    Unfortunately, a small variance in the proportion of good loans from 99% to 97% means a tripling in the number of bad loans❗️

    and consequently a huge excess load on the systems that are meant to deal with them. 

    Faced with this massive cognitive overload,
    the system froze. 

    And even more unfortunately,
    in a world in which trillions of dollars need to be rolled over and refinanced every day,
    the one thing that the financial sector cannot do is stop for a moment to regain its bearings. 

    If information processing was free and the bankruptcy process frictionless,
    the Global Financial Crisis would have been over in a month. 

    As it was, all the information which had been attenuated by the use of multiple layers of secured debt came back,
    suddenly unattenuated and needing to be dealt with.

    That’s the “cybernetic history” of the debt crisis which I outline in my book,
    and I think it’s a useful alternative perspective to the economic one,
    and one which makes it more comprehensible that a relatively small market for synthetic CDOs turned into a continental crisis. 

    But this might not even have been the most pernicious use of debt seen in our lifetimes.

    (2/3)

    profilebooks.com/work/the-unac

    #criminogenic #organisation #Stafford #Beer #Barry #Clemson #accountability #sink #Boeing #737MAX #Boeing #merger #McDonnell #Douglas #engineering #culture #cost #control #Ricardian #Fallacy #hard #data #culture #best #practice

  16. It’s really striking to compare the two big crises of the last two decades. 

    The Global Financial Crisis beginning in 2007 was purely a matter of book entries in computers. 

    No actual physical capital was destroyed, nobody died. 

    By contrast, the COVID-19 pandemic beginning in 2020 was a massive blow to productive capacity
    – millions of people died,
    buildings were rendered unusable. 

    But it was the first of these two crises that led to massive scarring and a prolonged global recession, not the second. 

    Why?

    It might be said that the reason why is that if you consider the world economy as an organism,
    the pandemic attacked its muscles and sinews
    while the financial crisis attacked its brain. 

    The global financial services industry is a crucial part of the distributed decision-making system of the world,
    and its core component is a very old, but still surprisingly poorly understood technology
    called #debt.

    In the strictest, purest sense,
    debt is an “#information #technology

    – it’s one of the mechanisms human beings have invented to handle information. 

    By structuring an investment in someone else’s project as a debt,
    you immediately reduce the space of possible outcomes to two
    – you get paid back, or you don’t. 

    There are a lot of other information-processing techniques that banks and investors use,
    from statistical credit scoring to modern portfolio theory,
    but this is the big one. 

    It allows a modern bank to keep track of vastly more financial investments than would ever have been possible for a medieval merchant in the first days of double-entry book-keeping. 

    Rather than having to preserve face-to-face relationships with every single borrower,
    you can rely on the fact that 99% of mortgage loans get paid back in full and on time,
    and concentrate your attention on managing the 1% of cases where something goes wrong.

    🔥The trouble is that if you build a business on this basis, what happens when it turns out that there’s a small variance❓

    Unfortunately, a small variance in the proportion of good loans from 99% to 97% means a tripling in the number of bad loans❗️

    and consequently a huge excess load on the systems that are meant to deal with them. 

    Faced with this massive cognitive overload,
    the system froze. 

    And even more unfortunately,
    in a world in which trillions of dollars need to be rolled over and refinanced every day,
    the one thing that the financial sector cannot do is stop for a moment to regain its bearings. 

    If information processing was free and the bankruptcy process frictionless,
    the Global Financial Crisis would have been over in a month. 

    As it was, all the information which had been attenuated by the use of multiple layers of secured debt came back,
    suddenly unattenuated and needing to be dealt with.

    That’s the “cybernetic history” of the debt crisis which I outline in my book,
    and I think it’s a useful alternative perspective to the economic one,
    and one which makes it more comprehensible that a relatively small market for synthetic CDOs turned into a continental crisis. 

    But this might not even have been the most pernicious use of debt seen in our lifetimes.

    (2/3)

    profilebooks.com/work/the-unac

    #criminogenic #organisation #Stafford #Beer #Barry #Clemson #accountability #sink #Boeing #737MAX #Boeing #merger #McDonnell #Douglas #engineering #culture #cost #control #Ricardian #Fallacy #hard #data #culture #best #practice

  17. It’s really striking to compare the two big crises of the last two decades. 

    The Global Financial Crisis beginning in 2007 was purely a matter of book entries in computers. 

    No actual physical capital was destroyed, nobody died. 

    By contrast, the COVID-19 pandemic beginning in 2020 was a massive blow to productive capacity
    – millions of people died,
    buildings were rendered unusable. 

    But it was the first of these two crises that led to massive scarring and a prolonged global recession, not the second. 

    Why?

    It might be said that the reason why is that if you consider the world economy as an organism,
    the pandemic attacked its muscles and sinews
    while the financial crisis attacked its brain. 

    The global financial services industry is a crucial part of the distributed decision-making system of the world,
    and its core component is a very old, but still surprisingly poorly understood technology
    called #debt.

    In the strictest, purest sense,
    debt is an “#information #technology

    – it’s one of the mechanisms human beings have invented to handle information. 

    By structuring an investment in someone else’s project as a debt,
    you immediately reduce the space of possible outcomes to two
    – you get paid back, or you don’t. 

    There are a lot of other information-processing techniques that banks and investors use,
    from statistical credit scoring to modern portfolio theory,
    but this is the big one. 

    It allows a modern bank to keep track of vastly more financial investments than would ever have been possible for a medieval merchant in the first days of double-entry book-keeping. 

    Rather than having to preserve face-to-face relationships with every single borrower,
    you can rely on the fact that 99% of mortgage loans get paid back in full and on time,
    and concentrate your attention on managing the 1% of cases where something goes wrong.

    🔥The trouble is that if you build a business on this basis, what happens when it turns out that there’s a small variance❓

    Unfortunately, a small variance in the proportion of good loans from 99% to 97% means a tripling in the number of bad loans❗️

    and consequently a huge excess load on the systems that are meant to deal with them. 

    Faced with this massive cognitive overload,
    the system froze. 

    And even more unfortunately,
    in a world in which trillions of dollars need to be rolled over and refinanced every day,
    the one thing that the financial sector cannot do is stop for a moment to regain its bearings. 

    If information processing was free and the bankruptcy process frictionless,
    the Global Financial Crisis would have been over in a month. 

    As it was, all the information which had been attenuated by the use of multiple layers of secured debt came back,
    suddenly unattenuated and needing to be dealt with.

    That’s the “cybernetic history” of the debt crisis which I outline in my book,
    and I think it’s a useful alternative perspective to the economic one,
    and one which makes it more comprehensible that a relatively small market for synthetic CDOs turned into a continental crisis. 

    But this might not even have been the most pernicious use of debt seen in our lifetimes.

    (2/3)

    profilebooks.com/work/the-unac

    #criminogenic #organisation #Stafford #Beer #Barry #Clemson #accountability #sink #Boeing #737MAX #Boeing #merger #McDonnell #Douglas #engineering #culture #cost #control #Ricardian #Fallacy #hard #data #culture #best #practice

  18. It’s really striking to compare the two big crises of the last two decades. 

    The Global Financial Crisis beginning in 2007 was purely a matter of book entries in computers. 

    No actual physical capital was destroyed, nobody died. 

    By contrast, the COVID-19 pandemic beginning in 2020 was a massive blow to productive capacity
    – millions of people died,
    buildings were rendered unusable. 

    But it was the first of these two crises that led to massive scarring and a prolonged global recession, not the second. 

    Why?

    It might be said that the reason why is that if you consider the world economy as an organism,
    the pandemic attacked its muscles and sinews
    while the financial crisis attacked its brain. 

    The global financial services industry is a crucial part of the distributed decision-making system of the world,
    and its core component is a very old, but still surprisingly poorly understood technology
    called #debt.

    In the strictest, purest sense,
    debt is an “#information #technology

    – it’s one of the mechanisms human beings have invented to handle information. 

    By structuring an investment in someone else’s project as a debt,
    you immediately reduce the space of possible outcomes to two
    – you get paid back, or you don’t. 

    There are a lot of other information-processing techniques that banks and investors use,
    from statistical credit scoring to modern portfolio theory,
    but this is the big one. 

    It allows a modern bank to keep track of vastly more financial investments than would ever have been possible for a medieval merchant in the first days of double-entry book-keeping. 

    Rather than having to preserve face-to-face relationships with every single borrower,
    you can rely on the fact that 99% of mortgage loans get paid back in full and on time,
    and concentrate your attention on managing the 1% of cases where something goes wrong.

    🔥The trouble is that if you build a business on this basis, what happens when it turns out that there’s a small variance❓

    Unfortunately, a small variance in the proportion of good loans from 99% to 97% means a tripling in the number of bad loans❗️

    and consequently a huge excess load on the systems that are meant to deal with them. 

    Faced with this massive cognitive overload,
    the system froze. 

    And even more unfortunately,
    in a world in which trillions of dollars need to be rolled over and refinanced every day,
    the one thing that the financial sector cannot do is stop for a moment to regain its bearings. 

    If information processing was free and the bankruptcy process frictionless,
    the Global Financial Crisis would have been over in a month. 

    As it was, all the information which had been attenuated by the use of multiple layers of secured debt came back,
    suddenly unattenuated and needing to be dealt with.

    That’s the “cybernetic history” of the debt crisis which I outline in my book,
    and I think it’s a useful alternative perspective to the economic one,
    and one which makes it more comprehensible that a relatively small market for synthetic CDOs turned into a continental crisis. 

    But this might not even have been the most pernicious use of debt seen in our lifetimes.

    (2/3)

    profilebooks.com/work/the-unac

    #criminogenic #organisation #Stafford #Beer #Barry #Clemson #accountability #sink #Boeing #737MAX #Boeing #merger #McDonnell #Douglas #engineering #culture #cost #control #Ricardian #Fallacy #hard #data #culture #best #practice

  19. February 4, 2024 - Day 35 - Check In
    Total Check Ins: 35

    Water goal: 2L
    Intake: 1L

    Exercise goal: 10m
    Actual: 10m8s

    Exercise: Walking
    Location: Outdoors

    Distance: 1km
    Pace: 9'47"/km
    Steps: n/a

    Kcal burned: 123

    HR (avg): 119BPM

    Comments:
    Yesterday was a hot one, peaking at 37C. I decided to get my walk in earlier in the day, figuring (correctly) that the heat would wipe me out, so I walked at midday, in the relatively cool 30C temperature.

    I came SO close to cracking the 10m mark for the walk (it IS a goal).

    Still struggling with the water.

    When I switched to a 1L water bottle, suddenly it was easy to drink water. The 2L bottle was too much.

    I kept the 2L sports-bottle in the fridge to refill the 1L bottle. Turns out, that's the pinch-point. The 2L bottle is hard to remove the lid, and it's messy to refill the 1L, and my brain just goes "nope, too hard."

    Off to Kmart for a second 1L bottle.

    #Project365 #2024Project #2024HealthProject #HealthyAllie2024

  20. What book are you reading right now?

    Daily writing prompt

    This question hurts my heart and soul a little bit. Actually it is probably more accurate to say it hurts my eyes.

    There is back story to this one. I was in seventh grade. 11 or 12 years old, I think? I don’t really remember. I went to the eye doctor and learned that I needed reading glasses. That was the first step that lead to my current reading situation. Around the time I started college I discovered the concept of reading for fun. That happened at the exact time that I couldn’t afford to spend time reading for fun, but what can you do, right? First it was Anthony Burgess. Next it was a deep dive into horror fiction, first with Clive Barker and then with Stephen King. That turned into a lifelong source of enjoyment.

    A few years ago… maybe more than just a few years ago, I learned that I need glasses for seeing distances too. That lead to my first pair of bifocals. Progressive lenses, actually but it’s the same difference. Unfortunately, that first pair of progressives made reading a book a little difficult. My eyes got super tired really fast from all the extra work needed to keep focusing through the right spot on the lens. It doesn’t make reading a book impossible, but it does take a bit of the fun out of it. I’ve gotten one new pair of glasses since then and they did make things a smidge easier, but my eyes still run out of gas much quicker than I would like them to.

    When the difficulties started I was commuting to work four days a week, and my commute was (as it still is now) very long. I signed up for Audible and my reading habit turned into an audiobook habit. That kept me going for a long time. Then the pandemic hit and I didn’t have a four day a week commute anymore so Audible became an expense that didn’t seem worth it anymore. Even driving in one day a week didn’t seem worth it. Starting in March we’re going to bump up to two days a week. When that happens I will likely sign up for Audible again and get back into books while I drive.

    The end result of all of this is the actual answer to today’s question. I am currently not reading (or listening) to any books. None. I am a little sad to admit it. A little ashamed too. There are still some releases that are worth the effort. One came out this week and another is about to come out. I will add them to my xmas wish list though so I won’t be reading them any time soon. One is Geddy Lee’s memoir, My Effin’ Life. The other is a new Stephen King short story collection. I also have a copy of Roger Daltrey’s autobiography that I started but haven’t finished. I very much want to get back into that. Don’t forget a book about the making of The Godfather that I started last xmas. I want to finish that too.

    Reading is a great source of enjoyment for me. I would read a bunch of pop-culture fiction, horror and science fiction and maybe a mystery thrown in, and then I would read a non-fiction book or two, histories or biographies mostly, or the odd piece of actual legitimate literature. The idea being that I would try to read something that could to broaden my brain in between things that were purely entertaining. These days though… nothing. Unfortunately.

    So the tl;dr thing here is that I am not currently reading anything and it will be a while before I try to start something new. Sorry about that, folks.

    https://robertjames1971.blog/2023/11/18/what-am-i-reading/

    #dailyprompt #dailyprompt2123

  21. What book are you reading right now?

    Daily writing prompt

    This question hurts my heart and soul a little bit. Actually it is probably more accurate to say it hurts my eyes.

    There is back story to this one. I was in seventh grade. 11 or 12 years old, I think? I don’t really remember. I went to the eye doctor and learned that I needed reading glasses. That was the first step that lead to my current reading situation. Around the time I started college I discovered the concept of reading for fun. That happened at the exact time that I couldn’t afford to spend time reading for fun, but what can you do, right? First it was Anthony Burgess. Next it was a deep dive into horror fiction, first with Clive Barker and then with Stephen King. That turned into a lifelong source of enjoyment.

    A few years ago… maybe more than just a few years ago, I learned that I need glasses for seeing distances too. That lead to my first pair of bifocals. Progressive lenses, actually but it’s the same difference. Unfortunately, that first pair of progressives made reading a book a little difficult. My eyes got super tired really fast from all the extra work needed to keep focusing through the right spot on the lens. It doesn’t make reading a book impossible, but it does take a bit of the fun out of it. I’ve gotten one new pair of glasses since then and they did make things a smidge easier, but my eyes still run out of gas much quicker than I would like them to.

    When the difficulties started I was commuting to work four days a week, and my commute was (as it still is now) very long. I signed up for Audible and my reading habit turned into an audiobook habit. That kept me going for a long time. Then the pandemic hit and I didn’t have a four day a week commute anymore so Audible became an expense that didn’t seem worth it anymore. Even driving in one day a week didn’t seem worth it. Starting in March we’re going to bump up to two days a week. When that happens I will likely sign up for Audible again and get back into books while I drive.

    The end result of all of this is the actual answer to today’s question. I am currently not reading (or listening) to any books. None. I am a little sad to admit it. A little ashamed too. There are still some releases that are worth the effort. One came out this week and another is about to come out. I will add them to my xmas wish list though so I won’t be reading them any time soon. One is Geddy Lee’s memoir, My Effin’ Life. The other is a new Stephen King short story collection. I also have a copy of Roger Daltrey’s autobiography that I started but haven’t finished. I very much want to get back into that. Don’t forget a book about the making of The Godfather that I started last xmas. I want to finish that too.

    Reading is a great source of enjoyment for me. I would read a bunch of pop-culture fiction, horror and science fiction and maybe a mystery thrown in, and then I would read a non-fiction book or two, histories or biographies mostly, or the odd piece of actual legitimate literature. The idea being that I would try to read something that could to broaden my brain in between things that were purely entertaining. These days though… nothing. Unfortunately.

    So the tl;dr thing here is that I am not currently reading anything and it will be a while before I try to start something new. Sorry about that, folks.

    https://robertjames1971.blog/2023/11/18/what-am-i-reading/

    #dailyprompt #dailyprompt2123

  22. What book are you reading right now?

    Daily writing prompt

    This question hurts my heart and soul a little bit. Actually it is probably more accurate to say it hurts my eyes.

    There is back story to this one. I was in seventh grade. 11 or 12 years old, I think? I don’t really remember. I went to the eye doctor and learned that I needed reading glasses. That was the first step that lead to my current reading situation. Around the time I started college I discovered the concept of reading for fun. That happened at the exact time that I couldn’t afford to spend time reading for fun, but what can you do, right? First it was Anthony Burgess. Next it was a deep dive into horror fiction, first with Clive Barker and then with Stephen King. That turned into a lifelong source of enjoyment.

    A few years ago… maybe more than just a few years ago, I learned that I need glasses for seeing distances too. That lead to my first pair of bifocals. Progressive lenses, actually but it’s the same difference. Unfortunately, that first pair of progressives made reading a book a little difficult. My eyes got super tired really fast from all the extra work needed to keep focusing through the right spot on the lens. It doesn’t make reading a book impossible, but it does take a bit of the fun out of it. I’ve gotten one new pair of glasses since then and they did make things a smidge easier, but my eyes still run out of gas much quicker than I would like them to.

    When the difficulties started I was commuting to work four days a week, and my commute was (as it still is now) very long. I signed up for Audible and my reading habit turned into an audiobook habit. That kept me going for a long time. Then the pandemic hit and I didn’t have a four day a week commute anymore so Audible became an expense that didn’t seem worth it anymore. Even driving in one day a week didn’t seem worth it. Starting in March we’re going to bump up to two days a week. When that happens I will likely sign up for Audible again and get back into books while I drive.

    The end result of all of this is the actual answer to today’s question. I am currently not reading (or listening) to any books. None. I am a little sad to admit it. A little ashamed too. There are still some releases that are worth the effort. One came out this week and another is about to come out. I will add them to my xmas wish list though so I won’t be reading them any time soon. One is Geddy Lee’s memoir, My Effin’ Life. The other is a new Stephen King short story collection. I also have a copy of Roger Daltrey’s autobiography that I started but haven’t finished. I very much want to get back into that. Don’t forget a book about the making of The Godfather that I started last xmas. I want to finish that too.

    Reading is a great source of enjoyment for me. I would read a bunch of pop-culture fiction, horror and science fiction and maybe a mystery thrown in, and then I would read a non-fiction book or two, histories or biographies mostly, or the odd piece of actual legitimate literature. The idea being that I would try to read something that could to broaden my brain in between things that were purely entertaining. These days though… nothing. Unfortunately.

    So the tl;dr thing here is that I am not currently reading anything and it will be a while before I try to start something new. Sorry about that, folks.

    https://robertjames1971.blog/2023/11/18/what-am-i-reading/

    #dailyprompt #dailyprompt2123

  23. What book are you reading right now?

    Daily writing prompt

    This question hurts my heart and soul a little bit. Actually it is probably more accurate to say it hurts my eyes.

    There is back story to this one. I was in seventh grade. 11 or 12 years old, I think? I don’t really remember. I went to the eye doctor and learned that I needed reading glasses. That was the first step that lead to my current reading situation. Around the time I started college I discovered the concept of reading for fun. That happened at the exact time that I couldn’t afford to spend time reading for fun, but what can you do, right? First it was Anthony Burgess. Next it was a deep dive into horror fiction, first with Clive Barker and then with Stephen King. That turned into a lifelong source of enjoyment.

    A few years ago… maybe more than just a few years ago, I learned that I need glasses for seeing distances too. That lead to my first pair of bifocals. Progressive lenses, actually but it’s the same difference. Unfortunately, that first pair of progressives made reading a book a little difficult. My eyes got super tired really fast from all the extra work needed to keep focusing through the right spot on the lens. It doesn’t make reading a book impossible, but it does take a bit of the fun out of it. I’ve gotten one new pair of glasses since then and they did make things a smidge easier, but my eyes still run out of gas much quicker than I would like them to.

    When the difficulties started I was commuting to work four days a week, and my commute was (as it still is now) very long. I signed up for Audible and my reading habit turned into an audiobook habit. That kept me going for a long time. Then the pandemic hit and I didn’t have a four day a week commute anymore so Audible became an expense that didn’t seem worth it anymore. Even driving in one day a week didn’t seem worth it. Starting in March we’re going to bump up to two days a week. When that happens I will likely sign up for Audible again and get back into books while I drive.

    The end result of all of this is the actual answer to today’s question. I am currently not reading (or listening) to any books. None. I am a little sad to admit it. A little ashamed too. There are still some releases that are worth the effort. One came out this week and another is about to come out. I will add them to my xmas wish list though so I won’t be reading them any time soon. One is Geddy Lee’s memoir, My Effin’ Life. The other is a new Stephen King short story collection. I also have a copy of Roger Daltrey’s autobiography that I started but haven’t finished. I very much want to get back into that. Don’t forget a book about the making of The Godfather that I started last xmas. I want to finish that too.

    Reading is a great source of enjoyment for me. I would read a bunch of pop-culture fiction, horror and science fiction and maybe a mystery thrown in, and then I would read a non-fiction book or two, histories or biographies mostly, or the odd piece of actual legitimate literature. The idea being that I would try to read something that could to broaden my brain in between things that were purely entertaining. These days though… nothing. Unfortunately.

    So the tl;dr thing here is that I am not currently reading anything and it will be a while before I try to start something new. Sorry about that, folks.

    https://robertjames1971.blog/2023/11/18/what-am-i-reading/

    #dailyprompt #dailyprompt2123

  24. So putting the #hackintosh setup on the backburner for the moment. Managed to get an OSX Monterey install finished and booting properly (had some more EFI 'fun' yet again due to my own hand, I completely flubbed the proper folder layout of the EFI partition. Now it can fully boot with no external input from me.). Now there's just a lot of tweakage involved in getting certain features working. Probably the biggest is getting the trackpad going properly. Can't do a simple tap-click which has become a hardwired action in my brain. And OSX doesn't seem to recognize that a trackpad exists.

    But that's for another day! On to another short-term hyperfixation brought to you by the #ADHD part of my #AuDHD brain!

    Thanks to my brother putting a bug in my ear, I'm going through working out the practical details of doing an IRL in-car/road trip streaming setup.

    The technical/behind-the-scenes details of streaming has become a big fixation of mine over the years and an IRL streaming setup has been one of the vestiges of this that has really intrigued me and something I definitely want to try and set up and put into actual use.

    I've got the mental checklist figured out regarding all the moving parts needed for this. Just down to actually getting it all working together. But I'm definitely looking forward to the challenge. 🙂

    #Streaming #obs #irlstreaming

  25. @SwiftOnSecurity #backstory I always just liked #computers and enjoy #helping people. Originally in #highschool I thought I'd like to be a #psychologist or something of the sorts. But the job security and money seemed more appealing than than saving actual lives unfortunately.

    I had an interview with Amazon shortly before graduating #undergrad, and made it all the way to final round where they flew me out, paid for my meals, the whole thing. I didn't get it and this crushed me for a minute.

    Even though I got my #bachelors degree right after high school in #cybersecurity, I started off in support because I just couldn't land my first cyber job directly. It was very disheartening.

    I got promoted from my first job to a network #analysts (small/medium company but 16 sites). I earned my networking grit from this by designing a whole network for a new location from the ground up. Including the rack, phone systems, WAP's, #firewall, #network segmentation. I got tired of running actual cables however so I switch to their systems role and finished my time at that company after 1.5 years.

    Following that I've had a couple jobs in the #finance industry (doing cyber). My primary focus has been PKI but I honestly hate it and I've been in it for almost 3 years.

    Looking forward, I wanna do something more exciting and more challenging again. PKI isn't exciting enough for my #ADHD brain, too repetitive. I can't figure out where in security I want to move to next but I know it's not this.

    Thanks for reading if you made it this far. =)

  26. @SwiftOnSecurity #backstory I always just liked #computers and enjoy #helping people. Originally in #highschool I thought I'd like to be a #psychologist or something of the sorts. But the job security and money seemed more appealing than than saving actual lives unfortunately.

    I had an interview with Amazon shortly before graduating #undergrad, and made it all the way to final round where they flew me out, paid for my meals, the whole thing. I didn't get it and this crushed me for a minute.

    Even though I got my #bachelors degree right after high school in #cybersecurity, I started off in support because I just couldn't land my first cyber job directly. It was very disheartening.

    I got promoted from my first job to a network #analysts (small/medium company but 16 sites). I earned my networking grit from this by designing a whole network for a new location from the ground up. Including the rack, phone systems, WAP's, #firewall, #network segmentation. I got tired of running actual cables however so I switch to their systems role and finished my time at that company after 1.5 years.

    Following that I've had a couple jobs in the #finance industry (doing cyber). My primary focus has been PKI but I honestly hate it and I've been in it for almost 3 years.

    Looking forward, I wanna do something more exciting and more challenging again. PKI isn't exciting enough for my #ADHD brain, too repetitive. I can't figure out where in security I want to move to next but I know it's not this.

    Thanks for reading if you made it this far. =)

  27. @SwiftOnSecurity #backstory I always just liked #computers and enjoy #helping people. Originally in #highschool I thought I'd like to be a #psychologist or something of the sorts. But the job security and money seemed more appealing than than saving actual lives unfortunately.

    I had an interview with Amazon shortly before graduating #undergrad, and made it all the way to final round where they flew me out, paid for my meals, the whole thing. I didn't get it and this crushed me for a minute.

    Even though I got my #bachelors degree right after high school in #cybersecurity, I started off in support because I just couldn't land my first cyber job directly. It was very disheartening.

    I got promoted from my first job to a network #analysts (small/medium company but 16 sites). I earned my networking grit from this by designing a whole network for a new location from the ground up. Including the rack, phone systems, WAP's, #firewall, #network segmentation. I got tired of running actual cables however so I switch to their systems role and finished my time at that company after 1.5 years.

    Following that I've had a couple jobs in the #finance industry (doing cyber). My primary focus has been PKI but I honestly hate it and I've been in it for almost 3 years.

    Looking forward, I wanna do something more exciting and more challenging again. PKI isn't exciting enough for my #ADHD brain, too repetitive. I can't figure out where in security I want to move to next but I know it's not this.

    Thanks for reading if you made it this far. =)

  28. @SwiftOnSecurity #backstory I always just liked #computers and enjoy #helping people. Originally in #highschool I thought I'd like to be a #psychologist or something of the sorts. But the job security and money seemed more appealing than than saving actual lives unfortunately.

    I had an interview with Amazon shortly before graduating #undergrad, and made it all the way to final round where they flew me out, paid for my meals, the whole thing. I didn't get it and this crushed me for a minute.

    Even though I got my #bachelors degree right after high school in #cybersecurity, I started off in support because I just couldn't land my first cyber job directly. It was very disheartening.

    I got promoted from my first job to a network #analysts (small/medium company but 16 sites). I earned my networking grit from this by designing a whole network for a new location from the ground up. Including the rack, phone systems, WAP's, #firewall, #network segmentation. I got tired of running actual cables however so I switch to their systems role and finished my time at that company after 1.5 years.

    Following that I've had a couple jobs in the #finance industry (doing cyber). My primary focus has been PKI but I honestly hate it and I've been in it for almost 3 years.

    Looking forward, I wanna do something more exciting and more challenging again. PKI isn't exciting enough for my #ADHD brain, too repetitive. I can't figure out where in security I want to move to next but I know it's not this.

    Thanks for reading if you made it this far. =)

  29. CW: Fedi meta

    no wait im on wafrn. I need to use the power of tags


    #According-to-all-known-laws-of-aviation #there-is-no-way-a-bee-should-be-able-to-fly.-Its-wings-are-too-small-to-get-its-fat-little-body-off-the-ground.-The-bee #of-course #flies-anyway-because-bees-don't-care-what-humans-think-is-impossible.-Yellow #black.-Yellow #black.-Yellow #black.-Yellow #black.-Ooh #black-and-yellow!-Let's-shake-it-up-a-little.-Barry!-Breakfast-is-ready!-Coming!-Hang-on-a-second.-Hello?-Barry?-Adam?-Can-you-believe-this-is-happening?-I-can't.-I'll-pick-you-up.-Looking-sharp.-Use-the-stairs #Your-father-paid-good-money-for-those.-Sorry.-I'm-excited.-Here's-the-graduate.-We're-very-proud-of-you #son.-A-perfect-report-card #all-B's.-Very-proud.-Ma!-I-got-a-thing-going-here.-You-got-lint-on-your-fuzz.-Ow!-That's-me!-Wave-to-us!-We'll-be-in-row-118 #000.-Bye!-Barry #I-told-you #stop-flying-in-the-house!-Hey #Adam.-Hey #Barry.-Is-that-fuzz-gel?-A-little.-Special-day #graduation.-Never-thought-I'd-make-it.-Three-days-grade-school #three-days-high-school.-Those-were-awkward.-Three-days-college.-I'm-glad-I-took-a-day-and-hitchhiked-around-The-Hive.-You-did-come-back-different.-Hi #Barry.-Artie #growing-a-mustache?-Looks-good.-Hear-about-Frankie?-Yeah.-You-going-to-the-funeral?-No #I'm-not-going.-Everybody-knows #sting-someone #you-die.-Don't-waste-it-on-a-squirrel.-Such-a-hothead.-I-guess-he-could-have-just-gotten-out-of-the-way.-I-love-this-incorporating-an-amusement-park-into-our-day.-That's-why-we-don't-need-vacations.-Boy #quite-a-bit-of-pomp-under-the-circumstances.-Well #Adam #today-we-are-men.-We-are!-Bee-men.-Amen!-Hallelujah!-Students #faculty #distinguished-bees #please-welcome-Dean-Buzzwell.-Welcome #New-Hive-City-graduating-class-of-9:15.-That-concludes-our-ceremonies-And-begins-your-career-at-Honex-Industries!-Will-we-pick-our-job-today?-I-heard-it's-just-orientation.-Heads-up!-Here-we-go.-Keep-your-hands-and-antennas-inside-the-tram-at-all-times.-Wonder-what-it'll-be-like?-A-little-scary.-Welcome-to-Honex #a-division-of-Honesco-and-a-part-of-the-Hexagon-Group.-This-is-it!-Wow.-Wow.-We-know-that-you #as-a-bee #have-worked-your-whole-life-to-get-to-the-point-where-you-can-work-for-your-whole-life.-Honey-begins-when-our-valiant-Pollen-Jocks-bring-the-nectar-to-The-Hive.-Our-top-secret-formula-is-automatically-color-corrected #scent-adjusted-and-bubble-contoured-into-this-soothing-sweet-syrup-with-its-distinctive-golden-glow-you-know-as...-Honey!-That-girl-was-hot.-She's-my-cousin!-She-is?-Yes #we're-all-cousins.-Right.-You're-right.-At-Honex #we-constantly-strive-to-improve-every-aspect-of-bee-existence.-These-bees-are-stress-testing-a-new-helmet-technology.-What-do-you-think-he-makes?-Not-enough.-Here-we-have-our-latest-advancement #the-Krelman.-What-does-that-do?-Catches-that-little-strand-of-honey-that-hangs-after-you-pour-it.-Saves-us-millions.-Can-anyone-work-on-the-Krelman?-Of-course.-Most-bee-jobs-are-small-ones.-But-bees-know-that-every-small-job #if-it's-done-well #means-a-lot.-But-choose-carefully-because-you'll-stay-in-the-job-you-pick-for-the-rest-of-your-life.-The-same-job-the-rest-of-your-life?-I-didn't-know-that.-What's-the-difference?-You'll-be-happy-to-know-that-bees #as-a-species #haven't-had-one-day-off-in-27-million-years.-So-you'll-just-work-us-to-death?-We'll-sure-try.-Wow!-That-blew-my-mind!-'What's-the-difference?'-How-can-you-say-that?-One-job-forever?-That's-an-insane-choice-to-have-to-make.-I'm-relieved.-Now-we-only-have-to-make-one-decision-in-life.-But #Adam #how-could-they-never-have-told-us-that?-Why-would-you-question-anything?-We're-bees.-We're-the-most-perfectly-functioning-society-on-Earth.-You-ever-think-maybe-things-work-a-little-too-well-here?-Like-what?-Give-me-one-example.-I-don't-know.-But-you-know-what-I'm-talking-about.-Please-clear-the-gate.-Royal-Nectar-Force-on-approach.-Wait-a-second.-Check-it-out.-Hey #those-are-Pollen-Jocks!-Wow.-I've-never-seen-them-this-close.-They-know-what-it's-like-outside-The-Hive.-Yeah #but-some-don't-come-back.-Hey #Jocks!-Hi #Jocks!-You-guys-did-great!-You're-monsters!-You're-sky-freaks!-I-love-it!-I-love-it!-I-wonder-where-they-were.-I-don't-know.-Their-day's-not-planned.-Outside-The-Hive #flying-who-knows-where #doing-who-knows-what.-You-can't-just-decide-to-be-a-Pollen-Jock.-You-have-to-be-bred-for-that.-Right.-Look.-That's-more-pollen-than-you-and-I-will-see-in-a-lifetime.-It's-just-a-status-symbol.-Bees-make-too-much-of-it.-Perhaps.-Unless-you're-wearing-it-and-the-ladies-see-you-wearing-it.-Those-ladies?-Aren't-they-our-cousins-too?-Distant.-Distant.-Look-at-these-two.-Couple-of-Hive-Harrys.-Let's-have-fun-with-them.-It-must-be-dangerous-being-a-Pollen-Jock.-Yeah.-Once-a-bear-pinned-me-against-a-mushroom!-He-had-a-paw-on-my-throat #and-with-the-other #he-was-slapping-me!-Oh #my!-I-never-thought-I'd-knock-him-out.-What-were-you-doing-during-this?-Trying-to-alert-the-authorities.-I-can-autograph-that.-A-little-gusty-out-there-today #wasn't-it #comrades?-Yeah.-Gusty.-We're-hitting-a-sunflower-patch-six-miles-from-here-tomorrow.-Six-miles #huh?-Barry!-A-puddle-jump-for-us #but-maybe-you're-not-up-for-it.-Maybe-I-am.-You-are-not!-We're-going-0900-at-J-Gate.-What-do-you-think #buzzy-boy?-Are-you-bee-enough?-I-might-be.-It-all-depends-on-what-0900-means.-Hey #Honex!-Dad #you-surprised-me.-You-decide-what-you're-interested-in?-Well #there's-a-lot-of-choices.-But-you-only-get-one.-Do-you-ever-get-bored-doing-the-same-job-every-day?-Son #let-me-tell-you-about-stirring.-You-grab-that-stick #and-you-just-move-it-around #and-you-stir-it-around.-You-get-yourself-into-a-rhythm.-It's-a-beautiful-thing.-You-know #Dad #the-more-I-think-about-it #maybe-the-honey-field-just-isn't-right-for-me.-You-were-thinking-of-what #making-balloon-animals?-That's-a-bad-job-for-a-guy-with-a-stinger.-Janet #your-son's-not-sure-he-wants-to-go-into-honey!-Barry #you-are-so-funny-sometimes.-I'm-not-trying-to-be-funny.-You're-not-funny!-You're-going-into-honey.-Our-son #the-stirrer!-You're-gonna-be-a-stirrer?-No-one's-listening-to-me!-Wait-till-you-see-the-sticks-I-have.-I-could-say-anything-right-now.-I'm-gonna-get-an-ant-tattoo!-Let's-open-some-honey-and-celebrate!-Maybe-I'll-pierce-my-thorax.-Shave-my-antennae.-Shack-up-with-a-grasshopper.-Get-a-gold-tooth-and-call-everybody-'dawg'!-I'm-so-proud.-We're-starting-work-today!-Today's-the-day.-Come-on!-All-the-good-jobs-will-be-gone.-Yeah #right.-Pollen-counting #stunt-bee #pouring #stirrer #front-desk #hair-removal...-Is-it-still-available?-Hang-on.-Two-left!-One-of-them's-yours!-Congratulations!-Step-to-the-side.-What'd-you-get?-Picking-crud-out.-Stellar!-Wow!-Couple-of-newbies?-Yes #sir!-Our-first-day!-We-are-ready!-Make-your-choice.-You-want-to-go-first?-No #you-go.-Oh #my.-What's-available?-Restroom-attendant's-open #not-for-the-reason-you-think.-Any-chance-of-getting-the-Krelman?-Sure #you're-on.-I'm-sorry #the-Krelman-just-closed-out.-Wax-monkey's-always-open.-The-Krelman-opened-up-again.-What-happened?-A-bee-died.-Makes-an-opening.-See?-He's-dead.-Another-dead-one.-Deady.-Deadified.-Two-more-dead.-Dead-from-the-neck-up.-Dead-from-the-neck-down.-That's-life!-Oh #this-is-so-hard!-Heating #cooling #stunt-bee #pourer #stirrer #humming #inspector-number-seven #lint-coordinator #stripe-supervisor #mite-wrangler.-Barry #what-do-you-think-I-should...-Barry?-Barry!-All-right #we've-got-the-sunflower-patch-in-quadrant-nine...-What-happened-to-you?-Where-are-you?-I'm-going-out.-Out?-Out-where?-Out-there.-Oh #no!-I-have-to #before-I-go-to-work-for-the-rest-of-my-life.-You're-gonna-die!-You're-crazy!-Hello?-Another-call-coming-in.-If-anyone's-feeling-brave #there's-a-Korean-deli-on-83rd-that-gets-their-roses-today.-Hey #guys.-Look-at-that.-Isn't-that-the-kid-we-saw-yesterday?-Hold-it #son #flight-deck's-restricted.-It's-OK #Lou.-We're-gonna-take-him-up.-Really?-Feeling-lucky #are-you?-Sign-here #here.-Just-initial-that.-Thank-you.-OK.-You-got-a-rain-advisory-today #and-as-you-all-know #bees-cannot-fly-in-rain.-So-be-careful.-As-always #watch-your-brooms #hockey-sticks #dogs #birds #bears-and-bats.-Also #I-got-a-couple-of-reports-of-root-beer-being-poured-on-us.-Murphy's-in-a-home-because-of-it #babbling-like-a-cicada!-That's-awful.-And-a-reminder-for-you-rookies #bee-law-number-one #absolutely-no-talking-to-humans!--All-right #launch-positions!-Buzz #buzz #buzz #buzz!-Buzz #buzz #buzz #buzz!-Buzz #buzz #buzz #buzz!-Black-and-yellow!-Hello!-You-ready-for-this #hot-shot?-Yeah.-Yeah #bring-it-on.-Wind #check.-Antennae #check.-Nectar-pack #check.-Wings #check.-Stinger #check.-Scared-out-of-my-shorts #check.-OK #ladies #let's-move-it-out!-Pound-those-petunias #you-striped-stem-suckers!-All-of-you #drain-those-flowers!-Wow!-I'm-out!-I-can't-believe-I'm-out!-So-blue.-I-feel-so-fast-and-free!-Box-kite!-Wow!-Flowers!-This-is-Blue-Leader #We-have-roses-visual.-Bring-it-around-30-degrees-and-hold.-Roses!-30-degrees #roger.-Bringing-it-around.-Stand-to-the-side #kid.-It's-got-a-bit-of-a-kick.-That-is-one-nectar-collector!-Ever-see-pollination-up-close?-No #sir.-I-pick-up-some-pollen-here #sprinkle-it-over-here.-Maybe-a-dash-over-there #a-pinch-on-that-one.-See-that?-It's-a-little-bit-of-magic.-That's-amazing.-Why-do-we-do-that?-That's-pollen-power.-More-pollen #more-flowers #more-nectar #more-honey-for-us.-Cool.-I'm-picking-up-a-lot-of-bright-yellow #Could-be-daisies #Don't-we-need-those?-Copy-that-visual.-Wait.-One-of-these-flowers-seems-to-be-on-the-move.-Say-again?-You're-reporting-a-moving-flower?-Affirmative.-That-was-on-the-line!-This-is-the-coolest.-What-is-it?-I-don't-know #but-I'm-loving-this-color.-It-smells-good.-Not-like-a-flower #but-I-like-it.-Yeah #fuzzy.-Chemical-y.-Careful #guys.-It's-a-little-grabby.-My-sweet-lord-of-bees!-Candy-brain #get-off-there!-Problem!-Guys!-This-could-be-bad.-Affirmative.-Very-close.-Gonna-hurt.-Mama's-little-boy.-You-are-way-out-of-position #rookie!-Coming-in-at-you-like-a-missile!-Help-me!-I-don't-think-these-are-flowers.-Should-we-tell-him?-I-think-he-knows.-What-is-this?!-Match-point!-You-can-start-packing-up #honey #because-you're-about-to-eat-it!-Yowser!-Gross.-There's-a-bee-in-the-car!-Do-something!-I'm-driving!-Hi #bee.-He's-back-here!-He's-going-to-sting-me!-Nobody-move.-If-you-don't-move #he-won't-sting-you.-Freeze!-He-blinked!-Spray-him #Granny!-What-are-you-doing?!-Wow...-the-tension-level-out-here-is-unbelievable.-I-gotta-get-home.-Can't-fly-in-rain.-Can't-fly-in-rain.-Can't-fly-in-rain.-Mayday!-Mayday!-Bee-going-down!-Ken #could-you-close-the-window-please?-Ken #could-you-close-the-window-please?-Check-out-my-new-resume.-I-made-it-into-a-fold-out-brochure.-You-see?-Folds-out.-Oh #no.-More-humans.-I-don't-need-this.-What-was-that?-Maybe-this-time.-This-time.-This-time.-This-time!-This-time!-This...-Drapes!-That-is-diabolical.-It's-fantastic.-It's-got-all-my-special-skills #even-my-top-ten-favorite-movies.-What's-number-one?-Star-Wars?-Nah #I-don't-go-for-that...-kind-of-stuff.-No-wonder-we-shouldn't-talk-to-them.-They're-out-of-their-minds.-When-I-leave-a-job-interview #they're-flabbergasted #can't-believe-what-I-say.-There's-the-sun.-Maybe-that's-a-way-out.-I-don't-remember-the-sun-having-a-big-75-on-it.-I-predicted-global-warming.-I-could-feel-it-getting-hotter.-At-first-I-thought-it-was-just-me.-Wait!-Stop!-Bee!-Stand-back.-These-are-winter-boots.-Wait!-Don't-kill-him!-You-know-I'm-allergic-to-them!-This-thing-could-kill-me!-Why-does-his-life-have-less-value-than-yours?-Why-does-his-life-have-any-less-value-than-mine?-Is-that-your-statement?-I'm-just-saying-all-life-has-value.-You-don't-know-what-he's-capable-of-feeling.-My-brochure!-There-you-go #little-guy.-I'm-not-scared-of-him.It's-an-allergic-thing.--Put-that-on-your-resume-brochure.-My-whole-face-could-puff-up.-Make-it-one-of-your-special-skills.-Knocking-someone-out-is-also-a-special-skill.-Right.-Bye #Vanessa.-Thanks.-Vanessa #next-week?-Yogurt-night?-Sure #Ken.-You-know #whatever.-You-could-put-carob-chips-on-there.-Bye.-Supposed-to-be-less-calories.-Bye.-I-gotta-say-something.-She-saved-my-life.-I-gotta-say-something.-All-right #here-it-goes.-Nah.-What-would-I-say?-I-could-really-get-in-trouble.-It's-a-bee-law.-You're-not-supposed-to-talk-to-a-human.-I-can't-believe-I'm-doing-this.-I've-got-to.-Oh #I-can't-do-it.-Come-on!-No.-Yes.-No.-Do-it.-I-can't.-How-should-I-start-it?-'You-like-jazz?'-No #that's-no-good.-Here-she-comes!-Speak #you-fool!-Hi!-I'm-sorry.-You're-talking.-Yes #I-know.-You're-talking!-I'm-so-sorry.-No #it's-OK.-It's-fine.-I-know-I'm-dreaming.-But-I-don't-recall-going-to-bed.-Well #I'm-sure-this-is-very-disconcerting.-This-is-a-bit-of-a-surprise-to-me.-I-mean #you're-a-bee!-I-am.-And-I'm-not-supposed-to-be-doing-this #Barry?-It's-pretty-big #but-they-were-all-trying-to-kill-me.-And-if-it-wasn't-for-you...-I-had-to-thank-you.-It's-just-how-I-was-raised.-That-was-a-little-weird.-I'm-talking-with-a-bee.-Yeah.-I'm-talking-to-a-bee.-And-the-bee-is-talking-to-me!-I-just-want-to-say-I'm-grateful.-I'll-leave-now.-Wait!-How-did-you-learn-to-do-that?-What?-The-talking-thing.-Same-way-you-did #I-guess.-'Mama #Dada #honey.'-You-pick-it-up.-That's-very-funny.-Yeah.-Bees-are-funny.-If-we-didn't-laugh #we'd-cry-with-what-we-have-to-deal-with.-Anyway...-Can-I...-get-you-something?-Like-what?-I-don't-know.-I-mean...-I-don't-know.-Coffee?-I-don't-want-to-put-you-out.-It's-no-trouble.-It-takes-two-minutes.-It's-just-coffee.-I-hate-to-impose.-Don't-be-ridiculous!-Actually #I-would-love-a-cup.-Hey #you-want-rum-cake?-I-shouldn't.-Have-some.-No #I-can't.-Come-on!-I'm-trying-to-lose-a-couple-micrograms.-Where?-These-stripes-don't-help.-You-look-great!-I-don't-know-if-you-know-anything-about-fashion.-Are-you-all-right?-No.-He's-making-the-tie-in-the-cab-as-they're-flying-up-Madison.-He-finally-gets-there.-He-runs-up-the-steps-into-the-church.-The-wedding-is-on.-And-he-says #'Watermelon?-I-thought-you-said-Guatemalan.-Why-would-I-marry-a-watermelon?'-Is-that-a-bee-joke?-That's-the-kind-of-stuff-we-do.-Yeah #different.-So #what-are-you-gonna-do #Barry?-About-work?-I-don't-know.-I-want-to-do-my-part-for-The-Hive #but-I-can't-do-it-the-way-they-want.-I-know-how-you-feel.-You-do?-Sure.-My-parents-wanted-me-to-be-a-lawyer-or-a-doctor #but-I-wanted-to-be-a-florist.-Really?-My-only-interest-is-flowers.-Our-new-queen-was-just-elected-with-that-same-campaign-slogan.-Anyway #if-you-look...-There's-my-hive-right-there.-See-it?-You're-in-Sheep-Meadow!-Yes!-I'm-right-off-the-Turtle-Pond!-No-way!-I-know-that-area.-I-lost-a-toe-ring-there-once.-Why-do-girls-put-rings-on-their-toes?-Why-not?-It's-like-putting-a-hat-on-your-knee.-Maybe-I'll-try-that.-You-all-right #ma'am?-Oh #yeah.-Fine.-Just-having-two-cups-of-coffee!-Anyway #this-has-been-great.-Thanks-for-the-coffee.-Yeah #it's-no-trouble.-Sorry-I-couldn't-finish-it.-If-I-did #I'd-be-up-the-rest-of-my-life.-Are-you...?-Can-I-take-a-piece-of-this-with-me?-Sure!-Here #have-a-crumb.-Thanks!-Yeah.-All-right.-Well #then...-I-guess-I'll-see-you-around.-Or-not.-OK #Barry.-And-thank-you-so-much-again...-for-before.-Oh #that?-That-was-nothing.-Well #not-nothing #but...-Anyway...-This-can't-possibly-work.-He's-all-set-to-go.-We-may-as-well-try-it.-OK #Dave #pull-the-chute.-Sounds-amazing.-It-was-amazing!-It-was-the-scariest #happiest-moment-of-my-life.-Humans!-I-can't-believe-you-were-with-humans!-Giant #scary-humans!-What-were-they-like?-Huge-and-crazy.-They-talk-crazy.-They-eat-crazy-giant-things.-They-drive-crazy.-Do-they-try-and-kill-you #like-on-TV?-Some-of-them.-But-some-of-them-don't.-How'd-you-get-back?-Poodle.-You-did-it #and-I'm-glad.-You-saw-whatever-you-wanted-to-see.-You-had-your-'experience.'-Now-you-can-pick-out-yourjob-and-be-normal.-Well...-Well?-Well #I-met-someone.-You-did?-Was-she-Bee-ish?-A-wasp?!-Your-parents-will-kill-you!-No #no #no #not-a-wasp.-Spider?-I'm-not-attracted-to-spiders.-I-know-it's-the-hottest-thing #with-the-eight-legs-and-all.-I-can't-get-by-that-face.-So-who-is-she?-She's...-human.-No #no.-That's-a-bee-law.-You-wouldn't-break-a-bee-law.-Her-name's-Vanessa.-Oh #boy.-She's-so-nice.-And-she's-a-florist!-Oh #no!-You're-dating-a-human-florist!-We're-not-dating.-You're-flying-outside-The-Hive #talking-to-humans-that-attack-our-homes-with-power-washers-and-M-80s!-One-eighth-a-stick-of-dynamite!-She-saved-my-life!-And-she-understands-me.-This-is-over!-Eat-this.-This-is-not-over!-What-was-that?-They-call-it-a-crumb.-It-was-so-stingin'-stripey!-And-that's-not-what-they-eat.-That's-what-falls-off-what-they-eat!-You-know-what-a-Cinnabon-is?-No.-It's-bread-and-cinnamon-and-frosting.-They-heat-it-up...-Sit-down!-...really-hot!-Listen-to-me!-We-are-not-them!-We're-us.-There's-us-and-there's-them!-Yes #but-who-can-deny-the-heart-that-is-yearning?-There's-no-yearning.-Stop-yearning.-Listen-to-me!-You-have-got-to-start-thinking-bee #my-friend.-Thinking-bee!-Thinking-bee.-Thinking-bee.-Thinking-bee!-Thinking-bee!-Thinking-bee!-Thinking-bee!-There-he-is.-He's-in-the-pool.-You-know-what-your-problem-is #Barry?-I-gotta-start-thinking-bee?-How-much-longer-will-this-go-on?-It's-been-three-days!-Why-aren't-you-working?-I've-got-a-lot-of-big-life-decisions-to-think-about.-What-life?-You-have-no-life!-You-have-no-job.-You're-barely-a-bee!-Would-it-kill-you-to-make-a-little-honey?-Barry #come-out.-Your-father's-talking-to-you.-Martin #would-you-talk-to-him?-Barry #I'm-talking-to-you!-You-coming?-Got-everything?-All-set!-Go-ahead.-I'll-catch-up.-Don't-be-too-long.-Watch-this!-Vanessa!-We're-still-here.-I-told-you-not-to-yell-at-him.-He-doesn't-respond-to-yelling!-Then-why-yell-at-me?-Because-you-don't-listen!-I'm-not-listening-to-this.-Sorry #I've-gotta-go.-Where-are-you-going?-I'm-meeting-a-friend.-A-girl?-Is-this-why-you-can't-decide?-Bye.-I-just-hope-she's-Bee-ish.-They-have-a-huge-parade-of-flowers-every-year-in-Pasadena?-To-be-in-the-Tournament-of-Roses #that's-every-florist's-dream!-Up-on-a-float #surrounded-by-flowers #crowds-cheering.-A-tournament.-Do-the-roses-compete-in-athletic-events?-No.-All-right #I've-got-one.-How-come-you-don't-fly-everywhere?-It's-exhausting.-Why-don't-you-run-everywhere?-It's-faster.-Yeah #OK #I-see #I-see.-All-right #your-turn.-TiVo.-You-can-just-freeze-live-TV?-That's-insane!-You-don't-have-that?-We-have-Hivo #but-it's-a-disease.-It's-a-horrible #horrible-disease.-Oh #my.-Dumb-bees!-You-must-want-to-sting-all-those-jerks.-We-try-not-to-sting.-It's-usually-fatal-for-us.-So-you-have-to-watch-your-temper.-Very-carefully.-You-kick-a-wall #take-a-walk #write-an-angry-letter-and-throw-it-out.-Work-through-it-like-any-emotion:-Anger #jealousy #lust.-Oh #my-goodness!-Are-you-OK?-Yeah.-What-is-wrong-with-you?!-It's-a-bug.-He's-not-bothering-anybody.-Get-out-of-here #you-creep!-What-was-that?-A-Pic-'N'-Save-circular?-Yeah #it-was.-How-did-you-know?-It-felt-like-about-10-pages.-Seventy-five-is-pretty-much-our-limit.-You've-really-got-that-down-to-a-science.-I-lost-a-cousin-to-Italian-Vogue.-I'll-bet.-What-in-the-name-of-Mighty-Hercules-is-this?-How-did-this-get-here?-cute-Bee #Golden-Blossom #Ray-Liotta-Private-Select?-Is-he-that-actor?-I-never-heard-of-him.-Why-is-this-here?-For-people.-We-eat-it.-You-don't-have-enough-food-of-your-own?-Well #yes.-How-do-you-get-it?-Bees-make-it.-I-know-who-makes-it!-And-it's-hard-to-make-it!-There's-heating #cooling #stirring.-You-need-a-whole-Krelman-thing!-It's-organic.-It's-our-ganic!-It's-just-honey #Barry.-Just-what?!-Bees-don't-know-about-this!-This-is-stealing!-A-lot-of-stealing!-You've-taken-our-homes #schools #hospitals!-This-is-all-we-have!-And-it's-on-sale?!-I'm-getting-to-the-bottom-of-this.-I'm-getting-to-the-bottom-of-all-of-this!-Hey #Hector.-You-almost-done?-Almost.-He-is-here.-I-sense-it.-Well #I-guess-I'll-go-home-now-and-just-leave-this-nice-honey-out #with-no-one-around.-You're-busted #box-boy!-I-knew-I-heard-something.-So-you-can-talk!-I-can-talk.-And-now-you'll-start-talking!-Where-you-getting-the-sweet-stuff?-Who's-your-supplier?-I-don't-understand.-I-thought-we-were-friends.-The-last-thing-we-want-to-do-is-upset-bees!-You're-too-late!-It's-ours-now!-You #sir #have-crossed-the-wrong-sword!-You #sir #will-be-lunch-for-my-iguana #Ignacio!-Where-is-the-honey-coming-from?-Tell-me-where!-Honey-Farms!-It-comes-from-Honey-Farms!-Crazy-person!-What-horrible-thing-has-happened-here?-These-faces #they-never-knew-what-hit-them.-And-now-they're-on-the-road-to-nowhere!-Just-keep-still.-What?-You're-not-dead?-Do-I-look-dead?-They-will-wipe-anything-that-moves.-Where-you-headed?-To-Honey-Farms.-I-am-onto-something-huge-here.-I'm-going-to-Alaska.-Moose-blood #crazy-stuff.-Blows-your-head-off!-I'm-going-to-Tacoma.-And-you?-He-really-is-dead.-All-right.-Uh-oh!-What-is-that?!-Oh #no!-A-wiper!-Triple-blade!-Triple-blade?-Jump-on!-It's-your-only-chance #bee!-Why-does-everything-have-to-be-so-doggone-clean?!-How-much-do-you-people-need-to-see?!-Open-your-eyes!-Stick-your-head-out-the-window!-From-NPR-News-in-Washington #I'm-Carl-Kasell.-But-don't-kill-no-more-bugs!-Bee!-Moose-blood-guy!!-You-hear-something?-Like-what?-Like-tiny-screaming.-Turn-off-the-radio.-Whassup #bee-boy?-Hey #Blood.-Just-a-row-of-honey-jars #as-far-as-the-eye-could-see.-Wow!-I-assume-wherever-this-truck-goes-is-where-they're-getting-it.-I-mean #that-honey's-ours.-Bees-hang-tight.-We're-all-jammed-in.-It's-a-close-community.-Not-us #man.-We-on-our-own.-Every-mosquito-on-his-own.-What-if-you-get-in-trouble?-You-a-mosquito #you-in-trouble.-Nobody-likes-us.-They-just-smack.-See-a-mosquito #smack #smack!-At-least-you're-out-in-the-world.-You-must-meet-girls.-Mosquito-girls-try-to-trade-up #get-with-a-moth #dragonfly.-Mosquito-girl-don't-want-no-mosquito.-You-got-to-be-kidding-me!-Mooseblood's-about-to-leave-the-building!-So-long #bee!-Hey #guys!-Mooseblood!-I-knew-I'd-catch-y'all-down-here.-Did-you-bring-your-crazy-straw?-We-throw-it-in-jars #slap-a-label-on-it #and-it's-pretty-much-pure-profit.-What-is-this-place?-A-bee's-got-a-brain-the-size-of-a-pinhead.-They-are-pinheads!-Pinhead.-Check-out-the-new-smoker.-Oh #sweet.-That's-the-one-you-want.-The-Thomas-3000!-Smoker?-Ninety-puffs-a-minute #semi-automatic.-Twice-the-nicotine #all-the-tar.-A-couple-breaths-of-this-knocks-them-right-out.-They-make-the-honey #and-we-make-the-money.-'They-make-the-honey #and-we-make-the-money'?-Oh #my!-What's-going-on?-Are-you-OK?-Yeah.-It-doesn't-last-too-long.-Do-you-know-you're-in-a-fake-hive-with-fake-walls?-Our-queen-was-moved-here.-We-had-no-choice.-This-is-your-queen?-That's-a-man-in-women's-clothes!-That's-a-drag-queen!-What-is-this?-Oh #no!-There's-hundreds-of-them!-Bee-honey.-Our-honey-is-being-brazenly-stolen-on-a-massive-scale!-This-is-worse-than-anything-bears-have-done!-I-intend-to-do-something.-Oh #Barry #stop.-Who-told-you-humans-are-taking-our-honey?-That's-a-rumor.-Do-these-look-like-rumors?-That's-a-conspiracy-theory.-These-are-obviously-doctored-photos.-How-did-you-get-mixed-up-in-this?-He's-been-talking-to-humans.-What?-Talking-to-humans?!-He-has-a-human-girlfriend.-And-they-make-out!-Make-out?-Barry!-We-do-not.-You-wish-you-could.-Whose-side-are-you-on?-The-bees!-I-dated-a-cricket-once-in-San-Antonio.-Those-crazy-legs-kept-me-up-all-night.-Barry #this-is-what-you-want-to-do-with-your-life?-I-want-to-do-it-for-all-our-lives.-Nobody-works-harder-than-bees!-Dad #I-remember-you-coming-home-so-overworked-your-hands-were-still-stirring.-You-couldn't-stop.-I-remember-that.-What-right-do-they-have-to-our-honey?-We-live-on-two-cups-a-year.-They-put-it-in-lip-balm-for-no-reason-whatsoever!-Even-if-it's-true #what-can-one-bee-do?-Sting-them-where-it-really-hurts.-In-the-face!-The-eye!-That-would-hurt.-No.-Up-the-nose?-That's-a-killer.-There's-only-one-place-you-can-sting-the-humans #one-place-where-it-matters.-Hive-at-Five #The-Hive's-only-full-hour-action-news-source.-No-more-bee-beards!-With-Bob-Bumble-at-the-anchor-desk.-Weather-with-Storm-Stinger.-Sports-with-Buzz-Larvi.-And-Jeanette-Chung.-Good-evening.-I'm-Bob-Bumble.-And-I'm-Jeanette-Ohung.-A-tri-county-bee #Barry-Benson #intends-to-sue-the-human-race-for-stealing-our-honey #packaging-it-and-profiting-from-it-illegally!-Tomorrow-night-on-Bee-Larry-King #we'll-have-three-former-queens-here-in-our-studio #discussing-their-new-book #classy-Ladies #out-this-week-on-Hexagon.-Tonight-we're-talking-to-Barry-Benson.-Did-you-ever-think #'I'm-a-kid-from-The-Hive.-I-can't-do-this'?-Bees-have-never-been-afraid-to-change-the-world.-What-about-Bee-Oolumbus?-Bee-Gandhi?-Bejesus?-Where-I'm-from #we'd-never-sue-humans.-We-were-thinking-of-stickball-or-candy-stores.-How-old-are-you?-The-bee-community-is-supporting-you-in-this-case #which-will-be-the-trial-of-the-bee-century.-You-know #they-have-a-Larry-King-in-the-human-world-too.-It's-a-common-name.-Next-week...-He-looks-like-you-and-has-a-show-and-suspenders-and-colored-dots...-Next-week...-Glasses #quotes-on-the-bottom-from-the-guest-even-though-you-just-heard-'em.-Bear-Week-next-week!-They're-scary #hairy-and-here-live.-Always-leans-forward #pointy-shoulders #squinty-eyes #very-Jewish.-In-tennis #you-attack-at-the-point-of-weakness!-It-was-my-grandmother #Ken.-She's-81.-Honey #her-backhand's-a-joke!-I'm-not-gonna-take-advantage-of-that?-Quiet #please.-Actual-work-going-on-here.-Is-that-that-same-bee?-Yes #it-is!-I'm-helping-him-sue-the-human-race.-Hello.-Hello #bee.-This-is-Ken.-Yeah #I-remember-you.-Timberland #size-ten-and-a-half.-Vibram-sole #I-believe.-Why-does-he-talk-again?-Listen #you-better-go-'cause-we're-really-busy-working.-But-it's-our-yogurt-night!-Bye-bye.-Why-is-yogurt-night-so-difficult?!-You-poor-thing.-You-two-have-been-at-this-for-hours!-Yes #and-Adam-here-has-been-a-huge-help.-Frosting...-How-many-sugars?-Just-one.-I-try-not-to-use-the-competition.-So-why-are-you-helping-me?-Bees-have-good-qualities.-And-it-takes-my-mind-off-the-shop.-Instead-of-flowers #people-are-giving-balloon-bouquets-now.-Those-are-great #if-you're-three.-And-artificial-flowers.-Oh #those-just-get-me-psychotic!-Yeah #me-too.-Bent-stingers #pointless-pollination.-Bees-must-hate-those-fake-things!-Nothing-worse-than-a-daffodil-that's-had-work-done.-Maybe-this-could-make-up-for-it-a-little-bit.-This-lawsuit's-a-pretty-big-deal.-I-guess.-You-sure-you-want-to-go-through-with-it?-Am-I-sure?-When-I'm-done-with-the-humans #they-won't-be-able-to-say #'Honey #I'm-home #'-without-paying-a-royalty!-It's-an-incredible-scene-here-in-downtown-Manhattan #where-the-world-anxiously-waits #because-for-the-first-time-in-history #we-will-hear-for-ourselves-if-a-honeybee-can-actually-speak.-What-have-we-gotten-into-here #isn't-it?-I-can't-believe-how-many-humans-don't-work-during-the-day.-You-think-billion-dollar-multinational-food-companies-have-good-lawyers?-Everybody-needs-to-stay-behind-the-barricade.-What's-the-matter?-I-don't-know #I-just-got-a-chill.-Well #if-it-isn't-the-bee-team.-You-boys-work-on-this?-All-rise!-The-Honorable-Judge-Bumbleton-presiding.-All-right.-Case-number-4475 #Superior-Court-of-New-York #Barry-Bee-Benson-v.-the-Honey-Industry-is-now-in-session.-Mr.-Montgomery #you're-representing-the-five-food-companies-collectively?-A-privilege.-Mr.-Benson...-you're-representing-all-the-bees-of-the-world?-I'm-kidding.-Yes #Your-Honor #we're-ready-to-proceed.-Mr.-Montgomery #your-opening-statement #please.-Ladies-and-gentlemen-of-the-jury #my-grandmother-was-a-simple-woman.-Born-on-a-farm #she-believed-it-was-man's-divine-right-to-benefit-from-the-bounty-of-nature-God-put-before-us.-If-we-lived-in-the-topsy-turvy-world-Mr.-Benson-imagines #just-think-of-what-would-it-mean.-I-would-have-to-negotiate-with-the-silkworm-for-the-elastic-in-my-britches!-Talking-bee!-How-do-we-know-this-isn't-some-sort-of-holographic-motion-picture-capture-Hollywood-wizardry?-They-could-be-using-laser-beams!-Robotics!-Ventriloquism!-Cloning!-For-all-we-know #he-could-be-on-steroids!-Mr.-Benson?-Ladies-and-gentlemen #there's-no-trickery-here.-I'm-just-an-ordinary-bee.-Honey's-pretty-important-to-me.-It's-important-to-all-bees.-We-invented-it!-We-make-it.-And-we-protect-it-with-our-lives.-Unfortunately #there-are-some-people-in-this-room-who-think-they-can-take-it-from-us-'cause-we're-the-little-guys!-I'm-hoping-that #after-this-is-all-over #you'll-see-how #by-taking-our-honey #you-not-only-take-everything-we-have-but-everything-we-are!-I-wish-he'd-dress-like-that-all-the-time.-So-nice!-Call-your-first-witness.-So #Mr.-Klauss-Vanderhayden-of-Honey-Farms #big-company-you-have.-I-suppose-so.-I-see-you-also-own-Honeyburton-and-Honron!-Yes #they-provide-beekeepers-for-our-farms.-Beekeeper.-I-find-that-to-be-a-very-disturbing-term.-I-don't-imagine-you-employ-any-bee-free-ers #do-you?-No.-I-couldn't-hear-you.-No.-No.-Because-you-don't-free-bees.-You-keep-bees.-Not-only-that #it-seems-you-thought-a-bear-would-be-an-appropriate-image-for-a-jar-of-honey.-They're-very-lovable-creatures.-Yogi-Bear #Fozzie-Bear #Build-A-Bear.-You-mean-like-this?-Bears-kill-bees!-How'd-you-like-his-head-crashing-through-your-living-room?!-Biting-into-your-couch!-Spitting-out-your-throw-pillows!-OK #that's-enough.-Take-him-away.-So #Mr.-Sting #thank-you-for-being-here.-Your-name-intrigues-me.-Where-have-I-heard-it-before?-I-was-with-a-band-called-The-Police.-But-you've-never-been-a-police-officer #have-you?-No #I-haven't.-No #you-haven't.-And-so-here-we-have-yet-another-example-of-bee-culture-casually-stolen-by-a-human-for-nothing-more-than-a-prance-about-stage-name.-Oh #please.-Have-you-ever-been-stung #Mr.-Sting?-Because-I'm-feeling-a-little-stung #Sting.-Or-should-I-say...-Mr.-Gordon-M.-Sumner!-That's-not-his-real-name?!-You-idiots!-Mr.-Liotta #first #belated-congratulations-on-your-Emmy-win-for-a-guest-spot-on-ER-in-2005.-Thank-you.-Thank-you.-I-see-from-your-resume-that-you're-devilishly-handsome-with-a-churning-inner-turmoil-that's-ready-to-blow.-I-enjoy-what-I-do.-Is-that-a-crime?-Not-yet-it-isn't.-But-is-this-what-it's-come-to-for-you?-Exploiting-tiny #helpless-bees-so-you-don't-have-to-rehearse-your-part-and-learn-your-lines #sir?-Watch-it #Benson!-I-could-blow-right-now!-This-isn't-a-goodfella.-This-is-a-badfella!-Why-doesn't-someone-just-step-on-this-creep #and-we-can-all-go-home?!-Order-in-this-court!-You're-all-thinking-it!-Order!-Order #I-say!-Say-it!-Mr.-Liotta #please-sit-down!-I-think-it-was-awfully-nice-of-that-bear-to-pitch-in-like-that.-I-think-the-jury's-on-our-side.-Are-we-doing-everything-right #legally?-I'm-a-florist.-Right.-Well #here's-to-a-great-team.-To-a-great-team!-Well #hello.-Ken!-Hello.-I-didn't-think-you-were-coming.-No #I-was-just-late-I-tried-to-call #but...-the-battery.-I-didn't-want-all-this-to-go-to-waste #so-I-called-Barry.-Luckily #he-was-free.-Oh #that-was-lucky.-There's-a-little-left.-I-could-heat-it-up.-Yeah #heat-it-up #sure #whatever.-So-I-hear-you're-quite-a-tennis-player.-I'm-not-much-for-the-game-myself.-The-ball's-a-little-grabby.-That's-where-I-usually-sit.-Right...-there.-Ken #Barry-was-looking-at-your-resume #and-he-agreed-with-me-that-eating-with-chopsticks-isn't-really-a-special-skill.-You-think-I-don't-see-what-you're-doing?-I-know-how-hard-it-is-to-find-the-right-job.-We-have-that-in-common.-Do-we?-Bees-have-100-percent-employment #but-we-do-jobs-like-taking-the-crud-out.-That's-just-what-I-was-thinking-about-doing.-Ken #I-let-Barry-borrow-your-razor-for-his-fuzz.-I-hope-that-was-all-right.-I'm-going-to-drain-the-old-stinger.-Yeah #you-do-that.-Look-at-that.-You-know #I've-just-about-had-it-with-your-little-Mind-Games.-What's-that?-Italian-Vogue.-Mamma-mia #that's-a-lot-of-pages.-A-lot-of-ads.-Remember-what-Van-said #why-is-your-life-more-valuable-than-mine?-Funny #I-just-can't-seem-to-recall-that!-I-think-something-stinks-in-here!-I-love-the-smell-of-flowers.-How-do-you-like-the-smell-of-flames?!-Not-as-much.-Water-bug!-Not-taking-sides!-Ken #I'm-wearing-a-Chapstick-hat!-This-is-pathetic!-I've-got-issues!-Well #well #well #a-royal-flush!-You're-bluffing.-Am-I?-Surf's-up #dude!-Poo-water!-That-bowl-is-gnarly.-Except-for-those-dirty-yellow-rings!-Kenneth!-What-are-you-doing?!-You-know #I-don't-even-like-honey!-I-don't-eat-it!-We-need-to-talk!-He's-just-a-little-bee!-And-he-happens-to-be-the-nicest-bee-I've-met-in-a-long-time!-Long-time?-What-are-you-talking-about?!-Are-there-other-bugs-in-your-life?--No #but-there-are-other-things-bugging-me-in-life.-And-you're-one-of-them!-Fine!-Talking-bees #no-yogurt-night...-My-nerves-are-fried-from-riding-on-this-emotional-roller-coaster!-Goodbye #Ken.-And-for-your-information #I-prefer-sugar-free #artificial-sweeteners-made-by-man!-I'm-sorry-about-all-that.-I-know-it's-got-an-aftertaste!-I-like-it!-I-always-felt-there-was-some-kind-of-barrier-between-Ken-and-me.-I-couldn't-overcome-it.-Oh #well.-Are-you-OK-for-the-trial?-I-believe-Mr.-Montgomery-is-about-out-of-ideas.-We-would-like-to-call-Mr.-Barry-Benson-Bee-to-the-stand.-Good-idea!-You-can-really-see-why-he's-considered-one-of-the-best-lawyers...-Yeah.-Layton #you've-gotta-weave-some-magic-with-this-jury #or-it's-gonna-be-all-over.-Don't-worry.-The-only-thing-I-have-to-do-to-turn-this-jury-around-is-to-remind-them-of-what-they-don't-like-about-bees.-You-got-the-tweezers?-Are-you-allergic?-Only-to-losing #son.-Only-to-losing.-Mr.-Benson-Bee #I'll-ask-you-what-I-think-we'd-all-like-to-know.-What-exactly-is-your-relationship-to-that-woman?-We're-friends.-Good-friends?-Yes.-How-good?-Do-you-live-together?-Wait-a-minute...-Are-you-her-little...-bedbug?-I've-seen-a-bee-documentary-or-two.-From-what-I-understand #doesn't-your-queen-give-birth-to-all-the-bee-children?-Yeah #but...-So-those-aren't-your-real-parents!-Oh #Barry...-Yes #they-are!-Hold-me-back!-You're-an-illegitimate-bee #aren't-you #Benson?-He's-denouncing-bees!-Don't-y'all-date-your-cousins?-Objection!-I'm-going-to-pincushion-this-guy!-Adam #don't!-It's-what-he-wants!-Oh #I'm-hit!!-Oh #lordy #I-am-hit!-Order!-Order!-The-venom!-The-venom-is-coursing-through-my-veins!-I-have-been-felled-by-a-winged-beast-of-destruction!-You-see?-You-can't-treat-them-like-equals!-They're-striped-savages!-Stinging's-the-only-thing-they-know!-It's-their-way!-Adam #stay-with-me.-I-can't-feel-my-legs.-What-Angel-of-Mercy-will-come-forward-to-suck-the-poison-from-my-heaving-buttocks?-I-will-have-order-in-this-court.-Order!-Order #please!-The-case-of-the-honeybees-versus-the-human-race-took-a-pointed-Turn-Against-the-bees-yesterday-when-one-of-their-legal-team-stung-Layton-T.-Montgomery.-Hey #buddy.-Hey.-Is-there-much-pain?-Yeah.-I...-I-blew-the-whole-case #didn't-I?-It-doesn't-matter.-What-matters-is-you're-alive.-You-could-have-died.-I'd-be-better-off-dead.-Look-at-me.-They-got-it-from-the-cafeteria-downstairs #in-a-tuna-sandwich.-Look #there's-a-little-celery-still-on-it.-What-was-it-like-to-sting-someone?-I-can't-explain-it.-It-was-all...-All-adrenaline-and-then...and-then-ecstasy!-All-right.-You-think-it-was-all-a-trap?-Of-course.-I'm-sorry.-I-flew-us-right-into-this.-What-were-we-thinking?-Look-at-us.-We're-just-a-couple-of-bugs-in-this-world.-What-will-the-humans-do-to-us-if-they-win?-I-don't-know.-I-hear-they-put-the-roaches-in-motels.-That-doesn't-sound-so-bad.-Adam #they-check-in #but-they-don't-check-out!-Oh #my.-Could-you-get-a-nurse-to-close-that-window?-Why?-The-smoke.-Bees-don't-smoke.-Right.-Bees-don't-smoke.-Bees-don't-smoke!-But-some-bees-are-smoking.-That's-it!-That's-our-case!-It-is?-It's-not-over?-Get-dressed.-I've-gotta-go-somewhere.-Get-back-to-the-court-and-stall.-Stall-any-way-you-can.-And-assuming-you've-done-step-correctly #you're-ready-for-the-tub.-Mr.-Flayman.-Yes?-Yes #Your-Honor!-Where-is-the-rest-of-your-team?-Well #Your-Honor #it's-interesting.-Bees-are-trained-to-fly-haphazardly #and-as-a-result #we-don't-make-very-good-time.-I-actually-heard-a-funny-story-about...-Your-Honor #haven't-these-ridiculous-bugs-taken-up-enough-of-this-court's-valuable-time?-How-much-longer-will-we-allow-these-absurd-shenanigans-to-go-on?-They-have-presented-no-compelling-evidence-to-support-their-charges-against-my-clients #who-run-legitimate-businesses.-I-move-for-a-complete-dismissal-of-this-entire-case!-Mr.-Flayman #I'm-afraid-I'm-going-to-have-to-consider-Mr.-Montgomery's-motion.-But-you-can't!-We-have-a-terrific-case.-Where-is-your-proof?-Where-is-the-evidence?-Show-me-the-smoking-gun!-Hold-it #Your-Honor!-You-want-a-smoking-gun?-Here-is-your-smoking-gun.-What-is-that?-It's-a-bee-smoker!-What #this?-This-harmless-little-contraption?-This-couldn't-hurt-a-fly #let-alone-a-bee.-Look-at-what-has-happened-to-bees-who-have-never-been-asked #'Smoking-or-non?'-Is-this-what-nature-intended-for-us?-To-be-forcibly-addicted-to-smoke-machines-and-man-made-wooden-slat-work-camps?-Living-out-our-lives-as-honey-slaves-to-the-white-man?-What-are-we-gonna-do?-He's-playing-the-species-card.-Ladies-and-gentlemen #please #free-these-bees!-Free-the-bees!-Free-the-bees!-Free-the-bees!-Free-the-bees!-Free-the-bees!-The-court-finds-in-favor-of-the-bees!-Vanessa #we-won!-I-knew-you-could-do-it!-High-five!-Sorry.-I'm-OK!-You-know-what-this-means?-All-the-honey-will-finally-belong-to-the-bees.-Now-we-won't-have-to-work-so-hard-all-the-time.-This-is-an-unholy-perversion-of-the-balance-of-nature #Benson.-You'll-regret-this.-Barry #how-much-honey-is-out-there?-All-right.-One-at-a-time.-Barry #who-are-you-wearing?-My-sweater-is-Ralph-Lauren #and-I-have-no-pants.-What-if-Montgomery's-right?-What-do-you-mean?-We've-been-living-the-bee-way-a-long-time #27-million-years.-Congratulations-on-your-victory.-What-will-you-demand-as-a-settlement?-First #we'll-demand-a-complete-shutdown-of-all-bee-work-camps.-Then-we-want-back-the-honey-that-was-ours-to-begin-with #every-last-drop.-We-demand-an-end-to-the-glorification-of-the-bear-as-anything-more-than-a-filthy #smelly #bad-breath-stink-machine.-We're-all-aware-of-what-they-do-in-the-woods.-Wait-for-my-signal.-Take-him-out.-He'll-have-nauseous-for-a-few-hours #then-he'll-be-fine.-And-we-will-no-longer-tolerate-bee-negative-nicknames...-But-it's-just-a-prance-about-stage-name!-...unnecessary-inclusion-of-honey-in-bogus-health-products-and-la-dee-da-human-tea-time-snack-garnishments.-Can't-breathe.-Bring-it-in #boys!-Hold-it-right-there!-Good.-Tap-it.-Mr.-Buzzwell #we-just-passed-three-cups-and-there's-gallons-more-coming!-I-think-we-need-to-shut-down!-Shut-down?-We've-never-shut-down.-Shut-down-honey-production!-Stop-making-honey!-Turn-your-key #sir!-What-do-we-do-now?-Cannonball!-We're-shutting-honey-production!-Mission-abort.-Aborting-pollination-and-nectar-detail.-Returning-to-base.-Adam #you-wouldn't-believe-how-much-honey-was-out-there.-Oh #yeah?-What's-going-on?-Where-is-everybody?-Are-they-out-celebrating?-They're-home.-They-don't-know-what-to-do.-Laying-out #sleeping-in.-I-heard-your-Uncle-Carl-was-on-his-way-to-San-Antonio-with-a-cricket.-At-least-we-got-our-honey-back.-Sometimes-I-think #so-what-if-humans-liked-our-honey?-Who-wouldn't?-It's-the-greatest-thing-in-the-world!-I-was-excited-to-be-part-of-making-it.-This-was-my-new-desk.-This-was-my-new-job.-I-wanted-to-do-it-really-well.-And-now...-Now-I-can't.-I-don't-understand-why-they're-not-happy.-I-thought-their-lives-would-be-better!-They're-doing-nothing.-It's-amazing.-Honey-really-changes-people.-You-don't-have-any-idea-what's-going-on #do-you?-What-did-you-want-to-show-me?-This.-What-happened-here?-That-is-not-the-half-of-it.-Oh #no.-Oh #my.-They're-all-wilting.-Doesn't-look-very-good #does-it?-No.-And-whose-fault-do-you-think-that-is?-You-know #I'm-gonna-guess-bees.-Bees?-Specifically #me.-I-didn't-think-bees-not-needing-to-make-honey-would-affect-all-these-things.-It's-not-just-flowers.-Fruits #vegetables #they-all-need-bees.-That's-our-whole-SAT-test-right-there.-Take-away-produce #that-affects-the-entire-animal-kingdom.-And-then #of-course...-The-human-species?-So-if-there's-no-more-pollination #it-could-all-just-go-south-here #couldn't-it?-I-know-this-is-also-partly-my-fault.-How-about-a-suicide-pact?-How-do-we-do-it?-I'll-sting-you #you-step-on-me.-That-just-kills-you-twice.-Right #right.-Listen #Barry...-sorry #but-I-gotta-get-going.-I-had-to-open-my-mouth-and-talk.-Vanessa?-Vanessa?-Why-are-you-leaving?-Where-are-you-going?-To-the-final-Tournament-of-Roses-parade-in-Pasadena.-They've-moved-it-to-this-weekend-because-all-the-flowers-are-dying.-It's-the-Last-Chance-I'll-ever-have-to-see-it.-Vanessa #I-just-wanna-say-I'm-sorry.-I-never-meant-it-to-turn-out-like-this.-I-know.-Me-neither.-Tournament-of-Roses.-Roses-can't-do-sports.-Wait-a-minute.-Roses.-Roses?-Roses!-Vanessa!-Roses?!-Barry?-Roses-are-flowers!-Yes #they-are.-Flowers #bees #pollen!-I-know.-That's-why-this-is-the-last-parade.-Maybe-not.-Could-you-ask-him-to-slow-down?-Could-you-slow-down?-Barry!-OK #I-made-a-huge-mistake.-This-is-a-total-disaster #all-my-fault.-Yes #it-kind-of-is.-I've-ruined-the-planet.-I-wanted-to-help-you-with-the-flower-shop.-I've-made-it-worse.-Actually #it's-completely-closed-down.-I-thought-maybe-you-were-remodeling.-But-I-have-another-idea #and-it's-greater-than-my-previous-ideas-combined.-I-don't-want-to-hear-it!-All-right #they-have-the-roses #the-roses-have-the-pollen.-I-know-every-bee #plant-and-flower-bud-in-this-park.-All-we-gotta-do-is-get-what-they've-got-back-here-with-what-we've-got.-Bees.-Park.-Pollen!-Flowers.-Repollination!-Across-the-nation!-Tournament-of-Roses #Pasadena #California.-They've-got-nothing-but-flowers #floats-and-cotton-candy.-Security-will-be-tight.-I-have-an-idea.-Vanessa-Bloome #FTD.-Official-floral-business.-It's-real.-Sorry #ma'am.-Nice-brooch.-Thank-you.-It-was-a-gift.-Once-inside #we-just-pick-the-right-float.-How-about-The-Princess-and-the-Pea?-I-could-be-the-princess #and-you-could-be-the-pea!-Yes #I-got-it.-Where-should-I-sit?-What-are-you?-I-believe-I'm-the-pea.-The-pea?-It-goes-under-the-mattresses.-Not-in-this-fairy-tale #sweetheart.-I'm-getting-the-marshal.-You-do-that!-This-whole-parade-is-a-fiasco!-Let's-see-what-this-baby'll-do.-Hey #what-are-you-doing?!-Then-all-we-do-is-blend-in-with-traffic...-without-arousing-suspicion.-Once-at-the-airport #there's-no-stopping-us.-Stop!-Security.-You-and-your-insect-pack-your-float?-Yes.-Has-it-been-in-your-possession-the-entire-time?-Would-you-remove-your-shoes?-Remove-your-stinger.-It's-part-of-me.-I-know.-Just-having-some-fun.-Enjoy-your-flight.-Then-if-we're-lucky #we'll-have-just-enough-pollen-to-do-the-job.-Can-you-believe-how-lucky-we-are?-We-have-just-enough-pollen-to-do-the-job!-I-think-this-is-gonna-work.-It's-got-to-work.-Attention #passengers #this-is-Captain-Scott.-We-have-a-bit-of-bad-weather-in-New-York.-It-looks-like-we'll-experience-a-couple-hours-delay.-Barry #these-are-cut-flowers-with-no-water.-They'll-never-make-it.-I-gotta-get-up-there-and-talk-to-them.-Be-careful.-Can-I-get-help-with-the-Sky-Mall-magazine?-I'd-like-to-order-the-talking-inflatable-nose-and-ear-hair-trimmer.-Captain #I'm-in-a-real-situation.-What'd-you-say #Hal?-Nothing.-Bee!-Don't-freak-out!-My-entire-species...-What-are-you-doing?-Wait-a-minute!-I'm-an-attorney!-Who's-an-attorney?-Don't-move.-Oh #Barry.-Good-afternoon #passengers.-This-is-your-captain.-Would-a-Miss-Vanessa-Bloome-in-24B-please-report-to-the-cockpit?-And-please-hurry!-What-happened-here?-There-was-a-DustBuster #a-toupee #a-life-raft-exploded.-One's-bald #one's-in-a-boat #they're-both-unconscious!-Is-that-another-bee-joke?-No!-No-one's-flying-the-plane!-This-is-JFK-control-tower #Flight-356.-What's-your-status?-This-is-Vanessa-Bloome.-I'm-a-florist-from-New-York.-Where's-the-pilot?-He's-unconscious #and-so-is-the-copilot.-Not-good.-Does-anyone-onboard-have-flight-experience?-As-a-matter-of-fact #there-is.-Who's-that?-Barry-Benson.-From-the-honey-trial?!-Oh #great.-Vanessa #this-is-nothing-more-than-a-big-metal-bee.-It's-got-giant-wings #huge-engines.-I-can't-fly-a-plane.-Why-not?-Isn't-John-Travolta-a-pilot?-Yes.-How-hard-could-it-be?-Wait #Barry!-We're-headed-into-some-lightning.-This-is-Bob-Bumble.-We-have-some-late-breaking-news-from-JFK-Airport #where-a-suspenseful-scene-is-developing.-Barry-Benson #fresh-from-his-legal-victory...-That's-Barry!-...is-attempting-to-land-a-plane #loaded-with-people #flowers-and-an-incapacitated-flight-crew.-Flowers?!-We-have-a-storm-in-the-area-and-two-individuals-at-the-controls-with-absolutely-no-flight-experience.-Just-a-minute.-There's-a-bee-on-that-plane.-I'm-quite-familiar-with-Mr.-Benson-and-his-no-account-compadres.-They've-done-enough-damage.-But-isn't-he-your-only-hope?-Technically #a-bee-shouldn't-be-able-to-fly-at-all.-Their-wings-are-too-small...-Haven't-we-heard-this-a-million-times?-'The-surface-area-of-the-wings-and-body-mass-make-no-sense.'-Get-this-on-the-air!-Got-it.-Stand-by.-We're-going-live.-The-way-we-work-may-be-a-mystery-to-you.-Making-honey-takes-a-lot-of-bees-doing-a-lot-of-small-jobs.-But-let-me-tell-you-about-a-small-job.-If-you-do-it-well #it-makes-a-big-difference.-More-than-we-realized.-To-us #to-everyone.-That's-why-I-want-to-get-bees-back-to-working-together.-That's-the-bee-way!-We're-not-made-of-Jell-O.-We-get-behind-a-fellow.-Black-and-yellow!-Hello!-Left #right #down #hover.-Hover?-Forget-hover.-This-isn't-so-hard.-Beep-beep!-Beep-beep!-Barry #what-happened?!-Wait #I-think-we-were-on-autopilot-the-whole-time.-That-may-have-been-helping-me.-And-now-we're-not!-So-it-turns-out-I-cannot-fly-a-plane.-All-of-you #let's-get-behind-this-fellow!-Move-it-out!-Move-out!-Our-only-chance-is-if-I-do-what-I'd-do #you-copy-me-with-the-wings-of-the-plane!-Don't-have-to-yell.-I'm-not-yelling!-We're-in-a-lot-of-trouble.-It's-very-hard-to-concentrate-with-that-panicky-tone-in-your-voice!-It's-not-a-tone.-I'm-panicking!-I-can't-do-this!-Vanessa #pull-yourself-together.-You-have-to-snap-out-of-it!-You-snap-out-of-it.-You-snap-out-of-it.-You-snap-out-of-it!-You-snap-out-of-it!-You-snap-out-of-it!-You-snap-out-of-it!-You-snap-out-of-it!-You-snap-out-of-it!-Hold-it!-Why?-Come-on #it's-my-turn.-How-is-the-plane-flying?-I-don't-know.-Hello?-Benson #got-any-flowers-for-a-happy-occasion-in-there?-The-Pollen-Jocks!-They-do-get-behind-a-fellow.-Black-and-yellow.-Hello.-All-right #let's-drop-this-tin-can-on-the-blacktop.-Where?-I-can't-see-anything.-Can-you?-No #nothing.-It's-all-cloudy.-Come-on.-You-got-to-think-bee #Barry.-Thinking-bee.-Thinking-bee.-Thinking-bee!-Thinking-bee!-Thinking-bee!-Wait-a-minute.-I-think-I'm-feeling-something.-What?-I-don't-know.-It's-strong #pulling-me.-Like-a-27-million-year-old-instinct.-Bring-the-nose-down.-Thinking-bee!-Thinking-bee!-Thinking-bee!-What-in-the-world-is-on-the-tarmac?-Get-some-lights-on-that!-Thinking-bee!-Thinking-bee!-Thinking-bee!-Vanessa #aim-for-the-flower.-OK.-Cut-the-engines.-We're-going-in-on-bee-power.-Ready #boys?-Affirmative!-Good.-Good.-Easy #now.-That's-it.-Land-on-that-flower!-Ready?-Full-reverse!-Spin-it-around!-Not-that-flower!-The-other-one!-Which-one?-That-flower.-I'm-aiming-at-the-flower!-That's-a-fat-guy-in-a-flowered-shirt.-I-mean-the-giant-pulsating-flower-made-of-millions-of-bees!-Pull-forward.-Nose-down.-Tail-up.-Rotate-around-it.-This-is-insane #Barry!-This's-the-only-way-I-know-how-to-fly.-Am-I-koo-koo-kachoo #or-is-this-plane-flying-in-an-insect-like-pattern?-Get-your-nose-in-there.-Don't-be-afraid.-Smell-it.-Full-reverse!-Just-drop-it.-Be-a-part-of-it.-Aim-for-the-center!-Now-drop-it-in!-Drop-it-in #woman!-Come-on #already.-Barry #we-did-it!-You-taught-me-how-to-fly!-Yes.-No-high-five!-Right.-Barry #it-worked!-Did-you-see-the-giant-flower?-What-giant-flower?-Where?-Of-course-I-saw-the-flower!-That-was-genius!-Thank-you.-But-we're-not-done-yet.-Listen #everyone!-This-runway-is-covered-with-the-last-pollen-from-the-last-flowers-available-anywhere-on-Earth.-That-means-this-is-our-Last-Chance.-We're-the-only-ones-who-make-honey #pollinate-flowers-and-dress-like-this.-If-we're-gonna-survive-as-a-species #this-is-our-moment!-What-do-you-say?-Are-we-going-to-be-bees #or-just-Museum-of-Natural-History-keychains?-We're-bees!-Keychain!-Then-follow-me!-Except-Keychain.-Hold-on #Barry.-Here.-You've-earned-this.-Yeah!-I'm-a-Pollen-Jock!-And-it's-a-perfect-fit.-All-I-gotta-do-are-the-sleeves.-Oh #yeah.-That's-our-Barry.-Mom!-The-bees-are-back!-If-anybody-needs-to-make-a-call #now's-the-time.-I-got-a-feeling-we'll-be-working-late-tonight!-Here's-your-change.-Have-a-great-afternoon!-Can-I-help-who's-next?-Would-you-like-some-honey-with-that?-It-is-bee-approved.-Don't-forget-these.-Milk #cream #cheese #it's-all-me.--And-I-don't-see-a-nickel!-Sometimes-I-just-feel-like-a-piece-of-meat!-I-had-no-idea.-Barry #I'm-sorry.-Have-you-got-a-moment?-Would-you-excuse-me?-My-mosquito-associate-will-help-you.-Sorry-I'm-late.-He's-a-lawyer-too?-I-was-already-a-blood-sucking-parasite.-All-I-needed-was-a-briefcase.-Have-a-great-afternoon!-Barry #I-just-got-this-huge-tulip-order #and-I-can't-get-them-anywhere.-No-problem #Vannie.-Just-leave-it-to-me.-You're-a-lifesaver #Barry.-Can-I-help-who's-next?-All-right #scramble #jocks!-It's-time-to-fly.-Thank-you #Barry!-That-bee-is-living-my-life!-Let-it-go #Kenny.-When-will-this-nightmare-end?!-Let-it-all-go.-Beautiful-day-to-fly.-Sure-is.-Between-you-and-me #I-was-dying-to-get-out-of-that-office.-You-have-got-to-start-thinking-bee #my-friend.-Thinking-bee!-Me?-Hold-it.-Let's-just-stop-for-a-second.-Hold-it.-I'm-sorry.-I'm-sorry #everyone.-Can-we-stop-here?-I'm-not-making-a-major-life-decision-during-a-production-number!-All-right.-Take-ten #everybody.-Wrap-it-up #guys.-I-had-virtually-no-rehearsal-for-that.
  30. The “High and Dry Club”: the thread about 30 years of the Forth car ferries running aground again, and again (and again)

    This thread was originally written and published in April 2023.

    Talking about ferries running aground, you might think that kind of thing is unfortunate, so spare a thought for the brand new Firth of Forth car ferry Robert the Bruce which ran aground at South Queensferry on Saturday 24th March, after barely 3 weeks in service. The vessel was on its penultimate cross-Firth trip of the day and became stuck fast at South Queensferry at the Hawes pier. It was not until late on the Sunday that she was successfully refloated. “New Ferry Boat Stranded at South Queensferry” said the headline in the Scotsman.

    Valentine & Sons postcard of “Robert the Bruce” at North Queensferry

    Barely a week later, on April 5th, Robert the Bruce suffered the ignominy of grounding once more at South Queensferry, ending up sitting high and dry, perpendicular to the pier. “New Ferry Boat Grounded Again” said the headline in the Scotsman.

    Robert the Bruce aground at South Queensferry on April 5th 1934.

    The hapless vessel was aground again 3 weeks later. It took 5 hours to get the passengers off. To paraphrase Oscar Wilde, to run aground once in a month may be regarded as a misfortune; to run aground twice in a month looks like carelessness. Three months later? You’ve guessed it. “Robert the Bruce” was aground again. This was getting to be rather common and the local paper hardly gave it a second mention, devoting only a single sentence to the mishap.

    The ferry boat Robert the Bruce ran aground on Sunday, but was refloated at high tide without any apparent damage

    Linlithgowshire Gazette, 6th July 1934

    In all, in her first 4 months of service, Robert the Bruce would run aground four times. Her identical sister ship Queen Margaret managed to avoid this awkward habit entirely. For now…

    The Forth car ferries were the brainchild of, were built by and were operated by the William Denny & Brothers shipyard in Dumbarton. Sir Maurice Denny had crossed the Forth in the old vessel Dundee one day and had thought to himself that a purpose-built car ferry (or pair of ferries) could provide a much more efficient service. As a captain of industry he had only to pick up the phone to the London and North Eastern Railway to set the wheels in motion. The LNER paid for the ferries and leased them back to Denny, who operated them. This arrangement meant that even if the ferries poached traffic away from the railway, the railway would still profit from them.

    Robert the Bruce at North Queensferry, by-NC-ND, Ballast Trust.

    The design was innovative and Denny had high hopes it would catch on. The vessels had a large, open car deck, with small passenger cabins fore and aft. There were ramps on each side at each end for loading and unloading vehicles. The bridge sat high above the deck on a gantry in the middle of the ship to give a commanding view in all directions. Propulsion was by paddle wheels, an antiquated system on paper, but one which had certain advantages when manoeuvring at slow speed and which was brought up to date with each paddle being independently driven by an electric motor. This, coupled with rudders fore and aft, meant for superb manoeuvrability and the ability to change power and the direction of drive very rapidly. Diesel engines under the car deck drove the generators for the motors, and exhausted through a pair of slender funnels. This arrangement allowed the ferries complete roll-on, roll-off operation for rapid loading and unloading and the ability to move forwards or backwards at the same speed and no loss of handling.

    Perhaps in sympathy with and to share in Robert‘s blushes, the older companion Dundee decided to get in on the action and ran aground at South Queensferry in 1939. Again, her passengers and cars were stuck aboard for hours, the Evening News printing an atmospheric night time photo of her with the ghostly outline of one of the piers of the Forth Bridge behind her.

    Dundee aground at South Queensferry, 24/1/39, Edinburgh Evening News

    The Forth ferries survived WW2 without further incidence but on 18th August 1947, perhaps as a late celebration of victory, one of them ran aground again in the mud off South Queensferry. This time however it was the Queen Margaret at fault, and Robert the Bruce redeemed herself by towing her off the mud.

    https://www.flickr.com/photos/23666168@N04/37190198854

    In 1949, the ancient Dundee was replaced by a new vessel, the Mary Queen of Scots, identical to Robert and Margaret except that post-war economies meant that the electric drive system for the paddles was replaced with a hydraulic one. To welcome the new member to the team, Robert the Bruce decided to show off as only she knew how, and on April 3rd 1950 she ran aground. Again. At South Queenferry. Again. This incident was on account of the mooring rope that should have been thrown to the pier landing short combined with a sudden gust of wind that blew her onto the mud before the engines, idle at the time, could respond.

    Robert the Bruce aground at South Queensferry in the 1950s. Credit National World sales.

    Queen Margaret tried to repay the towing compliment from 1947 back and rescue her stricken sister however the tow rope broke and then the tide receded, making further rescue attempts on that tide impossible. Two hours service was wasted and Robert had to wait to be rescued on the next high tide.

    Friday May 23rd 1952. Guess what happened. Go on. I’ll give you one guess… Wrong! It was actually Mary Queen of Scots which grounded this time. Strictly speaking she didn’t run aground, as she found herself stuck when the tide receded while she was both loading vehicles and taking on oil, the additional weight incurred settling her on the mud beneath her keel. Attempts by Robert the Bruce to get her off the mud at South Queensferry proved fruitless and again they had to wait for a high tide to free her

    Mary Queen of Scots at North Queensferry, with Queen Margaret behind her. Via University of St. Andrews Collections, © J. A. Weir Estate

    Never one to be outdone by her sisters, two months later Robert the Bruce managed to run aground 50 yards short of the pier at South Queensferry. Queen Margaret came to the rescue and tower her off the mud before the tide left her high and dry after a 20 minute struggle. It was almost a year before one of the ferries ran aground again. This time it was Mary Queen of Scots: caught by the combination of a westerly wind and an autumn equinox tide “which tends to empty the river” on August 27th 1953. She was left high and dry in the middle of the Firth for an hour and a half until a change in the tide allowed her to come unstuck. This left the passengers of a bus trip sorely disappointed; they had crossed on one ferry while their vehicle followed on the next (Mary Queen of Scots) and got stuck mid-stream. By the time the bus made it over, he found his passengers had given up and headed home to Edinburgh by alternative means.

    In 1955, due to booming traffic, the three Forth ferries were joined by a fourth Forth ferry (try saying that in a hurry), when the slightly larger Sir William Wallace joined the fleet.

    The Fourth Forth Ferry, “Sir William Wallace”. c. 1960, from THELMA Donor number: 0186-013

    True to the established tradition, Robert the Bruce welcomed her by running aground! On March 12th 1955, in dense fog, she hit a mudbank some 500 yards short of the pier. This time it was an exceptional spring tide at fault. It took an hour and a half to free her.

    The following year, it as Queen Margaret’s turn again and on December 2nd 1956? she was stuck at South Queensferry once more. It would take a whole 3 years in service for Sir William Wallace to join the “High and Dry Club”, which she first managed in February 1958. Again it was at the South Queensferry end and she had 40 cars on board when she got stuck. The passengers were rowed ashore and either bussed to Edinburgh, or waited 5 hours in the Hawes Inn for their cars. One hopes that the refreshments provided were only teas and coffees. She repeated the act at the end of September that year, getting within 20 feet of the pier at South Queensferry and then grounding on the mud. 50 passengers were taken ashore in the lifeboats. She became stuck at 740AM and it was not until a high tide at noon that she floated free.

    Sir William Wallace aground at Hawes Pier in February 1958. Picture from The Sphere.

    Queen Margaret tried something new and rammed one of the piers of the Forth Bridge in February 1961 when the wind and tide conditions conspired against her and made controlled progress impossible. There was one last grounding hurrah for the Forth ferries, when this same vessel took to the Hawes Pier mud for 1 and a ¼ hours on the appropriate date of Friday 13th October 1961. It took the combined efforts of Sir William Wallace and Mary Queen of Scots to free her.

    In the final decade of the ferries on the Forth, Sir William Wallace added an additional dimension to the difficulties of running the service; she was bigger than her sisters but had the same engines and same sized loading ramps, so was slower and took longer to load and unload. This made her a logistical pain in the bum for keeping to schedule and her smaller sisters frequently had to slow down when crossing against a tide or current to let her catch up. Her car deck was also slightly differently arranged and her master found out the hard way that if he packed them on tightly the same way as the other ships, then they became wedge in, couldn’t get onto the ramp and thus couldn’t get back off again! The solution was simple but inelegant – the ship sailed around to the other side of the pier and all the cars reversed off instead.

    Sir William Wallace – not aground – at Hawes Pier in South Queensferry. Date unknown, credit unknown.

    The owner-operators of the ferries went into liquidation in August 1963 and so the liquidators continued to run the service for a further 13 months until September 3th 1964 when the last sailed before the Forth Road Bridge was opened. Guests of honour on the last scheduled voyage were HM The Queen and HRH Prince Philip. Queen Margaret had clearly no sense of occasion and humour and refused to run aground with the royal party aboard.

    Last Ferry across the Forth. West Lothian Courier – Friday 11 September 1964

    As a postscript, I should note that nobody was harmed in any of these groundings, beyond the feelings of the ships’ masters. In actual fact, considering the intense scheduling of the route over 30 years hard work, in tricky waters, they actually had a pretty enviable safety record. In the late 1950s, all four ships ran an all-day service at 15 minute intervals, making 40,000 crossings a year, carrying 1,250,000 passengers, 600,000 cars and 200,000 commercial vehicles.

    The Forth ferries were laid up at Burntisland after the end of their working lives and the three oldest ones were unceremoniously scrapped. The press were far more interested in the new Road Bridge to be interested in three old ships. The newest and largest, Sir William Wallace, spent a few years service at Islemeer in the Netherlands before being scrapped too in 1970. After 30 years of car ferry service, the scores on the doors for running aground were:

    1. King Robert the Bruce, 7 times
    2. Queen Margaret, 3 times
    3. Joint, Sir William Wallace and Mary Queen of Scots, 2 times each
    4. Dundee, 1 time

    Note to readers: unfortunately in April 2026, a third-party plug-in more than exceeded its authority and broke many of the image links on this site. No images were lost but I will have to restore them page-by-page, which may take some time. In the meantime please bear with me while I go about rectifying this issue.

    If you have found this site useful, informative or amusing then you can help contribute towards its running costs by supporting me on ko-fi. This includes my commitment to keeping it 100% advert and AI free for all time coming, and in helping to find further unusual stories to bring you by acquiring books and paying for research.
    Or please do just share this post on social media or amongst friends and like-minded people, sites like this thrive on being shared.

    Explore Threadinburgh by map:

    Travelers' Map is loading...
    If you see this after your page is loaded completely, leafletJS files are missing.

    These threads © 2017-2026, Andy Arthur.

    NO AI TRAINING: Any use of the contents of this website to “train” generative artificial intelligence (AI) technologies to generate text is expressly prohibited. The author reserves all rights to license uses of this work for generative AI training and development of machine learning language models.

    #Lochend #Logan #Restalrig #StMargaret