On Moving NarraFirma from Dojo and JavaScript to Mithril and TypeScript

tl; dr We changed underlying technologies to make NarraFirma easier to maintain. For context, this document first describes a little about NarraFirma itself.

What does NarraFirma do?

In a nutshell, NarraFirma helps people gather stories from a community or organization and make sense of them to inform and improve collective decision making. The software supports project planning, story collection, data analysis, facilitation of group sessions, and recording of project results. More information about NarraFirma can be found on the main NarraFirma site, a Knight News Challenge entry on "How might we make data work for individuals and communities?", and an announcement on my wife’s blog.

My wife (Cynthia Kurtz) did most of the high-level application GUI design for NarraFirma based on the step-by-step process outlined in her book (and based on nine previous pieces of related software, some of which I helped her implement). I designed NarraFirma’s supporting architecture and did most of the implementation.

Here is a video overview of all the major functionality if you want to see what is possible in a single-page Mithril webapp using D3:

Where did the NarraFirma idea come from?

The NarraFirma application’s requirements were mostly based on my wife’s (Cynthia Kurtz’s) Creative-Commons-licensed 700-page textbook, Working With Stories in your Community or Organization: Participatory Narrative Inquiry. NarraFirma is about the tenth tool Cynthia has designed to support participatory story work. NarraFirma would likely not have been possible without Cynthia first spending several years to create the latest edition of her textbook, since NarraFirma closely follows the methodology she outlines there.

How does NarraFirma fit into a bigger landscape of “competitors”?

NarraFirma covers a lot of ground in about forty virtual pages (as a “single-page” webapp) to lead people through the “Participative Narrative Inquiry” (PNI) process — which is not surprising given it takes a 700 page textbook to explain the PNI process. And NarraFirma still does not directly support everything involved in the PNI process. NarraFirma supports planning sensemaking workshops and recording the results, but it does not support what goes on in the workshops. NarraFirma could eventually having online versions of all the dozens of different sensemaking exercises or methods that are done in face-to-face workshops. The clustering diagram part of NarraFirma is just the beginning of such tools, as a proof-of-concept in that direction (and one that we’d be the first to say could be improved further).

However, as much as we’d say PNI is a great tool, PNI is just one approach to sensemaking out of dozens that Cynthia has learned about that. Looking at sensemaking broadly, these approaches range from the very old (e.g. the Chinese I Ching, the Native American Medicine Wheel, and the Italian Tarot, to name a few) to the modern (Structured Dialog Design, Appreciative Inquiry, Cognitive Edge’s Cynefin process, PNI, IBIS, Compendium, and many more). Cynthia has plans for a book and/or wiki covering all of them someday. Even Bucky Fuller’s “Comprehensive Anticipatory Design Science” concept is a form of sensemaking about “livingry” to some extent. The fields of legal arbitration, mediation, and even just conventional jury trials also include sensemaking processes of a sort. Likewise, legislative processes including public town hall meetings also include sensemaking processes (often ad-hoc ones).

We feel PNI works well for a range of situations, but there are plenty of cultural, practical, and domain-specific reasons to consider other alternatives for sensemaking. These different approaches to sensemaking could be seen as a bit like different architectural styles or different musical styles. People may prefer different styles of architecture or music for all sorts of reasons. As great as, say, much country-western music is, and even as no doubt some people listen to that almost exclusively, we would all be poorer if country-western was the only kind of music around. Likewise our built landscape would be a lot less visually interesting if everything was Greek Revival style. Likewise, a claw hammer can be a useful thing to have in a toolbox for a variety of task, but other types of hammers may be easier to sue and produce better results for other task — as are other tools of completely different types like screwdrivers, tape measures, and saws.

Why did NarraFirma take over a year to finish?

We originally thought the project would take a few months, after which I intended to apply for a regular job (as I did after previous labor-of-love free software projects). However, implementing the NarraFirma software took a lot longer than we expected. These are some of the reasons.

Some of the extra time came from rewriting the GUI a couple of times, first with the Dojo Toolkit and then with Mithril, to make it more maintainable (especially in the long term) by my wife, who has less programming skill than I do, but is still an experienced programmer on her own. Mithril is similar to React, but sleeker, and it does not have the Facebook patent license gotcha.

