My company organizes a big event once per year. Around ~600 attendees. There are five simultaneous tracks for keynotes; Product, Project management, Design, Dev, Devops... It's the main event of the season for us.
You get the idea.
This year i decided to present a tech talk. 45 min long. The complete thing: slides & live coding.
I named it: «React in the Terminal? Hold my beer 🍺»
While the slides are in English, i'm afraid the talk itself was in my mother language (🇪🇸) and i won't share the recording.
However, here are the resources I used for the talk:
The slides: up & running hosted at Vercel; I used SliDev, a framework that turns markdown into a web app which behaves like a Keynote. It's pretty cool.
I genuinely think SliDev deserves its own post someday 🤔.my-react-dom: Repository with a custom implementation of
react-domused to live coding. Two branches:playgroundandmainink-world: Repository for a tiny-tiny-tiny game using Ink + React on the terminal again, used to live coding. Two branches:
playgroundandmain.
Talk Recap
I led a quick journey, starting with the simplest «Hello World» in React...
...But unrolling the jsx syntax, making more obvious where we're invoking react and where we are calling react-dom
This led us to the question: why are react and react-dom separated into two different packages? 
We discussed the philosophy that React embraces; they mention "interfaces" and how React is designed to plug into any interface.
Next step: react-reconciler: the package the React team provides to create your custom renderer.
Time to live coding session (my-react-dom)
This is the goal: replace the ReactDOM object with one of our own and keeping the Counter APP running.
import React from 'react';
-import ReactDOM from 'react-dom';
+import ReactDOM from './my-custom-react-dom';
import './styles.css';
✨ Ah! and that's also deployed at Vercel: https://my-react-hvpqtmgva-manu-artero.vercel.app/
If you open de dev tools, you may check the console:
At this point, I took a small leap: while implementing a tiny react-dom is one thing, crafting the plugin for the terminal is a different tale. 
So i introduced the solution by Vadim Demedes: Ink.
Ink is a React renderer for the terminal.
I did prepare a playground (check the playground branch) with just 2 dependencies: ink and react
You can check the final code at GitHub. Anyway, in a nutshell:
...
function useWorld({ onGameOver, onGameWin }) {
  const [world, setWorld] = useState([
    "tree",
    "character",
    "tree",
    "tree",
    "tree",
    "enemy",
  ]);
  useEffect(() => {
     ...
      if (random > 0.5) {
        return moveEnemyRight();
      }
      if (random < 0.5) {
        return moveEnemyLeft();
      }
    }
  });
  const moveEnemyRight = () => {
    setWorld((currentWorld) => {
      ... bla bla
    });
  };
  const moveEnemyLeft = () => {
    setWorld((currentWorld) => {
      ... bla bla
    });
  };
  const moveCharacterRight = () => ...
  const moveCharacterLeft = () => ...
  return { world, moveCharacterRight, moveCharacterLeft };
}
function App() {
  const { exit } = useApp();
  const { world, moveCharacterRight, moveCharacterLeft } = useWorld({...});
  useInput((input, key) => {
    if (input === "q") {
      exit();
    }
    if (key.leftArrow) {
      setDisplayText("<-");
      return moveCharacterLeft();
    }
    if (key.rightArrow) {
      setDisplayText("->");
      return moveCharacterRight();
    }
  });
  return (
    <>
      <Ground>
        {world.map((type, i) => (
          <WorldElement key={`${type}-${i}`} type={type} />
        ))}
      </Ground>
      <Text>{displayText}</Text>
    </>
  );
}
...
render(<App />);
Resulting in this little fella:
Honestly, it was a tremendous success; many people congratulated me.
thanks for reading 💛.
              




    
Top comments (2)
How the hell can you render that? And what the hell is going on? 😂
That is awesome. I would not have completed a sentence
React in...with wordterminal. This is 🤯