HNHacker News
TopNewBestAskShowJobs

nohuhu

20 karma · joined January 9, 2020

submissionscomments
nohuhu··on Show HN: Grid.js – Advanced table library that works everywhere
> The better ones are often tied to company-specific frameworks.

That is because to implement accessibility in a grid/tree widget to a meaningful level, you need a lot of underlying code. Even in modern browsers. Source: implemented accessibility in Ext JS framework.

One of the most often asked questions from users of Ext JS was: hey, can we have the Grid widget without all the bloat? Sure, and ~95% of the framework exists so that the Grid can have its features and work reliably across all the browsers. You can probably do without the rest 5%, no biggie.

nohuhu··on Recoil – A state management library for React
> Redux is fantastic and it's quite a simple library.

... and it's an extra library. You can do without it in React, you know.

> The rest is what gets you into trouble.

Exactly. My biggest beef with Redux (and React, too) has always been that it makes much pomp about things that are relatively easy to solve, like state computation (or rendering). The actually hard things are left unsolved to a various degree, and that is what devs struggle with the most. Things like: how do I take the business logic best expressed in imperative statements (get foo, if it equals to bar, do that, if not, do something else), and express it in React component state transitions, with loading state indication, error handling, and conditional branching?

The most contrived React code I've ever seen was dealing exactly with that: fitting a finite state machine into a React component, which Redux is essentially zero help with. Why do I need Redux if it doesn't solve the hard problems for me?

> Hardly anybody has a problem with redux until they have to deal with async actions

Srsly? So tons of boilerplate, action at a distance as a blessed pattern, reliance on globals, contrived testing, and perf issues are not problems at all?

> the correct way to handle that stuff is to write middlware.

There are as many correct ways to handle that stuff as there are developers. Some ways are just easier to read and follow (also to test, maintain, etc etc).

> By real messaging I mean CQRS with event mapping/filtering/normalization.

Thanks for the explanation. You forgot to answer the second part of my question, which is: why this is important for a front end application. Again no sarcasm, just genuine interest.

nohuhu··on Build Software from Front-to-Back
> it's the only way to go to build products.

This! Back-to-front is a good way to build a scalable, performant, cleanly designed software. Front-to-back is the only viable way to build a usable product.

> Users just do not care what kind of horrible kludge is running behind the slick UI.

For 99.9(9)% of users, the UI is the product. Even those who do know what "back end" means, do not care.

nohuhu··on Recoil – A state management library for React
> If that works with your model of the world that's great. Wouldn't kick it out of bed for farting.

Oh I see, entity naming could also be improved. ;)

> For me, the easiest way to handle async and effects in Redux is to write custom middleware for each context/entity.

Right, and you still have to deal with Redux to get there. Not a preferred choice for many people.

> have a real message based architecture

What is a real message based architecture, in your terms? And why is it so important? Genuine question.

> without hacks and (extra) libraries.

Extra libraries only if you base on Redux and go from there. It's almost as if Redux itself wasn't an extra library...

nohuhu··on Recoil – A state management library for React
One viable alternative for thunks and sagas that I came up with is using async functions and explicitly getting/setting state: https://github.com/riptano/statium#viewcontroller

Still a long list of chores to improve API, tooling, etc but very performant and battle tested.

nohuhu··on Hand Scraping a Truly Flat Plane (1908) [pdf]
> I could see a barn find in bad shape suffering a lot more than that.

Yeah well, in between being a bottom feeder and looking for fun, machines usually come to me as project pieces rather than usable tools. :) I'd never opted to restore any of these rust buckets if I'd depend on them to do woodworking for a living; that said, the purpose of a hobby is to occupy my mind and give me a challenge that is rarely encountered in my day job anymore. So, the rustier, the better. :)

> I've somehow become a Delta man for the stationary tools, probably because of the ubiquity of their old stuff.

I can definitely relate to that, W-T makes a minority of my resto projects. Most of them are Delta as well, as I'm looking to build myself a fully equipped vintage woodworking shop. I'm almost there in fact, as several projects are nearing the assembly stage: a '64 Unisaw, a '52 HD Shaper (going in tandem with the Unisaw), a '54 14" bandsaw, a '60 combo sander, a mid-50s LD shaper, and a '42 6" jointer that I got for free in a total rust-bucket condition. That one was a challenge in itself, especially the motor.