Some of the delay was from trying several different approaches to the data storage back end. (I’d still like another go at that someday to simplify it further, but as Jeff Atwood says, “tending your software garden” is never finished. At some point you need to ship what you produce).

Some time was spent converting much of the code base from JavaScript to TypeScript when the complexity of 100+ source files became hard to manage in pure JavaScript.

Some time was spent on reading (and experiments) to improve my understanding of other web technologies and their strengths and weaknesses in different situations. That’s how I ended up choosing Mithril over other possibilities such as Angular, Ember, Backbone, and even the excellent React.

Adding statistical results was more time consuming than I expected, as (surprisingly) there are not yet any complete statistical libraries for JavaScript (similar to Apache Commons Math or SciPy).

Some time was spent trying the Dojo loader and packaging approach and ultimately moving to requirejs and its packager.

Finally, of course, the project requirements my wife outlined grew as time went on, and one NarraFirma feature led to another and another — sometimes requiring substantial architectural changes. For example, we decided that we needed to support (limited) multi-user editing using periodic polling for fine-grained changes.

In other words, NarraFirma was yet another example of how "Software is Hard". :-)

"But the nature of software is that the problems are always different. You never have to solve the exact problem that someone’s solved before, because if software already existed that solved your need, you wouldn’t have to write it. Writing software is expensive. Copying software is cheap. Scott Rosenberg coins this as Rosenberg’s Law: Software is easy to make, except when you want it to do something new. The corollary is, The only software that’s worth making is software that does something new."

Did it take a long time to make a major GUI switch from Dojo to Mithril?

While deciding whether and how to change the GUI took a lot of thinking and learning, the actual process did not take that long. That was because I had set up an architecture where most GUI screens were defined by JSON data structures interpreted by a GUI panel builder assembling a set of pluggable components rather than being defined as code that constructed the GUI directly. That choice was driven in part by my wanting to support my wife outlining the design in an easy-to-read-and-write specification language rather than having her try to learn JavaScript at the start of the project.

The NarraFirma project that I converted from Dojo to Mithril has about 160 files of TypeScript (including about ten that are libraries in TypeScript) and about 27,000 lines of TypeScript for the application. It had an additional about 13,000 lines of TypeScript libraries and interfaces (some of which I wrote too, but most of which is lodash and D3 typings). It took me roughly about two months to move that project from JavaScript and Dojo to TypeScript and Mithril (might be a couple weeks more if I include the GFX to D3 conversion related to graphing and clustering done earlier). Beyond time spent learning as I went, a lot of that time was rewriting the underlying machinery of the panel builder, rewriting the standard widgets (not that hard), and also rewriting custom widgets like the "grid with item panel" in Mithril instead of Dojo (the hardest part).

Why did you design the system with a panel builder?

I had started using Dojo (including Dijit for widgets and GFX for drawing) several years before for a graphical app that ran on CouchDB. So it was the first thing I turned to. Dojo does have many great features including terrific data grids. Dojo pioneered much of what we now take for granted in web JavaScript development. Dojo 2.0’s move to TypeScript influenced my own decision to move to that later. But I also had some misgivings about Dojo from the start, both in itself and also because of the large numbers of JavaScript GUI libraries out there, the rapid change in that area, and how hard it was to pick one from all the alternatives given all the overlapping feature sets.

As a proverb says (Sun Tzu?), when confronted with 100 options, the best choice is always to run away. :-)

One way to “run away” in programming is to create an abstraction layer or layer of indirection. I did that by using a specification-based approach to define much of the GUI. A tradeoff in that specification-based approach to hedge our Dojo bet was more machinery to support the abstraction. Excessive abstraction can itself become a problem in making designs harder to debug, even as abstraction might make some other things easier to understand or specify. And in practice, that extra layer of abstraction probably caused its own delays as well, both as I re-engineered it a couple of times to make the abstraction clearer and also from debugging it. It also constrained the look of the GUI in some ways.

What issues did you encounter with Dojo?

First, I don’t want this to be seen as Dojo bashing. Dojo is a great toolkit with a lot of good components. Dojo has done a lot for the web. I am thankful for all the hard work the Dojo community has put into creating and maintaining it. Dojo can be a good choice in some situations, especially for people already familiar with it who have been using it for a long time. But I still found Dojo-based code fairly difficult to work with for various reasons. Not all those reasons were Dojo-specific either, as some relate to the general issue of DOM manipulation on the fly which one can find in JavaScript projects base on Backbone, Angular, Ember, Enyo, JQuery, and so on (compared to vdom approaches like used by React, Mercury, and Mithril).

