<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <generator>Persumi - Level up your writing and blogging with AI</generator>
  <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
  <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
  <link href="http://persumi.com/u/fredwu/tech/e/blog"/>
  <link href="http://persumi.com/u/fredwu/tech/e/blog/feed/rss"/>
  <link rel="self" href="http://persumi.com/u/fredwu/tech/e/blog/feed/atom"/>
  <author>
    <name>Fred Wu</name>
    <email>ifredwu@gmail.com</email>
    <uri>http://persumi.com/u/fredwu</uri>
  </author>
  <subtitle/>
  <id>http://persumi.com/u/fredwu/tech/e/blog</id>
  <title>Blog - Fred Wu&apos;s Tech</title>
  <updated>2026-03-10T22:25:59.455837Z</updated>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
After having soft launched &lt;a href=&quot;https://persumi.com&quot;&gt;Persumi&lt;/a&gt; in 2023, I quickly found myself wanting to explore better ways to promote the product. Unfortunately, most of digital marketing products are focused on three main areas:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
Keyword bidding, e.g. Google Ads or Facebook Ads  &lt;/li&gt;
  &lt;li&gt;
Cold outreach, e.g. Apollo  &lt;/li&gt;
  &lt;li&gt;
Search Engine Optimisation (SEO)  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
They each has its own pros and cons. As an indie developer without a huge budget, none of these tools work effectively.&lt;/p&gt;
&lt;h2&gt;
The Challenges&lt;/h2&gt;
&lt;h3&gt;
Keyword bidding and targeted ads are expensive&lt;/h3&gt;
&lt;p&gt;
Bidding wars drive up the cost of targeted ads, sometimes so significantly they price out many small businesses.&lt;/p&gt;
&lt;p&gt;
Users are increasingly using adblockers, making targeted ads ineffective.&lt;/p&gt;
&lt;h3&gt;
Cold outreach are rarely answered&lt;/h3&gt;
&lt;p&gt;
Highly sought-after leads are bombarded with cold emails every day, making the tactic ineffective.&lt;/p&gt;
&lt;p&gt;
Most cold emails end up in users’ spam bin, never to be seen again.&lt;/p&gt;
&lt;h3&gt;
Search Engine Optimisation is a lost cause&lt;/h3&gt;
&lt;p&gt;
SEO’ed content are being produced hastily, making them low quality and untrustworthy.&lt;/p&gt;
&lt;p&gt;
Sophisticated users have learnt to ignore highly SEO’ed content from untrusted sources.&lt;/p&gt;
&lt;h2&gt;
The Epiphany&lt;/h2&gt;
&lt;p&gt;
Reflecting on my own behaviour in choosing a product or service, I realised that over the years I have developed a good sensory to weed out the noise. Namely, I am very skeptical with highly ranked websites, I always use an adblocker (uBlock) to block annoying ads, and both my personal and work email inboxes are overflowed with cold emails I never read them.&lt;/p&gt;
&lt;p&gt;
So how do I do research, say when I’m buying a new TV, or subscribing to a new software package? I read user reviews. And not just questionable reviews on Amazon or review sites, but on Reddit, where (mostly) real users discuss and review products and services.&lt;/p&gt;
&lt;p&gt;
Of course, like any other place, Reddit can be filled with bots and fake content too. However, in my experience these are easily distinguishable, especially paired with content’s upvotes and user’s post history. With Reddit’s popularity, this makes it a highly desirable place for people to both look for answers, as well as to provide answers.&lt;/p&gt;
&lt;p&gt;
So I asked myself, what if there was a smart lead generation tool to help me promote my product on Reddit? What should the tool be capable of?&lt;/p&gt;
&lt;h2&gt;
The Solution&lt;/h2&gt;
&lt;p&gt;
In order to really stand out, and provide tangible value, I’ve focused on the following areas for the lead gen tool.&lt;/p&gt;
&lt;h3&gt;
Warm leads over cold leads&lt;/h3&gt;
&lt;p&gt;
By searching for and engaging with relevant content, the leads the tool finds for you are warm and targeted.&lt;/p&gt;
&lt;p&gt;
Many of the leads are already highly ranked on search engines, further boosting the content’s reach.&lt;/p&gt;
&lt;h3&gt;
Personalised and public&lt;/h3&gt;
&lt;p&gt;
Content the tool produces for the user are context-aware and personalised, making them highly relevant and trustworthy.&lt;/p&gt;
&lt;p&gt;
Even better, the content are made available publicly, boosting the user’s reputation and reach even further over time.&lt;/p&gt;
&lt;h3&gt;
Infinite scale at a fixed cost&lt;/h3&gt;
&lt;p&gt;
The tool finds leads and suggest responses for the user 24/7 non-stop, at a fraction of the usual marketing costs.&lt;/p&gt;
&lt;p&gt;
The pricing is fixed and transparent, so the user can scale their business without worrying about blowing the budget.&lt;/p&gt;
&lt;h2&gt;
The Bottom Line&lt;/h2&gt;
&lt;p&gt;
Ultimately, I want a lead generation tool that really provides value to not only its user (the marketer), but its user’s users (the target audience). Instead of focusing on &lt;strong&gt;selling&lt;/strong&gt;, it should focus on &lt;strong&gt;helping people&lt;/strong&gt;. This is where &lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt; comes in.&lt;/p&gt;
&lt;h2&gt;
How &lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt; Works&lt;/h2&gt;
&lt;p&gt;
With &lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt;, machine learning is put to good use. It’s not just another AI wrapper, it actually leverages many of the latest AI innovation to really take lead generation to the next level.&lt;/p&gt;
&lt;h3&gt;
Smart search&lt;/h3&gt;
&lt;p&gt;
&lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt; widens the search radius to find the most relevant or highly ranked content for the user. It may find leads a simple Google search couldn’t. Behind the scenes, keywords are expanded and multiple search queries are submitted to search engines.&lt;/p&gt;
&lt;h3&gt;
Continuous monitor&lt;/h3&gt;
&lt;p&gt;
&lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt; continuously monitors the social media platforms (Reddit to start off with) to find new leads 24/7, delivering them right to the user’s inbox. Whether they are highly ranked popular posts or the latest post in a particular subreddit, &lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt; is able to quickly deliver them to the inbox without fuss.&lt;/p&gt;
&lt;h3&gt;
Leads inbox, as simple as Gmail&lt;/h3&gt;
&lt;p&gt;
Leads are automatically sent to the user’s inbox, where they can review and decide whether to engage with them. It’s as simple as using email.&lt;/p&gt;
&lt;h3&gt;
“Rizz Score”&lt;/h3&gt;
&lt;p&gt;
As mentioned earlier, the tools should focus on helping people, rather than hard selling. To make it easier for the user, &lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt; calculates a score based on how relevant, helpful and spammy the generated or user edited response is. This ensures it always publishes high quality content for the target audience, making it a win-win.&lt;/p&gt;
&lt;h3&gt;
Self-Learning AI&lt;/h3&gt;
&lt;p&gt;
Last but not least, by using state of the art AI technologies that adapts to the users, &lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt; is able to help them automate and scale their lead generation and reputation building with ease.&lt;/p&gt;
&lt;h2&gt;
Taking It For a Spin&lt;/h2&gt;
&lt;p&gt;
As soon as I’ve deployed &lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt; to production, I started using it to promote &lt;a href=&quot;https://persumi.com&quot;&gt;Persumi&lt;/a&gt; and dare I say I am very happy and impressed with its results. Not only does it find relevant leads right away, it drafts up responses that are super helpful and relevant to the OP’s questions or posts, and is very subtle in pushing the “promotion” agenda. I know a lot of subreddits shun or outright ban self-promotion, so it’s extremely important to have helpful posts.&lt;/p&gt;
&lt;p&gt;
If you are looking for an affordable way to promote your product, service, event or anything really, please give &lt;a href=&quot;https://rizz.farm&quot;&gt;Rizz.farm&lt;/a&gt; a try. It comes with 7 days of free trial and 30 days of no-question-asked money back guarantee. For a limited time, you can also get 50% off for six months using the coupon code &lt;code class=&quot;inline&quot;&gt;LAUNCH2024&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
Happy lead generation and growth hacking everyone!&lt;/p&gt;
]]&gt;</content>
    <published>2024-01-06T13:10:47.679944Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/c/product-builders/u/fredwu/p/introducing-rizz-farm-an-ai-assisted-lead-generation-tool-for-reddit"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/c/product-builders/u/fredwu/p/introducing-rizz-farm-an-ai-assisted-lead-generation-tool-for-reddit</id>
    <title>Introducing Rizz.farm - An AI-Assisted Lead Generation Tool for Reddit</title>
    <updated>2024-01-06T13:10:47.679944Z</updated>
  </entry>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
For a project I’m working on, we are looking at different AI OCR (Optical Character Recognition) options that would allow us to import documents with various layouts and extract relevant data from them with high enough accuracy. Due to the nature of these documents and the information contained in them, it is paramount that there would be an easy way for us to train the AI models using our documents.&lt;/p&gt;
&lt;p&gt;
Without revealing exactly what types of documents we are working with, as they’re commercially sensitive, the basic premise is to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
Import a document that might be one or more pages, the document itself may be high quality PDF, or low quality scanned documents that may or may not be skewed  &lt;/li&gt;
  &lt;li&gt;
Each page may or may not contain relevant information we want to extract  &lt;/li&gt;
  &lt;li&gt;
Relevant information may be structured in different ways, but usually in a tabular form (but each “line item” can either be horizontal or vertical)  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
In our case, a traditional OCR solution wouldn’t work as the documents often contain heaps of irrelevant data, and for the relevant data, it needs to understand the context in order to work out which data elements to extract, and how they relate to each other. Therefore, a machine learning based OCR solution that could adopt to our documents is highly desirable.&lt;/p&gt;
&lt;p&gt;
The success of the project is measured by the end results of imported data:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
  How much data is detected and recognised  &lt;/li&gt;
  &lt;li&gt;
  How accurate the recognised data elements are  &lt;/li&gt;
  &lt;li&gt;
  At a minimum, 80%+ accuracy is needed in order to save time in manual data entry, and to reduce/avoid incorrect data from being checked by a human operator before entering the system  &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Available OCR Tools&lt;/h2&gt;
&lt;p&gt;
There are a number of OCR tools available, for our project the minimum criteria are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
AI powered solution so it can be further developed and tweaked by us for our documents  &lt;/li&gt;
  &lt;li&gt;
A UI solution for data training, preferably easy to use so that non-technical team members can help with data training too  &lt;/li&gt;
  &lt;li&gt;
A quick and easy way to test and verify trained models  &lt;/li&gt;
  &lt;li&gt;
A solution that is compliant with the ISO standards relevant for us  &lt;/li&gt;
  &lt;li&gt;
Pay by usage pricing model that’s not cost prohibitive  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The tools I have discovered and considered were:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
AWS Textract  &lt;/li&gt;
  &lt;li&gt;
Microsoft Azure Document Intelligence (formerly known as Azure Form Recognizer)  &lt;/li&gt;
  &lt;li&gt;
Google Cloud Document AI  &lt;/li&gt;
  &lt;li&gt;
Rossum.ai  &lt;/li&gt;
  &lt;li&gt;
Super.ai  &lt;/li&gt;
  &lt;li&gt;
Eden.ai  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
All six options are AI based OCR solutions. Amazon Web Services (AWS), Microsoft Azure and Google Cloud Platform (GCP) are the obvious “big three”, having their own AI models, whereas Super and Eden are aggregators that farms AI calls to providers like AWS, Azure and Google, and provides a middle layer that could potentially make the end result better (or worse). It’s unclear what model Rossum uses.&lt;/p&gt;
&lt;p&gt;
After some consideration, Rossum, Super and Eden were all taken off the table due to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
  Rossum and Super not having transparent pricing  &lt;/li&gt;
  &lt;li&gt;
  Eden being an API aggregator built by a small team, it’s unclear on its usefulness and longevity  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
With the longevity of the company and product in mind, as well as transparent pricing and commercial support, AWS, Azure and Google remain to be the leading choices.&lt;/p&gt;
&lt;h2&gt;
The Big Three: AWS, Azure and Google&lt;/h2&gt;
&lt;h3&gt;
AWS Textract&lt;/h3&gt;
&lt;p&gt;
Out of the big three, AWS is our preferred vendor due to its market leading position as a cloud service provider, as well as our existing projects already using AWS.&lt;/p&gt;
&lt;p&gt;
However, upon closer inspection, it appears Textract &lt;a href=&quot;https://stackoverflow.com/questions/68044070/how-to-customise-aws-textract&quot;&gt;does not allow custom data training&lt;/a&gt;. Textract is provided “as-is” using Amazon’s pre-trained models, it does not allow customers like us to provide their own training data to improve on the detection and recognition of different types of documents.&lt;/p&gt;
&lt;p&gt;
AWS’ machine learning blog has published an article on “&lt;a href=&quot;https://aws.amazon.com/blogs/machine-learning/building-an-end-to-end-intelligent-document-processing-solution-using-aws/&quot;&gt;end-to-end intelligent document processing solution&lt;/a&gt;“ in 2020, however it does not explain in detail exactly what the capabilities are, and the solution requires a complex architecture that needs significant amount of time and effort to set up and maintain.&lt;/p&gt;
&lt;h3&gt;
Azure Document Intelligence&lt;/h3&gt;
&lt;p&gt;
Azure’s offering, formerly known as Form Recognizer, is an end-to-end solution that offers &lt;a href=&quot;https://learn.microsoft.com/en-au/azure/ai-services/document-intelligence/concept-custom&quot;&gt;custom data labelling and training&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
Google Cloud Document AI&lt;/h3&gt;
&lt;p&gt;
Google’s offering, similar to Azure’s, is also an end-to-end solution that offers &lt;a href=&quot;https://cloud.google.com/document-ai/docs/workbench/build-custom-processor&quot;&gt;custom data labelling and training&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Comparison: Azure vs Google&lt;/h2&gt;
&lt;p&gt;
With the initial assessment done, we are left with Azure and Google, so let’s dive into the deep comparison of the two platforms.&lt;/p&gt;
&lt;p&gt;
We will compare the two platforms in several aspects:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
The ease of initial set up, i.e. how quickly can we get up and running right away  &lt;/li&gt;
  &lt;li&gt;
Whether a “base” pre-trained model is provided for documents with high enough accuracy so we save time in customisation and training  &lt;/li&gt;
  &lt;li&gt;
The detection and recognition – how much data is accurately detected and recognised  &lt;/li&gt;
  &lt;li&gt;
The custom training process, how easy is it to label custom data  &lt;/li&gt;
  &lt;li&gt;
How fast or slow the training is  &lt;/li&gt;
  &lt;li&gt;