It's just Walker-Turner machines are so beautiful, they're special. Next up after the lathe is a 1939 16" bandsaw, the final quest machine that I acquired last fall. I'll have to fight scope creep real hard on that one...

> My 14" band saw is (I think) pre-war, but the original buyer didn't spring for the cast art-deco base :-(

Ye shall seek and ye shall find, if you want to. :) Besides trawling your local Craigslist (that's where I find my projects), sign up on http://www.owwm.org and post an ad in BOYD forum. Cast iron bases do come up for sale somewhat regularly. Beware that even looking at that website is very dangerous, slippery slope ahoy. ;)

> Do you have pictures or a build thread on this project? I'd love to see it.

I don't usually take pics of the resto projects... I guess I'm just lazy. If you're into vintage tool porn, check out the OWWM community I linked above, and its sister site http://vintagemachinery.org. Lots of drool inducing pics there, I really cannot add anything that hasn't been done already. :)

> The paint job is not what anybody would call flawless, but at least it isn't coming off :-D

That's usually enough for many cases... If a machine doesn't have a sentimental value, why, just refurbing it to acceptable mechanical condition is par for the course. That's what I did with my current set of machines; no offense to Grizzly but their utilitarian cabinet saw aestetics do not really justify the amount of work that goes into stripping and repainting. A vintage Unisaw, on the other hand... I had to learn how to do cabinet scale electrolysis derusting, some basic metalworking, spray painting techniques, not to mention mechanical and electrical challenges. Heaps of fun! :)

Checked out your website... Wow. I have a long, long way ahead to that kind of woodworking projects. ;)

nohuhu··on Hand Scraping a Truly Flat Plane (1908) [pdf]
I haven't gotten to measuring wear on the ways yet, don't think I'll need to scrape them but that's a possibility. This is a pet project of mine, a barn find that was in a pretty bad shape when I got it: rusty, crusty, with missing parts and undesirable modifications by previous owners. Specifically the ways are pitted from rust; worse in places that were exposed to the elements. I'll have to try and measure the effect of this pitting on tailstock positioning. I don't think banjo positioning is going to be affected, the ways are not that bad. But then there's always the obsession with perfection, so who knows. :)

I have a soft spot for pre-1950 Walker-Turner machinery, their aestetics are off the charts; I'm trying to restore this lathe to its former glory, or even better. Not quite a classic car showroom condition but as close to it as I can get without spending a fortune in time and money. :)

The current stage is painting; turned out it's pretty tricky to spray glossy enamel so it would level out smooth! Especially in our cool and humid coastal climate, paint takes a while to dry and even longer to fully cure so the process is quite challenging. Not to mention the countless hours it took to grind out casting imperfections, apply bondo filler, sand it, etc etc.

I thought I was getting into woodworking but found that restoring machinery is lots of fun in its own right, and nothing compares to the satisfaction of using a well made and beautifully restored vintage tool. Especially when I'm the one who did the restoration. :)

nohuhu··on Hand Scraping a Truly Flat Plane (1908) [pdf]
Thanks for submission, a really interesting read! I'm into restoring old woodworking machinery, and hand scraping is one of the methods for truing lathe ways that I've read about. Could possibly be required for the Walker-Turner lathe I'm working on. :)
nohuhu··on How porting to TypeScript solved our API woes
A framework is usually the foundational code for an app, for sure. In this case it was a bona fide JavaScript framework, Ext JS.

It is that big because it implements a lot of things that other frameworks don't even try to try thinking about, things mostly used to build very boring line of business applications (think thousands of forms, huge grids, reports with charts, etc). Applications built with Ext JS can easily dwarf the framework itself; the biggest I've seen personally was ~30 mb of minified ES5 JavaScript.

...and it worked in IE8, BTW. :)

nohuhu··on How porting to TypeScript solved our API woes
> You still keep it all in your head, but the compiler errors protect you from small mistakes.

It is interesting how "protecting from small mistakes" is touted as "solving our API woes", innit?

At some point it is liberating to admit that static vs dynamic is a matter of personal preference and nothing more. If I like it, I will find a thousand reasons to justify it, and vice versa.

I just wish everybody would be open about it: I like "type safety" and the warm fuzzy feeling it gives me, and nothing you unwashed heathens can say about tight coupling, increased incidental complexity, over-engineered APIs and productivity loss can sway my opinion! Why, my productivity is _increased_ with static typing, because I make up for hours of bikeshedding about which type better conveys the underlying intent with writing less null checks and unit tests! Take that, type haters!