It became clearer as I continued to use Dojo and read mailing list posts and so on that as the web has matured over the past decade in terms of web browser getting better, especially with older versions of IE dying off. So, many of the features of the Dojo toolkit intended to isolate developers from compatibility issues are less needed given common browser support for various standards. With those changes in web browsers, it was not clear that the cost of using Dojo as an extra layer between me and the browser was worth it any longer.

For example, D3 uses the now common SVG standard, which is one reason I switched to it instead of continuing to use Dojo’s GFX. GFX is a lowest-common-denominator abstraction over several web drawing technologies including SVG, Canvas, Silverlight, and VML — but that cross-platform support just is not so important if you focus on supporting mostly just modern browsers. There was also a learning curve issue; there are tons of tutorials on using SVG and Canvas, but only a few on using GFX (and those may be out of date given changes in Dojo and GFX).

There are also now many mix-and-match options to various web challenges. Dojo offers relatively easy-to-use GFX-based charting which I used at first, but it was not as flexible as D3 (or several other charting options out there I evaluated but I did not use). Dojo has good solutions for many issues, but they are not always the best. Billing itself as a “toolkit” not a “library” or “framework”, Dojo was itself mix-and-match, but in practice there was still a significant needed core almost everything assumed. And even using batteries-included Dojo, I found I had to turn to underscore.js (and then lodash) for things like “startsWith” for string comparison — for some reason “startsWith” was a feature Dojo had removed at some point to save supposedly space (despite endless other features).

To be fair, though, I was learning a lot about how to shoot yourself in the foot with JavaScript throughout this entire process. :-) So, it’s hard to pin all the difficulties I wrestled with on Dojo, Dijit, GFX, and so on. I suspect Dojo gets a lot of ill-will from people who pick it but are still just going up the JavaScript learning curve; however, because Dojo adds an extra layer of complexity, it does sometimes feel like it makes just about every JavaScript error you can make harder to debug. And of course, Dojo has its own (very small) share of maybe bugs and/or gotchas (but to make up for the issues any library has, it has a great community). On the plus side of all that, I got much better at debugging code using complex JavaScript libraries. :-)

A major reason I stuck with Dojo so long was its accessibility and internationalization support. But ultimately I decide that something like Mithril would likely be a11y enough because it was close to plain HTML, and browsers were good at that (even if it could be better). I also ended up using some more custom internationalization support instead of Dojo’s built-in support, which requires indenting translatable tables in two different ways between English and other languages. NarraFirma’s i18n support is still not quite done, but it is something my wife has done on her own before, like for Rakontu.

How did you go about switching from Dojo to Mithril?

My growing feeling was that if I found Dojo hard to work with, especially all the complex GUI-to-Model dependencies, my wife would find Dojo-based code very hard to maintain. I looked at a lot of different options, and ultimately decided on switching to Mithril. Granted, I knew a lot more about the HTML DOM at that point, so I did not feel so much like I needed the “training wheels” Dojo and Dijit provided as it tried (and not always succeeded) to hide a lot of the DOM behind the Dijit library. It also was so much easier to find documentation on how to use the DOM directly compared to understanding how to interact with Dijit widgets to get them to use the DOM for me.

So, even after the Dojo GUI was more-or-less working well (and maybe 80% done), at some point in June, after a lot of research and experiment, and after previously converting the project to TypeScript to make refactoring easier, I made the switchover from Dojo/Dijit to Mithril for the main application’s GUI.

That full changeover was done after first making a lower-risk Mithril version of just the survey-taking code as toe-dipping — and the water felt fine.

As a partial move away from Dojo months earlier, I had also switched from Dojo’s GFX to D3 for graphing, which had worked out OK — even as I had been reluctant to lose some of GFX’s broad cross-browser support. But since almost all modern browsers now supported SVG (or can be polyfilled), using D3 with its SVG requirement instead of GFX seemed acceptable in a way it might not have been years ago with earlier browser versions. Also, by taking the lowest-common-denominator approach, GFX had its own limits (including some difficulties with touch events).