The end result – provided with the same training dataset, which platform offers better results  &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
The Initial Setup&lt;/h3&gt;
&lt;h4&gt;
Microsoft Azure&lt;/h4&gt;
&lt;p&gt;
Azure’s initial set up is relatively straightforward. There is a four-step dialog window to set up the required Azure resources, etc. After which, documents can simply be uploaded for immediate consumption - labelling and training, which will be touched on in later sections.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/08d15780-8791-4671-b162-0261dc1bbf65.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/137edab2-4967-426a-b459-4f0760526274.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h4&gt;
Google Cloud&lt;/h4&gt;
&lt;p&gt;
Google works slightly differently in this case. To set up a project it’s very simple, there is literally only the “Processor name” to fill out. However, it does require a separate step to set up the storage bucket required.&lt;/p&gt;
&lt;p&gt;
Also, instead of allowing files to be uploaded within the same UI like Azure, Google requires files to be uploaded to the cloud storage bucket first, then imported into Document AI.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/123124bc-8fc5-4204-9cd8-50385496603f.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/a0eced5c-9c94-4a62-8322-3f9ca3eae8c1.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h3&gt;
Auto Labelling Data&lt;/h3&gt;
&lt;h4&gt;
Microsoft Azure&lt;/h4&gt;
&lt;p&gt;
“Auto-labelling” refers to the AI OCR’s ability to do the initial labelling automatically, to save time and effort in the manual labelling work. It can be seen as the starting point of training the AI model.&lt;/p&gt;
&lt;p&gt;
In this case, the Azure experience is significantly better. It allows files to be uploaded, then auto-labelled by “current”, “unlabelled” or “all” documents. This gives the flexibility to users (i.e. us) to choose when a document should be auto-labelled – as it does take a bit of time, sometimes if a document is not very well structured and would require more manual labelling anyway, then it’s best to skip the auto-label step.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/380e737f-29ba-4b37-bdc6-809e2b308cc3.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h4&gt;
Google Cloud&lt;/h4&gt;
&lt;p&gt;
Google on the other hand, has a more cumbersome process. We first need to upload the files to the storage bucket, as mentioned before. Then, we select the path/folder of the uploaded files, and the “auto-labelling” is enabled or disabled for the entire import. Also, sometimes the import takes a long time, whereas on Azure it’s always instant.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/5e4f3304-92b0-42de-bde1-fc1fd4eb9a06.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
More on the accuracy of auto-labelling later.&lt;/p&gt;
&lt;h3&gt;
Text Detection and Recognition&lt;/h3&gt;
&lt;p&gt;
A big part of OCR is obviously text detection and recognition. Even without training, a good OCR solution should detect and recognise clear text effortlessly.&lt;/p&gt;
&lt;p&gt;
During our initial research, we’ve found &lt;a href=&quot;https://cazton.com/blogs/executive/handwriting-recognition-azure-aws-gcp&quot;&gt;this article&lt;/a&gt; that compared the text recognition accuracy between AWS, Azure and Google. Their finding was that Azure and Google were comparable with a slight edge to Azure (Azure performed better on 2 out of 3 documents, and Google performed better on 1 out of 3 documents), both were way ahead of AWS in terms of accuracy.&lt;/p&gt;
&lt;p&gt;
Our own testing has somewhat mirrored their experience. We found that in general, Azure performed better in the number of detected text elements, as well as the correctness of these text.&lt;/p&gt;
&lt;p&gt;
On Azure, it’s very rare for text to be undetectable, whereas on Google, we’ve found several instances where the text is very clear, yet Google was unable to detect the text at all.&lt;/p&gt;
&lt;p&gt;
Similarly on accuracy, Azure has rarely detected clear text incorrectly, whereas on Google, a lot of times units such as &lt;code class=&quot;inline&quot;&gt;x10*9/L&lt;/code&gt; get recognised incorrectly despite all instances appearing similar in their appearance (i.e. very clear), and sometimes dashes won’t get recognised (e.g. &lt;code class=&quot;inline&quot;&gt;10.0 - 12.50&lt;/code&gt; gets recognised as &lt;code class=&quot;inline&quot;&gt;10.0 12.50&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;
Custom Labelling&lt;/h3&gt;
&lt;p&gt;
During training, a big portion of time is spent on custom labelling, meaning we look for and assign text to our pre-defined data elements such as name and occupation - these are just fictional examples.&lt;/p&gt;
&lt;p&gt;
Overall, Azure and Google each has its strengths and weaknesses. Let’s go through them in detail.&lt;/p&gt;
&lt;h4&gt;
Auto Layout&lt;/h4&gt;
&lt;p&gt;
On Azure, there is a “Run layout” step that would recognise all the text elements, as well as tabular data in a given document.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/dfcad327-d48d-4a66-be65-8a4661ffa5af.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Once “run layout” is performed, all the recognised text are highlighted in yellow, giving a quick and easy overview of the usable data elements.&lt;/p&gt;
&lt;p&gt;
Google on the other hand, does not offer a similar function, therefore labelling needs to be performed with more effort, more on this later.&lt;/p&gt;
&lt;h3&gt;
Schema vs Schema-less&lt;/h3&gt;
&lt;p&gt;
One key difference between Azure and Google’s solutions, is that the Azure solution is schema-less whereas the Google solution is based on defined schemas.&lt;/p&gt;
&lt;p&gt;
On Azure, we can add a “field”, and then assign the field a type (string, number, etc). A field can then be renamed or re-assigned with a different type at any time.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/940cc894-20ba-4d22-8ecc-3b156adf1859.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/1514d2c8-1ed0-49ca-8669-68318db39e1a.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
There is a special field called “table field”, we can create tabular data using this field type.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/577d29d1-ff02-4eff-959c-70f5cd1a898b.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/9875641e-469a-4511-9230-fb949661f655.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Google works very differently. Instead of adding fields on the fly, Google requires a schema (a.k.a. field definitions) to be created first. Once a field is created, and data trained, it cannot be edited or deleted.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/00a08a47-6ff7-41a0-b970-9ece1642237a.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
One advantage of Google’s approach is a more definitive structure of OCR’ed data. When creating a label, not only do we have to choose a type (similar to Azure), we also can choose its occurrence logic, see the screenshot below.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/6390ae94-f3dc-4a96-8e5a-331f0e144032.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Despite this, we found that the schema-less approach on Azure offers far better versatility without being confined to a pre-defined schema, making training new revisions of models far easier.&lt;/p&gt;
&lt;h3&gt;
Labelling Data&lt;/h3&gt;
&lt;p&gt;
Most of the time spent on training, is the manual labelling of data elements on the documents. Azure’s approach in this case is significantly faster and more accurate, compared to Google’s.&lt;/p&gt;
&lt;h4&gt;
Microsoft Azure&lt;/h4&gt;
&lt;p&gt;
On Azure, because of the “run layout” step, all text elements are already detected. So labelling them as part of the test results is very simple, you click on the yellow elements to select the text you want, then click on the table cell on the right to assign them.&lt;/p&gt;
&lt;p&gt;
However, if somehow Azure detects the data incorrectly, there is no way for us to provide a correction. In this case, we could choose to either skip the cell, or simply assign the cell with the incorrect data – if more training data is provided over time then these edge cases will not have a big impact on the final accuracy of the model.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/d0a08e48-73a1-4757-9028-ef566773abe8.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
In the screenshot above, sensitive data elements are blacked out for the purpose of this blog post.&lt;/p&gt;
&lt;h4&gt;
Google Cloud&lt;/h4&gt;
&lt;p&gt;
On Google, this process is significantly more involved. Due to not having a “run layout”-like step, we need to draw over the text to select it, and there’s no way to tell whether Google has detected the text before using the tool, so sometimes you’ll draw over some text and get an error saying, “Cannot create labels with empty values”.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/f858e169-3f1b-47b5-a9cf-f7c5dc836d83.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Again, in the screenshot above, sensitive data elements are blacked out for the purpose of this blog post.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/f057079c-bd70-490d-9e8f-3c72bdd5fd8f.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
And because we can’t simply click on the highlighted text already detected, like on Azure, this makes the whole process significantly longer as we have to carefully draw over the text to ensure the boundary is accurate (for training purpose), sometimes we have to zoom in and reposition the document for accurate drawing.&lt;/p&gt;
&lt;p&gt;
The schema assignment is also less intuitive compared to Azure’s. Instead of having a table to easily see tabular data, Google’s schema is more like a series of key-value pairs, making glancing at assigned data much harder, and the key-value elements are ordered alphabetically, instead of logically like on Azure, making assigning data unnatural.&lt;/p&gt;
&lt;p&gt;
The one advantage of Google’s approach though, is that when the recognised data is incorrect, we can manually override it with our own correct data. However, after using both solutions for a while, we’ve found that Google’s has a much higher error rate compared to Azure’s to begin with.&lt;/p&gt;
&lt;h3&gt;
Auto-Label Accuracy&lt;/h3&gt;
&lt;p&gt;
In order to assess the auto-labelling accuracy, we have trained several of our documents with varying quality and layout. We then uploaded a new document with a layout that has not been trained.&lt;/p&gt;
&lt;p&gt;
The results are very telling.&lt;/p&gt;
&lt;h4&gt;
Microsoft Azure&lt;/h4&gt;
&lt;p&gt;
Azure has pretty much labelled things perfectly - all the data elements were detected correctly and within the correct contexts. The second comment block is also detected correctly.&lt;/p&gt;
&lt;p&gt;
In this case, the Azure auto-label has only missed the first comment block.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/27360181-ec22-46df-abc1-215124f568cf.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
The screenshot above is blurred to protect the sensitive nature of it.&lt;/p&gt;
&lt;h4&gt;
Google Cloud&lt;/h4&gt;
&lt;p&gt;
Google’s result unfortunately falls short of expectation.&lt;/p&gt;
&lt;p&gt;
As seen in the screenshot below, Google has missed several data elements, and incorrectly detected elements that should not be part of the result. Again, the screenshot is blurred to protect the sensitive nature of it.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/b0fdd124-69a1-4df6-8008-401c03cc02eb.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
This suggests two possible things about Google’s OCR solution:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
  The default text recognition is poor, therefore it’s missing data elements even though they are clearly presented, in the same way as other elements  &lt;/li&gt;
  &lt;li&gt;
  The neural network for language models is poor, therefore it incorrectly detected text that shouldn’t be part of any result  &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
Auto-Label Result Verification&lt;/h3&gt;
&lt;h4&gt;
Microsoft Azure&lt;/h4&gt;
&lt;p&gt;
Once Azure’s performed the auto-labelling, it’s very easy to check the results, as seen in the blurred screenshot below, we simply look at the table to ensure the correctness. However, as mentioned before, we can only correct detected regions of text, not the content itself.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/28acf5ba-e055-4269-989b-bc144a97f0a0.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h4&gt;
Google Cloud&lt;/h4&gt;
&lt;p&gt;
On Google, it is more involved. As seen in the blurred screenshot below, it requires a lot of scrolling to find the auto-labelled data. Alternatively, we can hover over the highlighted text to look at the auto-labelled text, although in this case, the pop-up gets in the way of other data which makes it an annoyance at times.&lt;/p&gt;
&lt;p&gt;
Curiously, despite having a schema, and setting certain elements to “required once” (per schema), Google still went ahead and falsely detected multiple results per schema.&lt;/p&gt;
&lt;p&gt;
But as mentioned before, Google does offer the ability to manually correct the text content, which is a big plus.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/6602041a-1c8a-4eb4-8ccd-d0c6008ca98c.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h3&gt;
Data Training Speed&lt;/h3&gt;
&lt;p&gt;
We have found training to be significantly faster on Azure.&lt;/p&gt;
&lt;p&gt;
With about 45 documents, it takes about 30 minutes to train on Azure.&lt;/p&gt;
&lt;p&gt;
Google takes about twice as long, about an hour to train, and another several minutes to deploy the trained model. Azure does not need a separate deployment step.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/9ef5c376-5136-4e88-a989-0c1e5e244833.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Interestingly, on Google, training a model requires having enough test data. So documents need to be split into training and test groups. It is unclear whether the test data is used for actual training.&lt;/p&gt;
&lt;p&gt;
There is also a required number of labelled elements (10 minimum, 50 recommended) before a model can be trained. Azure has no such limitations.&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/images/0b1b9f24-76d5-4b5b-8997-6982e0d17fe5.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h3&gt;
Data Regions and Compliance&lt;/h3&gt;
&lt;p&gt;
While both Azure and Google are compliant to many standards (ISO, GDPR, etc), Google’s Document AI can only be hosted out of their US or EU regions. Whereas Azure has no such limitation and can be hosted in any of their available regions.&lt;/p&gt;
&lt;p&gt;
This has a side effect on the performance of UI operations. Azure is very quick and snappy due to it being deployed in our local AU region, whereas Google due to it being deployed in the US region, is a little slow every time you open and close a document for example.&lt;/p&gt;
&lt;h2&gt;
Conclusion&lt;/h2&gt;
&lt;p&gt;
With the in-depth analysis done, it is no surprise that in the end we went with Microsoft Azure’s Document Intelligence for our AI OCR needs. I hope these findings are useful to other people too.&lt;/p&gt;
]]&gt;</content>
    <summary>The article compares six AI OCR tools: AWS Textract, Microsoft Azure Document Intelligence, Google Cloud Document AI, Rossum.ai, Super.ai and Eden.ai. It then does a deep comparison between Azure and Google, the two leading choices, in several aspects: initial setup, auto labelling data, text detection and recognition, custom labelling, auto-label accuracy, auto-label result verification, data training speed, data regions and compliance. The article concludes that Azure is the better choice.</summary>
    <published>2023-09-17T03:44:24.872189Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/c/product-builders/u/fredwu/p/comparison-of-ai-ocr-tools-microsoft-azure-ai-document-intelligence-google-cloud-document-ai-aws-textract-and-others"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/c/product-builders/u/fredwu/p/comparison-of-ai-ocr-tools-microsoft-azure-ai-document-intelligence-google-cloud-document-ai-aws-textract-and-others</id>
    <title>Comparison of AI OCR Tools: Microsoft Azure AI Document Intelligence, Google Cloud Document AI, AWS Textract and Others</title>
    <updated>2023-09-17T03:44:24.872189Z</updated>
  </entry>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
A few weeks ago I &lt;a href=&quot;welcome-to-persumi-a-modern-platform-for-content-creation&quot;&gt;soft launched&lt;/a&gt; an MVP - you are looking at it right now.&lt;/p&gt;
&lt;p&gt;
In this post I’ll talk about the features, the tech stack and the globally distributed infrastructure behind building this MVP, and of course, with a sprinkle of learnings too.&lt;/p&gt;
&lt;h2&gt;
The “MVP”&lt;/h2&gt;
&lt;p&gt;
Deciding what makes up an “MVP” is always interesting - I’ve heard some saying if the product &lt;em&gt;isn’t&lt;/em&gt; embarrassing you’re releasing it too late, and also if the product &lt;em&gt;is&lt;/em&gt; embarrassing, you’re not gonna make it.&lt;/p&gt;
&lt;p&gt;
For me, I’ve always had the idea of building all the essential features as part of the MVP, with one or two “hero” features that would differentiate the product from the competitions, and then build out more premium features over time.&lt;/p&gt;
&lt;p&gt;
If you can’t already tell, Persumi is a content creation platform with some social networking features. It may sound bland, but what I believe makes it stand out, is the desire of putting the focus back onto the content, rather than the VC-fuelled, ever increasing appetite for more ads and user hostile features.&lt;/p&gt;
&lt;h2&gt;
The Long Nights and Weekends&lt;/h2&gt;
&lt;p&gt;
There is no magic beans for productivity - especially when I have a full time job. Working on a side hustle means giving up on almost all social and entertainment activities. It’s not for everyone, but I didn’t mind it too much. Being an introvert definitely helped - I was happy to see night by night the MVP gradually taking shape to become more and more real.&lt;/p&gt;
&lt;p&gt;
Looking back, I spent about three months to build out most of the MVP, then another week or two on infrastructure, and another week or two for polishing, all whilst having a full time job.&lt;/p&gt;
&lt;p&gt;
It’s been a journey, I’m glad that it “only” took me 3-4 months to get to this stage, as initially I estimated for a 6+ months MVP build.&lt;/p&gt;
&lt;h2&gt;
The Features&lt;/h2&gt;
&lt;p&gt;
With all that in mind, I’ve set out to build the essential features that make a blogging and social networking platform:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
Short form content like a tweet  &lt;/li&gt;
  &lt;li&gt;
Long form content like a blog post or a book chapter  &lt;/li&gt;
  &lt;li&gt;
RSS feeds  &lt;/li&gt;
  &lt;li&gt;
Communities similar to forums and sub-reddits  &lt;/li&gt;
  &lt;li&gt;
