This is part one of the FeatureCat Diaries-series. FeatureCat is a feature- and feedback management SaaS I am building in public. This is a sort of Captain’s log, where I am rambling about my progress.
It’s February 2021 and I have an idea
I want to build an app for feature and feedback management.
I’ve been carrying the idea around with me for a while and now finally convinced myself to build it. There’s actually a slide deck I built in March of 2020 when I pitched the idea to a couple of friends, and this was the pitch: Getting any user feedback is hard. And getting good feedback is even harder. And if you get a lot of it, keeping track of what’s requested and providing public accountability - well, that’s hard as well.
FeatureCat proposes a solution: a platform to collect all kinds of information of what is requested (called artifacts in the app - like atomic requirements), and ways for user to directly suggest and vote on new features. The initial use case I’ll focus on is enabling feedback collection in my iOS apps: users can visit a feedback board in the app, are automatically logged in and can vote on features and suggest new ones.
The goal is to lower the barrier for users to provide new ideas by offering a place to do so that does not take them out of the app (e.g. having to send emails) and allowing them to vote on existing feature requests (coming from other users or features I am considering myself).
Hey Rails, lets meet at the basecamp
It’s gonna be a Rails app! I really like Ruby on Rails, and I only know Ruby on Rails (thanks to the amazing book by Michael Hartl). I’ve been working on a different project for a while now and was able to gain some initial experience.
This is also a great excuse to go all in on Hotwire from the beginning. Here’s the plan:
- Web framework: Ruby on Rails 6 on Ruby 3.0.0
- View rendering: standard Rails ERBs with Hotwire (Turbo Drive and Frames), plus Stimulus sprinkles where needed
- Hosting: Heroku or DigitalOcean’s App platform, with AWS services where needed
- User authentication: Devise & Devise-invitable
- CSS/UI Framework: Bulma 0.9.2 (I know Tailwind is all the rage, but Bulma is what I know. It’ll do fine)
- Payments and billing: Stripe or Paddle. We’ll see with how much VAT Moss and sales tax I can manage.
For the sake of completion, I’ll work in VSCode on my MacBook Pro and push my code to Github. HTTP testing is done in Insomnia, design in Sketch.
Off to the races.
Etch A Sketch
It’s Sketch day! I have an initial color scheme in mind, which I would describe as a Stripe-inspired take on the default Bulma theme. My primary color is a deep purple, with a lighter blue-ish variant as a secondary accent. Other than that, there’s green/yellow/red for success/warning/danger.
Since the name FeatureCat (the good old what it does+animal combo that brought you Bannerbear, FeedbackPanda and RevenueCat) popped up in my head on a run a few months back, I bought a whole bunch of domains (as one does). Now I need the cat.
That is the initial design, colors and cat and all. Lots of REST-resources hiding behind those navigation items already:
Features are what the app is all about. One thing that I always found challenging in my day job (product/project management) and in my indie work (iOS apps) is that feature requests have a lot of minutiae and nuance, which is hard to distill into a single title.
That is where artifacts come in. An artifact is a singular, atomic piece of information that, in combination with a range of other artifacts, comprise the requirements for a feature. These might be suggestions from multiple users for the same thing, but each being slightly different (same, same, but different). They might be inputs from stakeholders, emails or other documents, ROI calculations or business models, user testings, design inspirations — whatever.
There are a variety of requirements for each feature, and having all these in one place (and assigned to the feature they influence) should be a key differentiation for FeatureCat. New artifacts (user suggestions) arrive in the inbox and can be processed by team members by either assigning them to existing features, or creating new ones (or shoving them in the dreaded backlog).
Boards are collections of features that users can vote on. Not sure about the wording and organization here, but it’ll do for now.
Users are users of the product who have submitted suggestions or voted on features. In addition, I want to pass along information about the user on their board visit (e.g. how long have they used the product, what device are they on, etc.).
Lastly, there is the roadmap. That’s both internally and public facing. Communicating reliable roadmaps to internal stakeholders is hard, and I think I can come up with a good way to visualize it in a tool that already has all the things that are on the roadmap (since all features live in FeatureCat). The second part is public facing and is about a public roadmap to give guidance to users and provide accountability.
The rest is regular SaaS admin panel stuff. Settings, team management, notifications, search and all that jazz. Oh, and a feedback box. Which creates artifacts that directly land in the artifact inbox for FeatureCat in FeatureCat. Full circle dog fooding.
So that’s the basic design. Next up: building it.
A plan’s a plan
Since this is going to be a big project, I want to make sure I can get a first version in front of users as soon as possible. Here’s my thinking:
- Build public facing boards and test them inside my own iOS apps. Let users suggest and vote on features and see what happens. The internal admin panel can be basic
rails scaffoldsfor the time being. I call this the alpha phase.
- Find customers for FeatureCat. Ideally other indie developers with mobile apps, since that’s something I know and deeply understand. For that I need multi-tenancy and a decently working admin panel. Let’s call that the closed beta. No billing necessary at this point. I’d be glad to find anyone who might give it a try.
- Early access! Find customers who want the product. That means by now it needs billing and payments, basic documentation and it should be somewhat reliable. I might be able to support all customers with onboarding, but it should be on the way to self service.
- Launch! Everything leading up to this point is to validate that the product and core customer journey work, both from a UX perspective (customers understand what to do) and from a technical perspective (self-service works and nothing major breaks). Whether a public launch means a flood of new signups or a dribble — we’ll see.
- Profit? Thousands of customers. Or one. Who is me, because no one else cares. It will be a great learning experience either way.
IT’S TIME TO BUILD
rails new featurecat-app
First, a basic data model for public boards, with artifacts and features, users (not the admin type, but the ones who are automatically signed in to the app when visiting the feedback board) and votes.
I started with basic
rails scaffolds on artifacts and features to get the app up and running, then got to work on the public boards. These are supposed to be embeddable into any mobile app (e.g. with WKWebView on iOS) and allow users to both vote on features (create a vote for a feature) and submit new ideas (creating new artifacts). Both of these are forms that
POST to controller methods.
One thing I want to offer is user authentication and authorization. Authentication is required to identify the user on return visits and show them their previous votes. I also want to capture data about the user like device type or how long they have been using the app, which could be submitted on the first visit in the params or in the request body.
The authorization part is trickier: the boards themselves should be publicly accessible by default, but I want to limit voting and submissions to users from within the app. There needs to be some kind of token or key… not sure how to handle this yet.
Insomnia and Redirects
I decided against URL params in favor of using a JSON body in the request, since it allows me more flexibility in the data I can attach and is always encrypted over HTTPS. While you can submit a request body in a
GET request, it’s flakey and does not feel right. I changed the identification to be more of a regular “sign-up”: You configure the URL for the WKWebKit view with a
POST request and can include both a bearer token (Authorization) as well as a JSON request body.
The JSON request body has a
user_id, which is persisted locally on device and can be resubmitted every time the board is opened to authenticate the user. There’s also a
user_properties key, which for now simply gets stored as a JSON in the FeatureCat database and can contain arbitrary properties.
That gets posted to the
/identify path, the controller parses the request and either creates a new user or loads them by their identifier, starts a session and redirects to the public board path. From now forward, all actions by the user are identified by the session - GREAT SUCCESS. Boards are working now and all users are authenticated.
I’m probably overthinking the security aspect. All I am building prevents non-users from providing feedback, which is not the biggest concern in the beginning.
As much as I love Rails, the issue with using the newest Rails and Hotwire with its websocket magic is that when I get stuck, Rails discussions on StackOverflow are a decade too old. Rails has changed a lot and turbo_streams’ documentation is “sparse”.
I fought for hours with form submission responses only to realize I forgot to add the turbo_stream one. The rest of the day was spent on fiddling with the public board’s submission modal, which now looks exactly as it did before and I am one day older.
With the first public board version working, I remembered that Tailwind CSS is all the rage. So I created a new branch, stripped away all of Bulma, implemented the official-but-not-official Tailwind Rails gem and got to work.
Bulma does have scheme compatibility, but does not natively support dark mode. Since I’m relying on web views in iOS apps for the public boards, dark mode had to be supported. Nothing kills your willingness to provide feedback like coming from the app’s dark UI late at night and then staring directly into a super nova of a feedback screen. To prevent retina frying, the public boards screen has to support the dark theme media query.
In the end however, after an evening of rebuilding a single basic screen in Tailwind and not having it even close to what I had before, I resorted back to Bulma and its dark-mode extension. I’m sure Tailwind is super utilitarian, but that means building everything from scratch. Ain’t nobody got time for that (at least not in the “get-it-out-the-door-asap-phase”).
The Bulma dark mode required some fencing with the Rails asset pipeline and adding a lot of missing styles, but I’m happy with the way it looks now.
I have 4 apps in the App Store right now, and all need to get some FeatureCat. Which means, multi-product support should be there right from the start to maximize exposure.
I created a product data model which includes a subdomain string, since that’s how the public boards are accessible on the interwebs. All I had to do was to add some routing magic to Rails and setting
before_actions. Now the public board for Leap Habits is available at leaphabits.domain.com (or locally at leaphabits.lvh.me:3000 - lvh.me is super useful for localhost subdomain testing).
I added configuration to the products model to theme the public boards page with stuff like title, description, icon and brand colors. One last thing was to make sure that all non-registered subdomains get redirected to a friendly “not-found”-page. Once customers can create their own products, I’ll have to do a basic subdomain validation to make sure no-one registers
admin and the like.
I also chose to get rid of boards for now (the model that was behind the navigation option in the first Sketch screen, not the public variety I just finished). Public boards and a different board model even confused me at times, which meant they had to go. For know, the only boards are public boards.
The admin panel
It’s too early for a detailed admin panel (the one were customers can manage and view their data, not the one I’ll be using to manage customers). I’ve created the first models and controllers with
rails scaffold, which should do fine for my personal testing. But since I’m fussy and like to look at a somewhat nice UI, I spent a few hours polishing it up.
For the initial launch, I’ve got artifacts, features and users working. Dashboard and Settings remain empty and the entire navbar is dumb UI. Eventually these private routes and controllers will have authentication and authorization with Devise, but for know I’ll just slap HTTP Basic Auth on top.
Deployment and Testing but not Testing
I’ve used Heroku and various AWS services in the past, but recently came across DigitalOcean’s new App platform. I really like the whole developer experience over there, so DigitalOcean it is.
After a couple of development days, I deployed the code on DigitalOcean for the first time and… nothing. First bundler refused to work, then image assets were missing and crashing the views, then wildcard subdomains weren’t working. When I got that sorted out and was excited to add my first feature, I noticed the forms crash. DigitalOcean will have to endure a myriad of deployments.
There are a couple of things left to fix and do: I try to always use I18n-files for my Rails app to make it translation ready. That does mean however that I usually forget to add the English translations. Testing to the rescue!
As much as Chief Rails Explainer Michael Hartl primes you for test driven development, I do find it cumbersome in the early stages. I never even know what the spec is before trying a dozen variations. But for a production app, testing is non-optional. I’ll ramp up tests before inviting customers (don’t tell that to the non-testing iOS development side of me).
I set up the Minitest suite (requires the
rexml-gem for Rails 6.1+, which cost me an hour worth of trial and error on another project). For I18n testing I’ll use the super helpful
$ i18n-tasks add-missing to the rescue.
For monitoring I’ve set up a status page on UptimeRobot and created a few bots that ping the public boards and the admin panel every couple of minutes. Nobody needs a status page at this point, but UptimeRobot offers one for free. I’ll need exception monitoring with the likes of Honeybadger in the future, but that’s not a day-one kind of job.
What am I selling? (Aka “I need a landing page”)
The app with its public feedback boards is working. In the footer I placed the classic “powered by FeatureCat” and link to the featurecat.com landing page - which resulted in a server-not-found, because there is none.
Even with a soft launch of the first rough version to be used by myself, I wanted to make sure that 1) people could find it on the interwebs and 2) there was a place to go to contact me and follow along. Eventually featurecat.com will host marketing, documentation and a blog, but for now, a simple landing page will suffice: What is the thing, how can you get it and where can you follow along.
Using a site builder like Webflow or Squarespace might be quicker, but since I have a Bulma Jekyll template lying around and can reuse all stylings from the app, Jekyll it is. And until I’ve set up email capture, a
mailto: will do fine.
I started in Sketch with the logo and the basic value proposition. And the realization the good copy is hard, and even harder when you’re not sure what you’re selling.1 Might be a good time to think about that.
Simon Sinek’s golden circle (Why, How, What) can serve as a useful framework to figure out what the product actually does. I’ll start with what, because that’s the product I’m building: FeatureCat is about collection feedback and organizing features.
For feedback collection, it has to generate more and better user insights. Getting more feedback means lowering the barrier for users to provide feedback. Users do want to be heard and understood, but not enough to actively write an email. Users are lazy, and they should be. It’s my job to figure out what they need, and not their obligation to shout it from the rooftops.
Giving feedback thus has to be a natural part of the user experience. FeatureCat is about enabling a better way for users to provide feedback. It is about removing friction and making the feedback process effortless and delightful. Sharing your thoughts has to be meaningful and rewarding.
These are my goalposts for the feedback generation part of FeatureCat and will lay the groundwork for future marketing. I’m not sure though how I’ll break down the “organizing features”-part of the product. That’ll be a task for the next weeks.
For now, I’ll distill the what down into one sentence:
What: FeatureCat is a tool for collecting user feedback and organizing features.
One level up, “how” am providing value to customers?
I’ve written a whole guide on Matomo, a web framework that I’m running for user analytics in my iOS apps. That provides me with lots of quantitative data about what my users do, but none of the qualitative kind that tells me what my users think.
The best way to figure out a user’s thoughts, their problems, what they like and dislike, is talking to them. By talking to them, I can form an understanding of what concerns them. While I can force my friends to talk about their user experience with my apps, and I might be able to reach out to a few users who had contacted me previously, I have no practical way of talking to my users at scale.
FeatureCat is about scaling the developer-user-conversation, the part that A/B-tests and usage statistics cannot portray. FeatureCat is about understanding users in a way that scales.
Whether understanding your users does scale at all and FeatureCat can enable a sufficiently detailed picture of a user base is to be determined. Public feedback boards and a “submit your idea” button are obviously only the beginning and not enough to address this. But it’s a start. FeatureCat also does not have to (and cannot) reach every user, but it must enable a way to reach a statistically significant portion of the user base (at least more that the few unicorns who provide feedback by themselves). So how does FeatureCat provide value?
How: FeatureCat is about understanding your users at scale.
At the core of Sinek’s Golden Circle is “why”. Why am I doing this? Why should anyone else care? Why would they want to be doing this?
Understanding users is great, but provides no immediate benefit. Having a nice place to organize features is great for product teams, but users could not care less. What does benefit users is using a deeper understanding of their problems and desires to provide them with a better solution. A solution made for them.
That is the core motivation behind FeatureCat. It’s about creating value for users, providing a solution to their problems, fulfilling their desires and listening to their thoughts. It’s about giving users what they want.
Why: FeatureCat is about giving users what they want.
Eventually “Why” decisions in business are driven by economics: does this tool increase profit? A better product eventually lends itself to revenue growth, and a more efficient feedback process lowers cost. Giving user what they want is a close proxy to product growth make economic sense. So “giving users what they want” is what I’ll put on the landing page, along with a short description of the product.
Since I’m building this in public, I want people to be able to follow along. I’ve added links to FeatureCat’s twitter account and the FeatureCat Diaries (what you’re reading right now). It’s then again deployed with the static page app service on DigitalOcean (again, great experience) and now live on featurecat.com.
Taking a leap
Alpha launch means I need users and my first trial app is Leap Habits. I’ve set up “Leap Habits” as new a product in FeatureCat (via the console, because the UI does not exist yet), which will automatically make it available at leaphabits.featurecat.app. I’ve also created a bunch of features to give users something to vote on.
Next up is the integration into the app. There’s a couple things to do:
- Create a new WKWebView to display the feedback board (in the ‘Settings’ screen).
- Create a POST request to
leaphabits.featurecat.app/identify, which is where the user is authenticated and logged into FeatureCat.
- Configure the POST request with a
Bearertoken to authorize Leap Habits.
- Create the
UserStruct, which holds the
userID(created on first access and then cached in UserDefaults to identify the user on subsequent visits) and all the
userData-fields that I want to submit as additional user info.
- Encode the
UserStruct as JSON and submit it as the request body.
That’s it. I’ve added prompt on the main tab to ask users for feedback and submitted the update.
Zero to One
I wanted to build an app for feature and feedback management.
And I did.
A couple dozen commits, a few deployments, multiple domain purchases and 4,000 words right here: FeatureCat is live.
Live with asterisks. It’s one public board in one of my apps, with me being the only customer. But still, it is live on the interwebs. What started as an idea a year ago, accompanied by a couple of slides, is now a working prototype. And I’m really proud of that.
Making something from nothing feels great. It is obviously just the beginning of something, but turning something into something more is easier than making something from nothing. You got started, now you just need to keep going.
The Leap Habits update with FeatureCat has been live for roughly two weeks now (late March), and I’ve been pleasantly surprised by the results. A couple dozen users, hundreds of votes and a few submissions are orders of magnitude more feedback than I’d ever received via email. It feels like I’m onto something.
After the alpha launch, the next big step is the closed beta: getting other customers into FeatureCat. That requires me to add user management, multi-tenancy and a whole lot more. I also want to roll out FeatureCat to more of my own apps.
And finally, I’ll publish this very post, and tell IndieHackers and Twitter about it.
Still a long road ahead. I’ll see you in Part II (soon).
I’m already deep in the product-person-founder fallacy of “I’ll build it and they will come”: I want the thing, so I’ll build the thing. I’ll figure out later who else might need it. A better approach is to start with an audience whose problems you understand and then designing a solution to these problems. My way out is that I am the audience: a small development shop/indie that sells software without direct customer interactions and needs a better way to solicit feedback. ↩