Startup explorations #5 / Customer discovery: Further thoughts and first insights

In a previous post, I wrote about beginning to do customer discovery. Again, I note that I scraped together an education in this process by reading a few articles; in the future, I would love to see how a real professional conducts these interviews. This is a challenging step in the ideation process. I’d much rather skip all of it and go straight to building—however, in the end, it is well worth knowing that you’re working off of hard-earned data from real people, rather than just going off of assumptions and what?—Reddit? At any rate, in real life, we learn the skills we need to learn by doing. I’m very sure I’ll be doing more of these in the future, and that I’ll also learn as I go.

In this first round, I interviewed ten people. I used a combination of video calls, phone calls, and email. Calls are probably the best by default: it’s easier to ask follow-up questions and dig for more detail; but if you’re not careful, it’s also very easy to get derailed. However, I did not truly see a difference in the quality of responses I got between phone and email, but this is probably because I knew everybody I was interviewing to some degree. These are all people in an industry that I know well; I had a good context for each of them. I knew who would be thoughtful in writing, and who would be better off speaking spontaneously. In my non-expert opinion, it’s more important than any particular medium that your prospective customer is comfortable with that medium.

I also had a good idea of the kind of people I wanted to talk to. I went with a variety of creators, mostly but not limited to musicians. What they all have in common is that 1) they are all independent as artists, that is, not under professional management (whether they work non-creative day jobs or not); 2) are actively performing, producing content, or otherwise making a discernible effort; and 3) have the ultimate goal of working full-time as artists. Furthermore, all might be described as squarely “middle class” in terms of the creative economy—that is, they are not “stars” even though they are all very highly skilled and credentialed.

The following are some preliminary insights I’ve gleaned from these interviews as a whole:

1. Separation of concerns between building a following and converting it to an income. These are quite different tasks—the first one does not necessarily lead to the second, although it enables it, and some of the skills required of both overlap. At this time, I’m more interested in the first.

2. Clarifying following or audience. I observe two different senses in which these words are used. Nowadays when social media is ubiquitous, a following or audience is usually seen in terms of a number of followers or subscribers in any of the common platforms: YouTube, Facebook, Instagram, etc. There is usually a large component of strangers, or people an artist encounters online by chance. The main problem is that a large number of followers does not necessarily translate smoothly into an income. Rather, what it truly provides is a powerful kind of social validation, as well as a way to extend one’s reach beyond personal contacts.

In my observation, a smaller number of artists are rather suspicious of social media and don’t really bother much with them beyond casual personal use. Instead, they define their audience in terms of personal contacts which they build organically and over time. Usually this applies more to performers where “work” is much more defined—for example, an organization hires you for a specific one-time or short-term job. This kind of audience or following is not necessarily measured by headcount, but by reliability with regard to finding and securing work. The upside is that these relationships tend to be of a high quality. The downside is readily seen during times of disruption, such as the current coronavirus pandemic, when work dries up and an artist suddenly finds that their means to expand their reach are limited without social media.

3. Instagram is very popular. By far, nearly all of the people I interviewed favor Instagram, or otherwise are planning to use it more actively. Instagram is much more outward-facing than Facebook, more focused than YouTube, and it lends itself well to spontaneous connection with strangers. The concept is also very simple and the app is very easy to use. Among my interviewees, the one who has the most experience with Instagram also had the most to complain about: the app has changed a lot over the years, and has become much more unfocused. It has a lot more new features now, and continues to grow far beyond what it was originally intended to be. So it is going the way of Facebook (which acquired it many years back) in some ways; one no longer gets the sense that they are getting authentic updates from their friends and contacts, but rather just targeted content designed to get clicks.

4. The available tools are fine, but require initiative. Of course, this is true with anything in life. Many artists see the work it takes to build a following as a chore—it consumes a lot of time, and also most artists are not really trained to be businesspeople. They are unable to think of their audiences as customers. But no one tool can really do all the work of building someone else’s following. Instead, I think we have to think of facilitating the process instead, and making it a little smoother where we can. That said, there are some artists who do enjoy the business aspect of things—such as data analytics, coming up with strategies, etc.—even though it is only a secondary interest next to creating. How can we make all of it more interesting and encouraging to the average artist?

