On Building Features

We've released a couple of features recently at CodePen that I played a role in. It got me thinking a little bit about the process of that. It's always unique, and for a lot of reasons. Let's explore that.

What was the spark?

Features start with ideas.

Was it a big bright spark that happened all the sudden? Was it a tiny spark that happened a long time ago, but has slowly grown bright?

Documenting ideas can help a lot. We talked about that on CodePen Radio recently. If you actually write down ideas (both your own and as requested by users), it can clarify and contextualize them.

Documenting all ideas in Notion

There is tooling (e.g. Uservoice) which is specifically for user feedback guiding feature development as well.

Personally, I prefer a mix of internal product vision with measured customer requests, staying light on the public roadmap.

The addition of design assets on CodePen, one of the recent features I worked on, was more of a slowly-intenifying spark than a hot-and-fast one. It came from years of aggregated user requests. CodePen should have a color picker. That'd be neat, we would think. It should be easier to use custom fonts. Yeah... we also jump around copying code from Google Fonts awful regularly.

Then we get an email from Unsplash that was essentially hey, ya know, we have an API. Hmmmm. You sure do! The spark then was gosh all these things feel really related. They are all things that help you with design. Design assets, as it were.

Perhaps we could say this is a good recipe to kick off a new feature: It seems like a good idea. Your instinct is to do it. You want it yourself. You have enough research that your users want it too.

While you're in there...

The spark has been lit. It feels like a good idea and should be done now. Now what?

When you're working on a new feature for an existing project, you can't help but consider where it fit's into the applications UI and UX. Perhaps it's just the designer in me, but design-led feature development really seems like the way to go. First, decide exactly what it's going to do, be like to use, and look like, then build around that.

I'm always the buzzkill when it comes to non UI and UX features and improvements. I try to turn Let's switch to Postgres into Let's find a way, if we really gotta switch to Postgres, to give something to the users while we do it. But I digress.

I'd wager most new features aren't let's add an entirely new area to the site. Most site work is adding/removing/refining smaller bits to what is already there.

In the case of the new design assets feature we were building, it was clear we wanted to add it inside our code editor, as that's where you would need them. Our tendency is generally let's make a new modal! I'm not anti-modal in a situation like this. Click a button, switch mental contexts for a moment to find a design asset, copy what you need, then close it and use it. Plus we already use modals quite a bit within the editor, so there is a built-up affordance to this kind of interaction.

But a new modal? Maybe. Some things warrant entirely new UI. The minute we start considering new UI though, I always consider that a woah there cowboy moment. Not because new UI is difficult, in fact, because it's too easy. I'd much rather refine what we already have, when possible. That's where this feature took us.

We already have an assets feature, which allows people to upload files that are, quite often, design assets! Why not combine those two worlds? And this is the while you're in there... moment. Our existing Assets modal needed some love anyway. There is a similar backlog of ideas for improving that.

So this became an opportunity to not just create a new feature, but clean up an existing feature. We fleshed out the feature set for existing asset uploads as well, offering easier UX, like click-to-copy buttons and action buttons that allow you to add the URLs as external resources, or pop them open in our asset editor to make changes.

Cleaing up goes for UI design work, front-end code, and back-end code as well. Certainly the CSS, as readers of this site know! Features are a great excuse for spring cleaning.

Who can work on it?