Switching to D3 and TypeScript were fairly low risk bets, as was doing survey collection in Mithril. By contrast, the full switchover for the entire main application’s GUI from Dojo to Mithril still was a big risky change taking some time to do with unclear benefits other than maintainability/learnability in the long-term given things were working under Dojo/Dijit/GFX/dgrid. The codebase’s internal level of complexity, number of layers, difficulty in debugging, and internal learning curve just felt too high to me (even having already gone up that learning curve myself).

We had by then begun letting our credit card balances run up to preserve cash in the bank while we finished NarraFirma, so it was very questionable to do any major changes that would take time and so make finishing the first version of NarraFirma take longer and delay me eventually getting a “real” job. And with our past IBM connections, and with IBM having invested in Dojo, moving away from Dojo seemed like it might preclude using NarraFirma as a portfolio piece to get a job maintaining legacy Dojo code — when I was sure there were likely many such jobs that might pay well (not that I especially wanted them, given the frustration level, but such jobs were better than losing our home). And of course, using Dojo had been my original decision. So there were plenty of reasons not to switch. :-)

But, I also knew that once I took on other work, Cynthia would have to maintain the NarraFirma codebase. Experienced programmer as she is, I just could not bear to leave her with a mess of GUI-to-model interdependencies or the frustrations of learning Dojo’s complex ecosystem (as nice as parts of Dojo can be when you know them, and as much as the Dojo community has moved web development forward).

It ultimately was a tough call made out of concern for issues like love, beauty, simplicity, elegance, and joy — a decision and subsequent implementation done while watching our bank balance spiral downward and our credit card debt spiral upward.

What has been your experience using Mithril compared to Dojo?

Mithril in general has indeed been a joy to work with, as it runs very close to the HTML DOM. That makes it pleasantly easier to learn and use than libraries like Dojo, which attempt to hide the DOM but end up leaking it out anyway in practice. In those leaky cases, you still have to learn about and sort through DOM issues, as well as wrestle with the leaky and maybe buggy and incomplete abstraction. You still have to learn about CSS to style components and adjust their behavior. Once you know the DOM and CSS well, extra layers of abstraction begin to feel like clutter, unless they have some very clear benefit.

Like React, Mithril uses a vdom that closely parallels the real DOM. As with a typical 3D video game redraw loop, it is generally easy to reason about redrawing the entire page with Mithril when anything changes in the data model — relying on the vdom to minimize actual expensive changes to the actual DOM nodes.

The harder-to-maintain alternative that is typically used with Dojo and most JavaScript frameworks (e.g. Backbone) is trying to change only exactly what is needed in the DOM when the data model changes (typically using jQuery to make the actual change). These changes are triggered as needed by setting up potentially complex and often brittle dependencies between data model objects and GUI objects (as typically with Dojo widgets). It can usually be made to work OK. However, writing such code well gets hard when, say, two widgets can affect each other as well as the underlying model and you need to suppress “ringing” in the interface. Situations like that (and worse) can be hard to debug when things go wrong.

I say that as someone who has been setting up dependencies between data models and GUI widgets on-and-off for about twenty years since first doing that in Smalltalk, where such complex dependencies probably originated. :-) React’s Flux architecture (using single directional data flow) is intended to address that sort of issue. NarraFirma uses something similar, where changes to the triplestore trigger redraws in Mithril, as do most network messages. In this case, the Mithril/React/Mercury+vdom approaches with a Flux-ish architecture seem a step up from Smalltalk’s classical way of doing things.

Had I started with Mithril, knowing what I know now, I might have coded several things more directly in it. “Running away” from a decision has its price, even in programming. Ultimately, even with extra layers of abstraction, you still have to write code that actually does something; extra layers of indirection can make that fundamental code harder to understand, harder to debug, and harder to expand in new directions.

Why did you move the codebase from JavaScript to TypeScript?

I picked TypeScript over several other possible JavaScript alternatives I looked at because TypeScript kept as closely to JavaScript as possible (so, fewer extra layers to go wrong), while TypeScript was still significantly easier for writing and maintaining complex systems. I also knew I could easily ditch TypeScript and go back to plain readable JavaScript if things did not work out compared to some other transpilable-to-JavaScript languages.

TypeScript has its own issues, but overall it has been a good improvement over plain JavaScript. It rarely feels like it is in the way or keeping me from doing anything I might want to do. The biggest challenge is integrating third-party libraries, but between Definitely Typed and this example trick for writing a stub typing, I’ve found the integration not too much work for the benefits it brings.