5. By far, the one thing most artists really want is more time to create. Related to the previous point, this is pretty consistent across everyone I spoke with. Time spent promoting work or doing business tasks means less time creating. Creating art or producing content in itself takes enormous time and is often not very efficient. No work is ever really “finished.” But to an artist, creating is the whole point of anything—many dream simply of the freedom to pursue and hone their craft, not necessarily to become wealthy or famous, but to inspire, connect, and cultivate good relationships with others.

Startup explorations #4 / Brief thoughts on “Anything You Want” by Derek Sivers

I became increasingly interested in the notion of “doing my own thing” a few months ago as I was trying to figure out how to proceed with my career in the middle of the coronavirus pandemic. One of the first figures I found who provided a lot of inspiration was Derek Sivers. Sivers started out as a musician (like me) before “accidentally” founding CD Baby in the late ’90s—at first, only as a way to publish his CDs on the internet, which then grew to become one of the largest and most well-known online distributors of independent music. This story, as well as that of eventually moving on from his own company, is the impetus behind Sivers’s short book Anything You Want: 40 Lessons for a New Kind of Entrepreneurship.

Sivers takes a very lean, individual, and unapologetically casual approach to things, which I admire. The book is meant to be a distillation, short enough to read in one sitting, of ten years worth of business experience. If I were to distill it even further into one unifying message, from my point of view, it’s that a company can be an extension of one’s personality, a vision of one’s perfect world, “whatever you want.” A creator through and through, Sivers considers business no less a creative act than music or fine art. His approach emphasizes a more human side to an industry that can otherwise be impersonal, transactional, and overly formal.

Therefore, central to all of this is the need to help people above all; everything else, including money, growth, and all the usual trappings of running a company, is secondary. Sivers deemphasizes any grand plans or visions in favor of just “helping people today.” He advocates starting as small as possible—as he did with CD Baby—with what can be done now, regardless of funding: what problem can you help solve for a single person at this moment?

As I’ve said before, I believe any project that hopes to solve the most challenging problems facing artists and creative types cannot afford to neglect the human side of things; not only because we are dealing with a kind of people who are especially attuned to the “things of the soul,” but also because our world today is filled with so much noise, digital and otherwise, with no signs of slowing down. In such a state of affairs, it becomes increasingly difficult year after year to find genuine connection and community; I suspect that more and more people are becoming aware of this, and are seeking better options than those currently on offer.

Startup explorations #3 / Beginning customer discovery, and a self-interview

I’ve just started doing “customer discovery” interviews. According to one source, customer discovery is a “customer-centric, scientific process that puts evidence behind an assumed product-market fit.” My education in it consists of reading only a few articles in the last two days; but in less technical terms, as I understand it, it is a method for discovering where the problems are that might need solving, straight from prospective customers. The crucial thing here is to test one’s assumptions without imposing them on anyone. Hence, the interview questions are rather broad and open-ended, designed not to lead anybody to answer in any particular way.

At a first pass, with lots of help from the resources I consulted, here’s what I came up with :

  • What do you do?
  • What tools do you use to get people to follow your work?
  • What do you like about these tools?
  • What do you not like about these tools?
  • What’s the ideal outcome?
  • If you could come up with an instant, magical solution to get what you want, what would it look like?

Recall once again that the problem I’m interested in is that of audience building. Here I’m putting many of my assumptions to the test about what creators are doing to grow their followings and the problems they face as they do that. My assumptions, of course, come from my own experience as a musician. If somebody were to come to me with these questions, as a musician, I would answer as follows:

What do you do? I compose music orchestral, chamber, and vocal music, as well as musical theatre.

What tools do you use to get people to follow your work? Mainly Facebook and Instagram.

What do you like about these tools? The level of potential engagement on Facebook is pretty good; it feels more personal because my network is mostly people I know or have met in person. Instagram stories are really easy to do; because they expire, it feels like you don’t have to make as much of an effort; and you can see who’s viewing your stories even if they don’t really engage. Although I don’t have any real strategy for getting more followers on these platforms.

