Have you ever made, Make.cm?

Andy Fitzsimon
6 min readFeb 25, 2021

“Oh I built one of those” — Every developer

“It was awful” — Every wise developer

In 2006 if someone told me they made a PDF generator, I’d have told them “Oh my team at X made one of those. It only makes books. We used a rarely maintained library and some very intricate XSL. ” I’d expect the conversation to unearth common pains, learn about something that was slightly better and another that was slightly worse and then wonder if I’d get a chance to revisit that corner of the code universe in the future.

In 2019 if someone told me they made an image generator I’d tell them “Oh yeah I hacked one up client side using canvas. It spat out SVG icons as PNG so I could use them in Google Slides”.
I’d expect to hear their mature reasoning: why client side is risky, why puppeteer or another approach became a service, what the upper limits of image dimensions, filesize or optionality might be. And I’d wonder if there was any upside to refactoring my code.

After enough of these conversations (and there have been plenty in-between) you start to ask yourself some interesting questions:

Why do so many developers — like us, make the same thing? Why build a unique asset generator every time?

I’ve come to think it’s because no two codebases are the same.
Something to do with the law of the instrument and the famous idiom “if all you have is a hammer, everything looks like a nail”. I really get that. To want to make an asset for an app the same way we make everything else in an app.

We should be able to treat our PDF generators as just another view, our images as a simple route or component. It makes sense to leverage what already works and be able to summon everything you need into frame. For those gains, for the lack of duplicating your app logic, you start teaching separate and distinct libraries how your app thinks — eventually you’re on the hook to maintain it; beautiful bespoke abstractions and all.

Why do they all end up so fit for purpose?

No matter what software is being written, immediate priorities take the wheel and influence us. Why make a second rate app with a first rate image processor. Maturity of your code matters too. Opportunities to make things better most often come later as new demands arise. Why put the cart before the horse? So you do this one thing now and pit work. But to quote Akbar: It’s a trap!

Why can’t they do it all ?

Because good enough gets us back to higher priority work.
Sometimes, your code needs to make just one type of thing: a PDF, a GIF etc.
Often, you’ll need that thing for just one context (eg for an email)

What’s the incentive to solve for print at that exact moment ? None — for good reason.
The only cost is the risk of task-opinionated code. Tomorrow’s problem.

Why is this such a time sink?

Because making a ‘thing’ was all you wanted. Getting in the weeds on rendering and asset generation as demands evolve means you start writing entirely different software than what you are set out to do.

  • Why is it on you to fix quality issues and maintain that method in perpetuity?
  • Why can’t you know ahead of time what is needed in future?
  • Why must your code adhere to the overly-prescriptive personality of various media generators, each with their syntax, not yours.

By the time you’ve learned how to ‘talk to’’ jspdf — it has become all you can realistically use. Now everything must be done in that way, for that format, to those instructions, or no asset. You’ve committed self-inflicted technology lock-in. You’ll only realise you’re not hitting a nail the first time you’re screwed.

With Make.cm, we set out to build a holistic, scalable and low-dependency solution.
In-part this was for our parent company Outfit.io and in doing so we first asked ourselves:

What would it take for generating various media to no longer distract from making great software?

Knowing the pitfalls of bespoke generator development we were met with our challenge:

Make an enduring service that other developers easily talk to. Something that will survive the evolution of, and differences between:

  • JS frameworks, Vue Angular React, Svelte, NextJS
  • Templating languages, none at all, or mustache, or liquid, Ejs, etc
  • Development tools tools like yarn, npm, docker (personally, I prefer podman)

We imagined the answer as an API, that you can GET with signed URL’s or POST in JSON with your own deeply customisable data object. Made easier with an optional webhook integration.

In 2013 if you had asked me to build this, it would have used phantom, slimer or a similar headless-browser-in-package. In 2021, the best bet might be to go first with headless Chrome using puppeteer, maybe use another generation API with a custom JSON format and custom instructions. All these approaches take you down a road that bites hard once you find your first rut. Next year, or next week, it’s very likely that something new will emerge that offers advantages you would have to refactor in order to leverage. That is, unless you make assets with Make.cm

We saw beyond the tragedy of the latest and greatest and committed that Make.cm will remain current: A constantly best-of-breed service for generating creative materials, one that continuously moves with the times under the hood. One that all types of visual workloads and programmatic needs can rely on.

How do we keep nailing it ? we must!

Over the past 6 years at Outfit, we’ve hired specialists, focused on edge-cases and fixed countless unforeseen quirks — optimisations born at the thresholds of both performance and quality.
We run and scale our service for production already — tool-chaining custom solutions to meet the highest demands of enormous brands with aesthetic appetites to match. We’ve enjoyed every leap forward and thankfully; our customer’s needs have been so distinct from each other, that we’ve had to stay out of our own way — resulting in a fully agnostic generation and rendering service.

We’ve uncovered some truths

  • Few developers liked making asset generation as it represents an exit from their core code. PDF post processing or video generation isn’t the domain of most teams.
  • Doing so always introduces complex dependencies that reach beyond their utility.
  • What gets written is usually coding yourself into a box, and prone to maintainers bit-rot
  • Integration code that gets written represents an uncomfortable burden to track third parties upstream.
  • Edge cases are often surprises (in a bad way)
  • Implementations demonstrate a haunting lack of flexibility. Code becomes too essential to delete but incapable of doing more as new needs evolve.
  • It really hurts watching new solutions become the standard when running a legacy stack.
  • A really really big package.json file scares enterprise maintainers — and rightfully so

So if you’re anything like the friends we already know, you’ll comfortably rely on what we’ve built with make.cm

The code you make is the best code to work with

The same code you use to make your product can make your image assets.
The same code you use to make a print-ready annual report poster can be used to make your ‘year in review video’.

Make is holistic to all kinds of formats, and has some brilliantly easy optionality out of the box — you add whatever else you need and call on it exactly how you want.

Doing both the articulation of your own variables in a data object and the rendering of countless permutations through the same request is honestly quite liberating. There’s really nothing quite like it so I can only suggest you try it out and be ready for your next project.

We’re currently in Beta and to celebrate, we’re giving early adopters a free 5,000 — that’s FIVE THOUSAND synchronous generation credits to kick the tyres. Try it out! https://make.cm

--

--