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.
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.
Like all other social networks, IH is addictive as you'll click on the logo, "new", and refresh repetitively.
.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.
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.,
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.
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.
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.
@
should not be formatted in code blocks under tripple-ticks:/** [@type](/type) {Type} */ -> wrong
/** @type {Type} */ -> right