What do you not like about these tools? Nothing about the tools themselves, I guess. I don’t like using them. I don’t really enjoy attention and would be much happier if I didn’t have to bother with these sites. In general it feels rather “salesy,” although there are rare moments that seem like genuine connection. On the whole, using these tools has not really resulted in a following around my work. One would would have to be using them constantly to get any real traction. Also, I find that sharing media on Facebook doesn’t usually get far.

What’s the ideal outcome? Ideally, there would just be enough interest in my work for me to be getting a steady stream of commissions, performances, etc.

If you could come up with an instant, magical solution to get what you want, what would it look like? A way to share or point to my work that doesn’t feel like it requires so much effort before getting any traction; or a way to make the whole thing somehow feel more human, and not just transactional.

*

I wrote these answers down very quickly and without thinking about them too much, and later on I might change my mind about one thing or another; but, if prospective customers of our future product are anything at all like me, I would assume that they’d give similar answers; the thing to do now is to confirm these assumptions, or otherwise allow them to be challenged.

While all of this sounds rather simplistic, doing interviews in real life naturally comes with many challenges. In real life, people are much more dynamic and do not always give straight answers. Sometimes they overthink, and try to manufacture a “smart” answer, which obscures truth. Sometimes a conversation gets derailed, or veers off to unexpected places. I expect to learn a lot more about this whole enterprise as I get more practice. Talking to people strategically does not come naturally to me, and I suspect it is a stumbling block for many others as well. More than that, usually one would rather let their ideas run with reckless abandon and not have their assumptions challenged—but it’s the only way to get to the bottom of things.

Startup explorations #2 / Trends and opportunties: Beginning notes

I mentioned in my previous post that I’m interested in the problem of audience-building for artists or creators. There seems to be great opportunity in building off the current global trend of the booming creator or “passion” economy: middlemen between creators and audiences have largely faded away, creators have more control over what they produce, and audiences get to interact directly with their favorite creators. The subscription model and “micro-patronage” have become widespread and have been shown to work—we may find other useful models in the future, but the shift toward more direct relationships between creators and audiences has effectively facilitated meaningful human connection and is likely to last.

The dominance of video is also a current trend, greatly accelerated by the COVID-19 pandemic. Many performing artists, notably musicians, have been driven to adopt video (Zoom, YouTube, Facebook Live, etc.) as a short to medium-term solution for performance, teaching, collaboration, etc. Given these trends, it becomes important to remember, what are audiences paying for? Quality of content itself remains important, but it’s also meaningful and effective connection, which technology attempts to facilitate.

Some parallel directions this could take:

Meaningful connection through in-person events. Video will continue to be vital for many creators (a trend that should not be cast aside), but I’ve observed that many creators have also begun to be more aware of its limitations—notably, that it can never replace the human aspect of live, in-person experience. This would apply more to performing artists: instrumentalists, singers, actors, dancers, etc. Hence, the opportunity to take an opposite route and encourage audience-building with a hyperlocal approach. What if we could have a platform that enables performers and audiences to find each other in-person through a map system, updated in real-time with all events currently taking place near a given user’s location?

Meaningful connection over the internet. This is more applicable to creators: composers, songwriters, writers, filmmakers, visual artists, etc. Could we have a platform that focuses on enabling creators and fans to find each other by highlighting quality work? Many of the current independent creator subscription sites such as Patreon, Substack, etc. do not have developed systems for either discovering new work or audience-building.

One possible approach is a more developed system of personalized recommendations. Perhaps a user, with each sign in, can be shown a page with a dynamic list of work that they might like and consider supporting. Any user can choose to highlight any work they find particularly impressive, which goes into the system that manages these recommendations. To make this meaningful, quality work would have to be emphasized. Instead of organizing or ranking recommendations by “likes” or numbers of supporters (which can be off-putting to artists who don’t already have large followings), perhaps there would be a kind of endorsement from someone in the community who has chosen to highlight it. This could be one way to incentivize community engagement—by correlating it with platform visibility and discoverability.

*

In summary, my thinking is to build off all or some of the trends outlined above—the creator economy, dominance of video, the subscription model—while in parallel possibly resisting aspects of those trends that are negative—lack of meaningful connection, information overload, low-quality work, the concentration of success to creators who have large followings before they even get into a new platform.

