How We Work

This document is out of date and no longer represents exactly how we structure our projects and time at Tailwind Labs. I'm leaving it up as-is for now until I have a chance to rewrite it because lots of the content is still true, but we have made some fairly significant changes and I look forward to updating this when I have the time.  — Adam



We're a brand new company, so this just our first stab at capturing our beliefs about work, and creating a system that puts those beliefs into practice. We're going to learn what works and what doesn't, make improvements, and change our minds.

If you have suggestions, questions, or think we're missing something, let us know! Figuring out how we work as a company is a group project and we want everyone's input.


Our work

All of the work we do generally falls into the following five categories.

Projects
Projects are the big important things we’re working on, and always have a deadline associated with them. Everyone always has a project on their plate, and it’s where we spend the biggest percentage of our time — usually 20-25 hours per week.

We keep track of who’s working on what projects in “The Work”:
A list of our active projects in Basecamp. 109 KB View full-size Download

See the "Projects" section later on for a look at how we manage projects in more depth.

Quick ones
Even though we always have projects on our plates, we still have to take care of other small important things when they come up.

“Quick ones” are short but important tasks assigned to people on the team for them to pick off whenever they have a bit of time. These usually aren’t urgent, but it’s good to get to them within a few days of them landing on your plate.
A list of "quick ones" assigned to the team. 81.8 KB View full-size Download
You can take a break from your main project when you hit a good stopping point to tackle these, or take care of them when you’re simply less busy because the project you’re working on is demanding more of someone else’s time than yours.

House cleaning
House cleaning is things like customer support and managing GitHub issues. We’re a small team so we all have to chip in here.

We ask that every person on the team look at the customer support queue in Help Scout twice per day and clean up whatever they can. We don’t get a ton of customer support requests (maybe 10-20 per day) and each ticket usually takes less than a minute to get through, so as long as everyone pitches in it pretty much feels like no work at all. Please go through it once near the beginning of your day, and once before you wrap up.

GitHub issues are a bit more work, and we handle them differently. Every GitHub repository we run has an assigned “issue owner”, and it’s their job to keep things from spiraling out of control. GitHub issues usually aren’t urgent the same way customer support tickets are, so it’s fine if you want to batch this work and spend a few hours cleaning it up once every few days. We make sure to give everyone multiple days off between projects to make sure we have time for this sort of thing.

We keep track of who’s assigned to which GitHub repositories in our GitHub Issue Maintenance doc.

Helping each other out
We really value collaboration and we want to give people room to help each other out and work together even if they are not working on the same project.

If someone could use your help to work on a problem together for a couple of hours, block off some time for it. Similarly if you could use an extra pair of eyes on something, don’t hesitate to ask someone for some of their time, even if they’ve got their own project on the go.

We do more collaboration like this when someone is between projects and helping out with another active project, but there’s time in the week for this even when two people have their own projects going at the same time.

R&D time
Even though we always have projects on the go, you’ll still find yourself with quite a bit of unstructured time for a variety of reasons:
  • Maybe the project you’re on needs more design work than development work right now or vice versa.
  • Maybe you’re on a project with someone else in another timezone, and you want to hold-off on starting the next task until you’re both online to pair.
  • Or maybe you just wrapped up a project and you’ve got a few open days before you start the next one.
If we’re caught up on house cleaning and nobody could use your help on something, it’s totally up to you what you spend your time working on.

Here are a few ideas and examples:
  • Prototype a new project or feature that we haven't put on the schedule yet, and use that prototype as fuel for turning it into a real project for an upcoming cycle
  • Bang out an entire unscheduled small feature in its entirety
  • Write a blog post about something interesting from your recent work
  • Improve some of our documentation
  • Experiment with a new technology you think we might want to use for a future project to help us evaluate if it could be worth adding to our toolkit
You'll have more of this time than you probably think, and it's where a lot of interesting and creative work happens.

What should I be working on?

On a small team where everyone has to do a bit of everything, it's not always easy to know exactly how much of your time you should be spending on different types of work.

To give you a better idea, we've put together this make-believe two-week work journal to help paint a picture of what your days might look like.

Week 1: Monday
  • Checked Help Scout when I started for the day, saw 3 tickets (one person asking to upgrade, another had a license question, and the last one was just a reply to an earlier ticket saying "thanks!") and responded/closed
  • Starting new "Dark mode support for Tailwind CSS" project today, had call with Adam to talk through the details and ask some questions
  • Spent full-day working on proof of concept of dark mode and testing out different approaches
  • Checked Help Scout again at end of day, closed 2 tickets