Direct messaging between users  &lt;/li&gt;
  &lt;li&gt;
A voting (like/dislike) system  &lt;/li&gt;
  &lt;li&gt;
A bunch of CRUD glue pieces to make all these things work  &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
The “Hero” Features&lt;/h3&gt;
&lt;p&gt;
Beyond these seemly unremarkable features, I’ve also had in mind two key features that would differentiate the platform from the rest:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
The “persona” concept, whereby each user is allowed to have multiple personas to hold different content or topics of interest, e.g. a persona for professional stuff, a persona for gaming stuff and a persona for travel stuff, etc  &lt;/li&gt;
  &lt;li&gt;
AI generated audio content for text (also known as Text-to-Speech)  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
These two “hero” features are what drove me to build Persumi in the first place. Together, they solve some very real pain points for me, namely:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
Following specific topics of interest from people is difficult, with the algorithms taking over people’s home feeds, there are simply way too much noise, thanks to VC-fuelled “user engagement” metrics  &lt;/li&gt;
  &lt;li&gt;
Content consumption on the go (e.g. during commute or during workouts, etc) is becoming more and more prevalent, but the traditional platforms haven’t adopted to this new lifestyle other than shoving short form content down our throats  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
There’s also a third “hero” feature: the Aura system. Unlike the upvote/downvote or like/dislike buttons in many social platforms that only serve the algorithm to push more content to you, Persumi’s Aura system keeps track of user’s content quality over time, and would punish the low quality content and promote high quality content using visual cues - lower quality content has a much lower contrast making them easy to ignore. In the age of social media, self-curating content becomes essential to keep a platform healthy, engaging and usable.&lt;/p&gt;
&lt;h3&gt;
The Non-MVP Features, a.k.a. The Future&lt;/h3&gt;
&lt;p&gt;
There are many features that didn’t make the MVP cut, most of these are value-added features that will eventually make their way into paid subscriptions - if Persumi gains enough traction to attract users who don’t mind paying for premium features.&lt;/p&gt;
&lt;p&gt;
A prime example of such paid features is ones that help users monetise their content, e.g. ad revenue sharing and paid subscribers (like Patreon).&lt;/p&gt;
&lt;p&gt;
I also have the ambition of building out Persumi’s features so it can eventually compete against the likes of LinkedIn and Tinder.&lt;/p&gt;
&lt;p&gt;
Wouldn’t it be better for the world to have a platform like Persumi that doesn’t focus on dark patterns and exploiting users? 😉&lt;/p&gt;
&lt;h2&gt;
The Tech Stack&lt;/h2&gt;
&lt;p&gt;
Over the past decade or so I’ve mainly worked with two tech stacks: Ruby and Elixir. So naturally, Persumi was going to be built using one of them.&lt;/p&gt;
&lt;p&gt;
After some consideration, I’ve decided to go ahead with Elixir, the main reasons were:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
Elixir and Erlang/OTP support distributed systems out of box  &lt;/li&gt;
  &lt;li&gt;
I’ve been writing more Elixir than Ruby lately, so I’m more productive in Elixir  &lt;/li&gt;
  &lt;li&gt;
I really wanted to try and use &lt;a href=&quot;https://github.com/phoenixframework/phoenix_live_view&quot;&gt;LiveView&lt;/a&gt; in production  &lt;/li&gt;
  &lt;li&gt;
I prefer Phoenix’s application architecture more than Rails’  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
On top of Elixir, I’ve decided early on a few other things to go with it:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
Tailwind for CSS  &lt;/li&gt;
  &lt;li&gt;
Postgres for database, preferably a serverless option  &lt;/li&gt;
  &lt;li&gt;
A search engine  &lt;/li&gt;
  &lt;li&gt;
An easy to maintain infrastructure that doesn’t cost an arm and a leg  &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
Elixir&lt;/h3&gt;
&lt;p&gt;
I first discovered Elixir in 2014 while I was still actively involved in the Ruby and Rails communities, but it was two years later that I had the opportunity to really dive into it. I built a few open source libraries to help me learn Elixir and OTP:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/fredwu/crawler&quot;&gt;Crawler&lt;/a&gt; - a high performance web scraper.  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/fredwu/opq&quot;&gt;OPQ: One Pooled Queue&lt;/a&gt; - a simple, in-memory FIFO queue with back-pressure support, built for Crawler.  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/fredwu/simple_bayes&quot;&gt;Simple Bayes&lt;/a&gt; - a Naive Bayes machine learning implementation. Hey, I was doing machine learning before it was mainstream! 😆  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/fredwu/stemmer&quot;&gt;Stemmer&lt;/a&gt; - an English (Porter2) stemming implementation, built for Simple Bayes.  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
With a decent amount of experience building Phoenix web apps over the years, I unfortunately never had the opportunity to use LiveView…&lt;/p&gt;
&lt;p&gt;
I guess that’s finally changed now.&lt;/p&gt;
&lt;p&gt;
LiveView has been amazing, not only does it drastically reduce the amount of front-end code you have to write, make the entire web app feel super snappy, but it also virtually eliminates any front-end and back-end code/logic duplications. It is such an awesome piece of technology that improves both the user experience and the developer experience.&lt;/p&gt;
&lt;h4&gt;
Petal Pro&lt;/h4&gt;
&lt;p&gt;
During my initial tech research, I came across &lt;a href=&quot;https://petal.build/&quot;&gt;Petal Pro&lt;/a&gt; which is a boilerplate starter template built on top of Phoenix. It handles things like user authentication which almost every web app needs, but is somewhat tedious to build.&lt;/p&gt;
&lt;p&gt;
Petal Pro isn’t free but it ended up saving me so much time. I also started contributing small bug fixes and features to it too. If you are about to build something in Phoenix, check it out!&lt;/p&gt;
&lt;h3&gt;
Tailwind CSS&lt;/h3&gt;
&lt;p&gt;
As I kept progressing my career, there have been fewer and fewer opportunities for me to write front-end and CSS code. Last time I rebuilt my blog, I used &lt;a href=&quot;https://bulma.io/&quot;&gt;Bulma&lt;/a&gt; - that was 2019. Since then Tailwind has gained a lot more traction, so I wanted an excuse to try finally give it a shot.&lt;/p&gt;
&lt;p&gt;
There is a debate on how many new things you should try for building your MVP - the more you have to learn, the slower your MVP progresses. That said, given CSS is reasonably straightforward, I figured it wouldn’t slow me down too much, if anything, Tailwind’s flexibility might just eventually make up any time lost in learning.&lt;/p&gt;
&lt;p&gt;
I’m happy to report that it is indeed true - by using Tailwind, it became significantly easier for me to customise my components and elements. I can see why it became so popular. It’s not for everyone, but I like it.&lt;/p&gt;
&lt;h3&gt;
Postgres&lt;/h3&gt;
&lt;p&gt;
Choosing Postgres as a database was a no brainer, given how popular and versatile it is. I did briefly consider NoSQL options like DynamoDB but quickly wrote them off as I needed an RDBMS to get things off the ground quickly, and the DB is unlikely to be the bottleneck for a long time anyway.&lt;/p&gt;
&lt;p&gt;
In Elixir, the &lt;a href=&quot;https://hexdocs.pm/ecto/Ecto.html&quot;&gt;Ecto library&lt;/a&gt; works wonders for Postgres.&lt;/p&gt;
&lt;p&gt;
Later in the post I’ll touch on how I deploy and run Postgres in production.&lt;/p&gt;
&lt;h3&gt;
Search Engine&lt;/h3&gt;
&lt;p&gt;
For a search engine, my requirements were:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
The ability to search across multiple fields of a schema  &lt;/li&gt;
  &lt;li&gt;
The ability to rank them  &lt;/li&gt;
  &lt;li&gt;
The ability to have typo tolerance, word stemming and other similar language features to make search more intuitive  &lt;/li&gt;
  &lt;li&gt;
The ability to search multiple languages, including CJK (Chinese/Japanese/Korean) characters  &lt;/li&gt;
  &lt;li&gt;
Simple to run  &lt;/li&gt;
  &lt;li&gt;
Cheap to run  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Using Postgres’ full text search was probably going to be the simplest but it doesn’t offer all the functionalities I need without a bunch of set up and manual SQL queries so I didn’t pursue it.&lt;/p&gt;
&lt;p&gt;
Elasticsearch on the other hand, offers good search functionalities but takes a bit of effort to set up and maintain, and can be costly to run.&lt;/p&gt;
&lt;p&gt;
After doing some more research, I found the following three options that would fit my needs:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.algolia.com/&quot;&gt;Algolia&lt;/a&gt;  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.meilisearch.com/&quot;&gt;Meilisearch&lt;/a&gt;  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://typesense.org/&quot;&gt;Typesense&lt;/a&gt;  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Both Meilisearch and Typesense are open source, with commercial SaaS offerings, whilst Algolia is SaaS-only.&lt;/p&gt;
&lt;p&gt;
It’s been an interesting journey. I started with Typesense as I liked what I read, but I quickly discovered that it doesn’t search Chinese characters properly.&lt;/p&gt;
&lt;p&gt;
I then turned to Meilisearch. I especially liked the fact that they offered a generous free tier SaaS to get you off the ground running. Spoiler: during my implementation they did a bait and switch and removed the free tier.&lt;/p&gt;
&lt;p&gt;
At the time the Elixir support for Meilisearch wasn’t up to date, so I ended up &lt;a href=&quot;https://github.com/nutshell-lab/meilisearch-ex/pull/5&quot;&gt;contributing to a community library&lt;/a&gt; to add the features I needed.&lt;/p&gt;
&lt;p&gt;
Curious timing, after Meilisearch removed their free tier, I discovered that even though they officially support searching for Chinese characters, the implementation wasn’t perfect. I found some edge cases where characters weren’t detected properly, making the search results unreliable.&lt;/p&gt;
&lt;p&gt;
So, my last hope was Algolia. Despite them being the more expensive option out of the three, it does offer a free tier. It turns out, their search results for Chinese characters were much better than Meilisearch’s. Luckily, re-implementing the search from Meilisearch to Algolia didn’t take too much effort, it was pretty much done in one night.&lt;/p&gt;
&lt;h3&gt;
Infrastructure&lt;/h3&gt;
&lt;p&gt;
Early on during the development I’d already determined I wanted to try &lt;a href=&quot;https://fly.io/&quot;&gt;Fly&lt;/a&gt; and &lt;a href=&quot;https://neon.tech/&quot;&gt;Neon&lt;/a&gt;, for web and DB, respectively.&lt;/p&gt;
&lt;p&gt;
I am in no way associated with either company, I was curious about Fly due to its tie-in with the Elixir community (Phoenix Framework’s author Chris McCord works there), and Neon due to its serverless nature.&lt;/p&gt;
&lt;h4&gt;
Globally Distributed Infra&lt;/h4&gt;
&lt;p&gt;
With Fly, the infrastructure automatically becomes globally distributed as soon as I started provisioning servers in more than one region. As of the time of writing, Persumi is deployed to US West, Australia and EU.&lt;/p&gt;
&lt;p&gt;
Despite being simple to use, making Fly work initially actually took quite a bit of finessing due to its incomplete official documentation and flakiness. Some of the services were having issues during the course of my MVP development. Worse, they don’t report (or sometimes even acknowledge) the issues unless they are region-wide outages. To this date, I believe their blue/green deployment strategy which was recently introduced, is still buggy, I often have to use their rolling deployment strategy instead. Deployment logs were provided to Fly but I think they’re too busy with other things…&lt;/p&gt;
&lt;p&gt;
Still, I’m sticking with them for now due to the ease of use after the initial hurdle, and their globally distributed infrastructure without asking for my kidney.&lt;/p&gt;
&lt;p&gt;
To augment Fly’s web servers, I also use Cloudflare’s &lt;a href=&quot;https://www.cloudflare.com/application-services/products/cdn/&quot;&gt;CDN&lt;/a&gt; as well as &lt;a href=&quot;https://www.cloudflare.com/developer-platform/r2/&quot;&gt;R2&lt;/a&gt; to serve asset files and audio files.&lt;/p&gt;
&lt;p&gt;
Funny tangent, initially I used &lt;a href=&quot;https://bunny.net/&quot;&gt;Bunny&lt;/a&gt; for asset files and CDN, as I misread Cloudflare’s terms and thought I couldn’t serve audio files from Cloudflare. Bunny worked okay but their dashboard for some reason was painfully slow - not a good look for a CDN company. Like the search engine switch, it didn’t take me too long to switch over to Cloudflare.&lt;/p&gt;
&lt;h4&gt;
Serverless Postgres&lt;/h4&gt;
&lt;p&gt;
There are a few options to run Postgres:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
Run on a standard server for maximum portability, but it requires more server maintenance overhead  &lt;/li&gt;
  &lt;li&gt;
Run on AWS RDS/Aurora or a similar managed service, easy but can be costly  &lt;/li&gt;
  &lt;li&gt;
Run on a serverless option such as Aurora Serverless or Neon  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
For my use case, I think option 2 or 3 are better fitting. As I mentioned earlier, I started the experiment with &lt;a href=&quot;https://neon.tech/&quot;&gt;Neon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Neon worked well initially, until I started deploying Fly instances in multiple regions. Due to Neon being only available in one region (I chose US West), and I live in Australia, the round trips between Fly’s Australian instance and Neon’s US instance were a show stopper - especially when complex DB transactions were involved. Actions sometimes took &lt;em&gt;seconds&lt;/em&gt; to complete, yikes.&lt;/p&gt;
&lt;p&gt;
Despite Fly not offering a managed Postgres service, I ended up trying it anyway due to its &lt;a href=&quot;https://fly.io/docs/postgres/advanced-guides/high-availability-and-global-replication/&quot;&gt;distributed nature&lt;/a&gt;. After incorporating &lt;a href=&quot;https://github.com/superfly/fly_postgres_elixir&quot;&gt;Fly Postgres&lt;/a&gt; in the app, all DB operations immediately became more responsive. Paired with LiveView, it feels like running the application locally.&lt;/p&gt;
&lt;p&gt;
The current Persumi infra looks like:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
1 x Fly instance in US West, always on  &lt;/li&gt;
  &lt;li&gt;
1 x Fly instance in Australia, auto-shutdown when there’s no traffic  &lt;/li&gt;
  &lt;li&gt;
1 x Fly instance in Netherlands, auto-shutdown when there’s no traffic  &lt;/li&gt;
  &lt;li&gt;
1 x Fly Postgres writer instance in US West, always on  &lt;/li&gt;
  &lt;li&gt;
1 x Fly Postgres read replica instance in Australia, always on  &lt;/li&gt;
  &lt;li&gt;