Meh, wishful thinking.

nohuhu··on How porting to TypeScript solved our API woes
> I'm sure that class of bugs is relevant for Typescript programmers, because they never develop the skills to not implement those bugs in the first place.

This rings true, especially given that in my experience, most of the static typed people either never worked with dynamic languages at all, or converted from dynamic to static. Most of the dynamic minded people I know actually converted _from_ static typing after doing that for years (myself included).

The calculus is pretty simple IMO: if one has mental discipline to work with a dynamic weakly typed language, not having to mess with types and compilers is downright liberating: ye godz, just gimme that data! On the other hand the people who never experienced conditions leading to developing said mental discipline tend to abhor the idea of not having the "type safety" (cute marketing, that). Hence the chasm between Lisp crowd and Haskell mob, with JavaScript being the perpetual battleground somewhere in between.

nohuhu··on How porting to TypeScript solved our API woes
Ext JS is the framework in question. The last time I worked on it (Oct 2018), it was about that size shared between two major versions: Classic toolkit and Modern toolkit, including tests and examples. It could be more than that now but I haven't touched it since.

I used to do a lot of things on it, including _very_ deep refactorings with sweeping changes across the codebase. The secret sauce is focus on automated testing: when I left the company, we had ~70,000 test specs for the framework, and the test suite was executed on each commit to every PR pushed to Github. Depending on framework version (there were several in flight), and browser matrix (15+ supported browsers), each test run yielded 500,000-700,000 spec results (and finished in under 20 minutes).

There was a lot of custom tooling around this, of course. Including a test runner that I got open sourced right before leaving the company: https://github.com/sencha/jazzman. Sadly it looks like there were no new commits since I left; I hoped to pick it up later but so far I haven't encountered the need to run significantly sized test suites in massively parallel fashion. Nobody writes that many tests. :)

EDIT: I almost forgot that as a condition for open-sourcing the test runner they made me write a blog post about it: https://www.sencha.com/blog/ext-js-testing-story-under-the-h... :)

nohuhu··on How porting to TypeScript solved our API woes
> Funny, I usually see type haters claiming that they don't actually make the kinds of mistakes that are fixed by strong typing.

As your typical type hater, my preferred argument is: yes, static typing prevents a certain class of bugs from happening; no, this class of bugs is not nearly as relevant as type lovers seem to be claiming. By an order of magnitude if not more.

Source: 6 years of being a core developer of a front end framework consisting of 1,500,000 lines of ES5 JavaScript and SASS.

nohuhu··on Ask HN: What is your blog and why should I read it?
Not my blog but I find it fascinating: https://technicshistory.com

Really surprised nobody mentioned it yet...

nohuhu··on Miracles You’ll See in the Next Fifty Years (1950)
When people ask me what my wife does for a living, I tell them she's working as a full time mom to our 4 kids. She likes that a lot more than being a "housewife". :)
nohuhu··on Elon Musk’s plan to build one Starship a week and settle Mars
This makes total sense to me. If you can solve the hardest problems, it is reasonable to expect that you can solve the rest as well. If you fail at solving the hardest problems, the system will not work anyway.

The science, then, lies in identifying the hardest problems. The art lies in identifying people who can solve these problems.

nohuhu··on Elon Musk’s plan to build one Starship a week and settle Mars
So I guess this is how living in the 1960s felt like? :)
nohuhu··on Persisting React State in LocalStorage
> I'm not familiar with either of them, but that seems like a lot more code!

Sorry, I should have been more forthcoming with explanations but got paged at $work. Almost nobody is familiar with Statium yet, it's very new. :) It was developed for cloud applications UI here at DataStax.

Statium implements a very simple key/value storage in a React component called ViewModel. It is using `setState()` internally, so all the usual React rendering logic applies unchanged. Each ViewModel has access to keys of its ancestors, all the way up the chain. There is no global store but a chain of stores instead, which helps to keep state local to consumer components that use it.

Urlito is just a simple library for persisting state to and from URI, currently using query params. This is intended for local component state like selected tab, sort order in a table, or a list of expanded rows in a tree grid, the sort of things that do not deserve full blown URI routing pattern matching. We still use `react-router-dom` for that.

> How does changing the URL trigger a state change? Does the whole page need to reload?