Week 1: Tuesday
  • Checked Help Scout, closed 3 tickets
  • Spent morning on dark mode feature
  • Paired with Adam in afternoon for couple hours on some hard stuff he was trying to figure out for his typography plugin project
  • Finished day closing a few new GitHub issues and checking support again
Week 1: Wednesday
  • Checked support
  • Had a "quick one" for updating our open job posting to be closed and removing the ad from the Tailwind docs, spent an hour doing that before getting into project work
  • Spent bulk of day continuing to work on dark mode feature
  • Had a 30 minute call at end of day to help Brad with a weird CSS issue he was having
  • Checked support again before wrapping up
Week 1: Thursday
  • Checked support
  • Paired with Brad for about an hour and a half to get some help on the best way to add tests for this dark mode stuff
  • Wrapped up the important parts of the dark mode feature shortly after lunch
  • Spent most of rest of the day catching up on some GitHub stuff, planning to do dark mode docs tomorrow
  • Saw an interesting question from a user on Twitter about referencing default theme values in Tailwind, put together a little demo to help them and also shared publicly on Twitter because thought other people would be interested
  • Checked support again before wrapping up
Week 1: Friday
  • Checked support
  • Spent bulk of the day working on documentation for the dark mode feature, got it finished after lunch
  • Paired with Brad a bit in the afternoon on some work he was doing for the Try Tailwind site
  • Checked support again
Week 2: Monday
  • Checked support
  • Spent a few hours on an extra idea I had for the dark mode feature, turned out to be more complicated than I thought so reverted it
  • Wrote up the announcement post in the afternoon and put together a couple GIFs and screenshots to include to show it off
  • Checked support again
Week 2: Tuesday
  • Checked support
  • Published the announcement post in the morning
  • Spent a couple of hours paying attention to feedback from the community and answering questions about the new release
  • Spent the rest of the day going through some more GitHub issues
  • Checked support again
Week 2: Wednesday
  • Checked support
  • Had a mental breakthrough for the extra dark mode functionality I gave up on on Monday, hacked on it for a couple of hours and got it working, posted a message about it for the team to decide if we should do another minor release for it
  • Paired with Adam for the rest of the day on some improvements he was making to our backend Laravel app
  • Checked support again
Week 2: Thursday
  • Checked support
  • Paired with Brad a bit in the morning on the Try Tailwind site
  • Spent afternoon learning a bit of Svelte and playing with Sapper, used it as an opportunity to put together an official Sapper starter example for our setup-examples repo
  • Checked support again
Week 2: Friday
  • Checked support
  • Saw Adam assigned me to my project for next week which was starting on some animation utilities for Tailwind, so read the kick-off post and browsed around some existing UI kits and CSS libraries to start gathering ideas for what we should consider including. Did a bit of playing around to refresh my knowledge on how keyframes and stuff work in CSS in general.
  • Helped Adam out with some last minute stuff on the typography plugin for an hour near the end of the day
  • Checked support again

Working hours

We work a 40 hour week from Monday to Friday, but how you schedule that time is pretty much up to you. We're a distributed team so there really isn't a standard work day — if you like to work 7am–3pm, or 10am-6pm, or even 6am-10am then 3pm–7pm, go for it.

All we ask is that you co-ordinate your schedule with anyone else you're directly working with to make sure you can get what you need from each other efficiently.

Ultimately all we care about is that we're doing great work, so whatever works best for you works best for us, too.

We don’t track our time and the 40 hours thing isn’t strict by any means — again we just care that we’re putting in an honest days work and making progress on what we’re working on. If you take two and a half hours for lunch to catch up with a friend, no one is ever going to expect you to work extra to make it up or anything stupid like that. If you feel good about what you got done in a day, that’s good enough for us.

Progress updates

Our "What we're working on" project is set up to ask two automatic check-ins.

Every Monday morning it asks "what are you working on this week?" Use this is a chance to think through your priorities and let everyone else know what you're going to be up to. We've found it's really nice to be able to refer back to these during the week when you need to remind yourself what you really wanted to get done.

At the end of every work day (around 4pm your local time, but you can answer it whenever you want) it asks "what did you work on today?" This is a great way to share what you've been up to with the rest of the team, and learn about the work other people are doing. See some previous answers to get a sense for what these updates usually look like.

Something that's important to note — we don't do these progress updates to track how hard people are working or hold them accountable or anything. We do them because we're a distributed team and it helps everyone feel connected and in touch with what we're all up to. It's a social thing, not some sort of Orwellian surveillance strategy, so don't take it too seriously.

Working in public

If you're working on something cool that you think our audience would be excited to see, share it with the world! Post prototypes in Discord, share GIFs and screenshots on Twitter, create little CodePen demos to show things off — anything you can think of.

