1
0 Comments

Stand up and go

  1. Hooray stand ups! I first found out about standup practice when I started my first job in London right after getting a Master's degree from King's. Working in a small professional team led by a serial entrepreneur was the best start I could've ever gotten. In 2.5 years the standups were cancelled and soon after I lost my job as there was a disconnect between what I was doing and the management keeping track of it. In the last years since working for my own company, I picked up writing "daily log" occasionally and always dropped it in less than a month because it's actually a job and once you miss one day you don't feel like coming back. When you do standups you know you're actually working full-time rather than just enjoying doing stuff you like to do telling yourself you're an "entrepreneur". So let's try it here.

  2. Last week I found this ebook "Start marketing the day you start coding" from Rob Walling so I went on his website at lunch time to check him out and watched some videos there, in particular the 4th one, "how to validate your idea..." The main takeaway from it is that he emailed 17 people asking them if they were able to give him some feedback on the idea he's been developing, and after they agreed, sent them an outline, but most importantly with a question, if they were ready to Pay 99$ per month for it. The outcome was that all software developers said yes while bloggers and influences were not so keen since they could hack it using other tools. So for me, it's clear that Software Engineers are not cheap. I wouldn't pay even 10$ for anything because I have no money, but I shouldn't apply it to everyone. I'm working on pricing for my product and I though I settled on $59/year of updates before but now I think I'm going to put it up to $100 because it's a premium product that really solves the problem, and is unique to the market. I want it to be perceived as expensive.

Also it's so clear now that most of software people make nowadays are like SaaS marketing tools. Marketing is important for the economy, it's the pump that drives liquidity in the financial system, and internet software is really a communication engineering solution. And marketers and businesses are happy to pay enough money, because they have money since they're businesses. Yet in software development world, everything is different. With the rise of open source everything has become free. People don't pay any money for software, only for hosted solutions. Buying software is not a thing because everyone's cheap. Yet I do believe there's going to be pros who'll be willing to pay some money for my software.

Imagine you wanted something, but you needed to work for it a bit. And then finally you saved up a 100 bucks for that CD, installed it, opened the documentation, started to play with it. It's so much more rewarding that just installing some "free" open source product that everyone else is using. You pay for the experience, and those endorphins, open source will never provide. When targeting software pros who are not stingy , and not those myriads of free riders online, I might be able to win some hearts and souls. It's just because the culture of professional software has been destroyed and everyone's looking at Open Source as a virtue of the last era, like these "communities" have been building software that we all depend on and so we all owe them, but the truth is, there used to be software houses that also created quality software, and sold it.

None of my packages has any dependency that wasn't published by myself. This culture has been eliminated by the open source plague that has been presented to us a silver bullet. Sure it's got its benefits when people work on low level stuff like HTTP protocols etc but when they start praying to Open Source and it's "communities" repeating the same shit all over without even understanding what they're talking about, I can't handle it. No, Open Source is not everything and it's not good. You need to learn to pay for software again. There are people who's purpose in life is making software, who studied and specialised in programming and computer science, rather than script kids that learned to code and put it free online, and thus got rid of professionals and software cottage culture. In short, I loved to hear when he said that for software engineers, 100$ per month was no brainer, so they'll be able to spend 100$ per year on my product.

Shout out to @jones_spencera for the progress on PremiumJS.

  1. Published the first post on IH. Instinctively I was ready that people will comment shit like they do everywhere else like "that's so stupid" but I knew it was just a paranoia as a side effect of publishing on public communities where everyone is an armchair software general. A person commented saying nice things, this was rewarding. This helped to reduce the fear of speaking online. Again, in his book, Rob is saying how he was afraid of doing posts etc initially, but the more you do it the more you overcome this fear and it becomes fun. For many, there's no problem with putting stuff online but I get pretty anxious just anticipating to be attacked every time, or saying something wrong. I just feel I deserve certain respect for my work, and in real life, you'd get honours and like positions but not online. That's why I like IH is because people kind have any some idea of class.

le path

Like all other social networks, IH is addictive as you'll click on the logo, "new", and refresh repetitively.

  1. Actual work then. Didn't do a full day, got distracted by spider man on TV haha. The productivity has been really low these last couple of weeks. There were days I used to do 60 hour weeks but I guess I'm low-motivated now. The main focus is to finish refactoring my static website compiler, which produces HTML from layout + page + JSX components. The nice thing is that JSX can be statically rendered, so what you're doing is not one-page app like gatsby, but a normal HTML, where some elements can be defined in JSX if they need some cool JS logic. They can also be dynamically executed as components, when they come scrolled into view. The JS and CSS is then compiled with Closure tools which optimises all assets, such as that classes get renamed into something like .MyComponent span { color: red } to .a span {color:red}.

The MVP was working for a long time and I made many static websites, but I had to refactor it. From JSX components, you get a property called core from which you can access the API of the software package, to add files, export styles and scripts, etc:

export const Component = async ({ id, children, core }) => {
  await core.files.add('assets/menu.json')
  return (<div id={tag}>Hello World {children}</div>)
}

Before, this core was just one big class with over 1000 lines. It's OK when you're hacking your first versions of the product and are busy on actually using it to build websites, but when you context switch away from it for a month or two, and then come back, it hits you with massive anxiety. You don't know how to approach adding new features to it, where to start. That's why I've been refactoring it into sub-apis, for files, styles, scripts and paths. Each API is declared in an XML file:

<types namespace="_staticsitecompiler">
  <interface name="Scripts" desc="Methods to control scripts on the page.">
    <prop name="scripts" type="!Array<! _staticsitecompiler.Script>">
      The scripts and modules that are to be loaded on the page (either added before the closing body tag,
      or in the head using `defer` or `data-onload` strategy, [@see](/see) Config.scriptsStrategy for more detail).
    </prop>
    <prop name="jss" type="!Array<{ js: string, type: (string|undefined) }>">
      All JS code blocks that were added to the page and will be loaded after the parsing's finished.
    </prop>
    <fn name="script" return="boolean" returns="Whether the script was added.">
      <arg name="path" string>
        Path to the script relative to splendid app dir (e.g., `js/script.js`).
      </arg>
      <arg name="props" type="!Object<string, string>" opt>
        Additional attributes on the `<script>` tag, e.g., `data-` attributes if required.
      </arg>
      Adds a script onto the page.
    </fn>
    <fn name="module" example="../example/jsdoc/scripts/module.js">
      <arg name="path" string>
        Path to the module relative to splendid app dir (e.g., `js/script.js`).
      </arg>
      <arg name="props" type="!Object<string, string>" opt>
        Additional attributes on the `<script>` tag, e.g., `data-` attributes if required.
      </arg>
      Adds a module script onto the page.
    </fn>
  </interface>
</types>

The types are then compiled into abstract classes:

/**
 * Methods to control scripts on the page.
 * @abstract @implements {_staticsitecompiler.Scripts}
 */
export class AbstractScripts {
  /**
   * Constructor method.
   */
  constructor() {
    /**
     * The scripts and modules that are to be loaded on the page (either added before the closing body tag,
     * or in the head using `defer` or `data-onload` strategy, [@see](/see) Config.scriptsStrategy for more detail).
     * @type {!Array<! _staticsitecompiler.Script>}
     */
    this.scripts
    /**
     * All JS code blocks that were added to the page and will be loaded after the parsing's finished.
     * @type {!Array<{ js: string, type: (string|undefined) }>}
     */
    this.jss
  }
  /**
   * Adds a script onto the page.
   * @param {string} path Path to the script relative to splendid app dir (e.g., `js/script.js`).
   * @param {!Object<string, string>=} [props] Additional attributes on the `<script>` tag, e.g., `data-` attributes if required.
   * @return {boolean} Whether the script was added.
   */
  script(path, props) { }
  /**
   * Adds a module script onto the page.
   * @param {string} path Path to the module relative to splendid app dir (e.g., `js/script.js`).
   * @param {!Object<string, string>=} [props] Additional attributes on the `<script>` tag, e.g., `data-` attributes if required.
   * @example
   * ```js
   * <script type="module" src="hello.js"></script>
   * ```
   */
  module(path, props) { }
}

The abstract classes are extended by an actual implementation, that is kept clean of JSDoc so that I can focus on writing code. The IDE is then able to pick up the type of the param to each function, and give appropriate hints to it.

abstract classes

Motivation is really lacking and there's many times a day I just stand up and go to the kitchen / sit on the sofa / lie on the bed watching entrepreneurial videos. It's because of anxiety of doing the work when you're not in the flow. After lunch I felt really at ease and could sit down and write my tests with no problem, it was natural, felt good, calm, human. After 30 min-1 hour that dissipates, I become lazy not being able to focus. I haven't been eating that well and I think diet and exercise is important. Regarding testing, some methods use caching so that a file won't be added more than once if its mtime hasn't changed. Traditionally, it's quite hard to test since you need to create temp folders for caches, and temp folders for the produced files. But I'm using a TempContext with my testing framework, which makes this stuff easy:

/** @type {TestSuite} */
const T = {
  context: [Context, TempContext],
  async'uses cache'({ app, config }, { TEMP, write }) {
    const core = new Core({
      app,
      config,
      page: { key: 'page' },
    })
    const path = 'styles/test.css'
    const mtime = core.getLocaleMtimeSync(join(config.appDir, path))
    core.CACHE_DIR = TEMP
    const data = '.cached{border:1px solid}'
    await write('styles.inline.json', JSON.stringify({ [path]: { mtime, data } }))
    core.styles.inline(path)
    deepEqual(core.styles.inlineStyles, [data])
  },
}
export default T

