Cushion Project blocks
Cushion Redesigning the homepage
Cushion Multiple timelines
Cushion Archiving and estimate differences
Cushion Multiple financial goals
Cushion Zooming in on the timeline
Cushion Currency
Cushion Preferences, accounts, and typeface change
Cushion Sending out the first email
Cushion Currency inputs, notifications, and invoice nets
Cushion Dots and lines
Cushion Calculating in the database and revealing tendencies
Cushion Improved form UX
Cushion Cushion is online
Cushion Schedule timeline patterns
Cushion A slimmer schedule timeline
Cushion The schedule timeline
Cushion Plugging in real data for the first time
Cushion Transitions and project lists
Cushion Death to modals
Cushion The individual project page
Cushion Estimated incomes and talks with other freelancers
Cushion Statuses to lists and the paid beta
Cushion The timeline
Cushion Invoice terminology
Cushion Modal forms
Cushion Wiring the backend to the frontend
Cushion Balancing design and dev
Cushion Timecop, Monocle, and Vagrant
Cushion Going with Ruby and Sinatra
Cushion Ditching local-first and trying out Node.js
Cushion Switching to AngularJS
Cushion Building the Table with Vue.js
Cushion Clients, Projects, and Invoices
Cushion Introduction (to the Cushion journal)
Cushion Cushion
2014
Cushion Retention through useful features
Cushion The onboarding checklist
Cushion Spreading the word
Cushion From beta to launch - the subdomain
Cushion From beta to launch - sign up
Cushion From beta to launch - messaging
Cushion Launch
Cushion Authenticating with 3rd party services
Cushion Intro to integrations
Cushion Inspiration vs imitation
Cushion The emotional rollercoaster
Cushion Designing project blocks
Cushion Everything in increments
Cushion Deleting your account
Cushion Designing the subscription page
Cushion Rewriting the timeline
2015
Cushion Funding Cushion
Cushion Hiring a team of freelancers
Cushion Taking a real break from work
Cushion Slack as a notification center
Cushion Document your features
Cushion 300
Cushion Vacations
Cushion Offering discounts
Cushion Waves of traffic
Cushion Less blogging, more journaling
2016
Cushion My typical week as a founder
Cushion Building components in a sandbox
Cushion Reactive time with Vue.js
Cushion Visualizing daylight saving time
Cushion Recording screencast GIFs
Cushion Writing a job listing
Cushion Using feature flags to run betas
Cushion Our first company lunch
Cushion How to embed Vue.js & Vuex inside an AngularJS app... wait what?
2017
Cushion The “Update Available” alert
Cushion Improving readability with bigger fonts and higher contrast
Cushion My design workflow
Cushion Simplifying our build process and SSL with Cloudfront
Cushion Restructuring an evolving app
2018
Cushion The new invoice page is live
With only days before the SCA deadline, I launch the new invoice page with to be SCA-ready while also paving the way for more improvements.
Cushion Integration testing the invoice page with Cypress
Wrapping up my work on the invoice page, I set up integration testing using Cypress to make sure that everything continues to work end-to-end.
Cushion Tidying up as you go
Continuing to make progress on the invoice page, I talk about some of the ways I’m improving the codebase along the way.
Cushion A subsidized plan for 2021
A chat with a user leads me to consider a subsidized plan for the New Year to help folks through the pandemic.
Cushion Redesigning the invoice page for SCA with Stripe Elements
I pause work on the account page to make sure Cushion’s invoice payment integration is ready for the SCA deadline.
Cushion Rethinking the pricing page
In needing to redesign the pricing page for the new account section, I decide to rethink the structure of Cushion’s existing plans.
Cushion A dev’s troubleshooting journey
An innocent bug report unfolds into a roller coaster ride of a troubleshooting journey.
Cushion Scaffolding the account page
As I begin building Cushion’s new account page, I start by scaffolding a static version of it and building the components it requires.
Cushion Redesigning the account section for SCA with Stripe Billing customer portal
With SCA regulation going into effect at the end of the year, I prioritize migrating to the Stripe customer portal, which means redesigning the account section.
Cushion Designing a new layout system
After years and years of incrementally tweaking the design of Cushion, I take a holistic look at the layout system.
Cushion Redesigning the blog
After redesigning Cushion’s homepage, I take the next step in migrating to Contentful by rethinking the blog.
Cushion Animating the new homepage hero
To keep my mind busy while dealing with a tough time, I distract myself with Cushion’s new homepage animation.
Cushion Responsive images for different layouts
While building Cushion’s new homepage, I go the extra mile to swap out better-fitting images for different breakpoints.
Cushion A flexible way of using Nuxt.js with Contentful CMS
After migrating Cushion’s changelog to Contentful, I move onto the homepage, where I narrow in on an approach to compose pages entirely in the CMS.
Cushion Migrating the changelog to the Contentful CMS
In my initial step towards migrating Cushion’s marketing site to Contentful, I start with the changelog.
Cushion Promoting invoicing to the main nav
I reworked the main nav to include invoicing, which was met with a wave of thanks from users.
Cushion The next big rocks
After launching Cushion’s new onboarding, I detail the next few items on my to-do list, which for once are not new features.
Cushion Onboarding is live
A weekend turned into a month, but Cushion’s new onboarding is finally live. Instead of focusing on the launch itself, I talk through my favorite part.
Cushion Composable onboarding
To provide a more pleasant codebase for Future Jonnie to inherit, I restructure the onboarding to be composable and easily testable.
Cushion Writing my own utility methods
I decide to write a few utility methods myself, rather than relying on 3rd party library, and I’m glad I do.
Cushion Using a utility library vs building my own
Torn between adding a dependency for a utility method or writing it myself, I talk through the pros and cons of both approaches.
Cushion A reminder to write
Determined to launch thew onboarding flow, I forgot to write for a week and it shows.
Cushion The date picker component
Continuing my work on Cushion’s onboarding flow, I build a new and improved date picker component.
Cushion Building components for the long run
With my recent work on Cushion’s new onboarding flow, I take a meandering walk through the new components I built for it that are all typed and tested.
Cushion Investigating inflection points
Stepping back to look at Cushion’s growth over its entire lifetime reveals a crystal clear moment when everything went south.
Cushion Recalibrating my estimates
I start working on the new onboarding flow, but quickly realize it won’t be a weekend project.
Cushion A friendly onboarding flow
As a first stab at onboarding, I design a flow that includes myself asking questions, which hopefully provides a friendly intro to the app.
Cushion Bringing back onboarding
In an attempt to ease people into the app rather than pushing them out of the airplane, I decide to bring back a proper onboarding flow.
Cushion Rough sketches
After feeling reluctant to reveal any design progress, I decide to bite the bullet and share a few rough sketches—no matter how uncomfortable it feels.
Cushion Flattening the nav
Continuing the idea of the single click, I talk through a potential path to flattening the nav from multiple layers down to one.
Cushion Well, this is embarrassing
Browsing through Cushion, I realize something strange. As I troubleshoot the anomaly, I discover an embarrassing truth.
Cushion Sending newsletters again
I sent my first Cushion newsletter in over a year and a half, which sounds crazy, but nonetheless, it feels great to send them again.
Cushion Validating assumptions
Before diving into analytics, I decide to spend time writing database queries that could validate some of my assumptions using existing data.
Cushion Intentional analytics
After building Cushion so far based purely on assumptions and intuition, I finally start to think about using analytics to help guide me.
Cushion This app has good bones
A thought-provoking conversation leads me to realize that Cushion is still solid and worth iterating on, instead of restarting from scratch.
Cushion Keeping API requests simple
After establishing a new guiding principle to keep API requests simple, I describe how I could refactor a complex view that relies on a heavy API request.
Cushion A single click
I discuss a pain point in the current Cushion involving the number of clicks it takes to get to where you need to go. What if it only took one?
Cushion Shaping Vuex through testing
Cushion Excluding a folder from VSCode’s search (and disabling Jest’s generated coverage reports)
Cushion Retaining state with the router in a single page application
Cushion Custom focus rings using :focus-within
Cushion Testing v-on="$listeners" in Vue.js
Cushion Vue + ESLint + Prettier conflicts
Cushion Speeding up Jest tests with --runInBand
Cushion Moving the Cushion Journal to my blog
Cushion Updating Sentry
Cushion Updating Skylight and dealing with ActiveSupport
Cushion Reducing Heroku CI time by 35% for an extra penny
Cushion The build failed, but I swear it wasn’t me
Cushion A hiccup with subdomain routing
Cushion Upgrading to Ruby 2.7.1
Cushion QA’ing pull requests using Heroku Review Apps
Cushion Subdomain routing in Sinatra
Cushion Redirecting the Heroku “Open app” button to a custom domain
Cushion Reloading Ruby with Sinatra::Reloader
Cushion Exploring a modern Cushion
Cushion Migrating the Cushion website to S3 to avoid dealing with SSL
2020
Cushion Quick launches after a big launch
After launching the Schedule timeline beta, I’m able to easily launch a handful of smaller releases to keep progress going.
Cushion The new Schedule timeline is in beta!
To get folks to start testing the new Schedule timeline early, I released the initial beta this weekend.
Cushion Zooming into the schedule timeline
With the schedule timeline nearing a beta launch, I take a couple more weeks to sneak zooming into the feature set.
Cushion Flipping the schedule timeline
In an unexpected moment, I decide to try vertically flipping the new schedule timeline, so projects stack from the top.
Cushion Handling timeline labels
Determined to always display labels on the new schedule timeline, I detail all the edge cases I’ve gotten myself into.
Cushion Visualizing projects in the new schedule timeline
Now that I have a canvas for the new schedule timeline, I need to fill it with projects.
Cushion A freeform scrolling timeline
After thinking through a modern schedule timeline, I start by enlarging the timeline to full-page and adding freeform scrolling.
Cushion Exploring a modern schedule timeline
Taking a break from the Clients section, I get a burst of inspiration thinking about scheduling.
Cushion Revisiting the UX for client notes
Continuing work on the new Clients section, I revisit client notes, but with a few UX improvements.
Cushion Overflow shadows using the Intersection Observer API
Improving a upon the overflow shadows in Cushion, I replace scroll events with the Intersection Observer API.
Cushion Addressing beta feedback for the new Clients section
After rolling out the new Client section to a few dozen beta users, I start applying their feedback.
Cushion Upgrading to Vue 3
While making forward progress with the new Clients section, I take a break to upgrade the new codebase to Vue 3.
Cushion A Safari performance issue and other stresses
An already stressful time is made even more stressful by a Safari performance issue with nested grids.
Cushion Time period filter and totals for the Clients section
With the Clients section beta up and running, I launch my first incremental update.
Cushion A video call with a friend about marking projects as paid
A video call with a friend provides some interesting insight into a potential direction for restructuring the app.
Cushion The new Clients section is now in private beta
After a heads-down week, I managed to reach the first milestone in releasing the new Clients section—private beta.
Cushion Stabilizing PostgreSQL memory issues with pgbouncer
In an update of the database memory saga, I discover pgbouncer, which puts a stop to the constantly climbing memory woes.
Cushion A top-level “Clients” section
With the sidebar navigation ready to deploy this weekend, I get an early start on the top-level “Clients” section.
Cushion Improving the sidebar nav
After regretting, but living with, the skinny sidebar nav of obscure icons, I finally set a course to improve its UX.
Cushion Sending blog posts as emails - Part 2
Following up on the initial proof of concept, I build the complete system to send journal posts as emails.
Cushion Sending blog posts as emails
In an effort to grow readership, while also prototyping an idea, I start building a system to email my posts.
Cushion Sticky line item totals
Putting the final touches on the invoice form, I apply a sticky behavior to the line item totals.
Cushion Little details: Overflow shadows
I spend extra time getting a little detail right by tying shadows to whether the underlying content has overflow.
Cushion Redesigning the flow for importing tracked time into invoices
With the last remaining to-do on my list for the new invoice form, I tackle the flow for importing tracked time.
Cushion A week of cleanup
With the inline forms behind me, I spend a week cleaning up the codebase with a focus on Cushion’s form states.
Cushion Building the inline form system
After detailing how I planned to build inline forms in Cushion, I went ahead and built the first one for creating clients inline.
Cushion Inline forms and the weight of the next big task
In between big tasks, I distract myself with smaller tasks until I’m ready to finally face it—inline forms.
Cushion Designing a breadcrumbs component
Chopping away at the new invoice form, I designed and built a new component for breadcrumbs.
Cushion Thinking about a “test mode”
Aggravated by people signing up with no real intention to use Cushion leads me to consider a “test mode” where they can try the app without signing up.
Cushion Redesigning the invoice line item footer
While redesigning the invoice form, I share the decision-making behind the design of the new line item footer.
Cushion Migrating CI to GitHub Actions
Frustrated with Heroku, I start migrating away from it, beginning with continuous integration.
Cushion Troubleshooting the database upgrade
Upgrading Cushion’s database leads to a week of troubleshooting performance issues.
Cushion Upgrading the production database
After receiving an email from Heroku to upgrade Cushion’s database, I upgrade Cushion’s database.
Cushion 7 years old
With Cushion reaching the 7-year mark, I reflect on its life and plot a course for its future.
Cushion Thinking through a new invoice form
At the fork in the road, I choose the invoice form as the next step in renovating Cushion, including a long-awaited list of improvements.
Cushion The calm after the sprint
With a couple big launches behind me, I think about what to tackle next or whether I need to pick a direction just yet.
Cushion The new account page is live
After launching Cushion’s new invoice page last week, I launch the new account page this week with a ton of other goodies.
2021
Cushion “Software” with a capital “S”
I hit a roadblock designing a UI that didn’t excite me, so I decide to take a step back and rethink a more personalized design.
Cushion Adding hotkey labels to the UI
After taking a short break to collect myself, I eased back into work with a low-priority feature that I’ve been itching to add for a while.
Cushion Moving & resizing workloads in the timeline
While building the drag & drop interaction for workloads, I accidentally created the coolest interaction I’ve ever made.
Cushion Editing workloads in the timeline
After taking a couple weeks off to move into our new home, I’m back in the saddle with creating and editing workloads.
Cushion Vacations in the timeline
To continue reaching feature parity with the existing schedule view, I added vacations to the new timeline.
Cushion Nested modal drawers with parallax
Over the weekend, I ate the broccoli and built a nested drawer system, but ended up with a delightful parallax effect.
Cushion The evolution of a tooltip design
The full circle journey of designing a tooltip that’s both simple and useful.
Cushion Estimated workloads in the schedule timeline
After visualizing tracked time, I jumped from the past and into the future to visualize estimated workloads.
Cushion Total tracked time in the schedule timeline
Now that Cushion can visualize tracked time, the next step is to combine tracked time and highlight when you overworked yourself.
Cushion Lazy loading tracked time in the schedule timeline
After being close to launching tracked time in the schedule timeline beta, I decide to spend an extra week adding lazy loading.
Cushion Visualizing tracked time in the schedule timeline
Straying from the plan to bring the timeline to 1:1 feature parity with the existing timeline, I visualize tracked time.
Cushion Duplicating an invoice
I take a short break from the timeline beta to launch the ability to duplicate an invoice. No big deal.
Cushion Grouping and archiving projects in the schedule timeline
On the new path of pursuing a list-based layout, I group the projects by list and add an archive filter.
Cushion One step back, two steps forward
Foreseeing a problematic future with the stacking layout, I rethink the direction and end up down a better path.
Cushion Project actions in the Schedule timeline beta
After adding the ability to add and edit projects in the Schedule timeline, I implement more detailed interactions with project actions.
Cushion Creating a project via form in the schedule timeline
Back to working on the app, I take the leap into creating projects, but via form first instead of click & drag.
Cushion New year, new homepage
I spend my holiday break bringing more fun to the Cushion homepage with a new design, full of illustrations and animations.
2022
Cushion Building a table for the nth time
Now that I have data to wire up, I set out to build a table component, but first I revisit past attempts.
Cushion A return to tabbed navigation
With a focus on navigation, I return to the early days when Cushion had a simple tabbed nav.
Cushion End-to-end testing with Playwright
With the stack picked out, I set up end-to-end testing from the start, so I can get in the habit of testing user flows without any excuses.
Cushion Vercel, Supabase, Vue, and Vite
As I rethink Cushion in the modern age, I detail my choices for platform, stack, and database.
Cushion Imagining Cushion circa 2016 in 2024
With Cushion’s 10-year anniversary approaching, a theory leads to an attempt at a modern upgrade, but with 2016’s feature set.
Cushion A weekend marathon of an infrastructure upgrade
I spent a weekend upgrading Cushion’s Heroku stack and Ruby version, which sent me down a path of fixing hundreds of failing tests and removing a feature.
2023
Cushion Cleaning up the cobwebs
After years of side-eyeing an unreleased feature that has been nagging me while slowing down the app, I finally take the time to remove it from the app.
Cushion Building a table for the nth time - Part 2
Following up on the initial post about building a table in Cushion, I actually detail my approach this time.
Cushion How to use Playwright with GitHub Actions for e2e testing of Vercel preview deployments
I spent way too long trying to find out how to set up e2e testing with Vercel preview deploys, so I wrote a quick post to save others.
2024
Cushion Eating my own dogfood again
Now that I’m freelancing full-time, and using Cushion again, I’ve fallen in love with it all over again, but I also feel every rough spot.
2026