Working in public has a lot of advantages:
  • It's easy marketing. People love to get a behind-the-scenes look at new stuff before it's done and it gets people excited about what we're working on.
  • It's motivating. It's a great feeling to share a demo on Twitter and see tons of encouraging feedback.
  • It helps us do our best work. We've gotten tons of great ideas from people in our audience when we share unfinished work in public.
Sharing what we're working on is the number one reason we have an audience — nothing is a secret project here.

Serving the community

Although not a direct source of revenue, our open-source projects are our most important work and the only reason our commercial products can even exist.

A huge part of doing open-source well is serving the community and making sure that people are successful with our tools.

That includes things like:
  • Answering questions on our Discord server
  • Participating in conversions in GitHub Discussions
  • Helping people on Twitter
Try to keep your eyes open for opportunities to help people and make time to answer their questions. It's really important that we do our best to make sure people are having a good experience with our tools.



Projects

When we really want to make sure we get something done, we make it a project. Projects each get their own project in Basecamp, and we track who's working on what projects in "The Work".

Projects are how we spend most of our time, and everyone usually has a project on their plate.

Every project has a deadline

When projects don't have deadlines, they tend to go on forever. There are always things you can add or make better, so the work is never "done".

When we schedule a project, it always has a hard deadline. If we think we're going to miss the deadline, we figure out ways to make the project smaller, we never extend the deadline.

Deadlines aren't decided arbitrarily by leadership, we always talk through the project with the people doing the work to come up with something everyone feels comfortable with.

The question we're trying to answer is never:

> How many weeks will this take to build?

Instead, it's:

> Do we think it's possible to build some version of this in one week? How about two weeks?

We're never trying to estimate exactly how long it will take to build something — we think that's fundamentally impossible. What we do believe though is that there are always ways to trim a project down without making it unshippable.

By giving projects hard deadlines, we have a forcing function for getting something done, even if that something looks a bit different than what we had in mind when we started the project.

Project deadlines are captured as due dates in the "Work in progress" area of our "What We're Working On" project in Basecamp, and each due date is assigned to the team members working on that project. All of these dates are visible to everyone on the team on the "Launch Calendar".
Our launch calendar with current deadlines. 183 KB View full-size Download
When you need to cut something on a project to hit the deadline, make sure you capture the decision somewhere so the rest of the team is in the loop. A great place for this is as a comment on an individual to-do in the actual project, for example if you decide to ship something with a rough GitHub README instead of a proper documentation site, you could write about the decision to skip the docs site on an existing "Create documentation page" to-do, and move that to-do to a separate list like "Not Doing".

If you need to cut something but aren't sure what to cut, ask for input. We can figure out a way to trim down the project together and then document our decision in Basecamp.

40 hours is plenty

We never work overtime to meet a deadline. Deadlines are about shipping something in a pre-determined amount of working hours, not about burning the midnight oil to cram the work in at any cost.

A two week project is ~60 hours of work — about 5 hours per day over a 12 day period (since we ship on Tuesdays). If we can't live up to our original vision in that amount of time, we change the vision, not our work schedule.

Weeks, not hours

When we schedule a project, the time we decide to allocate to it is always measured in weeks, not days or hours. If something deserves to be called a project, it deserves at least a week to get it right.

Some small projects are scheduled for just one week, but we think two weeks is sort of the sweet spot for most projects. Occasionally a really big project might be scheduled for as long as four weeks, but if something feels like it’s going to take longer than that, we try to break it into multiple projects that we can ship independently.

For example, building a comprehensive headless Vue component library is way too much work to do in four weeks. So instead, we might make a project like "Headless Vue Listbox component", and focus on that one component for two or three weeks. We can release that component when it's done — we don't need to wait until we've finished the whole library to reach a shipping point.

If a project contains so many unknowns that we can't figure out a way to cut it into multiple smaller projects, it's usually a sign that it's not ready to actually go on the schedule yet. Instead, we experiment with these sorts of projects during R&D time until we have enough information to feel confident scheduling a 2–4 week project.

If something feels too small to allocate a full week, we try to either batch it with some other related work into a bigger project, or make a note of it as something to pick off during R&D time instead.

Kicking things off

We always start new projects on Mondays, and we always post a kick-off document towards the end of the previous week that outlines what we're trying to do.
Example of a recent kick-off document. 219 KB View full-size Download
When you're going to be working on a new project, spend some time reading through the plan at the end of the week before the new project starts so you have a chance to think of any questions or concerns you might have. You can add your comments as replies to the kick-off document.

For most projects, we do a kick-off call on Monday morning to make sure everyone is on the same page and knows where to start. After that, you're in total control of how you structure and execute on the actual work.

To-do lists