Still, I’m not against using other languages that compile to JavaScript as the assembly language of the web. Many, many people use languages like C/C++, D, or Delphi that usually compile to regular assembly language to great success, or other languages like C#, Java, or Smalltalk that usually compile to byte code. So, down the road, especially given improved source maps, asm.js and native client, and ever faster computers, I expect we’ll see lots more people compiling to JavaScript.

Moving to TypeScript was a low-risk high-reward decision for me to make at that point in the project, given increasing complexity. I also made that choice to make it easier for my wife, who did not know much JavaScript, to work with the code base. That is because TypeScript IDE tooling, like the Palantir plugin for Eclipse, can make even plain JavaScript easier to learn and use, given auto-completion suggestions. Also, I wanted to get really good at working in JavaScript even if I compiled to it later, and using TypeScript helped me continue down that path (but with less pain — given a project whose own source code plus library source code was weighing in at around two megabytes of text).

While there was a small hurdle to start compiling the code under TypeScript, I did not have to put typings in place for everything at once. There are some parts of NarraFirma for which it might be good to add typings for down the road or to convert to idiomatic TypeScript class definitions to get better IDE code completion and search support. I generally just add typings or rewrite classes incrementally as I go along, mainly when I start debugging or improving some part of the code.

Are there any things you lost in the transition or benefits that were less than expected from the conversion?

Of course, even the best things in a programmer’s life, like Mithril, can have their design challenges and surprises which consumed many hours to understand, document, and work around

And there were some Dojo/Dijit/dgrid features we sacrificed. For example, our Mithril grids are still not quite as nice as the Dojo dgrid grids, since the table headers don’t stay in place when you scroll the table. But we decided we could live with that for now (and maybe fix it later) for the benefit of being able to move away from Dojo and Dijit and leave behind model-to-view dependency management completely.

Still, it is not quite 100% true that we left explicit dependency management behind. To make the Mithril grids perform better, I felt I still had to do some data caching. So there is still a bit of extra one-way model-to-view-dependency complexity when underlying grid data changes (requiring a call to “GridWithItemPanel.prototype.updateData“). But that is not much dependency management compared to the previous approach, and it’s isolated to just a few easy-to-find places in the code.

What about accessibility (a11y) of Mithril, especially compared to React?

(This question was raised by Amanda Rush when I suggested Automattic's Calypso admin for WordPress could be converted from React to Mithril. I first answered it here and the below is mostly taken from that with some minor changes including additions from later comments there.)

The short answer is that Mithril runs close to pure HTML (as part of its brilliant and elegant design) and so is as accessible as plain well-written HTML can be in a standard web browser. Below is a longer answer.

Accessibility was a major reason we went with Dojo originally with NarraFirma and stuck with Dojo for so long despite difficulties with it. Dojo with Dijit has some of the best accessibility of any major JavaScript-based GUI toolkit. Here is Dojo's accessibility statement which probably is one of the best in the industry and which has been in force since around the start of the project more than a decade ago (including given IBM's involvement and a legal necessity to make various web pages accessible in the USA). Facebook's accessibly API for Native Widgets by contrast was made a couple days ago. However, what I also discovered is that full accessibility support in Dojo only really extends to the most common core widgets, and anything in third-party libraries or Dojo's own experimental (Dojox) libraries was not necessarily accessible. Those core widgets were mostly just wrappers around native HTML widgets, although sometimes with specific enhancements. I expect much the same will apply to Facebook's React. The more complex the widgets, the greater the accessibility concerns. The safest approach for accessibility is to keep as close as possible to native widgets, which may limit some design flexibility.

So, accessibility was a concern of ours in migrating to Mithril. However, Mithril runs very close to pure HTML as a thin layer on top of it with a very elegant component layer above that -- unlike Dojo's Dijit which introduces a complex widget layer and also hides all the native HTML behind other layers. So, you can in theory build accessible GUIs with Mithril by careful consideration of how you build your widgets like you would when making any HTML web page, relying on the accessibility of standard web components in a standard web browser using standard web best practices.