1 x Fly Postgres read replica instance in Netherlands, always on  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
With this setup, I think I’m quite happy with the cost and scalability balance - it costs ~$20/m to run, with the potential of both vertical and horizontal scaling with ease.&lt;/p&gt;
&lt;h2&gt;
The Missteps&lt;/h2&gt;
&lt;p&gt;
The search engine and CDN swaps mentioned earlier certainly took away some of my time, but they were nothing compared to a major misstep I encountered.&lt;/p&gt;
&lt;p&gt;
And that was:  the choice of how machine learning is done.&lt;/p&gt;
&lt;p&gt;
Let me explain.&lt;/p&gt;
&lt;h3&gt;
Machine Learning, and Inference&lt;/h3&gt;
&lt;p&gt;
Even before I started the first line of code, I already painted a picture in my head on the machine learning needed: a TTS (text-to-speech) model that I could run inference locally on the instance.&lt;/p&gt;
&lt;p&gt;
The reason being I believed it was the more flexible approach to gradually improve the inference  and therefore the end result by training my own AI models over time.&lt;/p&gt;
&lt;p&gt;
Given I didn’t want to rent expensive GPU instances, I opted for fast TTS models that could do near real-time inference on CPUs. I used &lt;a href=&quot;https://github.com/coqui-ai/TTS&quot;&gt;Coqui TTS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
The resulting out-of-box audio wasn’t great, but I kept pressing on.&lt;/p&gt;
&lt;p&gt;
The show stopper came when it was time to deploy everything onto Fly. Due to Fly’s architecture (they deploy small-ish Docker images, &lt; 2GB each, onto their global network), I struggled to keep the Docker image file small enough to be able to deploy. With Coqui TTS, I would need Python and all the dependencies that resulted in a Docker image around 4-5GB in size.&lt;/p&gt;
&lt;p&gt;
With my tunnel vision, I then chose to offload the entire Python and Coqui TTS dependency tree onto Fly’s &lt;a href=&quot;https://fly.io/docs/reference/volumes/&quot;&gt;persistent volumes&lt;/a&gt;. I knew it wasn’t a great option, as that meant my infrastructure (other than the database) was no longer immutable.&lt;/p&gt;
&lt;p&gt;
Sometimes it’s necessary to take a step back, re-evaluate, and then press on in a different direction. Which thankfully I did.&lt;/p&gt;
&lt;p&gt;
The new direction is quite simple really: instead of performing inference locally, use an external service instead.&lt;/p&gt;
&lt;p&gt;
After doing a quick comparison between the offerings from AWS, Azure and GCP, I ended up using &lt;a href=&quot;https://cloud.google.com/text-to-speech&quot;&gt;Google’s TTS&lt;/a&gt;. Honestly I think I would’ve been happy with any of the options, they all seem to have decent neural based TTS.&lt;/p&gt;
&lt;p&gt;
In hindsight, these giant corporations have much more resources and expertise to train better models than I ever could on my own.&lt;/p&gt;
&lt;p&gt;
The end result:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
The TTS sounds significantly better than before  &lt;/li&gt;
  &lt;li&gt;
It’s just as cheap to run (Google offers a certain amount of free TTS API calls per month)  &lt;/li&gt;
  &lt;li&gt;
It no longer needs complex Python calls and FFmpeg calls to make local TTS work  &lt;/li&gt;
  &lt;li&gt;
The Fly infrastructure is simple and immutable again  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
In hindsight, I never should’ve even entertained the idea of running ML locally on CPUs, no matter how simple and efficient a model might be.&lt;/p&gt;
&lt;p&gt;
That said, with TTS, it wasn’t as simple as just calling the APIs and getting the perfect resulting audio back. Some pre and post processing were needed, but that’s a topic for another time.&lt;/p&gt;
&lt;h3&gt;
More Machine Learning&lt;/h3&gt;
&lt;p&gt;
The cherry on top - now that Google’s APIs were integrated into the app, I ended up also using Google’s &lt;a href=&quot;https://ai.google/discover/palm2/&quot;&gt;PaLM 2&lt;/a&gt; to do text summarisation (it was initially done locally too) as well as for a ChatGPT-like AI prompt service, to power Persumi’s AI writing assistance feature.&lt;/p&gt;
&lt;h2&gt;
The Closing&lt;/h2&gt;
&lt;p&gt;
If you read this far, thank you! I hope you enjoyed reading (or listening) to this post. Please look around and kick tyres, I would love your feedback on how to improve Persumi.&lt;/p&gt;
&lt;p&gt;
Sign up for an account if you haven’t already, and leave a comment if you have any questions. Until next time!&lt;/p&gt;
]]&gt;</content>
    <published>2023-08-09T09:28:12.135201Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/c/persumi/u/fredwu/p/how-i-built-a-mostly-feature-complete-mvp-in-3-months-whilst-working-full-time"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/c/persumi/u/fredwu/p/how-i-built-a-mostly-feature-complete-mvp-in-3-months-whilst-working-full-time</id>
    <title>How I Built a Mostly Feature-Complete MVP in 3 Months Whilst Working Full-Time</title>
    <updated>2023-08-09T09:28:12.135201Z</updated>
  </entry>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
Like many software engineers and indie hackers, I dream of and experiment with different product ideas every now and then.&lt;/p&gt;
&lt;p&gt;
Five years ago, in 2018, I toyed with an idea where &lt;strong&gt;personas&lt;/strong&gt; and &lt;strong&gt;expressions&lt;/strong&gt; are the enablers for showcasing people’s talents and interests.&lt;/p&gt;
&lt;p&gt;
I called it, &lt;strong&gt;Persumi&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
The Origin&lt;/h2&gt;
&lt;p&gt;
The original idea was to break the pattern of modern day social media platforms like Facebook, Instagram and Twitter, where every person is hidden behind a two-dimensional facade. Words and photos are often used to skew the way people see who we are.&lt;/p&gt;
&lt;p&gt;
After a while, everything becomes bland as information is being overloaded and people’s attention span starts to decrease drastically. The signal to noise ratio is so low that more and more algorithms and tracking are invented to help curate content so advertisers would keep spending their dime on those social media platforms.&lt;/p&gt;
&lt;p&gt;
It’s a vicious cycle. There is now even a term for it: &lt;a href=&quot;https://knowyourmeme.com/memes/enshittification&quot;&gt;&lt;strong&gt;enshittification&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
Enshittification is when an online platform becomes more monetized and less user-oriented the longer it lasts.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
The Goals&lt;/h2&gt;
&lt;p&gt;
With Persumi, personas and expressions are the key concepts to modernise content creation, curation and consumption in a simple yet meaningful way.&lt;/p&gt;
&lt;p&gt;
I set out a few goals for Persumi, in the hope to change the social media landscape for the better:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
Find ways to encourage the creation and consumption of long form content  &lt;/li&gt;
  &lt;li&gt;
Make it easy for people to create vastly different topics without confusing their audiences  &lt;/li&gt;
  &lt;li&gt;
Make it easy for people to follow different topics, rather than relying on following users  &lt;/li&gt;
  &lt;li&gt;
Allow people to decorate their pages with their own personality and style via HTML + CSS, &lt;em&gt;bring back &lt;a href=&quot;https://en.wikipedia.org/wiki/Myspace&quot;&gt;MySpace&lt;/a&gt;!&lt;/em&gt;  &lt;/li&gt;
  &lt;li&gt;
An API-driven, open marketplace that allows developers to build and extend advanced functionalities  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Some example use cases outlined in my original “pitch deck”:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;social personas&lt;/strong&gt; for friends, family, work…  &lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;interest personas&lt;/strong&gt; as a gamer, traveller, photographer…  &lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;functional personas&lt;/strong&gt; for travel plan, marketing campaign…  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
It kind of makes sense, but there is one problem.&lt;/p&gt;
&lt;h2&gt;
The Problem&lt;/h2&gt;
&lt;p&gt;
The age-old “chicken-and-egg” problem of starting a platform that thrives on user-generated content - how do I get early-adopter users without a decent amount of users and content already?&lt;/p&gt;
&lt;p&gt;
These goals might be nice, but they probably aren’t enough to convince users to drop what they are used to for something experimental and without users or traction.&lt;/p&gt;
&lt;p&gt;
So I parked this idea…&lt;/p&gt;
&lt;h2&gt;
Revisit the Problem&lt;/h2&gt;
&lt;p&gt;
A few years have gone by, and with a whole pandemic thrown into the mix, this Persumi idea has all of a sudden awakened me yet again.&lt;/p&gt;
&lt;p&gt;
In early 2023, after wrapping up my last freelancing project I decided to tackle Persumi’s chicken-and-egg problem once more.&lt;/p&gt;
&lt;p&gt;
I reflected on how my own content consumption behaviour has changed over the past few years. Instead of reading physical books, e-books or blogs, I consume more and more podcasts and audio-books. Instead of consuming content fully concentrated, I often consume them while on the go or during my workouts.&lt;/p&gt;
&lt;p&gt;
Then a light bulb moment occurred - I don’t &lt;em&gt;need&lt;/em&gt; to build a massive social network platform to compete with the likes of Twitter. I just need to build a “simple” blogging platform for my own use and my own content. If I find it useful, other people will find it useful too. It doesn’t need to go viral, it just needs to be steadly discovered by like-minded people who share my frustration and vision in content creation and consumption.&lt;/p&gt;
&lt;h2&gt;
Iterate the Idea&lt;/h2&gt;
&lt;p&gt;
With a few more years of experience of leading teams and building products under my belt, I thought about how to iterate on the original idea, and came up with three main “twists” if you will:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
Long form text content needs to be consumable in audio form, to suit the modern lifestyle  &lt;/li&gt;
  &lt;li&gt;
An API-driven open marketplace is way too ambitious for a new platform, build the core concept first, then iterate  &lt;/li&gt;
  &lt;li&gt;
An aura system that helps in both curating content as well as driving away bad actors  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
The rest of the original goals are still as relevant as before. In hindsight, these are pretty obvious product direction pivots, the result is an MVP that builds on a simple core concept - &lt;strong&gt;to turn long form text content into audio&lt;/strong&gt;. And to make it easy to organically grow the platform and audience.&lt;/p&gt;
&lt;h2&gt;
Build a Sustainable Business&lt;/h2&gt;
&lt;p&gt;
With the chicken-and-egg problem behind me, it’s time for me to think about how to build a sustainable business to support my product ambition.&lt;/p&gt;
&lt;p&gt;
Interestingly, in Feb/March 2023, I was thinking about what the VC funding model did to the social media platforms we all love and hate, and why it’s a bad idea. The fact that then &lt;em&gt;during&lt;/em&gt; the short few months of developing Persumi, both Twitter and Reddit seemed to be actively imploding themselves just proved my initial hypothesis:&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;To build a truly user-oriented platform, it needs to be built for users and content creators, rather than investors and advertisers&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;
That means, no obnoxious ads, no annoying pop ups, every visitor can view content without being forced to sign in, etc, etc… We do what VC-backed companies don’t.&lt;/p&gt;
&lt;p&gt;
If you’ve seen the &lt;a href=&quot;/&quot;&gt;landing page&lt;/a&gt; then you probably would have noticed a few things either available now or later to help create more value for users, such as:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
The hero feature - AI audio, will be a paid feature, however, every user will be able to listen to audio posts, as well as to preview their own content with audio  &lt;/li&gt;
  &lt;li&gt;
Advanced expressions such as HTML and CSS for those who want to customise their pages to their own style  &lt;/li&gt;
  &lt;li&gt;
Ad-revenue share and paid subscribers - coming later, to make Persumi a platform that shares its success with content creators  &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Keep on Building&lt;/h2&gt;
&lt;p&gt;
The MVP was essentially built in three months in my spare time. It wasn’t easy juggling between having a day job as a CTO, and moonlighting on my side hustle every evening and weekend.&lt;/p&gt;
&lt;p&gt;
This is just the beginning. I have many things planned for Persumi, some of which are already mentioned on the landing page, but there are much more to come. Early alpha and beta users are also able to help shape what this platform can become.&lt;/p&gt;
&lt;p&gt;
In the next week or two I will write about &lt;em&gt;how&lt;/em&gt; I managed to build Persumi in three months - the tech choices, architecture and feature prioritisation I went through to make this product a reality.&lt;/p&gt;
&lt;p&gt;
Like what you’ve read or listened to? Why not &lt;a href=&quot;/auth/register&quot;&gt;sign up&lt;/a&gt; and try the platform yourself, the Pro plan is free during the alpha and beta testing stages. Also check out Persumi’s founder &lt;a href=&quot;/u/fredwu&quot;&gt;@fredwu’s profile here&lt;/a&gt; to see what personas and expressions look like and can achieve.&lt;/p&gt;
&lt;p&gt;
Update: Read about &lt;a href=&quot;how-i-built-a-mostly-feature-complete-mvp-in-3-months-whilst-working-full-time&quot;&gt;How I Built a Mostly Feature-Complete MVP in 3 Months Whilst Working Full-Time&lt;/a&gt;, it covers the features, the tech stack, the global infrastructure and the machine learning…&lt;/p&gt;
]]&gt;</content>
    <published>2023-07-17T04:18:07.386547Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/c/persumi/u/fredwu/p/welcome-to-persumi-a-modern-platform-for-content-creation"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/c/persumi/u/fredwu/p/welcome-to-persumi-a-modern-platform-for-content-creation</id>
    <title>Welcome to Persumi - A Modern Platform for Content Creation</title>
    <updated>2023-07-17T04:18:07.386547Z</updated>
  </entry>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