No, it's the usual React logic: when ViewModel renders it will call the function provided in `initialState` prop, which in turn will read the current state of the model from URI query string. Whenever ViewModel state changes, `observeStateChange` function is called, and updates URI to reflect the current model state.

Urlito implements the functions for reading keys/values from URI and writing them back to URI, with support for default values and key filtering.

> In my system, my "Reader" knows this object so it can just call the regular setState (I also have some mount/umount logic there to avoid leaking memory). This makes back/forward transitions very snappy!

Almost the same solution in Statium, except that we have a full blown class based React component to hold the state, and hooks are not used internally (there is a hook based consumer API). The main reason for not using hooks for us is that the values held in `useState` are hard to propagate down the component tree, and hard to test. ViewModel takes care of this easily, with each key available anywhere downstream, e.g. a Component somewhere deep can retrieve the value of the topmost ViewModel without having to access it directly. This helps mightily with testing too: just wrap your tested components with a ViewModel and pass whatever you want to it (including state changes).

No memory leak issues at all, since a ViewModel is simply a React component that outsources `this.setState` for consumer components. :)

Transitions are very snappy with Statium, too. In fact, state updates are lighting fast: value updater function will walk up the ViewModel tree, find the closest owner and set the value in it using `setState`. This will cause the owner ViewModel and its children to re-render, but the render will be automatically scoped to the least amount of components. Since the state is usually localized, the problem of updating the whole app state on a keypress does not apply by default.

> I can also use the same logic for my Server (another "Persistor" [sic]) which indeed uses POST for submitting updates, but responses come down a shared SSE stream (which I need anyway so that users can see eachothers changes in real-time).

