<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Armedev: blog</title><description>Software engineer in India. Building products end to end: Go, TypeScript, Rust.</description><link>https://arme.dev/</link><language>en-us</language><item><title>I built a second brain in Go - Khayal</title><link>https://arme.dev/blog/i-built-a-second-brain-in-go-khayal/</link><guid isPermaLink="true">https://arme.dev/blog/i-built-a-second-brain-in-go-khayal/</guid><description>Local LLM, plain markdown, no cloud. The hard way.</description><pubDate>Wed, 08 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have a problem with note-taking apps.&lt;/p&gt;
&lt;p&gt;Not a preference problem. A trust problem.&lt;/p&gt;
&lt;p&gt;Every tool I tried either lives on someone else&amp;#39;s server, requires an account,
or stores my thoughts in a format I do not fully own. Notion is great until
Notion decides to change pricing. Obsidian is local but has no capture layer.
Mem.ai is clever but completely cloud. And all of them want to be the center
of your workflow.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why not just use Obsidian with a plugin?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Because Obsidian has no capture layer. No CLI. No local LLM processing. No
semantic search.&lt;/p&gt;
&lt;p&gt;I did not want a center. I wanted a pipe.&lt;/p&gt;
&lt;p&gt;So I built &lt;a href=&quot;https://khayal.rawnaqs.io&quot;&gt;Khayal&lt;/a&gt; -- a local-first second brain
that runs on your machine, processes with your own LLM, and stores everything
as plain markdown. No accounts. No cloud. No telemetry. We genuinely do not
know if anyone is using it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;خيال - Arabic for imagination, vision, the mind&amp;#39;s eye.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Two binaries, not one&lt;/h2&gt;
&lt;p&gt;This was the first decision and it shaped everything else.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;khayal&lt;/code&gt; is the server. It owns the database, the worker queue, the Ollama
calls, and the embedded PWA. It is the thing you start once and forget about.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kl&lt;/code&gt; is the client. It is a thin HTTP wrapper. It knows one thing: where the
server is and what the token is. Everything else is the server&amp;#39;s problem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why not just one binary? Simpler to distribute.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yeah, and also couples everything together. You cannot update the client
without restarting the server. You cannot run the server on one machine and
the client on another. The mental model gets muddy fast.&lt;/p&gt;
&lt;p&gt;Two binaries is the right call. The added distribution complexity is worth it.
This is the hard way and I knew the tradeoffs going in.&lt;/p&gt;
&lt;h2&gt;The CGo decision&lt;/h2&gt;
&lt;p&gt;Go&amp;#39;s SQLite story is annoying.&lt;/p&gt;
&lt;p&gt;The standard driver is &lt;code&gt;mattn/go-sqlite3&lt;/code&gt;. It works great. It also requires
CGo, which means cross-compilation becomes painful, goreleaser needs a C
toolchain, and your Docker builds get complicated.&lt;/p&gt;
&lt;p&gt;I did not want any of that. Khayal should be &lt;code&gt;go build&lt;/code&gt; and done. So I used
&lt;code&gt;modernc.org/sqlite&lt;/code&gt; -- a pure Go SQLite port transpiled from the original C.
No CGo. No toolchain requirements. goreleaser just works.&lt;/p&gt;
&lt;p&gt;The tradeoff is sqlite-vec. The vector extension for SQLite is a C library and
it does not play nicely with modernc. So right now Khayal does not have native
vector search -- it has FTS5 keyword search and a cosine similarity fallback
computed in Go. It works. It is not as fast as a proper vec index. I am still
working through this.&lt;/p&gt;
&lt;p&gt;If you have solved the sqlite-vec + modernc tension I genuinely want to know.
The options I see are a separate &lt;code&gt;vec.db&lt;/code&gt; handled by a CGo process, or
accepting the pure Go cosine fallback forever. Neither is great.&lt;/p&gt;
&lt;p&gt;This is a real open problem and not knowing it upfront would have been a major
skill issue.&lt;/p&gt;
&lt;h2&gt;The search stack&lt;/h2&gt;
&lt;p&gt;Hybrid search with RRF -- Reciprocal Rank Fusion.&lt;/p&gt;
&lt;p&gt;FTS5 handles keyword matching with porter stemming. The embedding model
(&lt;code&gt;nomic-embed-text&lt;/code&gt; via Ollama) handles semantic similarity. Both produce a
ranked list. RRF merges them by taking the reciprocal of each result&amp;#39;s rank
and summing across both lists.&lt;/p&gt;
&lt;p&gt;The result is that &lt;code&gt;kl search &amp;quot;observer effect&amp;quot;&lt;/code&gt; finds both exact matches and
semantically related notes -- depending on what is in your vault.&lt;/p&gt;
&lt;p&gt;FTS5 configuration is where I lost the most time. It is very easy to
misconfigure silently. Missing porter stemming, wrong column indexing, UNINDEXED
columns that should be indexed -- none of these throw errors, they just quietly
degrade your search quality. I found bugs in my own FTS5 setup weeks after I
thought it was done.&lt;/p&gt;
&lt;p&gt;Search quality is the core feature. Do not defer FTS5 configuration like I
did. It is not infrastructure, it is the product.&lt;/p&gt;
&lt;h2&gt;The PWA is inside the binary&lt;/h2&gt;
&lt;p&gt;The PWA is embedded in the &lt;code&gt;khayal&lt;/code&gt; binary via &lt;code&gt;embed.FS&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;One binary, one port, the web interface just works at &lt;code&gt;http://127.0.0.1:1133&lt;/code&gt;.
No separate static file server. No deployment step. No nginx config. Just
start the server and open the browser.&lt;/p&gt;
&lt;p&gt;The PWA has an offline capture queue backed by IndexedDB. If the server is
down, captures queue locally and sync when it comes back. There is a live
pipeline visualization that shows notes moving through the processing stages
in realtime.&lt;/p&gt;
&lt;p&gt;Getting iOS Safari right was the most tedious part of the whole project.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;svh&lt;/code&gt; instead of &lt;code&gt;vh&lt;/code&gt; for viewport height. The &lt;code&gt;html&lt;/code&gt; background color must
match the nav bar color or Liquid Glass tinting breaks. &lt;code&gt;@media (display-mode: standalone)&lt;/code&gt; needs to override certain layout calculations or
you get a gap at the bottom in PWA mode. None of this is documented in one
place. You just discover it by breaking things.&lt;/p&gt;
&lt;h2&gt;Your vault is just a folder&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;~/Documents/brain/
├── 2026-04-07/
│   └── observer-effect.md
├── 2026-04-06/
│   ├── react-patterns.md
│   └── system-design.md
└── .khayal/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obsidian can open it directly. Git can version it. Any editor can read it.
Khayal is a capture and retrieval layer -- it does not own your data, it just
indexes it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So Khayal replaces Obsidian?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No. They are complementary. Khayal is the pipe, Obsidian is the editor.
Use both or neither.&lt;/p&gt;
&lt;h2&gt;What I would do differently&lt;/h2&gt;
&lt;p&gt;The worker queue overflow is a real failure mode I underestimated. Under load,
if Ollama is slow and captures are coming in fast, the job channel fills up.
I have a fix for v1.1 but it should have been in v1.&lt;/p&gt;
&lt;p&gt;I would also start FTS5 configuration on day one. It feels like infrastructure
so you defer it. Do not do that.&lt;/p&gt;
&lt;h2&gt;Try it&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;brew install rawnaqs/tap/khayal
khayal init
khayal start
kl &amp;quot;your first thought&amp;quot;
kl search &amp;quot;thought&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href=&quot;https://github.com/rawnaqs/khayal&quot;&gt;https://github.com/rawnaqs/khayal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Site: &lt;a href=&quot;https://khayal.rawnaqs.io&quot;&gt;https://khayal.rawnaqs.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are working on anything local-first or have thoughts on the sqlite-vec
problem, open an issue or reach out.&lt;/p&gt;
&lt;p&gt;If you have feedback regarding this blog post,
click on &lt;a href=&quot;https://github.com/armedev/feedback/issues/new/choose&quot;&gt;an issue on GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Making it Hard, and Soft</title><link>https://arme.dev/blog/making-it-hard-and-soft/</link><guid isPermaLink="true">https://arme.dev/blog/making-it-hard-and-soft/</guid><description>Pattern matching your way through a Rust database client, and why the hard way teaches more.</description><pubDate>Sat, 30 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The title of this blog post is just a peek of what we are going to do today.&lt;/p&gt;
&lt;h2&gt;Let&amp;#39;s get started&lt;/h2&gt;
&lt;p&gt;Today, we are going to see some tips and tricks regarding the usage of Rust language.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why are you choosing rust it&amp;#39;s a language used by blue hair personalities&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I know people often consider Rust to be an extremist language, because many of them are not trying to get things done rather just fighting with a borrow checker by banging the &lt;code&gt;Future&lt;/code&gt; on their toes just for simple asynchronous executions.&lt;/p&gt;
&lt;p&gt;But, that doesn&amp;#39;t mean Rust itself is bad, or it doesn&amp;#39;t have potential.&lt;/p&gt;
&lt;p&gt;Rust is the middle ground for both competitive coders and Project builders, &lt;em&gt;competitive coding is done by all of them, the opponent is borrow-checker, but the project building is done by only some of them&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Considering you know basics of Rust, let&amp;#39;s dive into it…&lt;/p&gt;
&lt;h2&gt;The match and its magic&lt;/h2&gt;
&lt;p&gt;Consider you had a task to create a subroutine, which is an initializer for a database client.&lt;/p&gt;
&lt;p&gt;&lt;sup&gt;“db refers to database”&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Ideally you will require a &lt;code&gt;name/namespace&lt;/code&gt;, and the host &lt;code&gt;endpoint&lt;/code&gt;(with credentials).
And tadaww you got yourself a client. In theory, it&amp;#39;s just simple.&lt;/p&gt;
&lt;p&gt;Now the code part,&lt;/p&gt;
&lt;p&gt;here we will be using Surreal as a database and its lib &lt;a href=&quot;https://github.com/surrealdb/surrealdb.git&quot;&gt;surreal db&lt;/a&gt; as our rust client,&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;use surrealdb::{
    engine::remote::ws::{Client, Ws},
    opt::auth::Root,
    Surreal,
};