As coding bootcamps such as &lt;a href=&quot;https://coderacademy.edu.au/&quot;&gt;Coder Academy&lt;/a&gt; and &lt;a href=&quot;https://generalassemb.ly/&quot;&gt;General Assembly&lt;/a&gt; churn out more and more software developers, and as more and more people start to realise the importance of software, companies these days are facing an increased amount of candidates applying for junior dev roles.&lt;/p&gt;
&lt;p&gt;
Recently we had to take down our job ad for a junior full stack React and Elixir role only a few days after posting it due to having received about 300 applications. Suffice to say, the competition is fierce at the entry-level end of the software engineer spectrum.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;a href=&quot;https://a16z.com/2011/08/20/why-software-is-eating-the-world/&quot;&gt;Software is eating the world.&lt;/a&gt; - Marc Andreessen  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
In the past three months alone I’ve had to sit through over a hundred interviews, many of which were for junior roles. Some candidates did really well but unfortunately the vast majority did quite poorly. In this article I am hoping to offer some tips and insights as a seasoned interviewer and hiring manager, to those who might be struggling landing an entry-level software engineer role.&lt;/p&gt;
&lt;p&gt;
I’ll break the tips into three sections: before an interview, during an interview and after an interview.&lt;/p&gt;
&lt;h2&gt;
Before an Interview&lt;/h2&gt;
&lt;p&gt;
This is arguably the most important stage of your interview - before it happens! Prepare yourself with enough knowledge and confidence in both software development and conversational skills in order to ace the interview and stand out amongst a sea of candidates.&lt;/p&gt;
&lt;h3&gt;
Study Software Engineering Fundamentals&lt;/h3&gt;
&lt;p&gt;
I get it, bootcamps and many online tutorials and courses focus on teaching the practical things to turn code into products. But just like running or even walking without correct postures, it can be incredibly dangerous over time.&lt;/p&gt;
&lt;p&gt;
My recommendation is to read on the basics of object-oriented programming, functional programming and some design patterns. For instance, build up some basic understanding of how the JavaScript prototype works or how the Ruby object model works can be extremely beneficial in progressing your technical capability on application design and architecture.&lt;/p&gt;
&lt;h3&gt;
Get More Project Experience&lt;/h3&gt;
&lt;p&gt;
Not having any substantial project experience on your CV is a sure way to significantly lower your chance of getting an interview.&lt;/p&gt;
&lt;p&gt;
Do junior developers really need substantial project experience, you may ask? Abso-fucking-lutely!&lt;/p&gt;
&lt;p&gt;
Build your own side projects, participate in open source projects, pick up some freelancing work - the choice is yours. These won’t be your most technically accomplished work, but they will help you accumulate experience, and more importantly to demonstrate your capability to your interviewers with real world experience.&lt;/p&gt;
&lt;h3&gt;
Why Software Development?&lt;/h3&gt;
&lt;p&gt;
I want you to put your hand on heart and answer this question honestly. If your answer is more money or FOMO, that’s okay, but be prepared to be disappointed with the reality - if you are not in this field because of your passion for building products or solving problems, you will find this a long and hard slog.&lt;/p&gt;
&lt;p&gt;
If you are passionate about building software, then let me tell you this - when you are starting your career you will have to give up your work life balance for a bit. That is, if you want to boost your career and progress quickly beyond being a junior developer.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
My interest is in the future, because I am going to spend the rest of my life there. - Charles Kettering  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Looking back at when I started my software career many moons ago, I never regretted giving up my social life early on in my career: I worked extremely hard, often did many jobs - a day job as a dev, a night job as a dev, freelancing and doing open source work all at the same time. Some would probably frown and say that I had no life, but I choose to believe that I was making sacrifices so I can become good at what I love doing in the shortest amount of time.&lt;/p&gt;
&lt;h3&gt;
Research the Company You Apply For&lt;/h3&gt;
&lt;p&gt;
If you are one of those who spam your CVs to every job opening, please consider changing your tactic. A well written cover letter will not only increase your chance of getting an interview, but also allow you to ask relevant questions during the interview.&lt;/p&gt;
&lt;p&gt;
Check out the company’s website and any social media pages on LinkedIn, Facebook and Instagram, etc. Do a bit of “stalking” on the people who work in the company, sometimes this will give you some insights into the type of work environment and culture the company has.&lt;/p&gt;
&lt;p&gt;
Doing enough research is not only for your own good - knowing whether you will enjoy working there should you end up getting a job offer, but also demonstrates your ability to do research and independent thinking to your interviewers.&lt;/p&gt;
&lt;h3&gt;
Read, Listen and Communicate&lt;/h3&gt;
&lt;p&gt;
This one might not be immediately obvious because it’s very high level and somewhat vague, bear with me.&lt;/p&gt;
&lt;p&gt;
Some people might be deep thinkers but really struggle to get their points across, and to communicate their ideas and thought process in a clear, concise and useful way. My advice is to read blogs, listen to talks and learn from other people on how they communicate. When you read and listen, pay more attention to how sentences are structured and how titbits of information are given.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
The most powerful person in the world is the story teller. - Steve Jobs  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
And don’t forget to practice! Get comfortable talking to others on various topics in software development.&lt;/p&gt;
&lt;h2&gt;
During an Interview&lt;/h2&gt;
&lt;p&gt;
Hopefully the tips given thus far would help you secure an interview. Now it’s show time!&lt;/p&gt;
&lt;h3&gt;
Turn Up On time, Have Equipment Sorted&lt;/h3&gt;
&lt;p&gt;
Whether you are attending an on-location interview, or more likely during Covid, an online interview, make sure you turn up on time!&lt;/p&gt;
&lt;p&gt;
If it’s an online interview, also make sure you have whatever software needed (Zoom, etc) installed and tested. I’ve had a few occasions where the first five minutes of the interview was spent on the candidate trying to get their mic or speaker working - it’s not a huge deal, but it does show the lack of preparation and organisational skills.&lt;/p&gt;
&lt;h3&gt;
A Smile Goes a Long Way&lt;/h3&gt;
&lt;p&gt;
Understandably, interviewing is stressful. However, remember to put on a smile when you greet your interviewer and when you do small talks. Everything needs a balance of course, when you’re giving technical answers it’s probably not a good idea to smile.&lt;/p&gt;
&lt;p&gt;
If you know you get uncomfortable talking to strangers or when under pressure - do more practices! If you can’t find a friend or don’t have a partner to practice with, use a mirror!&lt;/p&gt;
&lt;h3&gt;
Learn to Say “No, I don’t know”&lt;/h3&gt;
&lt;p&gt;
When you don’t know something or can’t recall the details of something, just say it. As an interviewer, when I ask you a technical question I can see through your hmms and ahs. A “sorry, I don’t know” is a much better answer than one that doesn’t make sense.&lt;/p&gt;
&lt;p&gt;
Bonus point: “Sorry I don’t know, but I will look it up after this interview.”&lt;/p&gt;
&lt;h3&gt;
Read Social Cues&lt;/h3&gt;
&lt;p&gt;
This one can be extremely easy or extremely hard depending on your personality. For those who might struggle with reading social cues, try pay more attention to what type of questions you were asked.&lt;/p&gt;
&lt;p&gt;
If it was an introduction of yourself to kick off the interview, make it more than just two sentences but also under five minutes - this is usually a warm up for you to find your feet and calm your nerve, and for the interviewer to extract any interesting information as a discussion point later. It doesn’t have to be your memoir and you shouldn’t robotically talk through your entire education and work history.&lt;/p&gt;
&lt;p&gt;
If it was a technical question, always try to time-box it. Don’t drag on and repeat yourself just because you have already answered it quickly and concisely. When in doubt, ask the interviewers whether they have anything in particular they were looking for.&lt;/p&gt;
&lt;p&gt;
If it was an open ended question, try to explain your thought process as you explain it. As an interviewer, I’d hate to ask an open ended question and get a short yes/no back. At the same time, give interviewers room to interject and ask follow-up questions by pacing yourself.&lt;/p&gt;
&lt;h3&gt;
Don’t Speak Too Fast&lt;/h3&gt;
&lt;p&gt;
Okay, you might be very nervous, or English might not be your first language, so you tend to speak fast to “get through it”.&lt;/p&gt;
&lt;p&gt;
If that’s the case, work on your speech pattern, make it concious enough that you will recognise it when you speak too fast. If interviewers can’t get your points clearly, they might not always ask you to clarify - because if you kept doing it repeatedly, you would already be written off as a suitable candidate.&lt;/p&gt;
&lt;h3&gt;
Be Humble&lt;/h3&gt;
&lt;p&gt;
I totally understand that in a competitive job market you want to present yourself in the best light. Just be confident and speak the truths.&lt;/p&gt;
&lt;p&gt;
As someone who’s been doing interviews for years, I really dislike people who overstate their capability either on their CV or during the interview because these are often very obvious. Claiming to be an Elixir expert but not knowing how the supervision tree works is a sure way to score a black mark, for example.&lt;/p&gt;
&lt;h3&gt;
Show Passion and Drive&lt;/h3&gt;
&lt;p&gt;
To counter the point on over-selling yourself, what works better is to show interviewers your willingness and determination to learn. Remember, you are still a junior therefore we don’t expect you to know everything we know.&lt;/p&gt;
&lt;p&gt;
What we do expect, is your commitment to learning - not by saying it, but by demonstrating it. Remember the earlier tip on getting more project experience?&lt;/p&gt;
&lt;h3&gt;
Ask Questions&lt;/h3&gt;
&lt;p&gt;
Usually towards the end of the interview, we’d ask you if you have any questions. Don’t say “no”.&lt;/p&gt;
&lt;p&gt;
Doesn’t matter how much research you’ve done on a company, there are always insights someone who’s working at the company can give you. How do they manage the delivery? How do they support learning? What makes them enjoy working at the company?&lt;/p&gt;
&lt;p&gt;
Use this opportunity to gain insights into why you should be working at this company, and to demonstrate your interests in working at the company to the interviewers too.&lt;/p&gt;
&lt;h2&gt;
After an Interview&lt;/h2&gt;
&lt;p&gt;
After completing an interview, it’s an opportunity to do a little retrospective and do a follow up when necessary.&lt;/p&gt;
&lt;h3&gt;
Close the Knowledge Gap&lt;/h3&gt;
&lt;p&gt;
Don’t over-analyse on what you could have or should have said. Instead, spend your energy on solidifying the topics you couldn’t or didn’t provide good answers for. If you’ve said “don’t know” or “not sure” during the interview, now is your chance to make it “sure”.&lt;/p&gt;
&lt;h3&gt;
Follow Up&lt;/h3&gt;
&lt;p&gt;
If during the interview there have been things mentioned that you could provide links or more information on, be sure to act on it. You never know, maybe the clarification is just what the interviewers needed to help them make a decision.&lt;/p&gt;
&lt;p&gt;
~&lt;/p&gt;
&lt;p&gt;
To all the junior developers out there - enjoy the journey! You are in for an amazing ride, make every second count.&lt;/p&gt;
&lt;hr class=&quot;thin&quot; /&gt;
&lt;p&gt;
&lt;em&gt;If you enjoyed this article, checkout my other tips articles:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;em&gt;&lt;a href=&quot;tips-for-becoming-a-better-software-developer/&quot;&gt;Tips for Becoming a Better Software Developer&lt;/a&gt;&lt;/em&gt;  &lt;/li&gt;
  &lt;li&gt;
&lt;em&gt;&lt;a href=&quot;tips-for-writing-a-good-cv-resume/&quot;&gt;Tips for Writing a Good CV / Résumé&lt;/a&gt;&lt;/em&gt;  &lt;/li&gt;
&lt;/ul&gt;
]]&gt;</content>
    <published>2020-09-27T05:56:03.000000Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/u/fredwu/tech/e/blog/p/tips-for-job-interviews-as-a-junior-software-developer"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/u/fredwu/tech/e/blog/p/tips-for-job-interviews-as-a-junior-software-developer</id>
    <title>Tips for Job Interviews as a Junior Software Developer</title>
    <updated>2020-09-27T05:56:03.000000Z</updated>
  </entry>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
Due to COVID-19, not many companies are hiring at the moment. The company &lt;a href=&quot;https://ourxplor.com&quot;&gt;I work for&lt;/a&gt; therefore is in a very fortunate position to still be thinking about growth and hiring.&lt;/p&gt;
&lt;p&gt;
As a hiring manager for almost a decade now, I’ve personally reviewed thousands of job applications and CVs, and many hiring managers would probably agree, the vast majority of CVs are terrible. Let’s change that!&lt;/p&gt;
&lt;p&gt;
During COVID-19 where more and more people are either losing jobs or having their work hours cut, we are experiencing an increased amount of applicants to &lt;a href=&quot;https://apply.workable.com/xplor/&quot;&gt;our job ads&lt;/a&gt;. I’d say on average &lt;strong&gt;I spend about 30 seconds per applicant&lt;/strong&gt; due to my busy schedule - most hiring managers are busy people, it is therefore crucial for candidates to realise the importance of having a CV that is clear, easy to read and most importantly sells yourself. And if you have a cover letter, which I highly encourage that you do, congratulations you just bought yourself another 30 seconds. ;)&lt;/p&gt;
&lt;p&gt;
I’m writing this post mostly from my own perspective - as a hiring manager in a tech company in the western culture (we’re based in Australia). Understandably, different cultural backgrounds and regions may have their own conventions, but certainly in Australia and many similar western cultures, there are things that you do and don’t do on a CV, and there are things that may help your CV stand out. Let’s talk about these things.&lt;/p&gt;
&lt;p&gt;
At the end of this post I will also share a copy of my own CV to help illustrate my points.&lt;/p&gt;
&lt;h2&gt;
30 Seconds? Surely It’s Unfair to the Candidates&lt;/h2&gt;
&lt;p&gt;
Yes, I agree, to think that you are only given 30 seconds for your perhaps carefully crafted CV and cover letter is definitely soul-crushing. But it is unfortunately the reality. I work for a company where I can still do the first round of vetting myself, many large corporations would use algorithms and/or HR people to reject your applications based on keywords and other things.&lt;/p&gt;
&lt;p&gt;
Knowing the reality and the constraints, there are a few things I’d like to address in the hope of improving your CV and your chance of scoring an interview, and in turn, helping myself and other hiring managers out there to have a better candidate CV screening experience.&lt;/p&gt;
&lt;h2&gt;
Have a Pronounceable Name or Alias&lt;/h2&gt;
&lt;p&gt;
This one surely would raise some eyebrows - you might think that your name is your identity and you should not change it for anyone. True, however, the reality is that a hard-to-pronounce name discourages your profile to be shared and spoken about. Why not add a pronounceable alias if means there’s an increased chance of getting an interview?&lt;/p&gt;
&lt;p&gt;
For clarity, I personally would never reject a candidate based on their name (or their cultural background for that matter), but I know some hiring managers might, and for some of them, they are NOT doing it on purpose. However, I have on several occasions had to ask a candidate how to correctly pronounce their name.&lt;/p&gt;
&lt;h2&gt;
A Short Blurb on Who You Are&lt;/h2&gt;
&lt;p&gt;
As a hiring manager, I care about who you are as a person - if you can summarise who you are as a professional in a sentence or two, it will help me determine whether you might be a good fit or not.&lt;/p&gt;
&lt;p&gt;
As an example, here’s a blurb about me:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
A passionate and hands-on software executive with two decades of experience and an entrepreneurial mindset.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
  &lt;p&gt;