One can do better than that sometimes as with Dojo's broad support for WAI-ARIA -- but at least basic HTML accessibility support is a start. Obviously, for custom components which manage internal state, one has to keep accessibility in mind (thus the value of something like WAI-ARIA). For example, when I did the conversion from Dojo which had an accessible custom slider, in the end I just used a native HTML5 slider -- something that was unavailable when Dojo was first created. I expected screen readers going forward would in general support native components better than custom ones. So, sometimes a bit of change is needed. For another example, in the code I wrote, I created a panel builder architecture that labels all core widgets to make them all easier to use and to navigate around (which is a general web best practice for multiple reasons).

Still, I have not tested our NarraFirma application with Mithril manually for full accessibility. For anyone who wants to try NarraFirma to get a sense of Mithril's possible accessibility and post accessibility issues on GitHub in the related project, I welcome feedback on that.

I know the interactive 2D Concept Map diagrams used on a couple of pages are not accessible other than by editing the concept maps in JSON. So text editing of those maps is supported -- but obviously who wants to edit JSON code by hand if there was some better alternative? I remain unsure how to improve that further, other than perhaps creating an alternative table interface to the concept maps (which would be nice to do as time permits).

The graphs used are also not accessible at all since they are fundamentally visual (other than by somehow examining the underlying SVG code, which is impractical). I'm not sure yet conceptually how to make those dynamically generated complex graphs accessible to visually impared users in a useful way, but I welcome suggestions about that.

We did however try to ensure the surveys were accessible. I ran that code through some web accessibility checkers listed at the top of this file. t passed after I made various improvements to the code (including adding labels). Even if the main NarraFirma application is not fully accessible (as it displays 2D graphs and 2D clustering diagrams), we wanted survey produced by the main application to be fully accessible. So, I know it is not that hard to make Mithril code that passes at least a basic standard of accessibility when that is conceptually possible -- although it may be useful to have some helper functions for that written in standard JavaScript (or TypeScript).

So, even if parts of NarraFirma are not as accessible as they could or should be, so if you find any significant accessibility issues, please don't take that as definitive proof that Mithril-based webapps can't be accessible. Take it more as proof that a couple blowing through all their cash and then running up their credit cards (not for the first time) to spend a year making a FOSS gift to the world just could not do everything they wanted to do in the short-term. :-)

Dojo has a long list of accessibility concerns it addresses listed here. Many webapps ignore those things. Color schemes to accommodate low-vision are another concern as indicated there. I doubt Mithril third-party libraries address them as thoroughly as React (beyond standard HTML). However, I can wonder if React, in practice, does that much a better job? Still, to my knowledge, Mithril does not have the equivalent of React's react-a11y project which is an automated tool for detecting accessibility concerns in React projects. However, I can't imagine that would be that hard to make work for Mithril given Mithril's close-to-low-level-HTML architecture. Still, the advantage there does indeed go to React in that sense. But I don't feel the advantage there is overwhelming in the sense of "infinitely harder" even if it might be "somewhat harder" (although I may be wrong about that). Also, as Facebook's announcement about React's Accessibility API is only from a couple days ago, it remains to be seen how it will play out in practice. I still have more faith myself in something like Mithril that runs close to pure HTML and so can rely more on standard screen readers than trying to get people to use a special API. Accessibility should ideally be baked into the core of the web and web browsers, not as an add-on API, IMHO -- even if add-ons are useful in practice along that journey.

Are there any lessons you learned, patterns you found useful, or difficulties integrating with other libraries?

(This was a question asked by Bondi French on the Mithril mailing list.)

As for lessons learned -- the biggest one is, start with Mithril and TypeScript instead of something else and JavaScript. :-)

The biggest single thing on our wishlist right now related to Mithril is that our grids no longer have a floating header under Mithril (compared to Dojo dgrids which were awesome, have to admit it, although sometimes tricky to configure). But I was willing to sacrifice those floating headers for now for simplicity. There are some floating header grid demos around for Mithril, but I did not want to add the clutter of yet more code complexity at the start while I still had so many other things to be concerned about. Someday, when I get substantial time again, I'd like to fix that though.

One thing about the grid though was that I felt (maybe incorrectly) that I needed to cache sorted data (you can sort multiple columns by clicking on headers in some sequence in grids). So that caching broke with the standard Mithril redraw everything model. When the grid data changes in one place, I need to update that cache. It is a minor nuisance, but not that hard to manage (and I already had architecture in place for that from the Dojo version).

