From 8dfa22358a053708402213705280ca260721c312 Mon Sep 17 00:00:00 2001 From: David Merfield Date: Mon, 25 Mar 2024 18:02:50 +0000 Subject: [PATCH] Updates notes --- app/documentation/notes.js | 11 ++-- app/documentation/redirector.js | 5 +- notes/business/-principles.txt | 3 +- notes/business/-tools.txt | 69 ++++++------------------- notes/business/history.txt | 1 - notes/business/influences.txt | 4 -- notes/business/marketing.txt | 4 +- notes/business/mistakes-and-regrets.txt | 12 ----- notes/business/mistakes.txt | 41 +++++++++++++++ notes/business/threats.txt | 29 +++++------ notes/politics/open-source.txt | 9 ++-- notes/programming/-principles.txt | 17 +++--- 12 files changed, 94 insertions(+), 111 deletions(-) delete mode 100644 notes/business/influences.txt delete mode 100644 notes/business/mistakes-and-regrets.txt create mode 100644 notes/business/mistakes.txt diff --git a/app/documentation/notes.js b/app/documentation/notes.js index ee71999b7f7..afdb601a9d7 100644 --- a/app/documentation/notes.js +++ b/app/documentation/notes.js @@ -24,7 +24,7 @@ notes.use(function (req, res, next) { notes.param("section", function (req, res, next) { res.locals.selected[req.params.section] = "selected"; - res.locals.toc = TOC.map((section) => { + res.locals.toc = TOC.map(section => { section.isSelected = req.params.section === section.id ? "selected" : false; return section; }); @@ -41,7 +41,7 @@ notes.param("article", function (req, res, next) { notes.get("/", function (req, res, next) { res.locals.showToc = true; - res.locals.toc = TOC.map((section) => { + res.locals.toc = TOC.map(section => { section.isSelected = false; return section; }); @@ -60,18 +60,19 @@ notes.get("/:section", function (req, res, next) { ); res.locals.subsections = TOC.filter( - (section) => section.id === req.params.section + section => section.id === req.params.section )[0].items; next(); }); // Hack to allow us to place some articles higher than -// others. This map allows us to retrieve +// others. This map allows us to retrieve // notes/business/-principles.txt from disk correctly const SORTING_MAP = { principles: "-principles", - technique: "-technique", + tools: "-tools", + technique: "-technique" }; notes.get("/:section/:article", function (req, res, next) { diff --git a/app/documentation/redirector.js b/app/documentation/redirector.js index f3368c0d976..119a8dab1fe 100644 --- a/app/documentation/redirector.js +++ b/app/documentation/redirector.js @@ -18,7 +18,10 @@ const internal = { "/about/contact": "/contct", "/about/notes/business/unlimited-bandwidth": "/about/notes/business/principles", - "/about/notes/business/project-management": "/about/notes/business/technique", + "/about/notes/business/technique": "/about/notes/business/tools", + "/about/notes/programming/technique": "/about/notes/programming/tools", + "/about/notes/design/technique": "/about/notes/design/tools", + "/about/notes/business/project-management": "/about/notes/business/tools", "/about/notes/design/aesthetic": "/about/notes/design/principles", "/about/notes/design/irritating-websites": "/about/notes/design/principles", "/updates": "/news", diff --git a/notes/business/-principles.txt b/notes/business/-principles.txt index 2174caeca20..583c1956f1d 100644 --- a/notes/business/-principles.txt +++ b/notes/business/-principles.txt @@ -32,5 +32,4 @@ I do not plan to raise investment in Blot. The main concern I'd have with bringi I set the price of Blot at whatever I would be comfortable paying myself. When I started Blot, it cost $1 a month. I've improved Blot since then and now a site costs $5 a month. I feel that's still a fair price since I provide web hosting and personal support. -I know I could get away with charging more. I know this because I get regular emails from customers telling me this. However, I'm interested in having Blot in the hands of more people, even if it means generating less revenue. - +I know I could charge more for Blot. However, I'm interested in having Blot in the hands of more people, even if it means generating less revenue. \ No newline at end of file diff --git a/notes/business/-tools.txt b/notes/business/-tools.txt index c12d8eaf347..3edd57586ef 100644 --- a/notes/business/-tools.txt +++ b/notes/business/-tools.txt @@ -1,63 +1,28 @@ # Tools -I haven't found the need to use much *software* to manage the daily operation of Blot. We like email because it is quieter and less hurried than messaging applications. We like working with plain text to manage our tasks and organize our plans because they are easy to track and share. +Not much software is needed to run the day-to-day operation of Blot. -## Task tracking - -We use a text-file ([todo.txt](https://github.com/davidmerfield/Blot/blob/master/todo.txt)) to keep track of tasks. If somebody needs to be notified when a task is complete, I include a link to the appropriate email thread in the task. This text-file is checked into version control which means we can easily summarize our completed tasks – the [feed of work completed](/news) on Blot's news page is generated automatically from this todo list. +## Email -I've used a variety of complicated tools to track tasks in the past but I still prefer a text-file. - -## Accounting +We communicate amongst ourselves and with our customers using email. Email is decentralized and asynchronous. Chat applications are not. At the moment we use the Google Workspace to host our email but we intend to move elsewhere. -I use a spreadsheet which I update once per month with my revenue and costs. +## Task tracking -## Email strategy +We use a text-file ([todo.txt](https://github.com/davidmerfield/Blot/blob/master/todo.txt)) to keep track of tasks. If somebody needs to be notified when a task is complete, we include a link to the appropriate email thread in the text file, along with a description of the task. This text-file is checked into version control which means we can easily summarize our completed tasks – the [feed of work completed](/news) on Blot's news page is generated automatically from this file. -My email inbox only contains email to which I need to respond. Once I respond to an email, it is archived. If there is a longer task which I need to complete, I will make an entry in [todo.txt](https://github.com/davidmerfield/Blot/blob/master/todo.txt) with a link to the archived email thread, so I can follow up with the customer as soon as the task is complete. +## Accounting -We use Gmail to host our email, since despite all the downsides its interface is the best available. We pay them a few dollars a month so we can use our own domain. +We use an Excel spreadsheet which we update once per month with revenue and costs. We use TurboTax to generate our tax documents. Ours costs are as follows, in approximate descending order: +- Payment processing fees +- AWS hosting +- Domain registration +- Google Workspace +- Updown.io status page +- Bunny CDN fees +- Microsoft Office +- iCloud +- Turbotax ## Payment processing -We use [Stripe](https://stripe.com/) to process payments. They have been excellent. - -## Customer service - -Before working on Blot, I hadn't had a customer-facing job. Here are a few of things I have learned over the years. It's worth mentioning that Blot's customers have been polite and good-natured, even in situations when a lapse in politeness would have been reasonable. - -### Tracking requests - -We use a [text-file](/about/notes/business/technique) to track all of the tasks for Blot. If the task involves following up with the customer – perhaps fixing a bug or adding a feature – we add a link to the relevant email correspondence. - -Because this text-file is also used to render our [News](/news) page, the customer has a public committment from us that we will fix their problem. This helps, especially when the problem takes a while to solve. - -### Responding to suggestions - -Plenty of the suggestions we receive from our customers are good and are eventually incorporated into the software. However, when the suggestion isn't suitable, it's important to learn how to say no politely and concisely. This became easier with practice. - -### Bad habits - -- **Asking the customer to provide information that is easy to look up** - - I often find myself asking the customer information that I could look up with a little effort (*what's the URL to your site? which blog post are you having that issue with?*). Responding with even a single question back makes it much more likely the customer will lose interest in the issue, which sometimes feels like solving the problem, but really isn't. - -- **Taking too long to respond** - - When the customer's inquiry involves a bug whose solution is easy, I found myself waiting to fix the bug before responding to the customer. The proper way to handle things is first to respond saying I am fixing the problem, then follow up with a response when the problem is fixed, rather than leave the customer in the dark until the problem is fixed. - -- **Avoiding responsibility for mistakes** - - When a bad bug in our product affects a customer, I found it easy to use language which seperated myself from the bug. I find it annoying when people fail in their job and don't take responsibility for it. I don't want to do that myself, although it is tempting. - -- **Mistyping the customer's name** - - I have made too many errors transcribing a customer's name from memory. I now copy and paste the name to avoid these mistakes. - -- **Constantly checking my support inbox** - - I often find myself aimlessly refreshing the inbox for supoprt requests when I should be working. I also find myself distracted by a new support - -### Always leave the door open - -I try and end all of my communication with customers with something along the lines of *Can I help you with anything else?*. I know it's cheesy but I worry that without it, an excessively polite customer might worry that I'm somehow annoyed that they've emailed me to ask something they could have found out with one or two web searches. +We use Stripe and PayPal to process payments. \ No newline at end of file diff --git a/notes/business/history.txt b/notes/business/history.txt index 3bc1ae2c50a..9556329f151 100644 --- a/notes/business/history.txt +++ b/notes/business/history.txt @@ -1,6 +1,5 @@ # History - **2013**     Blot begins as an idea. **2014**     Blot launches [on Hacker News](https://news.ycombinator.com/item?id=8183498) and receives its first customer. diff --git a/notes/business/influences.txt b/notes/business/influences.txt deleted file mode 100644 index 4786e6823c3..00000000000 --- a/notes/business/influences.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Influences - -- *Le pont vieux* was a small restaurant in a town in which I grew up. It opened for only two nights per week and served a few simple dishes. -- Maciej Cegłowski's [Pinboard](https://pinboard.in). \ No newline at end of file diff --git a/notes/business/marketing.txt b/notes/business/marketing.txt index 563d9b47627..e59ff8293e4 100644 --- a/notes/business/marketing.txt +++ b/notes/business/marketing.txt @@ -1,6 +1,6 @@ # Marketing -I dislike marketing. I have not tried to convince anyone, ever, to use Blot. I announced [the launch of Blot](https://news.ycombinator.com/item?id=8183498) on a forum for programmers. The people who saw that forum post have since spread the news by word-of-mouth. Every customer on Blot's books today is connected to those people who saw the launch announcement. +I dislike marketing. I have not tried to convince anyone, ever, to use Blot. I announced [the launch of Blot](https://news.ycombinator.com/item?id=8183498) on a forum for programmers. The people who saw that forum post have since spread the news by word-of-mouth. Every customer on Blot's books today is connected to the people who saw the launch announcement. ## Advertising @@ -12,7 +12,7 @@ Blot does not have a presence on any of the social media platforms. ## Discounts and promotions -I do not offer discounts. Offering a discount seem unfair to customers who pay full price. +I do not offer discounts. Offering a discount seems unfair to customers who pay full price. ## Trial accounts diff --git a/notes/business/mistakes-and-regrets.txt b/notes/business/mistakes-and-regrets.txt deleted file mode 100644 index 2cbdd468a4e..00000000000 --- a/notes/business/mistakes-and-regrets.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Mistakes - -Some of the decisions I've changed my mind on as I've run Blot - -## Charging annually rather than monthly - -For the first few years of business, Blot asked its customers to pay once a year. This has the following benefits: -- lower transaction fees -- money up front - -Charging monthly reduces the commitment involved, and although it's hard to know if this is mere correlation, the number of customers increased when I made the switch. It makes sense to me that more people are willing to take the plunge when the initial commitment required is 30 days. I also got far fewer requests for refunds – I always issue refunds when asked but it takes time to do this, and increases the cost of support. - diff --git a/notes/business/mistakes.txt b/notes/business/mistakes.txt new file mode 100644 index 00000000000..7e04778275d --- /dev/null +++ b/notes/business/mistakes.txt @@ -0,0 +1,41 @@ +# Mistakes + +This page describes some of the poor decisions I have made. + +## Charging annually, rather than monthly + +For the first few years of business, Blot asked its customers to pay once a year. This had the following benefits: +- lower transaction fees +- money up front + +Charging monthly reduces the commitment involved, and although it's hard to know if this is mere correlation, the number of customers increased when I made the switch. It makes sense to me that more people are willing to take the plunge when the initial commitment required is 30 days. I also got far fewer requests for refunds – I always issue refunds when asked, but it takes time to do this, and increases the cost of support. + +## Not having a clear pricing page + +Initially I only showed the price of the service on the sign-up page. + +## Not accepting PayPal + +Adding additional payment methods immediately increased Blot's revenue. + +## Bad habits when providing support to customers + +- **Asking the customer to provide information that is easy to look up** + + I often find myself asking the customer information that I could look up with a little effort (*what's the URL to your site? which blog post are you having that issue with?*). Responding with even a single question back makes it much more likely the customer will lose interest in the issue, which sometimes feels like solving the problem, but really isn't. + +- **Taking too long to respond** + + When the customer's inquiry involves a bug whose solution is easy, I found myself waiting to fix the bug before responding to the customer. The proper way to handle things is first to respond saying I am fixing the problem, then follow up with a response when the problem is fixed, rather than leave the customer in the dark until the problem is fixed. + +- **Avoiding responsibility for mistakes** + + When a bad bug in our product affects a customer, I found it easy to use language which seperated myself from the bug. I find it annoying when people fail in their job and don't take responsibility for it. I don't want to do that myself, although it is tempting. + +- **Mistyping the customer's name** + + I have made too many errors transcribing a customer's name from memory. I now copy and paste the name to avoid these mistakes. + +- **Constantly checking my support inbox** + + I often find myself aimlessly refreshing the inbox for supoprt requests when I should be working. I also find myself distracted by a new support diff --git a/notes/business/threats.txt b/notes/business/threats.txt index d317167c84d..393a360d64a 100644 --- a/notes/business/threats.txt +++ b/notes/business/threats.txt @@ -1,41 +1,36 @@ # Threats -A survey of potential crises to Blot's business +This page outlines the most significant potential threats to Blot. ## Payment processing -We use Stripe to process almost every single payment. If Stripe closed Blot's account, or if Stripe itself closed, we would be without revenue immediately. +We use Stripe and PayPal to process payments. If Stripe or PayPal refused to continue processing payments for Blot, or if Stripe or PayPal themselves closed, we would be without revenue immediately. *Solutions*: -- Spread payments across different payment processors. We could run a percentage of our payments through Stripe's competitor Braintree. -- Support other mediated payment methods: e.g. PayPal. -- Support payment methods without an intermediary: e.g. cryptocurrencies. +- Support payment methods without an intermediary: e.g. cryptocurrencies, cash. ## Hosting -We use AWS to host the site. If AWS decides something runs afoul of their intricate terms of use, we would be in trouble. What would happen? Well Blot is easy to deploy on a linux server. I would probably move to another provider, say Linode. What would break? Sites with A records pointing to Amazon's IP address would no longer resolve. Sites with CNAME records pointing to our hostname (blot.im) would continue to work. - -I don't make backups of the data on the system outside AWS. I should really do this, even if it's only weekly. AWS makes it fairly expensive to move the quanity of data Blot stores, which is one thing I resent about their service (it seems *strategic* to me). +AWS provides the hardware on which Blot runs. If AWS decides something published on Blot violates their intricate terms of use, we would need to move to another provider. Losing access to AWS would be a disaster. All of our backups are stored within AWS. *Solutions*: -- Control my own hardware -- Run my own hardware in my own building +- Make off-site backups. +- Control our own hardware. +- Run our own hardware in our own building. ## Cultural issues -We have a policy which means that we allow anything legal on our platform. I suspect that one day, someone will post something that pisses of someone else who's prominent enough to trigger a pile on against our platform. +We do no prohibit the publication of anything on our platform, provided it is legal for us to host. The day will come when someone posts something that upsets someone else who's powerful enough to apply substantial pressure against our platform. Perhaps enough of our customers will close their accounts. *Solutions*: - Have plans in place for a massive reduction in revenue at any point (i.e. cash reserve) -## Service provider issues - ## Legal issues We could get sued by a well-resourced customer, or someone who reads a customer's site. *Solutions*: -- Have enough money in place to hire a lawyer that's better than our opponent +- Have enough money in reserve to hire competent lawyers. ## Personnel issues @@ -43,14 +38,14 @@ We could get sued by a well-resourced customer, or someone who reads a customer' Blot's bus factor is still 1 – if I get hit by a bus the show stops. Since the source code is public, it would be possible for those who liked Blot to keep it going on a different server, but coordinating the switch might be tough. *Solutions*: -- Hire a full-time employee who is capable of running the site without me, write succession protocol - +- Hire a full-time employee who is capable of running the site without me. +- Write a succession protocol. ## Competitors Someone could come along and produce a superior product to Blot. *Solutions*: -- Keep working hard on Blot's product +- Keep working hard on Blot. diff --git a/notes/politics/open-source.txt b/notes/politics/open-source.txt index c83e934049a..7a9d18e81c2 100644 --- a/notes/politics/open-source.txt +++ b/notes/politics/open-source.txt @@ -1,17 +1,18 @@ # Open source +Making Blot's source code public means Blot is more appealing to technical people. More importantly 'open-source' implies an insouciance towards money which I like. -Open source feels good. It suggests a modest attitude to money that seems dignified. Although these aesthetic considerations are most important, open source is also appealing to a technical audience, who are often sceptical of proprietary closed-source software. So it makes business sense for me to make [Blot's source code](/about/source-code) available freely under the most permissive license possible. +It is not financially sensible for me to make [Blot's source code](/about/source-code) available freely under the most permissive license possible. However, I'm determined to not sell Blot, ever. Releasing the source code has the benefit of increasing the value of the hosted service to potential customers while reducing the value of Blot if I were to attempt to sell it in a moment of weakness. ## As a moral decision -Intellectual property as a legal regime has its costs and its benefits. Ideas are obviously innately free but sometimes there are advantages to setting up legal structures to protect them. But generally I think the legal structures we've established to protect intellectual property are overgrown and tend to limit rather than encourage creation, so I will not participate. +Intellectual property as a legal regime has its costs and its benefits. While ideas are inherently free, there can be advantages to establishing legal structures for their protection. However, I think the legal structures we've established to protect intellectual property are overextended. They often restrict rather than encourage creative endeavors. ## Working in public -I also quite like the spectacle of working in public. I suspect it's reassuring to potential customers to see my [git commits on the news page](https://blot.im/news), for them to know that Blot is _alive_. +I also like the spectacle of open-source. Work on Blot is done in public. I suspect it's reassuring to potential customers to see [my git commit messages](https://blot.im/news) neatly formatted on the news page, for them to know that Blot is alive. ## Terminology -I like the ideals of the free software movement and I like Richard Stallman. However, I think the *free* part of Stallman's term *free software* is confusing. After starting too many explanations with *it's not free as in beer...* I've not to push against the current of popular usage. I'm also aware of the politics of the term 'open source', so I decide to side-step both and simply say _Blot's source code is dedicated to the public domain_. +I like the ideals of the free software movement and I like Richard Stallman. However, I think the *free* part of Stallman's term *free software* is confusing. I'm also aware of the politics of the term 'open source', so I avoid both and when I address this topic on Blot's website I say that _Blot's source code is dedicated to the public domain_. diff --git a/notes/programming/-principles.txt b/notes/programming/-principles.txt index be4aa79f464..be422ec040d 100644 --- a/notes/programming/-principles.txt +++ b/notes/programming/-principles.txt @@ -1,23 +1,18 @@ # Principles -When I started working on Blot, I did not know how to program. I foolishly did less study than I should. I wasted time inventing tools that others built better, before me, but I enjoyed almost all of it. - -The most important goal is reliability, then speed. +When I started working on Blot, I did not know how to program. I did less research than I ought to have done. I wasted time creating tools that others had already made. ## Infrastructure -- **A limited palette of boring technology** I'd avoid using tools that have been around for less than a decade in anything you plan to depend upon. -- **Understand the environment in which your code runs** +- I avoid using tools that have been around for less than a decade. +- I try to understand the environment in which Blot's code runs. ## Back-end -- **Speed above everything** - -- **Avoid microservices** Perhaps there is way to make these work but I haven't achieved it yet. - -- **Keep track of your bottlenecks** Blot involves lots of i/o, like reading files from a disk or syncing a file over a network. Because of this, most of what really needs to be optimized is i/o. Nothing is especially computationally intensive. Shaving even one external HTTP request from a function will save infinitely more than endless language-level performance optimization. +- Reliability is the most important attribute of your software. I dislike software that is not dependable. +- Speed is the second most important attribute. I dislike software that is slow. Blot involves lots of i/o, like reading files from a disk or syncing a file over a network. Because of this, most of what really needs to be optimized is i/o. Nothing is especially computationally intensive. Avoiding even one external HTTP request from a function saves much more time than endless language-level performance optimizations. ## Front-end -- **Speed above everything**. I run almost everything send to the client through as many minifiers and compressors as is reasonable. I want to improve the speed of Blot. I also use a neat script called [instant.page](https://instant.page/) to begin fetching a page when the user hovers over a link. +- **Speed above everything**. I run almost everything send to the client through as many build-time minifiers and compressors as is reasonable. I want to improve the speed of Blot. I also use a neat script called [instant.page](https://instant.page/) to begin fetching a page when the user hovers over a link. - **As little JavaScript as possible**. In general, I want to do as much computation as possible on the server, as little as possible on the client. This is because I control the server, but not the client.