My thinking on all of this is naturally influenced by my personal experience as both a performer and creator, and my ability to sympathize with the difficulties of audience building. I have a good sense of the conflicts many artists face: they are sensitive people who strive always for meaningful connection and quality work rather than pure numbers, balanced with the need to compete and sell in a winner-take-all environment. I think we can work on building a platform with a strong human element to it that takes these things into account, that will ultimately encourage more creators to take their careers into their own hands.

Startup explorations #1 / Introduction, background, goals

I have never called myself a businessman, although all creative types must be businesspeople in some way. I started out my career as a composer in the classical music industry—I had to maintain an online presence, self-publish, write contracts, keep a payment system, etc. if I wanted any of my work to get performed. It all came down to the need to build an audience if I wanted my work to be sustainable. I wasn’t good at these things, but they needed to be done anyway, and they take a lot of work. Along my path, I decided that being a full-time musician wasn’t for me, but the question of audience-building remains pressing wherever one goes, if one hopes to do work that has any meaningful and lasting impact.

Approaching this question is more straightforward in some industries than others—when it comes to artistic types, one deals with a certain kind of people who are driven primarily by meaning, connection, beauty, and such parts of the human condition that are difficult to put into words but we all know are vital. The best artists are not necessarily those already at the top making all the money (sometimes, they have little concern for money), but we know that many of them deserve to be heard and supported for their potential to make meaningful, positive contributions to society. The currently booming creator economy is a testament to this potential, as well as to the truth in the idea that people can be empowered to control their own careers and do work that they truly care about.

Since winding down my own music career, I’ve developed and continue to develop a secondary skill set in technology. And as chance would have it, I’ve now found myself working for an exciting startup studio which sees great opportunity in the creator economy. It’s a great pleasure for me to rediscover many of the business and entrepreneurial concepts I learned as a student of music and administrator at a small arts company, and now with the added perspective of a developer, as I take on the challenge of creating a technological solution around a problem that will always be close to me: that of creators and audience-building.

Hence, this blog. To me, this is a creative and exploratory project with the twofold goal of: 1) documenting the journey of creating a new business—hopefully, with luck and persistence—from the very beginning, and 2) learning everything I can from the many resources available to me about startups, their economy, and how they’re built. I hope this project will prove both instructive in some way and entertaining to whoever reads it.

Building an RSS reader for Android from nothing: RSS feed retrieval and parsing

I’ve been meaning to write a series of posts about how I built NiceFeed—not a tutorial nor a step-by-step kind of thing, but more like a walkthrough of all the moving parts, how they came to be, and how they all fit together. I present it neither as an example of a great app nor of great programming—and naturally there are dozens of things that can be improved—but as a whole, I’m quite fond of it and use it everyday to get my news on my Android phone. My hope is to clarify some of my thinking about building the app and solving the many problems I encountered, so that it might be applied to future problems and projects. And of course, I hope that anybody who happens to stumble upon these posts may find them somehow instructive if not merely amusing.

RSS has been around for a long time and there are already many other readers and aggregators out there, but I’ve found many of them, particularly the free ones, awkward or difficult to navigate and jam-packed with features I don’t really need. My goal was an attractive and intuitive app, fully functional and with not too many frills.

*

An RSS feed appears in the wild as XML-formatted plain text, which needs to be parsed and converted to a form usable by an RSS aggregator application. I found that there were several third-party libraries for parsing RSS that already existed, so I didn’t have to write my own parsing code. I chose the aptly named RSS Parser because it seemed to be regularly updated and well documented. In addition, the library not only parses raw XML data, but executes its own HTTP requests, making it very easy to get up and running.

To start, I had to decide on what specific data I wanted the app to obtain. RSS Parser, after retrieving and parsing an RSS feed from the web, returns a Channel (or, the feed itself) object, which contains a collection of Articles (the contents of that feed). Both Channel and Article objects contain properties (title, author, URL, image, etc.) we definitely want and some that we don’t need. So, I created my own data classes, Feed and Entry, to contain only those properties that I wanted. Between the two is a many-to-many relationship: a feed is associated with many entries, and a single entry can be associated with more than one feed—we’ll return to this particular detail another time.