Here, my tests get configs from a context with all meta-data required and shared by tests, and use the temp dir created for each test by the second, TempContext. So I read the mtime of the target file first, and generate the cache file that will be read by the styles.inline method. The method itself will check for existing mtime, and the one in the cache, and if they match, it will return the one from the cache instead of compiling CSS anew which is what is happening in the test. Without my TempContext, I'd spend my whole day in front of TV just trying to avoid the pain of testing such logic :)

Another cool thing about contexts is that they provide access to their APIs with JSDoc via destructuring, e.g.,

context

I can see what utilities are available via the context and how to use them. TempContext is published as a separate package, and it is even tested itself, so that you're sure your tests are not giving false positives.

As you can see, I'm a big fan of JSDoc and believe that it's a natural part of the language. TypeScript is evil for me and I can't stand how everyone's so hyped about it. But this is because it solves their pain point of accessing IDE hints and autocompletions, which were pretty hard to manage without a separate system for managing types. This is what my product solves. So answering rosiesherry's question yesterday, how are you the only, I'm the only preserving JS tradition and saving it from MS and Open Source and I'm pretty proud of it.

  1. Finally, submitted confirmation statement to Companies' House and renewed a registered address at registeredaddress.co.uk for the 2nd time. They're really good and polite on the phone and you should use their services when you register your company in the UK. I don't know if this is allowed on IH (please redact if not), but here's my code:

Use my code 276354 to get 10% off your #virtualoffice plus mail forwarding! at RegisteredAddress.co.uk: https://registeredaddress.co.uk/registration

I had to borrow money from family since I literally could not pay that bill. In the beginning, I thought I'm just going to publish my tools to Open Source but that was just inadequate thinking imposed by the brainwashing from GitHub etc how all things are Open Source nowadays. In his talk
Great Leaders Do What Drug Addicts Do, the speaker mentions how he and his partners borrowed debt, maxed out their credit cards, and bid all on their product. And getting the major contract wasn't an excitement, it was a relief for him, because he put everything in it. I find myself in a similar position. I've been working for a long time, but unlike those businesses where you validate the market first, I know what the market needs because I needed this software. I didn't make it for people I make it for myself because I know how I want things done, traditional and without any influence from corporations.

  1. Finally, I listened to 25 Ways to Win with People by John Maxwell Audiobook before sleep as I love this kind of books. I fell asleep quite quick but a few points stuck in my mind, like the 30 seconds rule: don't try to present yourself in the best light possible when meeting people, present them in the best light, compliment their achievements and praise their reputation. This is amazingly true, who wouldn't want to hear a nice thing being said about them from a stranger? If I meet a person and he tells me he's familiar with my work and appreciates my ideas, I'd instantly like him. He/she'll immediately get positively personal and make an image of a kind fellow.

The leadership books are amazing, and I love leadership. Rob Walling says he's enjoying his micropreneurship because he doesn't need to "read another book on leadership" but that's where I don't agree with him. Leaders are those who see the problem, propose and implement a solution and have clarity of thought. It's sad that there's really a very limited number of true leaders today, but we can take responsibility to work to improve this, using our own vision, and goals, so that things eventually work out. It's hard to fight a fight you pick yourself being the only person seeing the purpose in it, but eventually it must work.

  1. Suggestions for IH
  • to integrate with Keybase verification
  • to add a preview button for comments
  • to add drag-n-drop image upload to posts/comments
  • to allow to resize the text input field in new posts
  • syntax highlighting for code blocks
  • ability to save drafts of posts otherwise it's pretty scary a long text's going to go away if you click in the wrong place.
  • @ should not be formatted in code blocks under tripple-ticks:
/** [@type](/type) {Type} */ -> wrong
/** @type {Type} */ -> right
  1. Goals for today:
  • to complete refactoring the static site compiler core, improve test coverage, and integrate the core back into the main package.
  • to use it to crack on with the website for my product (the types management system based on JSDoc), and to write an article outlining the abstract classes strategy. Btw, the product is not just for managing types, but to enable PROPER JS compilation with the compiler. It's a complete alternative to TypeScript based on traditional approach to JS programming. I've already got a landing page but my aim is to write that article and collect some newsletter sign ups.
  • Possibly to outline 3 case studies for the product.
posted to Icon for group Daily Stand-up
Daily Stand-up
on May 6, 2020
Trending on Indie Hackers
How I Closed My First SaaS Client Without Writing a Single Line of Code User Avatar 13 comments Why Building in Public Changed My SaaS Journey Forever User Avatar 13 comments Meme marketing for startups 🔥 User Avatar 12 comments From $0 to $10k MRR: My Indie Hacker Journey – Part 1 User Avatar 6 comments Protect your momentum like your life depends on It User Avatar 5 comments How do I change my username on Indie Hackers? User Avatar 1 comment