This is a huge question to answer when it comes to new feature development. Even small teams (like I'm on) are subdivided into smaller ones on a per-feature basis.

To arrive at the answer for a new feature, it can be hugely beneficial to one-sheet that sucker. A one-sheet is a document that you construct at the beginning of building a new thing where you scope out what is required.

It forces you to not think narrowly about what you are about to do, but broadly. That way you avoid situations where you're like I'll just add this little checkbox over here ... 7 months later, 2,427 files touched ... done!

A one-sheet document might be like this:

  • Overview. Explain what you're building and why.
  • Alternate solutions. Have you thought of multiple ways to approach this?
  • Front-end overview. Including design, accessibility, and performance.
  • Back-end overview.
  • Data Considerations. Does this touch the database?
  • API and services considerations.
  • Customer support considerations. Is it likely this will cause more or less support?
  • Monitoring, logging, and analytics considerations.
  • Security considerations.
  • Testing considerations.
  • Community safety considerations.
  • Cost considerations.

If you've gone through that whole list in earnest and written up everything, you'll be in much better shape. You'll know exactly what this new feature will take and be closer to estimating a timeline.

Crucially, you'll know who you need to work on it.

This passage, from Fabricio Teixeira, rings true:

Designers have to understand how digital products work beyond the surface layer, and how even the tiniest design decision can create a ripple effect on many other places.

You have to bring other disciplines to the table when you start talking about a “minor design change” in your product. There’s a good chance “minor design changes” don’t really exist.

When it came to our design assets mini feature, one of the major reasons we were able to jump on it was because, assuming we scoped what it was going to do appropriately (see next section), 90%+ of the work could be done by a single front-end developer/designer. Of anyone, I had the most open schedule, so I was able to take it on.

Some feature, perhaps most features, require more interdiciplinary teams. Huge features, on our small team, usually take just about everybody.

Version One vs. The Future

It's highly likely you'll have to scope down your ideas to something manageable. It's so tempting to go big with ideas, but the bigger you go, the slower you go. I'm sure we've all been in situations where even small features take three times as long as you expected them to.

I try to be the guy jamming stuff out the door, at least when I'm a place where I know refininements and polish aren't pipe dreams. I tend to find more trouble with scope creep and delays than things going out too quickly.

When it came to our design assets feature, as I mentioned, I wanted to scope it to an almost front-end-only project at first, so that it didn't require a bunch of us to work on it. That was balanced with the fact that it I was sure we could make it pretty useful without needing a ton of backend work. I wouldn't hamstring a feature just for people availability reasons, but sometimes the stars align that way.

The color-picker part of the design assets modal is a good example of that. Right away we considered that someone might want to save their own favorite colors as a palette. Perhaps on a per-Pen basis or global to their account. I think that's a neat idea too, but that requires some user database work to prepare us for that. It seems like a quite small thing, but we would definitely take our time with something like that to make sure the database changes were abstract enough that we werent just slapping on a "favorite colors" column, but a system that would scale appropriately.

So a simple color picker can be "v1"! No problem! Get that thing out the door. See how people use it. See what they ask for. Then refine it and add to it as needed.

To be perfectly honest, there hasn't been an awful lot of feedback on it. That's usually one for the win column. People vocally loving it is certainly better, but that's rare. When products work and do what people want, the usually just silently and contentfully go about their business. But if you get in their way, at least at a certain scale, they'll tell you.

Perhaps one day we'll revisit the design assets area and do a v2! Saved favorites. More image search providers. More search in general. Better memory for what you've used before and showing you those things faster. That kind of refining might require a different team. It's also just as satisfying of a project as the v1, if not more so.

Here's a better look at what v1 turned out to be:

Another example... CodePen's new External Assets

Speaking of refining a feature! Let's map this stuff onto another feature we recently worked on at CodePen. We just revamped how our External Assets area works. This is what it's like now:

It's somewhat unlikely most people have a strong memory of what it was like before. This isn't that different. The big UI difference is that big search box. Before, the inputs were the search fields, typeahead style. We're still using typeahead, but have moved it to the search box, which I think is a stronger affordance.

Moving where typeahead takes place is a minor change indeed, but we had lots of evidence that people had no idea we even offered it. Using the visual search affordance completely fixes that.

Another significant UX improvement comes in the form of those remembered resources. Whenever you choose a resource, it remembers you did, and gives you a little button for adding it again. Hey! That's a lot like favoriting design assets, isn't it?! Good thing we didn't make that "favorite colors" database column because already we're seeing places a more abstract system would be useful.

In this case, we decided to save those favorites in localStorage. Now we get to experiment with a UI in a way that handles favorites, but still not need to touch the database quite yet. The advantage of moving it to the database is that favorites of any kind could follow a user across browsers and sessions and stuff without worry of losing them. There is always a v3!

There was also some behind-the-scenes updates here that, internally, we're just as excited about. That typeahead feature? it searches like tens or hundreds of thousands of resources. That's a lot of data. Before this, we handled it by not downloading that data until you clicked into a typeahead field. But then we did download it. A huge chunk of JSON we stored on our own servers. A huge chunk of JSON that went out of data regularly, and required us to update all the time. We had a system for updating it, but it still required work. The new system uses the CDNjs API directly, meaning that no huge download ever needs to take place and the resources are always up to date. Well, as up to date as CDNjs is, anyway.

Speaking of a v3, we already have loads of ideas for that. Speed is a slight concern. How can we speed up the search? How can we scope those results by popularity? How can we loosen up and guess better what resource you are searching for? Probably most significantly, how can we open this up to resources on npm? We're hoping to address all of this stuff. But fortunately, none of it held up getting a better thing out the door now.

Wrapping Up

A bit of a ramble eh?

Definitely some incomplete thoughts here, but feature development has been on the ol' brain a lot lately and I wanted to get something down. So many of us developers live in this cycle our entire career. A lot of us have significant say in what we build and how we build it. There is an incredible amount to think about related to all this, and arguably no obvious set of best practices. It's too big, too nebulous. You can't hold it in your hand and say this is how we do feature development. But you can think real hard about it, have some principles that work for you, and try to do the best you can.