A long time open source developer who has created and contributed to a few dozens of projects, including Ruby on Rails.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
In two sentences, I explained my industry experience as well as my open source contributions - two things that help define who I am as a working professional. It also invites more questions from hiring managers: what kind of things have I done as an entrepreneur; what other open source projects have I contributed to?&lt;/p&gt;
&lt;h2&gt;
Work Rights&lt;/h2&gt;
&lt;p&gt;
Many companies have restrictions or policies around who they can hire based on their residency and visa status. If you are not a resident or are on a particular visa, make it clear in your job application so you don’t end up wasting time for the employer and for yourself.&lt;/p&gt;
&lt;h2&gt;
List Keywords, But Don’t Overdo It&lt;/h2&gt;
&lt;p&gt;
In the tech space it is important to have keywords visible to highlight your skills. If you are a software developer, your tech stacks should be clearly stated in your CV. As a hiring manager, if I am hiring a PHP developer, I expect to see PHP mentioned in your CV. There are of course exceptions, for example when we were hiring Elixir developers I did not expect to see Elixir as a keyword simply due to the supply constraint.&lt;/p&gt;
&lt;p&gt;
It is a balancing act however - I’ve seen CVs where candidates put 20-50 keywords on their CVs. I’m sorry but unless you are extremely gifted, you cannot possibly be good at all those things. Do not put keywords on your CV simply because you’ve read an article on the subject.&lt;/p&gt;
&lt;p&gt;
Oh, and unless you’re going for a data entry role, I honestly don’t care about your Excel skills…&lt;/p&gt;
&lt;h2&gt;
Do Not Overstate Your Capability&lt;/h2&gt;
&lt;p&gt;
Similarly, try to avoid overselling your capability. I once interviewed a candidate who claimed to be an “expert” on Ruby. We were actually hiring for a non-Ruby position, but given the candidate’s CV, I questioned him on some advanced Ruby subjects during our interview and he struggled all the way through and was sweating bullets. Suffice to say that he did not get the job.&lt;/p&gt;
&lt;p&gt;
Be confident, but also be honest and be humble. Lying on your CV to get an interview is a waste of everyone’s time.&lt;/p&gt;
&lt;h2&gt;
Keep Things Short&lt;/h2&gt;
&lt;p&gt;
As I mentioned in the beginning, I spend on average 30 seconds on each CV. Keep things short and easy to read! I really don’t care about how awesome you were in your last dozens of projects - these will get covered during interviews.&lt;/p&gt;
&lt;p&gt;
On a CV I expect short and concise blurbs on what you did in each role. Also, take recency into account too - if you’ve been working in the industry for a decade or two, what you did 20 years ago really doesn’t matter as much, so save yourself some time and cut things short.&lt;/p&gt;
&lt;p&gt;
For example, here’s the blurb for my current role:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
Leading a department of 25+ engineers to make great child care and education software. As part of the leadership team and reporting to the CEO, helping building and turning the company into a market leader.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
And here are the blurbs for my older roles:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&amp;nbsp;  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Yes, the blurbs for my older roles are left empty intentionally.&lt;/p&gt;
&lt;p&gt;
Now, again there are exceptions. If something happened a while ago but is interesting and relevant, do tell! For example, here’s the blurb for my oldest “role”:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
Built my first ever website using Microsoft FrontPage Express, on a Pentium 166Mhz computer, uploaded via a 33.6kbps modem.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
Explain Over-Qualified Titles&lt;/h2&gt;
&lt;p&gt;
There were a few times where a “CTO” or even a “CEO” applied for a developer role. In most cases it wasn’t about over-qualification, but about what the candidate wanted to achieve professionally. So, either in the CV or in the cover letter, explain what you are looking for in your next role, otherwise you run the risk of being assessed as over-qualified.&lt;/p&gt;
&lt;h2&gt;
Spare the Personal Details That Are Too Personal&lt;/h2&gt;
&lt;p&gt;
This is predominantly a culture thing as I’ve seen it from mostly candidates of certain cultural backgrounds. I really don’t care about your age, gender, marital status or favourite sport. These things do not define who you are as a professional - we might talk about your favourite sport and food during the interview but they are irrelevant on your CV.&lt;/p&gt;
&lt;h2&gt;
Space Things Out&lt;/h2&gt;
&lt;p&gt;
Look up &lt;a href=&quot;https://www.google.com/search?q=crap+principles&quot;&gt;CRAP Principles&lt;/a&gt; - make sure your CV has enough white spaces and contrast, and has fonts that are readable! Scrolling through walls of text is no fun and is a sure way to get your CV dismissed.&lt;/p&gt;
&lt;h2&gt;
2-4 Pages&lt;/h2&gt;
&lt;p&gt;
This is not scientific, for me personally I prefer to see CVs of 2-4 pages. Use the length as a constraint to cut things down. There were several occasions where I ran into CVs with 10+ pages. I guarantee you, unless a hiring manager is &lt;em&gt;extremely&lt;/em&gt; bored, he or she does not have time to read your War and Peace.&lt;/p&gt;
&lt;h2&gt;
PDF Over Word&lt;/h2&gt;
&lt;p&gt;
When possible, submit your CV in PDF format instead of Word format. Now, sometimes if you use a recruiter you’ll be asked to submit your CV in Word format so they can &lt;del&gt;fuck it up&lt;/del&gt; add their branding. A PDF formatted CV ensures the correct formatting and layout always get shown to the hiring managers.&lt;/p&gt;
&lt;h2&gt;
Cover Letter&lt;/h2&gt;
&lt;p&gt;
Always attach a cover letter when possible, but keep it short too. Given the amount of CVs a hiring manager needs to go through, having a crafted cover letter is another way to grab their attention and increase your chance of getting an interview.&lt;/p&gt;
&lt;p&gt;
Don’t repeat the same information in the cover letter though. Your &lt;strong&gt;CV is about the facts of your experiences&lt;/strong&gt;, your &lt;strong&gt;cover letter should be about your thoughts on why the company should hire you&lt;/strong&gt;. Focus on the value you can bring to the table.&lt;/p&gt;
&lt;h2&gt;
Find A Referral&lt;/h2&gt;
&lt;p&gt;
When possible, find someone who can refer you. A referral gets preferential treatment during the CV screening stage and does not suffer from the same 30-second fate.&lt;/p&gt;
&lt;h2&gt;
Pleasing Design&lt;/h2&gt;
&lt;p&gt;
This one is a “nice-to-have”: if your CV is really well designed, you would earn another 30 seconds of my attention. ;)&lt;/p&gt;
&lt;p&gt;
~&lt;/p&gt;
&lt;p&gt;
These are the main points, hopefully they are helpful. To help illustrate, here is &lt;a href=&quot;/img/posts/2020-05-20/cv-example.pdf&quot;&gt;a copy of my own CV&lt;/a&gt;, with contact details removed.&lt;/p&gt;
&lt;hr class=&quot;thin&quot; /&gt;
&lt;p&gt;
&lt;em&gt;If you enjoyed this article, checkout my other tips articles:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;em&gt;&lt;a href=&quot;tips-for-becoming-a-better-software-developer/&quot;&gt;Tips for Becoming a Better Software Developer&lt;/a&gt;&lt;/em&gt;  &lt;/li&gt;
  &lt;li&gt;
&lt;em&gt;&lt;a href=&quot;tips-for-job-interviews-as-a-junior-software-developer/&quot;&gt;Tips for Job Interviews as a Junior Software Developer&lt;/a&gt;&lt;/em&gt;  &lt;/li&gt;
&lt;/ul&gt;
]]&gt;</content>
    <published>2020-05-20T08:59:24.000000Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/u/fredwu/tech/e/blog/p/tips-for-writing-a-good-cv-resume"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/u/fredwu/tech/e/blog/p/tips-for-writing-a-good-cv-resume</id>
    <title>Tips for Writing a Good CV / Résumé</title>
    <updated>2020-05-20T08:59:24.000000Z</updated>
  </entry>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
Over the past decade or two, both as a software developer and as a manager I have accumulated a few tips for becoming a better software developer.&lt;/p&gt;
&lt;p&gt;
For context, I’ve been working as a software developer for more than a decade, mostly in small product-based companies; over the last decade or so I’ve worked as a team lead or manager in various capacities; and I’ve moonlighted as a consultant, freelancer and open source contributor in-between. Check out &lt;a href=&quot;https://www.linkedin.com/in/wufred/&quot;&gt;my LinkedIn profile&lt;/a&gt; and &lt;a href=&quot;https://github.com/fredwu&quot;&gt;Github profile&lt;/a&gt; if you are interested.&lt;/p&gt;
&lt;p&gt;
Now, let’s break down the tips into three main areas: &lt;strong&gt;mindset&lt;/strong&gt;, &lt;strong&gt;technical&lt;/strong&gt; and &lt;strong&gt;people&lt;/strong&gt;. The goal of this article is to raise awareness of the topics mentioned, if you want to understand more on a particular topic I encourage you to do your own research.&lt;/p&gt;
&lt;h2&gt;
Mindset&lt;/h2&gt;
&lt;h3&gt;
Have a Growth Mindset&lt;/h3&gt;
&lt;p&gt;
This one hopefully should be obvious, if you haven’t heard of it, please &lt;a href=&quot;https://www.google.com/search?q=growth+mindset&quot;&gt;read more here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
Have a StarCraft Mindset&lt;/h3&gt;
&lt;p&gt;
This one is “new”, I’ve given a talk that includes more details on what it means, &lt;a href=&quot;https://www.youtube.com/watch?v=MBczdO7RgNo&quot;&gt;check it out here&lt;/a&gt;. In essence, it’s a mindset that requires you to always consider things around you, and forces you to think beyond your narrowly focused task at hand.&lt;/p&gt;
&lt;h3&gt;
Recognise the Dunning–Kruger Effect&lt;/h3&gt;
&lt;p&gt;
I once interviewed a mid-level developer who rated himself as a 9.9 out of 10. The &lt;a href=&quot;https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect&quot;&gt;Dunning-Kruger effect&lt;/a&gt; is essentially the opposite of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Impostor_syndrome&quot;&gt;Imposter Syndrome&lt;/a&gt;, both are very common in our field.&lt;/p&gt;
&lt;h3&gt;
Agile is Not a Process, It’s a Mindset&lt;/h3&gt;
&lt;p&gt;
Some people are overly obsessed with the processes of “being agile”. In truth, every organisation, every project and every team is different, there is no point to follow a set of processes that might slow you down and not add any value. Discover what being agile means to your team, your project and your organisation is an ongoing effort and should be treated as such.&lt;/p&gt;
&lt;h3&gt;
Different Organisations Require Different Engineering Approaches&lt;/h3&gt;
&lt;p&gt;
Some projects and organisations require tech-driven decisions be made upfront, some on the other hand require product-driven decisions instead. Knowing how your organisation operates and what it values plays a key part in understanding how software development should be approached.&lt;/p&gt;
&lt;h3&gt;
A Sense of Entitlement Only Gets You So Far&lt;/h3&gt;
&lt;p&gt;
Let’s be honest, as a software developer we are extremely lucky to be in a high demand field. As a result, many have started building a sense of entitlement - some ex-colleagues of mine even complained about the lack of tissue boxes in the office. Starting and running a business is extremely hard work, let’s all appreciate what we have before throwing a tantrum.&lt;/p&gt;
&lt;h3&gt;
9-5 is Not Evil, Nor is Crazy Work Hours&lt;/h3&gt;
&lt;p&gt;
Every now and then I see conflicts between people who share different philosophies on what work and career mean to them. We should embrace the different ways people prefer to spend their time and energy on, rather than force our own ideology on them. Discovering and knowing the difference between working at a giant corporation versus working at a small start-up is key to our happiness.&lt;/p&gt;
&lt;h3&gt;
Pain and Gain, There’s Always a Trade-off&lt;/h3&gt;
&lt;p&gt;
An extension of the 9-5 vs crazy work hours: adjust your expectation based on the effort you put in. You can’t have everything, prioritising family life over career building is 100% okay, as long as you know what you are giving up on, vice versa. In my 20s, many of my similarly aged friends and colleagues would go out and have fun after work and on weekends while I was in front of my computer building open source projects, is an example of a conscious trade-off I made.&lt;/p&gt;
&lt;h3&gt;
Speed vs Quality&lt;/h3&gt;
&lt;p&gt;
Internalising the need for speed and the need for quality should always be on our mind. Pursuing only quality or only speed will significantly limit your problem-solving capability as well as your career progression.&lt;/p&gt;
&lt;h3&gt;
Think, Then Do&lt;/h3&gt;
&lt;p&gt;
It’s a balance - don’t &lt;a href=&quot;https://en.wikipedia.org/wiki/Analysis_paralysis&quot;&gt;overthink it&lt;/a&gt;, but also don’t do without think first. When in doubt, ask more experienced people for advice and guidance.&lt;/p&gt;
&lt;h2&gt;
Technical&lt;/h2&gt;
&lt;h3&gt;
Avoid Second System Syndrome&lt;/h3&gt;
&lt;p&gt;
I’ve seen &lt;a href=&quot;https://en.wikipedia.org/wiki/Second-system_effect&quot;&gt;Second System Syndrome&lt;/a&gt; over and over again throughout my career. Some people always assume a rewrite is a much better approach than alternatives, more often than not though, it is not the case.&lt;/p&gt;
&lt;h3&gt;
Micro-Services is Neither New nor the Holy Grail&lt;/h3&gt;
&lt;p&gt;
There’s the age-long debate of monolith vs micro-services architecture, and SOA (Service-Oriented Architecture) has been around for decades. Each has its own pros and cons, don’t get bought into the hype because a blog post says so, or a particular product and company found it successful. Use the right tool for the right job.&lt;/p&gt;
&lt;h3&gt;
TDD (Test-Driven Development) is not the Holy Grail&lt;/h3&gt;
&lt;p&gt;
Just like micro-services, TDD is not the holy grail and should not be treated as much. Chasing the TDD dream without knowing its pros and cons is just as counter-productive as not doing TDD when necessary.&lt;/p&gt;
&lt;h3&gt;
Code Aesthetics Matter&lt;/h3&gt;
&lt;p&gt;
A lot of people treat coding as more of a scientific endeavour: they focus purely on the algorithms and results. Software development to me is a creative endeavour, and I often use white spaces and the general look and feel of the code base to determine how well-organised a project is - deeply nested code and long functions for instance are obvious ways to determine &lt;em&gt;potential&lt;/em&gt; code smell.&lt;/p&gt;
&lt;p&gt;
You’ve all heard of the &lt;a href=&quot;https://en.wikipedia.org/wiki/SOLID&quot;&gt;SOLID principles&lt;/a&gt;, but have you heard of the &lt;a href=&quot;https://www.google.com/search?q=CRAP+principles&quot;&gt;CRAP principles&lt;/a&gt;?&lt;/p&gt;
&lt;h3&gt;
Read As Much Code As Possible&lt;/h3&gt;
&lt;p&gt;
Don’t get me wrong, writing code is important, practice is important, but time and time again I come across developers who clearly have little exposure to established patterns and conventions.&lt;/p&gt;
&lt;h3&gt;
Tech Stack Exposure and Diversity are Always a Good Thing&lt;/h3&gt;
&lt;p&gt;
No matter whether you are in a highly specialised field or being a generalist, having exposure to different tech stacks and paradigms is always a good thing - it widens your field of vision and increases the boundary of your technical understanding. Don’t be the guy or gal who is known as “a &lt;em&gt;\&lt;insert tech stack&gt;&lt;/em&gt; developer”.&lt;/p&gt;
&lt;h3&gt;
Have a Deeper Technical Understanding Helps&lt;/h3&gt;
&lt;p&gt;
This is strictly speaking a “nice to have”, but I lost count of the number of candidates I interviewed who claimed to be a Ruby &lt;em&gt;expert&lt;/em&gt; yet cannot explain the &lt;a href=&quot;https://www.google.com/search?q=the+ruby+object+model&quot;&gt;Ruby object model&lt;/a&gt; and have never heard of &lt;a href=&quot;https://en.wiktionary.org/wiki/eigenclass&quot;&gt;eigenclasses&lt;/a&gt;, or senior developers who cannot explain the difference between &lt;code class=&quot;inline&quot;&gt;git merge&lt;/code&gt; and &lt;code class=&quot;inline&quot;&gt;git rebase&lt;/code&gt;. Sure, you may not need the deep understanding in order to do your job, but it will certainly help!&lt;/p&gt;
&lt;h2&gt;
People&lt;/h2&gt;
&lt;h3&gt;
Always Assume Incompetence over Malice&lt;/h3&gt;
&lt;p&gt;
If you haven’t, &lt;a href=&quot;https://en.wikipedia.org/wiki/Hanlon%27s_razor&quot;&gt;read more about it here&lt;/a&gt;. Knowing this, and paired with having a growth mindset, you should therefore be encouraged to teach, educate and influence, rather than being defensive and participate in “us vs them”.&lt;/p&gt;
&lt;h3&gt;
Truth = Visibility x Tolerance&lt;/h3&gt;
&lt;p&gt;
This is another topic &lt;a href=&quot;https://www.youtube.com/watch?v=MBczdO7RgNo&quot;&gt;covered in my talk&lt;/a&gt;. If you find yourself regularly dissatisfied with the information you receive, ask yourself: what information is and isn’t available to you, and are you sure you have the stomach to tolerate the new information?&lt;/p&gt;
&lt;h3&gt;
Rapport and Productivity are Built Over Time&lt;/h3&gt;
&lt;p&gt;
Some people assume a team’s productivity is determined largely by team member’s individual capability, some also assume a &lt;a href=&quot;https://www.google.com/search?q=10x+engineer&quot;&gt;10x engineer&lt;/a&gt; is a reflection on one’s technical capability. It’s not. Productivity evolves over time - building rapport with those around you is often the unsung hero in productivity.&lt;/p&gt;
&lt;h3&gt;
Champion Team Over Champion Individual&lt;/h3&gt;
&lt;p&gt;
This one hopefully is obvious, but I just have to emphasis its importance. Please, if you struggle to work with your team, ask for help! If you have a team mate who is difficult to work with, reach out and help them!&lt;/p&gt;
&lt;h2&gt;
Final Thoughts&lt;/h2&gt;
&lt;p&gt;
Software development is evolving rapidly, some fundamentals however are always useful and relevant. I hope you find this article useful.&lt;/p&gt;
&lt;p&gt;
I’ve mentioned my talk a few times, but if you haven’t already, check it out below, it covers a few topics mentioned in this article, and some more. Also check out &lt;a href=&quot;https://www.youtube.com/channel/UCYzkbDiuqtiNkQvQBzStVqQ&quot;&gt;my tiny Youtube channel&lt;/a&gt; for more tech talks I’ve done in the past.&lt;/p&gt;
&lt;p&gt;
&lt;code class=&quot;inline&quot;&gt;video: https://www.youtube.com/watch?v=MBczdO7RgNo&lt;/code&gt;&lt;/p&gt;
&lt;hr class=&quot;thin&quot; /&gt;
&lt;p&gt;
&lt;em&gt;If you enjoyed this article, checkout my other tips articles:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;em&gt;&lt;a href=&quot;tips-for-writing-a-good-cv-resume/&quot;&gt;Tips for Writing a Good CV / Résumé&lt;/a&gt;&lt;/em&gt;  &lt;/li&gt;
  &lt;li&gt;