#[derive(Clone, Debug)]
pub struct SurrealClient {
    db: Surreal&amp;lt;Client&amp;gt;,
}

impl SurrealClient {
	pub async fn init() -&amp;gt; Option&amp;lt;Self&amp;gt; {
		let surreal_url_host = &amp;quot;127.0.0.1:1000&amp;quot;;
		let surreal_username = &amp;quot;root&amp;quot;;
		let surreal_pwd = &amp;quot;toor&amp;quot;;

		let res = match Surreal::new::&amp;lt;Ws&amp;gt;(surreal_url_host).await {
			Ok(db) =&amp;gt; {
				let res = match db.use_ns(&amp;quot;skill&amp;quot;).use_db(&amp;quot;issue&amp;quot;).await {
					Ok(_) =&amp;gt; {
						db.signin(Root {
							username: surreal_username,
							password: surreal_pwd,
						})
						.await
					}
					e =&amp;gt; e,
				};
				res.map(|_| db)
			}
			e =&amp;gt; e,
		};

		return match res {
			Err(e) =&amp;gt; {
				dbg!(&amp;amp;e);
				println!(&amp;quot;error: {}&amp;quot;, e);
				None
			}
			Ok(db) =&amp;gt; Some(Self { db }),
		};
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: &lt;a href=&quot;https://tokio.rs/&quot;&gt;Tokio&lt;/a&gt; is used as an async runtime&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;the above might look like a normal subroutine in the first glance but under the hood if you look closely you would find out that it has slight wisdom to it,&lt;/p&gt;
&lt;p&gt;firstly, we have a level of abstraction over a client, some argue it to be good, others argue it to be bad. Nonetheless, it gets things done. In our client we have a field &lt;code&gt;db&lt;/code&gt; which is of type &lt;code&gt;Surreal&amp;lt;Client&amp;gt;&lt;/code&gt;. Here, Surreal is an Arc pointer to a web-socket client. So it is straight forward.&lt;/p&gt;
&lt;p&gt;Then we have our &lt;code&gt;impl&lt;/code&gt; block, which has &lt;code&gt;init&lt;/code&gt; subroutine to initialize our client with some parameters, really simple.&lt;/p&gt;
&lt;p&gt;Then, we have our juiced up magic match expressions, let&amp;#39;s understand them one by one,&lt;/p&gt;
&lt;p&gt;First match expression accounts for a &lt;code&gt;Result&amp;lt;Client, Error&amp;gt;&lt;/code&gt;.
Second match expression accounts for a &lt;code&gt;Result&amp;lt;(), Error&amp;gt;&lt;/code&gt; which runs only when the first match expression resolves to be &lt;code&gt;ok&lt;/code&gt;.
Inside our second match expression we have &lt;code&gt;db.signin&lt;/code&gt; which also returns &lt;code&gt;Result&amp;lt;(), Error&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So one would think there are too many conditions to check, here&amp;#39;s where the Rust&amp;#39;s pattern matcher comes to rescue.&lt;/p&gt;
&lt;p&gt;Inside every match expression, we previously accounted for an &lt;code&gt;Ok&lt;/code&gt; variant, but there is also another variant in &lt;code&gt;Result&lt;/code&gt;, the &lt;code&gt;Error&lt;/code&gt; variant.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Info: Result is an Enum in Rust, for more &lt;a href=&quot;https://doc.rust-lang.org/std/result&quot;&gt;info&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Surprise‼ we are not accounting for the &lt;code&gt;Error&lt;/code&gt; in every match expression instead we are just returning the &lt;code&gt;Result&lt;/code&gt; like &lt;code&gt;e =&amp;gt; e&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are multiple benefits of this,&lt;/p&gt;
&lt;p&gt;firstly, we are squashing multiple errors into one without making borrow checker angry.
Secondly, we don&amp;#39;t care what happens to the underlying expressions, we just bubble up those results.
Thirdly, the most important part, we get back a single &lt;code&gt;Result&lt;/code&gt; with which we are satisfied in this scenario.&lt;/p&gt;
&lt;p&gt;And at last we return an Option type of our client.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But, how will you handle individual error of the Results, is it not a good practice to handle it?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yeah kinda, it is a good practice to acknowledge the expressions which can result in error, to handle it or not solely depends on the developer.&lt;/p&gt;
&lt;p&gt;For e.g., in JS:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;let something = &amp;#39;&amp;#39;;
JSON.parse(something);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not knowing that the above expressions might throw an error, is a major skill issue but knowing it and voiding it, is whole different scenario.&lt;/p&gt;
&lt;p&gt;Stop making too many abstractions and branching of code, just to make your code come under a good coding practice.&lt;/p&gt;
&lt;p&gt;Coding practices are a &lt;strong&gt;Myth&lt;/strong&gt;, they are present to make it easy for developers who have &lt;strong&gt;skill issues&lt;/strong&gt;, understand your code.
But, I strive for my code to be efficiently understood by the machine it runs on, not the developer who sees it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I think I conveyed my point :P&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The first part Making it Hard is done.&lt;/p&gt;
&lt;p&gt;Now it&amp;#39;s time for the second part,&lt;/p&gt;
&lt;h2&gt;The soft part&lt;/h2&gt;
&lt;p&gt;If you do know Rust to at least to an extent that you can get things done, then you probably might be thinking the above is just an engineer flexing the &lt;code&gt;match&lt;/code&gt; expressions.&lt;/p&gt;
&lt;p&gt;Yeah, &lt;strong&gt;True!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And also not true here&amp;#39;s why,&lt;/p&gt;
&lt;p&gt;There is a method called &lt;code&gt;and_then&lt;/code&gt; on the &lt;code&gt;Result&lt;/code&gt; type, which does all of the above error squashing.&lt;/p&gt;
&lt;p&gt;But, here&amp;#39;s the point you should not blindly use something other people created without trying it out yourself first. This is where you will actually learn things.&lt;/p&gt;
&lt;p&gt;Whenever I try to create something, let it be a simple subroutine, I always make it “by my way”.
In this process I will know what tradeoffs I am making and what are the weak points of the subroutine.&lt;/p&gt;
&lt;p&gt;Then, even in the future if I try to change it to convince some people on the internet, I will have a full context of what is happening under the hood.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;If you are just learning or just new to what you are doing, try to make many mistakes as you can by doing it your way (&lt;strong&gt;Hard way&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;Mistakes make you think better, they broaden your thinking process.&lt;/p&gt;
&lt;p&gt;If you just go the road of Soft way, as long as you are in that fairy tale dream land, you will never encounter the mistakes. Which will result in major skill issue.&lt;/p&gt;
&lt;p&gt;Only, when you get proficient in your &lt;strong&gt;hard way&lt;/strong&gt;, you should be deciding to go &lt;strong&gt;soft way&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Indeed, with hardships there will be ease.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you have feedback regarding this blog post,
click on &lt;a href=&quot;https://github.com/armedev/feedback/issues/new/choose&quot;&gt;an issue on GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>My First Blog!</title><link>https://arme.dev/blog/blog/</link><guid isPermaLink="true">https://arme.dev/blog/blog/</guid><description>How this blog got made: no framework, a template, and a build script.</description><pubDate>Wed, 06 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Initial words&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Hypermedia&lt;/strong&gt; is great.
This is it, so lets jump right into it.&lt;/p&gt;
&lt;h2&gt;Pre-build&lt;/h2&gt;
&lt;p&gt;I liked the content I was used to fed by the social platform &lt;em&gt;ALGORITHMS&lt;/em&gt; nonetheless it was worth it BUT it was starting to feel a little annoying in the recent years due to &lt;strong&gt;MILK YOUR CUSTOMER&lt;/strong&gt; analogy by the so called &lt;em&gt;Anti-social social platforms&lt;/em&gt;, It was pretty obvious I need to move away from all this so called monitored and monitized social platforms but I need to find a better way to absorb good content so....&lt;/p&gt;
&lt;p&gt;I started to think and wander like wild buffaloes run towards a end of the hill not knowing its pitfall and even if they try they cannot stop, falling in it, yeah I am talking about all those communities where you become one of them without yourself ever knowing it.&lt;/p&gt;
&lt;p&gt;So I wondered what are the good tools I can use to avoid becoming a part of any &lt;em&gt;community&lt;/em&gt; and learn new things and also avoid those creepy algorithms, ads, popups, subscriptions and the list goes on,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Yeah, I chose &lt;strong&gt;Blogs&lt;/strong&gt; like a &lt;em&gt;caveman&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here is the Interesting part you get to choose your own blogs and avoid any misleader or false content just like some &lt;em&gt;tweets&lt;/em&gt;.
So I started setting up rss feeds I like and just like that I had this huge list of blog posts I can learn or just read to get things going.&lt;/p&gt;
&lt;p&gt;And I thought am I a &lt;strong&gt;dummmy&lt;/strong&gt; because you see I am saying blogs are awesome what year is this? 2010.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Historic_recurrence&quot;&gt;Historic Recurrence&lt;/a&gt; came into rescue and I thought may be history is trying to repeat itself and why not be part of it, so I started creating this Blog.&lt;/p&gt;
&lt;h2&gt;Build&lt;/h2&gt;
&lt;p&gt;I chose to go full on &lt;strong&gt;no JS framework&lt;/strong&gt; mode to create the blog I like with the tools I desire.&lt;/p&gt;
&lt;p&gt;So HTML, CSS and JS(~10loc)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(JS was used only to switch themes hahaha classic JS)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I said I did not use JS, but I did use it, only to create HTML files.&lt;/p&gt;
&lt;h3&gt;Templates&lt;/h3&gt;
&lt;p&gt;filename: &lt;code&gt;blog-template.html&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I laid a bunch of HTML tags and left some unique distinguishable keywords in it so that I can inject the content of my blog post dynamically when I plan to publish a post like this one.
I take the markdown file and convert it to HTML and replace the unique tags in template file with it, its that simple.&lt;/p&gt;
&lt;p&gt;No it&amp;#39;s not, where are your manners about security and threats if you had some malicious content in it.&lt;/p&gt;
&lt;p&gt;for the most part, It is right its not advisable to inject content directly in a file and publish it but I know whats in their and the script is only running in my local development mode &lt;strong&gt;remember&lt;/strong&gt;(where I said JS 10loc).&lt;/p&gt;
&lt;h3&gt;Styling&lt;/h3&gt;
&lt;p&gt;There are no stylings, content is Information not &lt;em&gt;Animations&lt;/em&gt;.
There are some properties for the displaying of content with a good font and colors and also the &lt;strong&gt;DARK MODE&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Interaction&lt;/h3&gt;
&lt;p&gt;The only interactions a Blog post should have is scrolling and clicking which is already handled by browser so &lt;em&gt;use IT&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Post build&lt;/h2&gt;
&lt;p&gt;Now this is the part that is pretty interesting its how I manage to publish future blog posts with it.&lt;/p&gt;
&lt;p&gt;Its simple if you think about it, Create a markdown file and run the script to output a HTML file in your public directory and publish it to your repo. Thats it.&lt;/p&gt;
&lt;p&gt;With the help of either Github CI/CD or any simple hosting techniques, It can be published in a matter of seconds. That I think is blazingly fast.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Imagine the scenario if you had used a framework, stuck in an endless rat race trying to make it work and perfect because you chose a framework which will without your notice do some breaking changes. Now you have to update the site and also create blogs aghhhhh.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Yeah I know its not extra-ordinary but do you want to use a extra-ordinary tool which may or may not work in future where there will be different ways to do things just to throw out some HTML files at the end.&lt;/p&gt;
&lt;p&gt;No, and also It depends, the main question you have to ask &lt;strong&gt;yourself&lt;/strong&gt; is what is it that you desire?&lt;/p&gt;
&lt;p&gt;If you want to create a &lt;em&gt;Thing&lt;/em&gt; to just do its &lt;em&gt;Thing&lt;/em&gt; then avoid doing other things even though it is a &lt;em&gt;Standard&lt;/em&gt;.
But if you want to focus on other things apart from your &lt;strong&gt;Goals&lt;/strong&gt; then I think you are a &lt;em&gt;dummmmy&lt;/em&gt;&lt;/p&gt;
</content:encoded></item></channel></rss>