When I first heard about unveiling Dark in September 2019, I was intrigued. The “Dark in Action” video where Ellen Chisa demonstrated building a backend for an office sign-in application reminded me of a famous “How to build a Blog engine in 15 min” demo from DHH revealing Ruby on Rails to the world back in 2005. I’ve been building Web apps for over 15 years now, with a strong focus on the backend & infrastructure and frankly, after playing with Dark for a bit now, I want to admit that I haven’t been that excited about building software for the Web since moving from PHP to Rails, or On-Premises hardware to Cloud Computing. Immediately, I picked one of the side-project ideas I had on my list and submitted it for a Dark Private Beta. In this post, I would like to share my experiences building Snipy (Slack app for the code snippets) with Dark, without a single line of (“traditional”) code, without never-ending software installs, without messy server configurations, without complex deployments.

Disclaimer: I am not employed by Dark, nor have any affiliation with their team — I just happened to fall in love with what they’re building and their mission, and I believe it’s a kind of software development we will do in the nearest future.


Why Snipy?

Snipy is a handy app that helps you find, share & organize code snippets with your Slack team. I had several ideas on my side-project list, but I picked Snipy because it was something I needed myself: I always keep losing the code snippets I share and the teams I work with (via Slack) tend to recreate the same kind of code for the same kind of problems (maintenance & support scripts, coding optimizations, data crunching, etc.).

In addition to yet another chance to scratch my own itch, Snipy, in my opinion, is a perfect application for Dark use cases. As Slack is the primary user interface for Snipy, I did not have to build any frontend, besides the landing page that runs in Webflow. Also, having gained some experience building Slack-first products before (Dockbit and SlashDeploy), I knew the kind of architectural components I would need, which Dark already supports: HTTP handlers, key/value datastores, background workers, and Cron jobs. Moreover, knowing I will have to interact with APIs a lot (and really, as in pretty much any Web-based development today, where everything is a service), the Dark’s Live values, their core feature to see live requests as you code (more about it later), seemed like an awesome development accompaniment.

How does Snipy work?

If you ever built Slack apps before (especially, slash command-driven), you’d know that one of the primary interfaces to the Slack application is the Slash (/) command, which is a bit like a CLI (Command Line Interface) in your terminal.

In a nutshell, Snipy users type /snipy create, which brings up a Slack dialog window where users type in the code snippet filename, content, description and tags. Then, Dark backend stores a snippet, together with any additional information provided (like tags), and uploads it back to Slack as a Slack File. This allowed me to leverage Slack’s File upload API for MIME type detection, code highlighting, etc. To be able to quickly find code snippets by tags, descriptions or code contents, I’ve hooked up Dark with Algolia — as of writing this post, Dark does not yet support full-text search, nor advanced data store querying (see What Dark could improve?).

Here is a preview of Snipy in Action:

Why not Slack’s native code snippets, you might ask? Well, in my opinion storing code snippets independently from the rest of conversations in Slack opens up a whole slew of other possibilities: such as being able to categorize code snippets to quickly find them and create a reusable collection of team code snippets, building a separate frontend (like a desktop or Web app, see What’s next for Snipy?) with all sorts of team collaboration features around code snippets that Slack lacks and lastly having a flexibility to index code snippets differently from Slack’s internal search, for instance giving rankings to tags, or code context, etc.

As you can imagine, Snipy builds upon a familiar Web architecture with request/response cycle, with the only exception — I haven’t written a single line of traditional code (either dynamically or statically typed languages you’re used to), nor have I had to upload my code anywhere, nor set up a server to handle requests, nor had I to deploy anything — I’ve simply written everything in the Dark Web editor. Every single slash command is hit and processed by Dark platform, without me having to worry about how it runs behind the scenes.

Here are some of the things I didn’t have to do that I normally do for such a Web application:

  • Choose a language framework (Rails/Express/Django/Phoenix/<insert your popular framework here>).
  • Install operating system packages and framework dependencies (version managers, compilers, databases, background workers, etc.).
  • Deal with containers in development mode (Docker, minikube, etc.).
  • Set up local tunneling to receive API events during development (ex.: Ngrok), request interception (ex.: RequestBin), construct sample requests with Postman/curl and copy them back to my codebase, etc.
  • Write configuration management nor deployment recipes (Dockefile, Terraform, AWS Beanstalk extensions, etc.) for the production environment.
  • Then spend hours debugging why things that initially worked in development no longer work in production.
  • Configure production logging, queues, backups + a bunch of other things I can’t remember now.