&lt;em&gt;&lt;a href=&quot;tips-for-job-interviews-as-a-junior-software-developer/&quot;&gt;Tips for Job Interviews as a Junior Software Developer&lt;/a&gt;&lt;/em&gt;  &lt;/li&gt;
&lt;/ul&gt;
]]&gt;</content>
    <published>2020-05-03T06:34:25.000000Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/u/fredwu/tech/e/blog/p/tips-for-becoming-a-better-software-developer"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/u/fredwu/tech/e/blog/p/tips-for-becoming-a-better-software-developer</id>
    <title>Tips for Becoming a Better Software Developer</title>
    <updated>2020-05-03T06:34:25.000000Z</updated>
  </entry>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
Over the past few years as I gain more and more experience in not only building software and products but also in leading teams and projects, I realised that my desire of wanting an agile tool that’s super simple to use yet super flexible to adapt to different needs has grown stronger and stronger.&lt;/p&gt;
&lt;p&gt;
Given the COVID-19 situation that’s going on at the moment, I’ve finally decided to spend a few nights working on a pitch deck for myself to validate the value proposition, and some high level wireframes to visualise the ideas.&lt;/p&gt;
&lt;p&gt;
Over the weekend I’ve put together a landing page to “market” my ideas. It’s a quick job, but the underlying thinking has been on the back of my mind for years now.&lt;/p&gt;
&lt;p&gt;
Introducing Focussist, or rather Focussist’s landing page: &lt;a href=&quot;https://focussist.com/&quot;&gt;Focussist.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Please check it out and give me your feedback, and don’t forget to sign up. ;)&lt;/p&gt;
]]&gt;</content>
    <published>2020-03-23T11:04:55.000000Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/u/fredwu/tech/e/blog/p/launching-focussist-landing-page-an-upcoming-agile-project-management-tool"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/u/fredwu/tech/e/blog/p/launching-focussist-landing-page-an-upcoming-agile-project-management-tool</id>
    <title>Launching Focussist Landing Page - An Upcoming Agile Project Management Tool</title>
    <updated>2020-03-23T11:04:55.000000Z</updated>
  </entry>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
