My Static Showdown 2016 entry
I participated in Static Showdown again this year. This is a global, online hackathon where we build static web applications without custom server-side code within 48 hours. This is my 3rd time participating.
I built a web-based mobile app development environment, geared towards people who wants to learn programming.
It’s available at https://ss16-wonderstudio.firebaseapp.com.
Update: Source code is released: https://github.com/dtinth/wonderstudio
Think of it as Visual Basic 6 for the mobile app age. Design your UI at the left, and write code at the right. You can click on a UI control to change its properties.
As you work on your application, you can click on the Publish button at the top right to save your application to the cloud. This allows you to preview on your mobile device. It gives you a link and a QR code you can scan to open the app in your phone.
Scanning the QR code with your phone opens up the application in the browser. If you’re using Android, you can save the application to home screen and it will work in full-screen, even when you’re completely offline.
The goal of this project is to create an environment where people can learn the basics of programming with the least learning curve. I want to try to make programming an enjoyable and rewarding experience. Instructors and individuals can use wonderstudio to teach the basics of programming.
The following will be the motivations behind this project, the making-of, and the future of this project.
Backstory and Motivation
I fell in love with programming 13 years ago.
I started programming in Visual Basic 6 when I was nine years old. Compared to the tools of today, VB6 is very well integrated and it’s so easy to build GUI apps and save as an .exe file you can send to others.
The learning curve is so low, and it feels rewarding whenever I have a program that does what I want. It triggers my brain’s reward center. It made me love programming. I write programs — from boring math homework solver, to screensaver, to games, and so on, in VB6.
But even these days, according to a statistics in Thailand, only around 30% of software major graduates work in the software industry. There are posts in online forums complaining about the outage of great programmers here. People don’t want to write programs.
From my observation, it seems that people don’t like programming because it’s more frustrating than rewarding. And you know once something become frustrating it’s not even challenging anymore.
A lot of students have to start with C, C# or Java. They have to learn how to use pointers or classes upfront, and cope with a very strict syntax. They have to fiddle around for a long time just to get some text to appear in a black console window.
I don’t think that’s fun and rewarding.
Or maybe it’s web application programming, which requires you to learn at least 3 different languages and multiple tools. That can be very overwhelming. No wonder why people don’t want to write code.
I want to try to change that.
That’s why I created this.
The design philosophy for this application is mostly inspired from my experience with VB6.
- Drag-and-drop, GUI oriented environment. HTML can wait for later.
- Dead easy API. Like VB6, web programming used to be easier. I can refer to DOM elements simply by spelling its ID. Now everyone has to use document.getElementById().
- Imperative API for GUI. To keep things simple. When this happens, do that. Functional programming is cool and all, but that too can wait.
- Be visually attracting. The controls in user-created app comes from material-ui which look gorgeous.
- Fast feedback cycle. No one wants to wait ten seconds just to test their app in an emulator.
- Minimal API. Try to provide only one way to accomplish something, even if that leads to more verbose code, so users can learn to build their own abstractions and appreciate its beauty.
- Limited by design. Controls can only be arranged vertically (for now). In VB6 there wasn’t type generics and we have to write our own sorting procedure for each data type! It’s is not a complete tool for writing any type of app, and you have to learn not to stick with any particular tool.
- Tries its best to help you. Helps you write your code. Formats your code automatically. Tells you immediately when something goes wrong.
- Easy to test and share. To encourage people to show off their masterpiece.
In the past Static Showdowns, I challenge myself by trying new libraries that I’m not familiar with. Last year I tried using Polymer. This year I want to use the tools I know well and see how far I can push in 48 hours.
Development went this far in 48 hours thanks to a lot of technology behind it.
- React and hot reloading. I can change the way my application looks on-the-fly. Don’t have to refresh the browser that often anymore. Perfect for polishing the UI.
- nwb binds webpack, Babel, and Karma together in a nice package. No more boilerplates. Comes with unit testing and code coverage measuring out-of-the-box. No boilerplates.
- material-ui powers the controls in the user-created apps.
- Stylus is used for super-speedy CSS writing. Using CSS Modules to keep style in different components isolated. The user interface style for the studio is mostly handwritten Stylus code.
- react-fa provides instantly usable FontAwesome icons as a React component.
- Redux powers the user-created app, which means the state in the app is never mutated. (The API exposed to users is a thin wrapper that dispatches actions to and query data from the store which makes it look imperative.)
- reselect allows efficient computation of derived state.
- updeep allows easy creation of function that takes an old state, and returns an updated state.
- React DnD powers the drag-and-drop interface of the studio.
- CodeMirror powers the text editor. Tern is used for IntelliSense-like completions. standard-format is used to format the code when the user edits the code. It’s also responsible for reporting syntax errors.
- Firebase provides a very easy-to-use data store.
Here are some techniques that I feel that I’m quite proud of.
Each control available to a user-specific app is defined in one place. Each control is a React component, with extra metadata specifying what properties it has. Each property contains a type, documentation, and getter/setter logic.
For example, here’s a Checkbox component:
Everything here are just pure functions, which means they can all be hot-reloaded. I can export another React component here, and it will immediately appear in the “add new control” box while it’s opening.
That helped me a lot in speeding up development.
The code editor also uses this metadata to generate APIs and feed it into Tern so that it can auto-complete and give documentation while writing code.
Dirty service worker installation:
Since I don’t know in advance what files are going to be there (webpack manages it) and have no time to fiddle with stats file and introducing more build steps, I just cache whatever file gets requested from the app.
However, when a service worker is installed, it will only take effect on next page load. To work around this, if a service worker is just installed the app will just reload the page!
To allow “install to homescreen” in Android devices, I need to add this to the <head> tag:
<link rel="manifest" href="manifest.json">
But this means every app will share the same manifest. Otherwise, I need to set up a server that will serve a different manifest file for each app (which goes against the rules).
Redux with more OO goodness:
Instead of dispatching an action object which is then consumed by each reducer, I dispatched a function and the reducer simply calls that function with its current state.
This makes the architecture closer to the Elm Architecture. It’s somewhat more complex than what I described above. I’ll write more about that later.
I plan to open source this app and improve it further. I also hope that people might want to contribute to this project.
Update: It’s been open-sourced at https://github.com/dtinth/wonderstudio.
Here is the a wishlist of features not implemented during the competition.
- Display run-time errors. Right now, errors in user code fail silently. The user needs to open the web inspecter to find out what’s wrong.
- Horizontal layouts. Allow components to be laid out horizontally on the same row (evenly spaced).
- Forking. Allow user to fork an existing app and improve upon it.
- iOS Web Apps. The meta tags are not there yet.
- More complex components. Such as radio button, list box, and select boxes.
- More example apps.
- Customizable colors.
- Images. A component that displays an image given a URL.
- Drawing. Vector or raster graphics. Not sure yet.
- APIs. Integrations with web APIs such as Twitter or Facebook.
- IoT. What if a wonderstudio app can control hardwares?
Feel free to send me a response if you have any suggestion!
Oh by the way, during a family reunion last Sunday, I’ve been coding this wonderstudio thing in a restaurant. A five year old girl came and asked me what I am doing. Unable to explain, I told her I’m “writing some computer code.”
“What for?” She asked. “To solve problems that would take very long time for a human to solve manually,” I answered while switching to a terminal to open a Ruby console.
“You know what’s 10 + 50?” I asked while typing that into the Ruby REPL. “Sixty!” she answered quickly. “Great! But what if the number is very very large?” I punched in some random numbers and press enter. “Computers can answer that quickly.”
“Today is Sunday, right? How about 1,000 days later? What day is it?” I quickly wrote a Ruby program. “Saturday, but what date, what month, and what year?” I punched in more code. “It gives you an answer instantly! That’s why!”
She wanted to play with the computer. Then I showed her the app I’m building and asked her to drag the controls around using the trackpad. Once she can use the trackpad to drag a button around the screen, she shouted excitedly, “Wow! Computers ARE fun!”
That made me feel great, although I’m still amazed at how dragging buttons could possibly be fun. I think this story could illustrate how wonderful programming could have felt like!