Determining which properties to include and exclude involved a lot of hemming and hawing as I became more familiar with the RSS data I was getting. I also added a few of my own: in Feed, category, which defaults to “Uncategorized,” and unreadCount, which simply holds the number of entries associated with that feed that have are not marked as read; and in Entry, the properties isStarred and isRead, both pretty self-explanatory and necessary if we want to be able to keep track of whether entries have been read and/or starred (or marked as favorite).

@Entity
data class Feed(
    @PrimaryKey val url: String, // Doubles as Feed ID
    var title: String,
    val website: String,
    val description: String? = null,
    val imageUrl: String? = null,
    var category: String = "Uncategorized",
    var unreadCount: Int
): Serializable

@Entity
data class Entry(
    @PrimaryKey val url: String, // Doubles as Entry ID
    val title: String,
    val website: String,
    val author: String?,
    val date: Date?,
    val content: String?,
    val image: String?,
    var isStarred: Boolean = false,
    var isRead: Boolean = false
) : Serializable {

    ...
}

Now for the real action. I created a class called FeedParser to contain all RSS Parser-related code. This class would contain all the needed methods for interacting with RSS Parser, and act as the authority across the entire app on retrieving and parsing RSS feeds from the internet. Naturally the class evolved over time as the app grew, but its role was always the same. Note: RSS Parser uses Kotlin Coroutines so the methods that use it have to be “suspend” functions.

/*  Responsible for retrieving and parsing RSS feeds */
class FeedParser(private val networkMonitor: NetworkMonitor) {

    private lateinit var rssParser: Parser
    private val _feedRequestLiveData = MutableLiveData<FeedWithEntries>()
    val feedRequestLiveData: LiveData<FeedWithEntries?>
        get() = _feedRequestLiveData

    suspend fun getFeedSynchronously(url: String): FeedWithEntries? {
        rssParser = Parser.Builder().build()
        return if (networkMonitor.isOnline) {
            try {
                val channel = rssParser.getChannel(url)
                ChannelMapper.makeFeedWithEntries(url, channel)
            } catch(e: Exception) {
                null
            }
        } else null
    }

    suspend fun requestFeed(url: String, backup: String? = null) {
        rssParser = Parser.Builder().build()
        if (networkMonitor.isOnline) {
            BackupUrlManager.setBase(backup)
            executeRequest(url)
        } else _feedRequestLiveData.postValue(null)
    }

    fun cancelRequest() {
        rssParser.cancel()
        BackupUrlManager.reset()
    }

    private suspend fun executeRequest(url: String) {
        // Automatically makes several requests with different possible URLs
        Log.d(TAG, "Requesting $url")

        try {
            val channel = rssParser.getChannel(url)
            val feedWithEntries = ChannelMapper.makeFeedWithEntries(url, channel)
            _feedRequestLiveData.postValue(feedWithEntries)
        } catch (e: Exception) {
            // If the initial request fails, try backup URL in different variations
            BackupUrlManager.getNextUrl()?.let { executeRequest(it) }
                ?: let {
                    _feedRequestLiveData.postValue(null)
                    Log.d(TAG, "Request failed")
                }
        }
    }

    ...

    companion object {

        private const val TAG = "FeedParser"
        private const val UNTITLED = "Untitled"
        const val FLAG_EXCERPT = "com.joshuacerdenia.android.nicefeed.excerpt "
    }
}

FeedParser takes a NetworkMonitor as an injected dependency. We’ll take a look at that at a later time, but it’s very simple: just an object that monitors the device’s internet connectivity. It contains one public property: isOnline, which at any given time is either true or false. All web requests are first checked against this property before executing.

There are three public methods, the first two of which are very similar, and begin with a new instance of RSS Parser:

First, getFeedSynchronously, which is really only for retrieving a feed as a background task. It takes a String called url (the address of an RSS feed), uses it to make a web request, and returns a FeedWithEntries: an additional data class that combines one Feed with a list of associated Entries. As it is meant to run in a background thread, the function waits for the web request to be completed before proceeding to the next step—hence, it is synchronous.

data class FeedWithEntries(
    @Embedded val feed: Feed,
    @Relation(
        parentColumn = "url",
        entityColumn = "url",
        associateBy = Junction(
            value = FeedEntryCrossRef::class,
            parentColumn = "feedUrl",
            entityColumn = "entryUrl"
        )
    )
    val entries: List<Entry>
)