Asynchronous logic is hard to handle in synchronous React rendering paradigm... That was the reason for me to come up with a ViewController concept (https://github.com/riptano/statium#viewcontroller), which is the other part of Statium. The idea is to write business logic in a more imperative style, statements not functions:

    const loadUserPosts = async ({ $get, $set }) => {
        let [user, posts, comments] = $get('user', 'posts', 'comments');
    
        if (!posts) {
            await $set({ loading: true });
        
            posts = await loadPosts(user);
        
            await $set({ loading: false, posts });
        }
    
        if (!comments) {
            await $set({ loading: true });
        
            comments = await loadComments(user, posts);
        
            await $set({ loading: false, comments });
        }
    };
Decyphering this: $get is a function that returns ViewModel state values by keys, and $set allows updating these values. This is a matter of personal preference of course, but I think this approach makes the logic much easier to read and understand than Redux thunks or sagas.

There's also the RealWorld example app I came up with for React + Statium, check it out: https://github.com/nohuhu/react-statium-realworld-example-ap.... It's not yet submitted to the official list because I'm stuck trying to come up with a sensible logo for it... :)

nohuhu··on Persisting React State in LocalStorage
This is what Statium and Urlito are for:

    import ViewModel from 'statium';
    import stateToUri from 'urlito';

    const defaultState = {
        foo: 'bar',
        qux: {
            time: Date.now(),
        },
    };

    const [getStateFromUri, setStateToUri] = stateToUri(defaultState, [
        'foo',
        {
            key: 'qux.time',
            uriKey: 'time',
            fromUri: time => parseInt(time, 10),
            toUri: time => String(time),
        },
    });

    const Component = () => (
        <ViewModel initialState={getStateFromUri}
            observeStateChange={setStateToUri}>

            {/* ... */}
        </ViewModel>
    );
nohuhu··on Things I wish I knew about state management when I started writing React apps
No generation gap here. I was building my first web apps in early 2000s as well, with Apache and mod_perl. That was exactly the point of that experiment: hey I recall this stuff was _easy_, I don't need it fancy, let's take the modernest server side framework and go for it.

No thanks, not gonna do that ever again. Rosy glasses are rosy, and cleanly separated client side app + back end API is clean and separated.

nohuhu··on Things I wish I knew about state management when I started writing React apps
Everybody is different. You might be more productive at doing stuff the "Rails way", somebody else might not be. I know I won't be, simply because I don't know Ruby and/or Rails enough to be productive in it.

Not every organization can use this approach either. E.g. I work at a True Java Shop(tm), where voicing the idea of using Ruby for a back end service would get me laughed out of the room with a permanent label of That Funny Guy Who Likes Toy Languages.

Using React for a front end client application that consumes back end API built in Java is 10x more productive than doing the traditional "Java Way" application with server-rendered HTML.

nohuhu··on Things I wish I knew about state management when I started writing React apps
How does that play with Redux Hooks for example? https://react-redux.js.org/next/api/hooks

If you are using hooks in your components, you need the global store instance. To call this unit testing is too big a stretch for me.

nohuhu··on Things I wish I knew about state management when I started writing React apps
> The ~100ms between submitting a form and getting error messages isn't that big of a hurdle, in my experience.

The issue here is not the length of time it takes for the response to come back, rather the fact that there is any delay at all. Client side validation code can be synchronous, submitting any validation info to the server makes it asynchronous by definition. State synchronization between client and server is a big enough problem as is, there is no need to add to it.

Consider this scenario: you have typed an email into a field, tabbed to the next field and realized that you made a typo. Our client sent a validation request to the server, and meanwhile you shift-tabbed back and corrected the typo. The server response came back with invalid indication for the already outdated state, what do you do?

This kind of issue is happening in real life a lot more often than you might think.

> HTML5 has validation attributes for forms, which can handle every one of your examples.

There is no input type for credit card number but there is a very basic and easy to implement algorithm that checks the credit card number validity. This alone is worth implementing client side validation, if your application has to handle payments in any form.

> Negative. You can do an ajax call, and re-render part of the page (e.g., the entire <body> pjax-style). This is fast, doesn't cause the "flash" of a page reload, and doesn't require more than a few lines of js to setup.

Double negative. Re-rendering part of the page received via Ajax call obliterates the current state of that page, or worse yet, a part of the page. User started typing and the page reloaded, all their input - and even which field was focused - is lost. This is a very undesirable user experience.

> Again, turbolinks on pjax has solved this problem very well. Just re-draw the bulk of the page. All the simplicity of reloading the page with none of the user pains of actually reloading the page.

It's actually vice versa: all of the pain of actually reloading the page with no real benefit whatsoever. If you are going to reload the bulk of the page, might as well reload the whole page, just to have consistent state. But that brings us to square one: why having all this complexity in the first place? Because we want user interaction to be smooth, quick, and painless. This implies eliminating roundtrip delay, however small it is.

100 milliseconds might not be much but it can easily turn into 10 seconds if the server is overloaded. 10 seconds delay after submitting a _validated_ form to complete sales transation and display a success message is not a big deal, the user has already made a decision and now they're going to see the positive result. Your site is slow == that's ok, I made the purchase anyway.

10 seconds delay to validate form values and display an error message would most probably result in a lost sale. Your site is slow == it's bad, I won't spend my money here.

It's as simple as that.

> I agree. But I don't agree React _benefits_ developer productivity. On the contrary, I think it (and its competitor frameworks) are responsible for a lot of wasted developer time and frustration.

That's a highly subjective assessment. Do you have a way to measure productivity gains or losses? I don't either, just some anecdata.

About a year ago I needed to build an app for my ongoing personal (at some point to be commercial) project. Think a simple portal for adding, editing, and deleting entities. I decided that since it was internal use only, I can ditch the fancieties and do a quick and dirty old style app: server side logic, form submissions, full page reloads, etc. Back to 1999.

I spent a month of evenings trying to get it done, and didn't get halfway before ditching the effort and rewriting it as simple front end single page app + simple back end that exposed stateless API for the client to consume. That took me 2 weeks worth of evenings.

Lesson learned: never again, there's just too much mess with server side HTML templating, state propagation between page loads, form validation, etc etc. I don't even want to think about partial updates that _still_ involve server side HTML templating but combine that with a double dose of state propagation and synchronization. I didn't even get to writing any tests for that server side, simply because abstracting templating code from actual logic code was painful.

It can be argued that I did not use the best server side framework, did not know what I was doing, etc. That's actually my point: if doing old style web apps was so much easier, I should have been able to complete it fast without much sweat, no?

nohuhu··on Things I wish I knew about state management when I started writing React apps
> Clicking "save" and getting that feedback in ~100ms is not, in my estimation, worth the massive extra overhead of using a front-end framework, duplicating your validation requirements, etc.

Is it worth spending more developer time (think $$) on optimizing things for imaginary savings on initial page load time?

> Right.. But so is just re-loading (most of) the page from the server. Again, e.g., Phoenix Live View or Action Cable style.

How is that less complex than a client side application? You are essentially advocating for splitting the logic between server and client side. Of course that is possible and people do that all the time for various reasons. Does not mean that's the best way of doing things.

I think you are missing the elephant in the room. Emergence of the front end development frameworks like React was caused by ever increasing complexity of the front end applications. Which, in turn, is driven by customer demand. Customers pay for features, not for code quality, and churning out features is much easier and quicker using React vs. e.g. jQuery.

Lamenting front end application overhead is the same as lamenting using high level languages for back end services. Everybody knows that Real Programmers wrote Real Programs in assembler back in the olden days!

nohuhu··on Things I wish I knew about state management when I started writing React apps
> The server still needs to validate, no?

Client input should never be trusted. Server needs to validate, but that doesn't mean client shouldn't validate as well.

> I've never seen a form that really benefitted from client-side validation. As long as required fields are clearly marked, I don't really understand the value here.

Client side validation is not only about required fields, it's much more than that. Have you ever used a web store where you need to enter your shipping address, credit card info, etc? Address, zip code (or worse, UK style postal code), phone number, email, credit card number - all that needs to be validated.

Sure the server can (and should) validate that. The problem then is how to let the user know they've made a mistake and how to fix it. Accessibility issues aside, users need to be told that they've made a mistake as soon as it is made, otherwise there is a chance they won't find the error message, and simply give up trying. Lost sales is the reason client side validation was invented.

> Hmm? What about them needs React?

If you don't want to submit a form with full page reload, you need to make an Ajax call with form info. When response comes back with a list of errors, you need to walk through the fields on the page and mark the relevant ones as invalid, with corresponding error messages displayed _close_ to the input fields. Of course that is doable in plain JavaScript, and doing that seems trivial for one form. Then you have to duplicate that code for another form, or abstract it in a library... Congrats, you're on your way to reinventing React. Or worse yet, Angular.

> You can poll very cheaply. And even Websockets are pretty simple.

When the results of that poll come back, you need a way to display them. You need to decide which part goes where, which elements to hide and which to create, etc. The mechanics of this is what React (or a similar library) does for you, so that you could concentrate on writing logic instead.

> We're talking about React being overkill in a lot of places.

React might be overkill in a lot of places, but it's extremely hard to tell where and when. If you start with a simple hand rolled JavaScript app, at some point you might realize that maintaining it is a chore beyond one person's capacity, and hiring someone to do that for you is plainly impossible. You should have started with (React|Angular|Vue|whatever) in the first place, and now it's a choice between ground up rewrite in (React|Angular|Vue|whatever), or long stagnation and eventual death of your business. Do you want to take that chance?

Optimizing for developer productivity is the only safe bet in the majority of cases, unless we're talking about a personal project with no commercial value.

nohuhu··on Things I wish I knew about state management when I started writing React apps
How do you test individual components in isolation if they depend on the global state store?
nohuhu··on Things I wish I knew about state management when I started writing React apps
Another way of doing controller stuff is by actually using a Controller: https://github.com/riptano/statium#viewcontroller. Example: https://github.com/nohuhu/react-statium-realworld-example-ap...

Logic flow doesn't have to be hard to do.

nohuhu··on Things I wish I knew about state management when I started writing React apps
Check out Statium: https://github.com/riptano/statium, and the RealWorld example that I threw together in a couple of evenings: https://github.com/nohuhu/react-statium-realworld-example-ap.... The basic idea is to have state kept in a separate component that deals just with state, a ViewModel. Internally it works just the same as usual React components: by calling `this.setState()`; externally it exposes API for getting key values and setter functions, same as hooks do.

It's really easy to work with, and the concept of hierarchical state store is something that I haven't seen in any other library. If there was I probably wouldn't end up writing Statium in the first place. :)

nohuhu··on A Simplified Jira Clone Built with React/Babel and Node/TypeScript
(shameless plug!)

... or you can use something like Statium's ViewModel, which is basically a hierarchically linked, locally scoped state container component: https://github.com/riptano/statium

RealWorld example: https://github.com/nohuhu/react-statium-realworld-example-ap...

Sorry... Just... Couldn't... :)

nohuhu··on A Simplified Jira Clone Built with React/Babel and Node/TypeScript
IMO this "Jira clone" is way beyond the middle ground, it's way too complex for that. Might be a lot closer to a product than you think. ;)

For technology showcases the RealWorld example is pretty popular: https://github.com/gothinkster/realworld. Showcasing your tech prowess is quite a bit different, I get that.

Kudos for readable hook-based code. :)