It just felt like the old days when all it took to deploy a website was to FTP a few files and it was immediately available to the world — heck, I didn’t even have to upload anything. By skipping the whole shebang I have to do to ship a simple, production-ready application, allowed me to focus 100% on the business logic. I think 80% of that time I spent on studying and experimenting with the Slack/Algolia APIs and 20% figuring out how to code with Dark, a programming language I have never used before. 🚀

For example, here is a Dark handler to search through tags in Algolia and deliver results back to Slack:

Dark handler to search for results in Algolia and deliver to Slack

As you see, it just looks like any other language you use today, with features like type-safety, boolean logic, HTTP requests handling, functional iterators, JSON responses, etc. — except that it runs right in the Cloud from the get-go, as close to the end-users as possible, without any intermediary complexity.

If you’re interested in getting a feel of Dark, I recommend you to first taking a look at the original video Ellen Chisa posted when they revealed Dark and then applying to Dark Private Beta.

To sum up, here is the entire list of “tools” I have used to get Snipy Slack application out to production:

  • Dark (language, request interception, debugging, infrastructure)
  • Slack Block Kit (building UI for the Slack dialog window)
  • Sketch (prototyping and designing)
  • Webflow (landing page)

What did I like about Dark?

Although Dark is still in its infancy for the mass adoption and there are things to improve (see What Dark could improve?), here are just some of the Dark’s features I loved: 😻

Live values

Dark wants you to code based on the real requests coming from your users, 3rd party apps and APIs you’re integrating with. You can’t build a valid code in Dark without receiving a live value from a real request first. In my opinion, it’s the most natural way to develop applications for the Web, since you operate on the actual expectation, which you usually try to simulate locally and build your code upon. It’s just like TDD, but without “fictional simulation”, which by the way is often the root cause of the bugs itself. Honestly, TDD has never stuck with me, because I found it easier to work with the real requests/expectations before writing any code.

Deployless

It felt scary and liberating at the same time to know that whatever you code in Dark editor is available right away to the end-user — so, in Dark, there is no “deployment” process at all, a.k.a Deployless.

Thinking of it a bit more: if this concept is developed further in the industry (Dark is building feature flags to support experimentation and code versioning), we can get rid of a bunch of complexity and tooling that we’ve built over the years just to be able to release software confidently. I’ve been “guilty” building such tools myself, one being Dockbit, another SlashDeploy — both created to help teams ship code safer and faster. But hold on, if there isn’t a “deployment” process per se, then, are there any problems in the first place?! 🤔

No installations

Kind of a nice side effect of not having to deploy your code is that you don’t have to install anything with Dark. Think of not having to run yarn install or docker compose up (only to download the entire Internet 😉), every time you need a new package or sync up with your team. I know, Web-based IDEs have been providing such a benefit for a while now. But what we ended up doing, is moving the tooling and its related problems from a local development machine to the Cloud, resulting in similar problems (dependencies, upgrades, production deployments) without giving back anything to a developer, in terms of productivity gain.

Immutability

Another feature I liked about Dark and it’s probably “a must-have” for such a development environment experience is that everything is by default Immutable. In Dark, you have to code in a functional manner and can’t mutate the state of your program — the editor simply won’t allow it. Dark even goes a step further and tracks all the function and variable names so that when you rename them in one place, Dark automatically updates them everywhere else. It’s not working 100% flawlessly yet (remember Dark is still in private beta), but I can see how powerful this feature is — something that I usually do semi-manually (with find & replace in the IDE), is done automatically for me.

Assisted development

Something that felt weird initially is that Dark does not allow you to freely type and modify text as you would normally do in other IDEs. The primary reason for it is that Dark continuously validates your code (against internal AST) and makes sure it is error-free. For example, it checks that there are no Null values, that function calls match their signatures, and other useful stuff. I think this feature was the biggest challenge for me as I started to code with Dark, but once I got a hang of it, I liked it — it has already saved me from a few bugs when I missed some parameters, which Dark clearly outlined in the UI of the editor.

Type safety