I integrated D3 with Mithril, and it was not really that hard using Mithril's support for wrapping DOM nodes via "config". The biggest issue was making sure that D3 callbacks on events forced Mithril updates (like brushing to select part of a graph which then populated a Mithril grid).

I also had to to queue redraws in for a networking library I wrote to talk to AJAX backends in Node.js and WordPress/PHP given I used my own lower-level code to send and receive JSON. I did not use m.route or Mithril's networking because I had a different approach already in place from Dojo, so I can't comment much on those.

There was a point at which I debounced redraws myself related to network events because of a possible race condition in how I updated an internal data store. See Application.ts:

        redrawFromProject() {
                // The tripleStore may not be updated yet, so this redraw needs to get queued for later by the application
                if (this.runningAfterInitialIdle) {
                        if (!this.pendingRedraw) {
                                // console.log("queueing redrawFromProject");
                                this.pendingRedraw = setTimeout(() => {
                                        // console.log("redrawFromProject");
                                        this.pendingRedraw = null;
                                        m.redraw();
                                }, 0);
                        }
                }
        }

I used the "humane" library for "toast" alerts, and it worked well with Mithril.

Writing dialogs was a bit of custom work compared to Dojo. Here is how I did it, with a global variable I would set to the dialog (which can't support nesting, unfortunately): dialogSupport.ts

As a comment there says:

        // TODO: Using a global here to avoid parameterizing mounted components until the following Mithril issue is resolved or clarified:
        // https://github.com/lhorie/mithril.js/issues/638

This is not exactly a Mithril issue, but before the Dojo to Mithril conversion we had also changed the GUI interactive architecture to essentially modeless. It used to be you had to click OK to save changes to panels, and we made the updates to the server happen instead when you left a field. We have not yet really thought that through entirely. The difficulty in doing modal dialogs also limited our options, not that we really wanted to go modal to solve this issue. So, there are some GUI warts related to that we still need to improve, mainly where you add a grid item and then have to explicitly delete it rather than pick a "cancel" option. There is also one place in the GUI where the panel builder framework limited us to essentially begging the user to not leave the page without pressing save. However, it is not Mithril's fault if we ended up shooting ourselves in the foot once or twice with it, same as we did with Dojo. :-) We hope to clean those issues up eventually (even as the system is usable, if not perfect).

I did post a couple related issues to GitHub of things that came up.
https://github.com/lhorie/mithril.js/search?utf8=%E2%9C%93&q=pdfernhout&type=Issues

The biggest single issue of those was the issue of incremental development. The biggest unexpected confusing stumbling block (and it was not very large, but did take a couple days to fully understand it) was from a textarea (and some other widgets I found later too) was not being updated to overwrite its user-entered contents unless the related model value itself changes (which then causes Mithril to decide the textarea's value is out-of-date). Essentially, if you don't hook up a widget's data to be displayed reliable from the model, the output can have unpredictable results when users make changes via the browser. That can be very surprising if you are developing code incrementally. Now that I understand it is more a feature than a bug, I know I can ignore it until an application is fully hooked up -- but it was worrisome for a time that maybe something fundamental was broken in Mithril (even if arguably maybe that behavior should be more consistent across widgets). The related issues:
https://github.com/lhorie/mithril.js/issues/701
https://github.com/lhorie/mithril.js/issues/691

Some difficulties with unmounting components also got in the way. The quickest solution was just never to unmount anything, thus the above mentioned dialog approach with a global that defines the current dialog and can be set to null. :-)
https://github.com/lhorie/mithril.js/issues/694

I can't really think off-hand of many other unexpected lessons or patterns I learned (beyond standard Mithril stuff Leo Horie so thoroughly explains in various essays and other documentation).

Some of my experiences with the conversion are maybe not 100% applicable to others because I had use a "panel builder" architecture under Dojo out of some concerns I might not stay with Dojo (given so many alternatives and some early struggles with Dojo's Dijit). Display panels were mostly specified via JavaScript structures, which abstracted some GUI configuration from a specific library but also made the code more complex with another layer of abstraction for the machinery to build the panels and connect the events.

--Paul Fernhout
http://pdfernhout.net

The biggest challenge of the 21st century is the irony of technologies of abundance in the hands of those still thinking in terms of scarcity.