Second, requestFeed, like the above, takes a String URL, and optionally a “backup” or second URL. Instead of returning anything, the main URL is passed first to a private method, executeRequest, which does the actual requesting via the current instance of RSS Parser. An object called BackupUrlManager notes the backup URL, if any, and hangs on to it until needed. We’ll take a closer look at it at a future time, but for now, all we need to know is that it generates different variations of the backup URL that can be used to retrieve a particular RSS feed.

Regarding the private method executeRequest: if there are any of these aforementioned variations of the backup URL, the method repeats itself via recursion until all variations are exhausted. Upon a successful request, the result is posted asynchronously to the class-level property feedRequestLiveData, which can then be read by whichever part of the app initiated the request.

The third public method is cancelRequest, which simply cancels the current instance of RSS Parser (and with it any pending request), and clears the BackupUrlManager.

You’ll notice also that in all of the above methods except cancelRequest, there is a reference to an object called ChannelMapper. As I said earlier, the RSS Parser object returns a Channel, which contains several properties as well as a collection of Articles. ChannelMapper is nested within FeedParser and contains methods for converting a Channel into a FeedWithEntries (again, a combination of one Feed and multiple Entry objects). This is just my way of organizing the code and keeping these methods in one place.

/*  Maps 'Channel' data into 'Feed' and 'Entry' objects */
private object ChannelMapper {

    private const val MAX_ENTRIES = 300 // Arbitrary
    private const val DATE_PATTERN = "EEE, d MMM yyyy HH:mm:ss Z"

    fun makeFeedWithEntries(url: String, channel: Channel): FeedWithEntries {
        val entries = mapEntries(channel, url)
        val feed = Feed(
            url = url, // The url that successfully completes the request is applied
            website = channel.link ?: url,
            title = channel.title ?: channel.link?.shortened() ?: url.shortened(),
            description = channel.description,
            imageUrl = channel.image?.url ?: channel.image?.link,
            unreadCount = entries.size
            )

        Log.d(TAG, "Retrieved ${entries.size} entries from $url")
        return FeedWithEntries(feed, entries)
    }

    private fun mapEntries(channel: Channel, url: String): List<Entry> {
        val entries = mutableListOf<Entry>()
        for (article in channel.articles) {
            if (entries.size < MAX_ENTRIES) {
                val entry = Entry(
                    url = article.link ?: article.guid ?: "",
                    website = channel.link ?: url,
                    title = article.title ?: UNTITLED,
                    author = article.author,
                    content = article.content ?: article.description.flagAsExcerpt(),
                    date = parseDate(article.pubDate),
                    image = article.image
                )
                entries.add(entry)
            } else break
        }
        return entries
    }

    private fun parseDate(stringDate: String?): Date? {
        return if (stringDate != null) {
            SimpleDateFormat(DATE_PATTERN, Locale.ENGLISH).parse(stringDate)
        } else null
    }

    private fun String?.flagAsExcerpt() = FLAG_EXCERPT + this
}

Here, the one public method, makeFeedWithEntries, accepts a String URL and Channel object and initiates the process of assigning all the data we need to properties that we specified earlier in the data classes Feed and Entry, and discarding the rest. The private method mapEntries, which makeFeedWithEntries calls within itself, does the same by looping through each Article contained in the Channel. In the end, we get a FeedWithEntries, ready to be stored or presented by the app.

Side note: at the bottom of ChannelMapper is a method flagAsExcerpt which extends a nullable String. I use it to flag any Entry whose content property is null and the description is not empty—in the wild, it means the entry is probably an excerpt. Many RSS feeds nowadays, especially from subscription sources, do not syndicate full versions of their content, only short excerpts. I have yet to do anything with flagged Entries, but might in the future: for example, the app could be made to open any Entry flagged as an excerpt automatically with the device’s default browser, instead of within the app.

And a final remark: I’ve written all my code with modularity and flexibility in mind, to the extent that I’m able. RSS Parser serves all my current needs but is not a perfect library—notably, it does not support Atom, and in the future I might want to use a different one. Since all the relevant code is contained entirely within the class FeedParser, we could easily create a new class with which to replace it as the final authority on all things related to retrieving and parsing RSS, without affecting much else in the app.