To be able to support the features I described earlier (deployless, code assistance, etc), type safety is, of course, an integral part of Dark. Having been coding with dynamically typed languages for a while now (I moved from Java to PHP to Ruby & JS) and experiencing the benefits of type safety (I’m a big fan of Go and Swift), I think it’s just a must in environments like Dark, so not much to say here, really — you gotta provide types ahead of time for Dark to be able to assist you.

Everything is versioned

I think this was kind of an obvious and required feature outcome for Dark, resulting from “No installations” and “Deployless”. Every standard library function provided in Dark is versioned. So, when calling HTTPClient::get(v4) , for example, Dark automatically autocompletes it with the latest version of the function available in their standard library. This is great and important because it allows me not to worry about software updates (think of upgrading the Node version and related code). I can change to the new function signatures in Dark at the time convenient to me, while still having the new code use the newest versions.

Support

As soon as I got my invitation to Dark’s Private Beta, I got an email from their CEO (Ellen Chisa), who personally on-boarded me to their platform and walked me through creating a simple Slack-based authentication handler. Then I was provided access to Dark Community Slack, where pretty much entire Dark team is there to help you. I was surprised by the fact that Dark’s CTO (Paul Biggar) was always available in Slack to help me personally, and many times jumped into my Dark Canvas (albeit it sounds cool, it’s a Dark term used to describe an IDE for a single project) to resolve any issues I had — surely, brilliant support! 🤘


The story behind a lot of these concepts is really well explained by Paul Biggar, so be sure to watch the Dark’s Philosophy video:

What Dark could improve?

Dark is currently in private beta, so I kind of expected to have all sorts of bugs to pop up. To my surprise, I haven’t found anything major that would prevent me from shipping Snipy to production. Apart from solely behavioral changes of how I used to code before and with Dark, there were a couple of bigger themes that are already being addressed by the team.

The first one is the performance of an editor. As my Dark application grew in size, it felt laggish and hard to type in, probably because of all the AST validation the platform has to do behind the scenes. Dark’s CEO reached out to me immediately to say that they started working on it (during the holiday season) and in a couple of days Paul Biggar informed me that it’s been improved.

The second issue for me was the lack of feature flags in their new editor, which made me feel anxious about how to introduce new features without affecting existing users — since you don’t have Git nor any other version control system you are used to. It’s already a highly prioritized feature and Ellen Chisa made sure it’s going to be available right after the holiday season, yay! 💪

Here are few more improvements that Dark could do and I believe that most of them are already in the backlog or being worked on:

  • Richer standard library — The standard library is quite complete now, allowing you to do most of the code manipulations you would expect. However, some things were completely lacking that would have saved me a dozen keystrokes: regular expressions and advanced database queries (like sorting, limiting result set or SQL “LIKE” queries).
  • Secure storage for secrets — Currently I had to use functions to store secrets as plain text and there isn’t native storage for sensitive data. I would have expected to have a separate space where I’d securely upload my secrets, they’d be masked across the application and I could then reference them through some kind of “labels” throughout my code.
  • Safari support — Dark only works in Chrome currently and what I would love to see is support for Safari, because then I could code on the iPad (iPad OS 13 supports desktop browsing), on the go, FTW.
  • Project organization — Currently, projects in Dark are built off the canvases and there is not a lot of code organization you can do. For instance, it’d have been great to be able to move database/worker/cron handlers into a separate space/board away from the actual business logic, rename & copy around canvases, add collaborators and being able to set the visibility of the project: public, private, team, etc.

But seriously, I am pretty sure all the above-mentioned improvements are already on the Dark’s hit list, so I don’t expect long to see them out in the wild.

What’s next for Snipy?

Snipy is already available to the public at https://snipy.io and is currently free (during Beta). I will be introducing pricing as soon as I see it’s being used more actively and in the meantime, I plan to build a frontend for it. I would like to use Dark as my primary backend for the entire application and on the frontend build a Desktop/Web-based client, where users would be able to search through the code snippets, organize by tags and collaborate with team members. The app will also be soon available in the Slack Apps directory.

I was also planning on recording a screencast of how I’ve built Snipy from the ground up, so if you’re interested in watching it, leave me a comment below and I will get back to you once it’s out.

Until then, have a nice holiday! 🎆