Seven years ago in 2012 I spoke at &lt;a href=&quot;http://2012.rubyconfchina.org/&quot;&gt;RubyConf China 2012&lt;/a&gt;. It was a technical talk on how to become a better developer, if you’re interested you can check out &lt;a href=&quot;https://www.youtube.com/watch?v=DeBsmdDmB9A&quot;&gt;the video recording&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Seven years later in August 2019, I headed back to Shanghai again to speak at this year’s &lt;a href=&quot;http://rubyconfchina.org/&quot;&gt;RubyConf China&lt;/a&gt;. And this time around, it was a non-technical talk on how to develop one’s career. Check out the video recording below:&lt;/p&gt;
&lt;p&gt;
&lt;code class=&quot;inline&quot;&gt;video: https://www.youtube.com/watch?v=MBczdO7RgNo&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;
And, here are &lt;a href=&quot;https://photos.app.goo.gl/VavY5PgBGezZaqMr6&quot;&gt;some photos&lt;/a&gt; of yours truly. :)&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/5WAF3kG7lcjoHBJyW1cZXjyfQ50CtiAFtE9jDZQNVxqv3Vx8poJ2pkJ0gN-iRy8Xll0WmQLbnNdu8ackq5QIyNi4U6pP8YLSOjeD99azl4Id_nQZ6-ZDIEF5yg7NWdoKinEKZP9umzdhPsDP4E9eilxOctHWG9BZ5oWS0NcYoGyWCx6wgv0zV2VQxX_ND49YkAz7VLe0RvoGkqVBBsGiqaNXMePFVp3yiS9QkVkp866duSJk1o8kBd3eUgP54znSoFG3G7zKgPmsyRcPkJiR4TjFQX_EcLY4EhGPPhJBy371E_h3jdA88Y_W2Y-qQLqmrTtRzx_c6zVJonVLSOZRPg3H4ZZU3ZpwbeWq09wzv6XgI_obzvRX9uWThj43TXbJGbAym_pwagzurao08D5i0-EfM0P2StjJ72Fl2pissiMsxlKm5m3j5SBmKiO_mp5hXIVuOe0W81sTIv7DB4yKGC-_meQgrKZDV2jFObdAIJ0pLR8TbsLYra2ljl9JBKi_1m0Q2kNhN3EX9eqxV4-i1yabOkl132DzVHg81MXBHt58oi2byfqmtv5Nzibf2UdGWku7up_71N4jl-hP9ZiRE5vxjvpx1FMuX_g9JSXAjQpbFIOxoYNG98TuP6i1zUwy-ItUfdK-KpTgd6tvtR0eU7tVnbdfGF4uQgpgTWMYxsRHT98xflCS0twqnoDxMH1UhTLMbjyVbBFlTihtl5dvMRWiwB8v6if74HA5b3jcmJTLjN0CWQ=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/MqS8YsePpXrxE1x6ZdUTexS_YkFXV3ivU5deks73l-hdXjrNsg3qu6dU8ykdjnfrIGI5o9aScbHNDe6soOF3tp8-k7ho340cj0kU9tbQSxr7A45WdF0Vc1DjiGlTOeTq8m0pDdCW_FsE5hejK0Ojv9Gmmv6AE9jfv-9ny1xtD3aYc-TE26x8RMZImPWVcASX-Q4j7vxwL7QkCXGSJqxk__fsJBST4_DAm9SAJckJURRsSLrxMELejTIgklg89Ku57n8ErpPyQLZeII1qtMzP71D_IZpYw4IbkXnRdEkmgtAoKlnkbhfm9dTeNaLA3cbbQH7MdhyjCA1BHV4Pb-GS0WmlJz0UznC97240N7NYwc9eydZIRl7XIWSIpQa422MjYexp9HaXE_0kigj4im6r1F1yyXUa4nZZl27IX4dSDNUuDeswXOHjlhZ6LwPzCU38ybsP3N-D5DmAwBfxZ4HceiC4TIw0h-TASjdO9GiFT5L0kQWdlYCyodG_PTiRcH66C8eKMbFpNRo4kHyC9xv9cpCitpuo1zpK71iG0qGted8RqKumc1IUmOVmixLUGMBn4N8fLzH9bHWI5-QgIFcAwjX-KpBF66bOQ8KFu80AfYvrjj_-uuLiJMAslQrdTH4Emke_GTiB33TqO-Sg_PlVtlxIY02apmukpgvA6g_zr8UBSNCeZBEGXFR55JuIXt6sQJyuqKJf5kwWiUNTB3dGK_VUxz8zQQ6OvZO2hAIkOzYnh1TwSA=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/GwcPQdQwUj4EZ5phpPq7oQSrsxz5xMPCNHzrcHx9NDTGsVvFJigPPgH_9Nomo3dfSnMjgZvVNWiOUA6schD2N_yiEYU9jVBDitTQjop3OLCTjOGgU-9Q_JFP6YWwW4qvcKr4E_WkUR2ncZXicpMlVTF9vDHteCUK03-h-0SQQklQRSyP4CZsm7CJUqPAieV5TlsGspbIaZ0HncXp1IHCcsA9hcsZszDLwI5XclX2ZYHWpccbYc8EngNP61wDDL6Jj8USkxlPBN_J2fjkpexA_RU16GN_PzP_mHcWOrX20Qo_U1ftx1O2BR47C_EMk_7eQBYFeyISV6Njvc7_rmoTFme01SK8rvpJhpaY2FjhmwaiwnTG_QxaPOezLq20N4LbNGJjJAspkjHoGmB_VRl2WzGTGv-sizvRHltpcZBhLFI2NaKBkjxbdCbGbmW-fwa192jx5SW_rqDxMRuGf0F9GDAWPNzI46-gfLIeMUbKZiq6D5FRqU1LBnhyK0BKX6QxtWiqY_cIHk1BThjMUuMCAUBvVJKaRz3-k7de-JH0YV8Wg6d-yHMU0nclpShtnHKKH-ZABLxF8S_6GC6lsGyObm8BwxA-eZesp4I3_pM2-GSn5YYbYxp5cf5mS34TcrnHbWBORYENVddDX9RVZBf6J9Hn42rO0z8lKEK4O3K7xkLXh3ntmfeJikM6RB-xXx-VZYMdLx_IZkjKP1NhnpSWaJhrBiXeAk9pdNRzbzz7JBxrAOFTRA=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/o629eWYguKoS9bjBAWpeQ05j2I_ulKDUDx7mBoigOaQAumd7ALULmPJ0rMDmkeSJOjm17lj4s_HPM2Xdz5aS8IqCDqDPHfIBOaVD2xw-5TwWMN3WrKMWC3sPArh2R5HHmw8XApO3SpgNCoLPJirwg-WsJaVzqdWKoJmLZIfPMf-aT-z0jJFTAUyLJzmxxJ_GNUtiX0BBuKLaS6ae7J-kWGLeeJ3Wodli7jWzOwdTQi0inem5ro9inHfS-HcOsOUn2bofObday9QGVnDmG4h5cuc7jwvUUUNtx1tw__HHvaPs5wF_lPSitwhBGmUlvR_DWe-o_ZIphXPtUE3N5rA_GitUxI_BAYpMG_AYq4GYUXwoyTotrtZdqn4cD1Vc9DE3bWfGeIEWV4Rk3XkMSFfLCGIta6LWoPYYtU0onJPNERgTgog4blAmoLPNotUFH_JRLji3VOAl3dwksL4FPVHH6huqDyYfcBKGZ8714_-8qvOZjs5D-vuTWMjZ5ggxeHceORfHROZK8uBGAF0Dfwd8ySZi1ZQMkU0fTjGpUu6Vw0HX91xpoyTuDimDkdpfHD5KSIS4EaWsvfsDh1bScFi3wb0fZNTDbNeXTM2gbLE5kzcXkLC_bB27UggVXNJHcgyjEvKrO6WohKVUyk0S3TMhuQzebBNA-cKAwjg6uNjAc7iw9dunJy9o685Pn4i9C0Th1V6hT-ECp__QkDLnP4EMPsQmhtCVdKad8NFTJljl82Wnm71vyg=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/0-9oruOGEu8TI9ziGr7Wjyu3p6i_yct3-cpoUAaUEcRXcVOD0g4M0Wi23eGsYJaG-JclUVm8gSEvbZRmIOrV2ypJ_dbfp7ew6BNThn5XXYz8is3whtfsF0us0Aoyge3HKppHGPFbHelWLPCw4mx2DuW5JYFMC0LyP4GxSj0s0rd08BmYrWQ82UY87gpGCUV1NrrS5PqasdUceXu0kJkQZ2zrnFyTIe0fgR74y1wPwJCFjEBZ-trO1trCztMyOdGvYjimSYSJ7NC4c-MaBcKfGVt96wdqm91FBmPW65msShxW_qJclHwxbJnHYbJ27vEbl6LxF2Cq67zb4X5zQlxxPVaYUJDiEE98e1cInOAFa0p3DGey8kiefhJJLLXBz4hss-IjyruuyC5O4l9uWdpkJ4oSGMp4wQlTli6DHrx08BRxW-JbBsjxxFjl5DoG4wViNNRhz2aCP1F4Vi2Y9-2O8RWHZvZr1wPOwzItrlV8yWSd1R2piOCbsz5I86mC7JcdhAAcOHjz-x8WkBW2l48hWDyArUmF3GQJXPs-c7LOMusb7dFSkDNfMQbpz9gMX-MGPHKXBU4D0F79kpK2IlucKXqJ0dwNnv3tJHaxA3CO1GNlvl0CbfnZ75SbewmnJ8p-hh4laRWsprzYEa8lzV5BpdUT2irF2hol370SIAyfYPo_YXI-FWJtxjQqPm37AodQFAEiVknbsLb7gHGSPwJXbVXkbkikmgGoo2izpmHNN1qmSNJCmQ=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/QWWFWmgn9SI9hc-F9xM9xydgPCiSW2VWVmDjRg435ajhVogEiAoB9PX-1RKaVUjDiKRyhc0mj2qkbA4PLt-zwjFZJv4NdisLfrTkrq5nIJNyF3tCbqnSCbccv7Z5RVTDS9Mooq7NuB81pvvF-S9JTXkJSwsXBv6VNY3x-dJy0Dhv_GM7rglLs3z5wqQNExtoMLaNZ7nly0ZXUom1AD-bGMOk1e0HXNe6YPiROS5FS6fvkZpNq4mPJXOYrAO7TYNpxGJ_8lL5-cWEWz881u4dtqC00V9jjYmB3Zv3GIcg_BNzJ-chAeVxYVNWtSbjSbVrIDv3c6-2toJy3q7RZsIlnJIzEsq2qo9zhAxVrBDMt4kJ50rqLvIJp4aYKDIbKH_YrYjWKXG3Nz9h1pkqyYw93J6oRq_8JS2W8k8aFzbKM4ASBCcCSvOHrfQLW4F9Jda743roruGOP7O0vMS-9gUZEGwWY-l-KM1pye7Mk93heJFgO38LVTxbHprsqAoxJ3YsegKVK3iHR54Roh4Ad8DZT_3egIsoM4RDas3a58nb8u3i7v9knNRMcXcdRiAHXVjDOLDEcQ1uxWYZehG9sUhfXHB85bvkbzPruTsMJRNJNUHv-XxDy4qN4Mp-KMiWXa5yQcajZ18znq8T5Fh8MwNvZ-n7V7fmR12NzIs6P4QFU7pV21W6dIFLMftdVMHg5Tyb7cgnhrPFA9xIllzC6uU5LpwpQ-F8Mul0zj4NuX_eQdgM4CRa9g=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/gmv02CzGXpgNFo9j7TSxNJSBPQ1SHS0ezY6KLnKVcOMuSY0BciIr00Q9eQovmNZsKn8k_7c6BZZKdKd42hIutQEY9LWOW0eiHrI6ZaKLB5S5QBkvTfUR1MGWlWPO_04EeRNi5dE8SLc-1gjjpS3eAv0HiHVyDWc2P3SEslkFX94-qXB_5HjQgny8H-wIdpdYOzjwfjIqnVaePN-MOVCZooQUNRSu760DSegdU2gdSAisAVoQqMzejevk3XkiAHXNgCeQMwUCt33qMh9BhQWjPLP6r1DRFUAQ9SWKFodVe_pTxAIgxky4KS5dfGC9uhE6A5wefxiXFLJLtyJJT7uG3-v0Bp7fCxt_8SWqK0F7iqTUlv_qjIcaDt6DtBdDTFX96A2QZYArAUH9f9boiQO-TmERuc4faN6g2o0d9JgAD5DsLFmO_O6i6hgD1ONP-vzoKd0ZFQHMeVX9xhPIMV40uqUr0w72_S9LFlSIKnHmEM0JyHM_v-e4n2EnkQwKWt5W4IgQdmSDiBmnxX1KTjAoo9ddkPhXoXmzhezma0z8uRAO2M3aM_jr67sAhfSZMvPBUkwTwS7h0_KLqjJoVKmXGcNBVM9zxVWipSiu1Ny07wNdixDkS27oGY2aejzudYp2L2dNrQJuN16cesP97oodYCSOs6Qy1CF4N_7i6wrCtd9bMEK7CxEljc7gGrV9hhP-3PNDLePt3Lcb8B8RNgRdsOhTJIs5v8hsQj_VzyOTxfqzTrmy6g=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/22Jb93H__Xpik_DJBWm1ulTks-BG0v0jwpmZj3rQzWG_cvmjZfrFrGA9y-XhddG5-9l7pe0lMLRK8UsX3eBr7wKb8ShNX73S_kCGdMSsJ1JvL4hEatyOQ7-0RhRCkZ0jot9KPJV2zJRM764kT2KR_IicD_EhTzXgoA-RoGu9C3NcQ9rAX5uWF3pleHLJ1LNmu0DEeBxF3XuoF3IVW9dbkfioyBMF-kn82RDe1f9RIIRabJSOWXl_QIYI47aE07XrCU7SRlf9jnF-W0-YxiMYHmElDKoD7HP8ySLx6QCkjQNF5lMC7dF6R25jcwrK4co7rCU20gsMBb2vkalwHvfFxcsIgShugRDzjUjdqzoZ3GT_4WFA9MoYBAShvNAn0L-eWMrAhv-XOXpkjfeeS-BVP2SwusFHK0wLkCzsmH5FD7d0J44QpkgvFojZX0zj6x-KbIsGD-yl2cEqsUkzYGZufBlo2tRobAyNOv89E9aT1BeQs76cvwykybO5AMWCsV6ikr_fExZQMPwqMTg-8FoOhpff6mTUyKVqMXlbk0-8JP-IkaCr8V8rqUUpDtDrZLNVXxIDj0rEXp9MzIZgiSe7MDViHKnEpOGY6vP_GGGpvWkZY8mAEpTTyRH0cJFAZ4jVV6hQmzqMvREmZcOLUDKIFdG_fM-bJOO-bGMx1Bi3371GJch81K273_pdJka7AUB391dOPv0wZCp3y_qRWeabrhfhpYSD_87ncMY7pgvMqtJMMmwDaQ=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
]]&gt;</content>
    <published>2019-09-14T08:05:09.000000Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/u/fredwu/tech/e/blog/p/conference-talk-adaptable-human-rubyconf-china-2019"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/u/fredwu/tech/e/blog/p/conference-talk-adaptable-human-rubyconf-china-2019</id>
    <title>Conference Talk: Adaptable Human @ RubyConf China 2019</title>
    <updated>2019-09-14T08:05:09.000000Z</updated>
  </entry>
  <entry>
    <content type="html">&lt;![CDATA[&lt;p&gt;
In 2010 I set up this blog on &lt;a href=&quot;https://tumblr.com&quot;&gt;Tumblr&lt;/a&gt; mostly due to the ease of publishing and not having to worry about the hosting. I also went through two design iterations done in Photoshop:&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/2019-01-20/blog-layouts.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
You can probably tell that these designs were done before the flat and minimalist design trend we are seeing in recent years.&lt;/p&gt;
&lt;p&gt;
As I decided to revamp my blog once again, I thought I’d use &lt;a href=&quot;https://www.sketchapp.com/&quot;&gt;Sketch&lt;/a&gt; this time around and aim for a simpler, cleaner and more mature design approach that’s quicker to design and to build. And this is exactly what I did:&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/2019-01-20/sketch.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Thanks to Sketch, the design process was much better than I would’ve had in Photoshop.&lt;/p&gt;
&lt;h2&gt;
Why the Revamp?&lt;/h2&gt;
&lt;p&gt;
A big part of the reason for the blog revamp was to move away from Tumblr, now that it is part of the dying &lt;a href=&quot;https://yahoo.com&quot;&gt;Yahoo!&lt;/a&gt;, and to invest in modern technologies to make the blog function better by adding responsive design and a proper grid system, etc.&lt;/p&gt;
&lt;p&gt;
As I was reading up on and researching technologies as I often do, I came across &lt;a href=&quot;https://www.gatsbyjs.org/&quot;&gt;Gatsby&lt;/a&gt;, and I was immediately convinced that this was going to power my new blog as it appears super fast (by building static content and pre-fetching), is based on &lt;a href=&quot;https://reactjs.org/&quot;&gt;React&lt;/a&gt; and has &lt;a href=&quot;https://www.gatsbyjs.org/docs/plugins/&quot;&gt;a huge collection of useful plugins&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
At work I often joke about how I hate JavaScript (&lt;code class=&quot;inline&quot;&gt;rm -rf node_modules&lt;/code&gt; anyone?), the truth is I started off my career doing a lot of JavaScript, &lt;a href=&quot;https://github.com/fredwu/jquery-endless-scroll&quot;&gt;my most popular open source library&lt;/a&gt; by GitHub star count is in JavaScript, and I have always worked as a full stack dev until recent years.&lt;/p&gt;
&lt;p&gt;
Due to the shift of my responsibilities more into leadership over the past few years, I have opted to focus more on the backend, but deep down I love software in general and given the frontend scene has seen some major improvements in the past few years, not to mention that at work we have several React code bases, it’s time I dig my teeth into it again.&lt;/p&gt;
&lt;p&gt;
Disclaimer: until recently I had only done two React projects before and my exposure to ES6 has been somewhat limited.&lt;/p&gt;
&lt;h2&gt;
Gatsby&lt;/h2&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/2019-01-20/gatsby.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
The thing about Gatsby that impressed me the most is how fast it is due to its out-of-box support for pre-fetching. With a wealth of different &lt;a href=&quot;https://www.gatsbyjs.org/starters/&quot;&gt;starter templates&lt;/a&gt; it is also very easy to hit the ground running. I used &lt;a href=&quot;https://www.gatsbyjs.org/starters/netlify-templates/gatsby-starter-netlify-cms/&quot;&gt;gatsby-starter-netlify-cms&lt;/a&gt; as it supports &lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt; and is fairly simple.&lt;/p&gt;
&lt;h2&gt;
Export Tumblr Posts&lt;/h2&gt;
&lt;p&gt;
First thing first, I will need to export all my tumblr posts into Markdown files so that Gatsby can consume them. There are heaps of such tools including &lt;a href=&quot;https://tumblr.zendesk.com/hc/en-us/articles/360005118894-Export-your-blog&quot;&gt;Tumblr’s own export functionality&lt;/a&gt;. I ended up having to use these two:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://import.jekyllrb.com/docs/tumblr/&quot;&gt;Jekyll importer&lt;/a&gt; for converting all Tumblr posts into Markdown  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/bbolli/tumblr-utils&quot;&gt;tumblr-utils&lt;/a&gt; for downloading all images in the posts (Tumblr’s own export tool and many others only download images hosted on Tumblr)  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Of course, many search-and-replace as well as manual massaging were required to get the new Markdown files to a useable state.&lt;/p&gt;
&lt;h2&gt;
Add More Gatsby Plugins&lt;/h2&gt;
&lt;p&gt;
The starter template was great, but I needed more functionalities so I ended up adding these over time:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-styled-components/&quot;&gt;gatsby-plugin-styled-components&lt;/a&gt; for supporting &lt;a href=&quot;https://www.styled-components.com/&quot;&gt;Styled Components&lt;/a&gt;  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-remark-embed-video/&quot;&gt;gatsby-remark-embed-video&lt;/a&gt; for embedding videos  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-remark-prismjs/&quot;&gt;gatsby-remark-prismjs&lt;/a&gt; for syntax highlighting  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-awesome-pagination/&quot;&gt;gatsby-awesome-pagination&lt;/a&gt; for pagination  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-remark-reading-time/&quot;&gt;gatsby-remark-reading-time&lt;/a&gt; for adding reading time  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-feed/&quot;&gt;gatsby-plugin-feed&lt;/a&gt; for RSS feed  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-google-analytics/&quot;&gt;gatsby-plugin-google-analytics&lt;/a&gt; for Google Analytics  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-redirect-from/&quot;&gt;gatsby-redirect-from&lt;/a&gt; for page redirects (of old Tumblr pages)  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-sitemap/&quot;&gt;gatsby-plugin-sitemap&lt;/a&gt; for sitemaps  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-robots-txt/&quot;&gt;gatsby-plugin-robots-txt&lt;/a&gt; for &lt;code class=&quot;inline&quot;&gt;robots.txt&lt;/code&gt;  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Using many of these plugins only requires you to add the plugin itself and some config, then off you go - it could not be any easier!&lt;/p&gt;
&lt;h2&gt;
GraphQL&lt;/h2&gt;
&lt;p&gt;
One other reason why I was interested in Gatsby was because of its &lt;a href=&quot;https://www.gatsbyjs.org/docs/querying-with-graphql/&quot;&gt;out-of-box support&lt;/a&gt; for &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt;. I came across GraphQL a while back but never had the chance to work with it. &lt;a href=&quot;https://www.ourxplor.com/&quot;&gt;At work&lt;/a&gt; one of our projects started using GraphQL and the team behind it rates it highly, so I really wanted to get some first hand experience using it.&lt;/p&gt;
&lt;p&gt;
With the inclusion of &lt;a href=&quot;https://github.com/graphql/graphiql&quot;&gt;GraphiQL&lt;/a&gt; the in-browser GraphQL IDE, the GraphQL experience in Gatsby is extremely simple and satisfying.&lt;/p&gt;
&lt;h2&gt;
Querying Data using Gatsby’s Page Components and StaticQuery&lt;/h2&gt;
&lt;p&gt;
It’s been a bit of journey.&lt;/p&gt;
&lt;p&gt;
The starter template I used has GraphQL queries in the page components, but I wanted the GraphQL queries in shareable components so I opted to using Gatsby’s &lt;a href=&quot;https://www.gatsbyjs.org/docs/static-query/&quot;&gt;StaticQuery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Until I decided to add &lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-awesome-pagination/&quot;&gt;gatsby-awesome-pagination&lt;/a&gt; which requires the GraphQL queries to have variables therefore &lt;a href=&quot;https://github.com/gatsbyjs/gatsby/issues/9047&quot;&gt;incompatible with StaticQuery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Despite the back and forth between page components and &lt;code class=&quot;inline&quot;&gt;StaticQuery&lt;/code&gt;, I still loved the GraphQL experience in Gatsby.&lt;/p&gt;
&lt;h2&gt;
It’s All Just React (In a Good Way)&lt;/h2&gt;
&lt;p&gt;
The great thing about Gatsby is that despite making things easier by including a bunch of useful functionalities and plugins, down to its core, everything is based on &lt;a href=&quot;https://reactjs.org/docs/components-and-props.html&quot;&gt;React Components&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
What this means is that as long as you have a working knowledge of React and React Components, extending Gatsby’s capability is simple and straightforward.&lt;/p&gt;
&lt;h2&gt;
CSS Powered by Bulma&lt;/h2&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/2019-01-20/bulma.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
The starter template also includes &lt;a href=&quot;https://bulma.io/&quot;&gt;Bulma&lt;/a&gt; - a modern and popular CSS framework.&lt;/p&gt;
&lt;p&gt;
Until now I’ve always relied mostly on &lt;a href=&quot;https://getbootstrap.com/&quot;&gt;Bootstrap&lt;/a&gt; so it’s nice to get to experience another CSS framework. And it turns out, Bulma is quite nice and easy to use too.&lt;/p&gt;
&lt;p&gt;
Thanks to Bulma, supporting responsive design was a breeze.&lt;/p&gt;
&lt;h2&gt;
Gotcha: CSS Rules and “gatsby-plugin-purgecss”&lt;/h2&gt;
&lt;p&gt;
&lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-purgecss/&quot;&gt;gatsby-plugin-purgecss&lt;/a&gt; is included as part of the starter template to reduce the size of the CSS files by removing unused CSS rules. It’s wonderful as it saves about &lt;code class=&quot;inline&quot;&gt;200Kb&lt;/code&gt; of CSS (before minifying and gzipping) from unused rules from Bulma.&lt;/p&gt;
&lt;p&gt;
One gotcha I soon realised though, is that it also purges any CSS rules that are only rendered in the Markdown components. My guess is that the purging happens before the static contents were rendered therefore it cannot detect them.&lt;/p&gt;
&lt;p&gt;
The fix was quite simple, given that by default it only purges the main css file (in my case, &lt;code class=&quot;inline&quot;&gt;all.scss&lt;/code&gt;), and all the specific rules in this file were defined by me, all I had to do was to add the comment lines to tell the plugin not to purge these rules:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;scss language-scss&quot;&gt;@import &quot;~bulma&quot;;

/* purgecss start ignore */
.my-own-css-rules-here {
}
/* purgecss end ignore */&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;
Gotcha: CSS Conflicts Between Bulma and Prism.js&lt;/h2&gt;
&lt;p&gt;
One more issue with CSS was the conflicts between Bulma and &lt;a href=&quot;https://prismjs.com/&quot;&gt;Prism.js&lt;/a&gt; due to the way some of the CSS rules are defined in Bulma.&lt;/p&gt;
&lt;p&gt;
What I had to do was to “reset” those CSS rules so they can inherit from Prism.js instead:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;scss language-scss&quot;&gt;.content {
  .number,
  .tag {
    align-items: inherit;
    background-color: inherit;
    border-radius: inherit;
    color: inherit;
    display: inherit;
    font-size: inherit;
    height: inherit;
    justify-content: inherit;
    line-height: inherit;
    margin-right: inherit;
    min-width: inherit;
    padding: inherit;
    text-align: inherit;
    vertical-align: inherit;
    white-space: inherit;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;
Netlify: Deployment and Hosting Made Easy (and Free!)&lt;/h2&gt;
&lt;p&gt;
Before Netlify and similar services were available, many people used &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; to host their static content sites. It worked reasonably well but in the end this isn’t GitHub’s core competency and the features are limited.&lt;/p&gt;
&lt;p&gt;
Netlify takes deployment of static content sites to &lt;a href=&quot;https://www.netlify.com/github-pages-vs-netlify/&quot;&gt;a whole new level&lt;/a&gt; and I cannot be happier to have finally jumped on the bandwagon too.&lt;/p&gt;
&lt;h2&gt;
Closing&lt;/h2&gt;
&lt;p&gt;
Suffice to say, I am very satisfied with this revamp experience - Sketch, Gatsby, GraphQL, Netlify and many other software have made it a walk in the park.&lt;/p&gt;
&lt;p&gt;
It only took me around 50 hours to get to 99%, and a few hours more to add in things like &lt;a href=&quot;https://github.com/disqus/disqus-react&quot;&gt;Disqus&lt;/a&gt; and &lt;a href=&quot;https://github.com/nygardk/react-share&quot;&gt;social sharing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Oh, and for those who are curious, the source code of this blog is &lt;a href=&quot;https://github.com/fredwu/fredwu.me-v3&quot;&gt;available on GitHub here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Let me just say:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
The last time I fell in love with JavaScript was when &lt;a href=&quot;https://jquery.com/&quot;&gt;JQuery&lt;/a&gt; first came to the scene many moons ago. Ever since then I dread working on the JS stack mostly because I’ve been spoiled by the Ruby and Elixir ecosystems. It’s nice to fall in love JavaScript again after so many years of simply “getting by”.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
I hope you like my new blog, and if you have a similar experience to share, I’d love to hear from you!&lt;/p&gt;
]]&gt;</content>
    <published>2019-01-20T11:27:22.000000Z</published>
    <category label="Blog" scheme="http://persumi.com/u/fredwu/tech/e/blog" term="blog"/>
    <category label="Tech" scheme="http://persumi.com/u/fredwu/tech" term="tech"/>
    <link href="http://persumi.com/u/fredwu/tech/e/blog/p/new-blog-with-new-design-and-gatsby-js-loving-javascript-again"/>
    <author>
      <name>Fred Wu</name>
      <email>ifredwu@gmail.com</email>
      <uri>http://persumi.com/u/fredwu</uri>
    </author>
    <id>http://persumi.com/u/fredwu/tech/e/blog/p/new-blog-with-new-design-and-gatsby-js-loving-javascript-again</id>
    <title>New Blog with New Design and Gatsby.js - Loving JavaScript Again</title>
    <updated>2019-01-20T11:27:22.000000Z</updated>
  </entry>
</feed>