We believe in assigning project, not tasks. We use to-do lists in Basecamp to keep track of what's left to do, but we leave it to the team to add and manage those tasks — we never add them on your behalf.
Example of a to-do list from a current project. 160 KB View full-size Download
If you need help making a plan or figuring out where to start, let's work together to figure it out, of course! But we don't want to prescribe some exact set of instructions for you to follow by default, we care about giving you the freedom to structure the work the way that makes the most sense to you.

Usually people start a project by jotting down some things they know they need to do, and while they are working on those they inevitably discover more tasks they need to do that they don't want to forget and they add those to the list, too. Ryan Singer talks about this idea as imagined vs. discovered tasks.

Keeping these to-do lists visible to the whole team in Basecamp is helpful for feeling like we have everything organized and in one place, so please use Basecamp instead of a personal to-do app, especially since you'll often be working together with other people on the team.

Seal it with a blog post

Part of finishing any project is putting together an announcement post for our users and customers.

For us this serves two purposes:
  1. It lets people know what we've been working on and shows them that we're actively developing new ideas.
  2. It keeps us honest about making sure our projects are really "done".
Number two is the most important one. If you don't feel comfortable announcing something, it's probably not really ready to be announced, which means we've made a mistake in our process somewhere.

By committing to putting together an announcement at the end of every project, we have a built-in gut check for making sure we're actually finishing what we start before moving on to the next thing.

These announcements will be in the form of blog posts soon (we're working on the Tailwind blog next week!) but in the mean time, an announcement post on our Discussions forum works great.

Announcements can be short — they definitely don't have to be huge in-depth postmortems. This announcement on "Canceling Ongoing Deployments" from the Vercel blog is a great example of what we should aim for.

The Monday afternoon before a launch is a great time to start putting together the announcement.

Ship on Tuesdays

Every project starts on a Monday, and is scheduled to ship on a Tuesday. That means that even though we think of projects in terms of weeks, every project actually has a couple of extra days allocated to it.

A two week project that starts on November 2nd ships on November 17th, not November 13th, so we actually get 11 days + the launch day, not just 10.

We do this for a few reasons:
  1. It's a bad idea to ship anything at the end of the week because no one is going to be around to deal with urgent issues if they happen over the weekend.
  2. Tuesdays are a great day to share news, because it gives our audience enough time to get through their Monday backlog but is still early enough that people aren't day-dreaming about the weekend yet.
  3. It leaves a nice chunk of time after a launch for house cleaning, helping out on other projects, and R&D.
We try to ship things by 1pm EST on Tuesdays whenever possible. Make Monday your last day of real work on a project, and use Tuesday mornings for small final checklist items like polishing the announcement post.

Dealing with surprises

Sometimes important works lands on our plate unplanned. For example, a month or two after launching Tailwind UI, we started noticing an increase in database errors due to extremely long query times. This was impacting the browsing experience for all of our customers so we had to drop what we were doing to diagnose it and fix it, which ended up involving migrating our production database out of DigitalOcean’s managed database service and on to a new server.

Even though this only took 3-4 hours of actual work, it threw a big wrench into the schedule for that day, meaning the remaining 3-4 hours were broken up into multiple smaller chunks of time and making them much less productive than they would’ve been otherwise. We got maybe 10% of our normal amount of scheduled work done that day, not 50%.

Things like this don’t happen that often but when they do there are a few of ways they can go:
  1. Nothing is actually disrupted because the surprise work can be handled by someone who is currently on roaming hours anyways.
  2. Work is disrupted, but at the end of the day it doesn't get in the way of shipping the regular project on time anyways.
  3. Work is disrupted, but we can cut a bit of scope on the regular project and ship it on a Tuesday like originally planned.
  4. Work is disrupted, and we push the regular project launch to Wednesday or Thursday and eat into a day or two of roaming hours.
Option 1 is better than 2, 2 is better than 3, and 3 is better than 4. Hard deadlines are our most powerful constraint — it's okay to push something to Wednesday or Thursday when we absolutely have to, but if we do it too often we'll stop taking them seriously.

What's on deck

We always have more projects listed in Basecamp than what we're actually working on. Active projects (projects with an upcoming deadline) are prefixed with "🟢" so you can easily tell at a glance what projects we're actually working on. We recommend "pinning" active projects to the top.
Our active and on-deck projects in Basecamp. 163 KB View full-size Download
Any projects without the green circle emoji are "on deck". These are projects we aren't working on right now but are going to work on soon, and they're the ones we choose from when we're putting new projects on the schedule. We keep them open in Basecamp ahead of time so we have a place to talk about them and flesh them out when they are still in the early planning stages, and so everyone on the team has a bit of a view into the future.


Development practices

Thoughts on code quality, testing, code review, pair programming, version control, and more. Coming soon!