<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/atom.xsl" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Pranab&#x27;s site</title>
    <subtitle>I &lt;3 reading, programming, games with people, note-taking and UX.
</subtitle>
    <link rel="self" type="application/atom+xml" href="https://pranabekka.neocities.org/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-08-31T00:18:53+00:00</updated>
    <id>https://pranabekka.neocities.org/atom.xml</id>
      
        <entry xml:lang="en">
            <title>Neocities!</title>
            <published>2026-08-31T00:18:53+00:00</published>
            <updated>2026-08-31T00:18:53+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/neocities/"/>
            <id>https://pranabekka.neocities.org/neocities/</id>
            <summary type="html">
              🐱
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/neocities/">
              &lt;p&gt;🐱&lt;&#x2F;p&gt;
&lt;p&gt;After a few hours of work,
I’m on Neocities!
The site is still mirrored on Github Pages,
but all links point to Neocities.&lt;&#x2F;p&gt;
&lt;p&gt;My site really doesn’t fit
the usual look or content on Neocities,
but I like it here.
It has me quite excited,
which is quite refreshing
after the current state of the internet
and the tech world.&lt;&#x2F;p&gt;
&lt;p&gt;IndieWeb FTW!&lt;&#x2F;p&gt;
&lt;p&gt;You should join up,
if you haven’t already!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I had to read up a fair bit on Github Actions,
since I was already used to automatic deployments
and I wanted to keep that going for Neocities,
even though my specific setup wasn’t documented.
It was suprisingly easy,
especially with examples to look at.
The JS stuff used by some actions was confusing,
especially since the action file points at &lt;code&gt;dist&#x2F;&lt;&#x2F;code&gt;,
which I eventually learnt was build output,
and thus hard to read.
The docs on Actions are quite comprehensive,
though it took some effort to find docs
that didn’t just tell me to use actions,
and I wish they didn’t create
a programming language over YAML.
I was actually quite apprehensive
about getting it done without loosing my mind,
but it really didn’t take much time.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
        <entry xml:lang="en">
            <title>Loop in Gleam</title>
            <published>2026-04-22T18:00:05+00:00</published>
            <updated>2026-04-22T18:00:05+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/loopin-gleam/"/>
            <id>https://pranabekka.neocities.org/loopin-gleam/</id>
            <summary type="html">
              How to survive without for loops.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/loopin-gleam/">
              &lt;p&gt;How to survive without &lt;code&gt;for&lt;&#x2F;code&gt; loops.&lt;&#x2F;p&gt;
&lt;p&gt;This is a simple introduction
to build intuition for recursion,
which can be used for looping in any language
with functions,
though it will be of limited use
if it’s not optimised.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Tail_call#Language_support&quot;&gt;Languages with optimised recursion&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let’s get started.&lt;&#x2F;p&gt;
&lt;p&gt;Looping and recursion is all about repeating.
In fact, the regular word “recurse”
is a synonym for “repeat”.&lt;&#x2F;p&gt;
&lt;p&gt;Say you have a function to greet somebody:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pub fn main() -&amp;gt; Nil {
	greet()
}

fn greet() -&amp;gt; Nil {
	io.println(&amp;quot;Howdy!&amp;quot;)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we wanted to repeat the greeting multiple times,
we can just call the function again.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pub fn main() -&amp;gt; Nil {
	greet()
	greet()
	greet()
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That’s rarely a valid option, though.
Instead, we can simply call the function again
at the end of the function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn greet() -&amp;gt; Nil {
	io.println(&amp;quot;Hallo!&amp;quot;)
	greet()
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the essence of recursion:
calling a function again at the end.
After this point we just need to take care
that it stops before the program
crashes or force quits.&lt;&#x2F;p&gt;
&lt;p&gt;For the &lt;code&gt;greet&lt;&#x2F;code&gt; function,
we will want a number to track how often
the greeting should be repeated.
The function must be called
with that parameter each time.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn greet(times: Int) -&amp;gt; Nil {
	io.println(&amp;quot;Hi!&amp;quot;)
	greet(times)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each time we repeat the function,
we decrease the number by 1.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn greet(times: Int) -&amp;gt; Nil {
	io.println(&amp;quot;Hi!&amp;quot;)
	greet(times - 1)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If the number reaches 0,
then we don’t repeat the function, just return &lt;code&gt;Nil&lt;&#x2F;code&gt;.
We also check if the number is negative,
otherwise the program would go on, as before,
until it crashes or force quits.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn greet(times: Int) -&amp;gt; Nil {
	case times &amp;lt;= 0 {
		True -&amp;gt; Nil
		False -&amp;gt; {
			io.println(&amp;quot;Hi!&amp;quot;)
			greet(times - 1)
		}
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, let’s greet four times.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pub fn main() -&amp;gt; Nil {
	greet(4)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;greet&lt;&#x2F;code&gt; function will print,
then call &lt;code&gt;greet&lt;&#x2F;code&gt; with &lt;code&gt;3&lt;&#x2F;code&gt;,
print, then &lt;code&gt;2&lt;&#x2F;code&gt;, print, then &lt;code&gt;1&lt;&#x2F;code&gt;,
print, then &lt;code&gt;0&lt;&#x2F;code&gt;, and stop.&lt;&#x2F;p&gt;
&lt;p&gt;There are a few implications of this,
each leading into the other:
creating a loop means creating a function,
which can be reused anywhere as a function,
and given by other people in a library,
and even given to other people in your own libraries.&lt;&#x2F;p&gt;
&lt;p&gt;See the language tour to learn more about
recursion, tail calls, common looping functions,
and Gleam in general.
It takes just an afternoon,
and you can join the Discord server
to get help immediately.
The community is very friendly!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tour.gleam.run&quot;&gt;The Gleam Language Tour&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;Fm8Pwmy&quot;&gt;Gleam Discord server&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
        <entry xml:lang="en">
            <title>Objects is modules, cuz</title>
            <published>2026-01-31T16:31:39+00:00</published>
            <updated>2026-01-31T16:31:39+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/objects-is-modules/"/>
            <id>https://pranabekka.neocities.org/objects-is-modules/</id>
            <summary type="html">
              Makin’ methods from plain ol’ funcs, no interface.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/objects-is-modules/">
              &lt;p&gt;Makin’ methods from plain ol’ funcs, no interface.&lt;&#x2F;p&gt;
&lt;p&gt;Just import functions for a type as methods on the type
when the module is imported.
That’s what the other systems are doing
— objects, interfaces, traits, what have you.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s say we have a module &lt;code&gt;foo&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pub type Bar { ... }

pub fn new_bar() -&amp;gt; Bar {
	...
}

pub fn bar_func(bar: Bar) -&amp;gt; Bar {
	...
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here’s how we can use it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;import foo

pub fn main() -&amp;gt; Nil {
	let my_var = foo.new_bar()
	
	&#x2F;&#x2F; Call as method
	my_var.bar_func()
	
	&#x2F;&#x2F; Call as plain ol&amp;#39; func
	foo.bar_func(my_var)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Probably change method syntax
to not look like a variable field or module access,
but yeah, we’ve made methods with plain ol’ funcs.
Everything works the way you like,
but with less boilerplate.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;import foo
import baz

pub fn main() {
	foo.new_bar()
		::bar_func()
		::mo_func()
		::een_mo_func()
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; baz.file

import foo.Bar

pub fn mo_func(bar: Bar) -&amp;gt; Bar {
	...
}

pub fn een_mo_func(bar: Bar) -&amp;gt; Bar {
	...
	bar::bar_func()
	...
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Arbitrary proper markup</title>
            <published>2026-01-21T21:07:03+00:00</published>
            <updated>2026-01-21T21:07:03+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/arbitrary-proper-markup/"/>
            <id>https://pranabekka.neocities.org/arbitrary-proper-markup/</id>
            <summary type="html">
              Ruminating on Ginger Bill’s post on the same.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/arbitrary-proper-markup/">
              &lt;p&gt;Ruminating on Ginger Bill’s post on the same.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gingerbill.org&#x2F;article&#x2F;2026&#x2F;01&#x2F;19&#x2F;two-families-of-markup-languages&quot;&gt;The Only Two Markup Languages&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;He says XML and TeX are the only families
of proper arbitrary markup.
I guess the biggest difference between the two
is that a TeX-like would be less verbose
than an XML derivative,
but I feel like &lt;code&gt;&amp;lt;&#x2F;node&amp;gt;&lt;&#x2F;code&gt; can become &lt;code&gt;&amp;lt;&#x2F;&amp;gt;&lt;&#x2F;code&gt;
and then the difference in verbosity is negligible.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, here’s the two families for demonstration.&lt;&#x2F;p&gt;
&lt;p&gt;SGML&#x2F;XML:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;node&amp;gt;Some arbitrary text&amp;lt;&#x2F;node&amp;gt;
&amp;lt;node attribute=value&amp;gt;Some arbitrary text&amp;lt;&#x2F;node&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;TeX-like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;\node{Some arbitrary text}
\node[attribute=value]{Some arbitrary text}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While Ginger Bill claims only the above two
allow wrapping arbitrary text,
in truth, any data format allows it,
because text&#x2F;strings are a universal data type.&lt;&#x2F;p&gt;
&lt;p&gt;JSON:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[&amp;quot;node&amp;quot;, &amp;quot;Some arbitrary text&amp;quot;]
[&amp;quot;node&amp;quot;, {&amp;quot;attribute&amp;quot;: &amp;quot;value&amp;quot;}, &amp;quot;Some arbitrary text&amp;quot;] 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;NestedText (I can’t write YAML):&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;-
  - node
  - Some arbitrary text
-
  -
    attribute: value
  - Some arbitrary text
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;S-expression-like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[:node &amp;quot;Some arbitrary text&amp;quot;]
[:node [@ :attribute &amp;quot;value&amp;quot;] &amp;quot;Some arbitrary text&amp;quot;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;KDL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;node &amp;quot;Some arbitrary text&amp;quot;;
node attribute=value &amp;quot;Some arbitrary text&amp;quot;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are only three differences between TeX&#x2F;XML
and the other languages in the examples above.&lt;&#x2F;p&gt;
&lt;p&gt;First, we’re working with a subset of these languages.
This means proper arbitrary markup in KDL
will always be valid KDL,
but not all valid KDL will be
valid proper arbitrary markup.
That’s not a big deal, though,
because not all plain-text files are valid TeX either.
In fact, using a subset of a structured language
like KDL or S-expressions is quite useful.&lt;&#x2F;p&gt;
&lt;p&gt;The second difference is that these other languages
require wrapping the whole document,
because text&#x2F;strings only allow text inside them.
While I don’t think TeX requires it,
XML and well-formed HTML do require it,
and most authors do wrap the whole document.
Additionally, even for a derived format,
these documents are implicitly wrapped
in a &lt;code&gt;\texdoc&lt;&#x2F;code&gt; or &lt;code&gt;&amp;lt;html-doc&amp;gt;&lt;&#x2F;code&gt; node anway.
It helps to imagine the data structure,
which would be some kind of document struct.
Finally, it’s trivial to add an extra node
while you’re marking up the rest of the document.&lt;&#x2F;p&gt;
&lt;p&gt;The third difference is that
nesting nodes is a bit roundabout and unintuitive,
which is also because strings only allow text inside.
Nesting uses the same amount of insertion points,
but it’s not as simple as an open and close tag.
Instead, it’s more of a close previous and open new.
I don’t think it’s too hard to learn, though.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s how XML looks:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;outer&amp;gt;Some arbitrary text&amp;lt;&#x2F;outer&amp;gt;
&amp;lt;outer&amp;gt;Some &amp;lt;inner&amp;gt;arbitrary&amp;lt;&#x2F;inner&amp;gt; text&amp;lt;&#x2F;outer&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here’s how KDL looks:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;outer &amp;quot;Some arbitrary text&amp;quot;
outer &amp;quot;Some &amp;quot; { inner &amp;quot;arbitrary&amp;quot; } &amp;quot; text&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In XML we insert &lt;code&gt;&amp;lt;inner&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;lt;&#x2F;inner&amp;gt;&lt;&#x2F;code&gt;,
but in KDL we insert &lt;code&gt;&amp;quot; { inner &amp;quot;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;quot; } &amp;quot;&lt;&#x2F;code&gt;.
It’s helpful to think of it as
closing the previous part of the text
and then opening the next part of the text,
and maybe NestedText would make this easier
because opening and closing are easy to see.
This would be the key difference between
TeX&#x2F;XML-likes and the other languages I mention.&lt;&#x2F;p&gt;
&lt;p&gt;Though we’re essentially at the end of our rumination,
I’m going to briefly mention escaping.&lt;&#x2F;p&gt;
&lt;p&gt;NestedText requires indenting your text content
instead of allowing you to just add nodes,
but even TeX and XML require escaping characters
inside the text content of the nodes.
KDL is the only format
that allows just adding nodes
without escapes for the characters inside them.
TeX&#x2F;XML-likes could probably create something similar.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;node #&amp;quot;Some arbitrary text with a &amp;quot; character&amp;quot;#
node ##&amp;quot;Some arbitrary text with &amp;quot;# characters&amp;quot;##
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I’d like to conclude this post by saying
Wasted Eyes by Amaarae is a fun song.
I don’t understand genres,
but Wikipedia says she’s known for
her fusion of pop, R&amp;amp;B, Afrobeats and alté.&lt;&#x2F;p&gt;
&lt;p&gt;Have fun!&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Borrow inferrer</title>
            <published>2026-01-20T13:59:52+00:00</published>
            <updated>2026-03-01T20:09:53+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/borrow-infer/"/>
            <id>https://pranabekka.neocities.org/borrow-infer/</id>
            <summary type="html">
              Mutation thout annotations xor bugs.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/borrow-infer/">
              &lt;p&gt;Mutation thout annotations xor bugs.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This post doesn’t communicate the idea well.
The following discussion on the Rust user forums
is a better explanation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;users.rust-lang.org&#x2F;t&#x2F;aliased-xor-mutable-core-for-a-high-level-language&#x2F;138482&quot;&gt;Aliased Xor Mutable core for a high-level language&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The core idea is a high-level language
that presents normal values as copies to the user,
while using references under the hood,
and unique ownership for external resources,
which means a safer and more performant
high-level language.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The key part of Rust is sharing xor mutating,
where “xor” means “either but not both”,
so you can share or you can mutate,
but you cannot do both at the same time.
This gives Rust some high-level properties
that only functional programming languages have,
but not any of the mainstream languages.
The ownership and performance aspects of Rust
are a sort-of side-effect of the share xor mutate rule.
Manish Goregaokar has an excellent post
on the subtler errors caused by shared mutability.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;manishearth.github.io&#x2F;blog&#x2F;2015&#x2F;05&#x2F;17&#x2F;the-problem-with-shared-mutability&#x2F;&quot;&gt;The Problem With Single-Threaded Shared Mutability&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The problem with Rust is that
it requires explicit annotations for borrows and clones,
which is not suitable for a high-level language,
even if lifetimes are the truly scary bit.
Rust’s language design suggests that
we must have annotations or we must have bugs,
but we cannot remove both while still allowing mutation.
However, I might have a way to completely remove bugs
and annotations at the same time,
by using Rust’s share xor mutate rule and a syntax tweak,
so that instead of just checking,
we can infer clones, moves and borrows.&lt;&#x2F;p&gt;
&lt;p&gt;We start by looking at moves in Rust:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn main() {
	let mut list = [&amp;quot;ay&amp;quot;, &amp;quot;bee&amp;quot;, &amp;quot;sea&amp;quot;];
	list = list_fn(list);
	dbg!(list);
}

fn list_fn(mut list: [&amp;amp;str; 3]) -&amp;gt; [&amp;amp;str; 3] {
	list[0] = &amp;quot;ecks&amp;quot;;
	list
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There’s a borrow annotation because of
the specific string type,
but otherwise there’s no reference
or lifetime annotations here.
It looks almost like a high-level language.
If we remove explicit borrow annotations,
then our new language would require assignment syntax
to invisibly mutate with moves or mutable borrows.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fun main()
	let mut list = [&amp;quot;ay&amp;quot;, &amp;quot;bee&amp;quot;, &amp;quot;sea&amp;quot;]
	list = list_fn(list)
	dbg!(list)

fun list_fn(list)
	list[0] = [&amp;quot;ecks&amp;quot;]
	list
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This means that a function must return a parameter
if it intends to mutate it, and then we need to
assign the result back into the variable.
Conversely, if a function doesn’t return a parameter,
that means it doesn’t mutate it,
so it receives an immutable borrow or move.
Now &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; are inferred without annotations.
The call to &lt;code&gt;dbg!&lt;&#x2F;code&gt; above would use an immutable borrow
because it has a smaller lifetime and
it doesn’t mutate &lt;code&gt;list&lt;&#x2F;code&gt;,
which means we can use &lt;code&gt;list&lt;&#x2F;code&gt;
even after passing it to &lt;code&gt;dbg!&lt;&#x2F;code&gt;,
which is not possible with Rust.&lt;&#x2F;p&gt;
&lt;p&gt;Values are copied when they’re assigned to a new variable,
based on the fact that there’s no point to
creating a new variable if you’re going to have it
point to the same thing as the original.
The new variable needs to be different from the old,
so it needs to be copied.
Now we don’t need &lt;code&gt;.clone()&lt;&#x2F;code&gt; or &lt;code&gt;derive(Copy)&lt;&#x2F;code&gt;.
In this example,&lt;code&gt;list2&lt;&#x2F;code&gt; is a copy of &lt;code&gt;list&lt;&#x2F;code&gt;
that is mutated by &lt;code&gt;list_fn&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fun main()
	let list = [&amp;quot;ay&amp;quot;, &amp;quot;bee&amp;quot;, &amp;quot;sea&amp;quot;]
	let list2 = list_fn(list)
	dbg!(list)
	dbg!(list2)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some types won’t be magically copied in this way,
such as files and network connections,
and types that use them would also be treated the same.
The language would use moves when
assigning such values to a different variable,
and require explicit clones, if possible.
Any types that used those would also use
moves and explicit clones.
The compiler would provide built-in types and functions
for these resources.&lt;&#x2F;p&gt;
&lt;p&gt;Even iterators would ensure that we cannot
mutate a list directly while looping over it,
because iteration requires sharing,
which would prevent mutation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fun main()
	let mut list = [&amp;quot;ay&amp;quot;, &amp;quot;bee&amp;quot;, &amp;quot;sea&amp;quot;]
	list = for list item {
		item = string.join(item, &amp;quot;!!&amp;quot;)
		&#x2F;&#x2F; ERROR:
		list = push(list, item)
	}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;for&lt;&#x2F;code&gt; loop takes a mutable reference to each item
and mutates it in-place,
then returns the result with the reference.
It’s similar to &lt;code&gt;map&lt;&#x2F;code&gt;,
but it allows mutable access to variables outside the loop.
If we wanted to add items to &lt;code&gt;list&lt;&#x2F;code&gt;,
we could loop over indexes or do it after the loop.&lt;&#x2F;p&gt;
&lt;p&gt;All this should give us most of Rust’s performance
along with the safety guarantees,
but without any of the low-level annotations.
In fact, you could say this language is higher level
than Python and even functional languages,
because you don’t need to think about references
or tail-call optimisation. &lt;&#x2F;p&gt;
&lt;p&gt;The language would also
make numbers and other values use the same mutation syntax,
it would have only one string type,
it would have only one parameter passing method,
instead of references vs moves,
it would make functions much easier to reuse,
and it would allow chaining any normal functions
as long as their outputs and inputs match,
which is super fun!&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fun main()
	[&amp;quot;ay&amp;quot;, &amp;quot;bee&amp;quot;, &amp;quot;sea&amp;quot;]
	|&amp;gt; fn_one()
	|&amp;gt; fn_two()
	|&amp;gt; fn_three()
	|&amp;gt; dbg!()

fun fn_one(l)
	l[0] = &amp;quot;ecks&amp;quot;
	l

fun fn_two(l)
	l[1] = &amp;quot;why&amp;quot;
	l

fun fn_three(l)
	l[2] = &amp;quot;zed&amp;quot;
	l
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can learn more about chaining
by trying it out in Gleam,
where it’s called piping.
The code example in the link below is interactive,
so you can edit it to see how it works.
You’ll see that it’s much more flexible
than method chaining.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tour.gleam.run&#x2F;functions&#x2F;pipelines&#x2F;&quot;&gt;Chaining normal functions in Gleam&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The snippets I’ve shown so far
might remind some people of functional programming,
but this language would allow
clear in-place mutation,
higher performance,
and the popular imperative programming semantics.
That said, part of the inspiration for this
came around June 2025,
when I was wondering how to adopt pipes
from functional languages like Gleam
to imperative languages,
though learning and understanding Rust
showed a better way to achieve it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.github.io&#x2F;all-you-need-is-pipes-and-assignment&#x2F;&quot;&gt;An inferior reference inference idea&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Going back to the point,
we would have a language that’s safe,
correct, high-level, familiar
to the vast majority of imperative
and low-level programmers,
high performance, and fun to use!
It wouldn’t even have a garbage collector!
There’s still a lot to figure out,
especially for concurrency,
but the compiler should be able to
provide built-in types and functions for it,
and we have a solid foundation regardless!&lt;&#x2F;p&gt;
&lt;p&gt;I hope you see the potential!
There’s lots to figure out still,
so I’d love any feedback you have!&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>parsing aim logs in gleam</title>
            <published>2026-01-01T03:10:41+00:00</published>
            <updated>2026-01-01T03:10:41+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/parsing-aim-logs-gleam/"/>
            <id>https://pranabekka.neocities.org/parsing-aim-logs-gleam/</id>
            <summary type="html">
              just some quick fun with the plain text logs.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/parsing-aim-logs-gleam/">
              &lt;p&gt;just some quick fun with the plain text logs.&lt;&#x2F;p&gt;
&lt;p&gt;based on michael lynch’s post on trying gleam,
where he wants to take old chat logs in various formats
and put them all in the same file format.
he starts with the plain-text logs,
and i thought i’d have a go :)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mtlynch.io&#x2F;notes&#x2F;gleam-first-impressions&#x2F;&quot;&gt;michael lynch’s post&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;starting-simple&quot;&gt;starting simple&lt;a class=&quot;zola-anchor&quot; href=&quot;#starting-simple&quot; aria-label=&quot;Anchor link for: starting-simple&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;plain-text log sample:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Session Start (DumbAIMScreenName:Jane): Mon Sep 12 18:44:17 2005
[18:44] Jane: hi
[18:55] Me: hey whats up
Session Close (Jane): Mon Sep 12 18:56:02 2005
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;first, we &lt;code&gt;gleam new&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;gleam new aim_log_parser
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;because i’m just having fun,
i’ll paste the test input into the main file.
plus it makes it easy to follow along
even in the online playground&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;const test_input =
	&amp;quot;Session Start (DumbAIMScreenName:Jane): Mon Sep 12 18:44:17 2005&amp;quot;
	&amp;lt;&amp;gt; &amp;quot;[18:44] Jane: hi&amp;quot;
	&amp;lt;&amp;gt; &amp;quot;[18:55] Me: hey whats up&amp;quot;
	&amp;lt;&amp;gt; &amp;quot;Session Close (Jane): Mon Sep 12 18:56:02 2005&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;gleam run&lt;&#x2F;code&gt; for fun, and gleam tells me
i can remove &lt;code&gt;test_input&lt;&#x2F;code&gt; because it’s never used.
well, let’s do something about that.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pub fn main() -&amp;gt; Nil {
	string.split(test_input, &amp;quot;\n&amp;quot;)
	|&amp;gt; echo as &amp;quot;log lines&amp;quot;
	Nil
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;let’s &lt;code&gt;gleam run&lt;&#x2F;code&gt; that&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src&#x2F;parse_aim_log.gleam:12 log lines
[&amp;quot;Session Start (DumbAIMScreenName:Jane): Mon Sep 12 18:44:17 2005[18:44] Jane: hi[18:55] Me: hey whats upSession Close (Jane): Mon Sep 12 18:56:02 2005&amp;quot;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ah, there’s just one list item there.
i changed the input because it looked ugly,
but i forgot to add the line breaks.
i could use &lt;code&gt;\n&lt;&#x2F;code&gt;, but that doesn’t feel much better.
let’s just stick to copy-pasting the input.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;const test_input =
&amp;quot;Session Start (DumbAIMScreenName:Jane): Mon Sep 12 18:44:17 2005
[18:44] Jane: hi
[18:55] Me: hey whats up
Session Close (Jane): Mon Sep 12 18:56:02 2005&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and &lt;code&gt;gleam run&lt;&#x2F;code&gt; that&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src&#x2F;parse_aim_log.gleam:12 log lines
[&amp;quot;Session Start (DumbAIMScreenName:Jane): Mon Sep 12 18:44:17 2005&amp;quot;,
&amp;quot;[18:44] Jane: hi&amp;quot;,
&amp;quot;[18:55] Me: hey whats up&amp;quot;,
&amp;quot;Session Close (Jane): Mon Sep 12 18:56:02 2005&amp;quot;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;alright, we have 4 lines in the list.
processing a list usually means &lt;code&gt;list.map&lt;&#x2F;code&gt;,
since we want to go over each item.&lt;&#x2F;p&gt;
&lt;p&gt;feels like a sad chat, by the way&lt;&#x2F;p&gt;
&lt;p&gt;a message line starts with “[”,
while the other two have
“Session Start” and “Session Close”.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pub fn main() -&amp;gt; Nil {
	string.split(test_input, &amp;quot;\n&amp;quot;)
	|&amp;gt; list.map(fn(line) {
		case line {
			&amp;quot;[&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; &amp;quot;Message&amp;quot;
			&amp;quot;Session Start&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; &amp;quot;Start&amp;quot;
			&amp;quot;Session Close&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; &amp;quot;Close&amp;quot;
			_ -&amp;gt; panic as &amp;quot;Unkown log entry&amp;quot;
		}
	})
	|&amp;gt; echo as &amp;quot;log lines&amp;quot;
	Nil
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;gleam run&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src&#x2F;parse_aim_log.gleam:21 log lines
[&amp;quot;Start&amp;quot;, &amp;quot;Message&amp;quot;, &amp;quot;Message&amp;quot;, &amp;quot;Close&amp;quot;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;so we start message, exchange two messages, then close.
looks good.
let’s pull out that function from &lt;code&gt;list.map&lt;&#x2F;code&gt;.
call it &lt;code&gt;parse_line&lt;&#x2F;code&gt;.
we’ll add types soon.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pub fn main() -&amp;gt; Nil {
	string.split(test_input, &amp;quot;\n&amp;quot;)
	|&amp;gt; list.map(parse_line)
	|&amp;gt; echo as &amp;quot;log lines&amp;quot;
	Nil
}

fn parse_line(line) {
	case line {
		&amp;quot;[&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; &amp;quot;Message&amp;quot;
		&amp;quot;Session Start&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; &amp;quot;Start&amp;quot;
		&amp;quot;Session Close&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; &amp;quot;Close&amp;quot;
		_ -&amp;gt; panic as &amp;quot;Unkown log entry&amp;quot;
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;runs the same. always good to confirm.
could’ve forgotten the line breaks.&lt;&#x2F;p&gt;
&lt;p&gt;i’d normally start with types,
but we didn’t really need them then.
now we want to store information.
let’s turn the strings into types.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type LogEntry {
	Message
	SessionStart
	SessionClose
}

fn parse_line(line) {
	case line {
		&amp;quot;[&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; Message
		&amp;quot;Session Start&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; SessionStart
		&amp;quot;Session Close&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; SessionClose
		_ -&amp;gt; panic as &amp;quot;Unkown log entry&amp;quot;
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;running it looks good.
we still have start, two messages and close,
but they’re not strings anymore.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src&#x2F;parse_aim_log.gleam:14 log lines
[SessionStart, Message, Message, SessionClose]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;we can start saving information about the entries,
like the username and date or time.&lt;&#x2F;p&gt;
&lt;p&gt;i’ll start with the messages.
they’ve got a time, an author,
and a body with the actual message contents.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[18:44] Jane: hi
            ^^ separates metadata and body
       ^ separates time and author
^-----^ wraps time
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type LogEntry {
	Message(time: String, author: String, body: String)
	SessionStart
	SessionClose
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;first, we split the metadata and body on &lt;code&gt;: &lt;&#x2F;code&gt;.
gleam doesn’t know, but we assure it
that splitting will always work.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let assert Ok(#(metadata, body)) = string.split_once(line, &amp;quot;: &amp;quot;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;then we split the metadata into time and author on &lt;code&gt; &lt;&#x2F;code&gt;,
again assuring gleam that the split will succeed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let assert Ok(#(time, author)) = string.split_once(metadata, &amp;quot; &amp;quot;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;then we construct a &lt;code&gt;Message&lt;&#x2F;code&gt; from that&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn parse_line(line) {
	case line {
		&amp;quot;[&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; {
			let assert Ok(#(metadata, body)) = string.split_once(line, &amp;quot;: &amp;quot;)
			let assert Ok(#(time, name)) = string.split_once(metadata, &amp;quot; &amp;quot;)
			Message(time, name, body)
		}
		&amp;quot;Session Start&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; SessionStart
		&amp;quot;Session Close&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; SessionClose
		_ -&amp;gt; panic as &amp;quot;Unkown log entry&amp;quot;
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;a quick &lt;code&gt;gleam run&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src&#x2F;parse_aim_log.gleam:14 log lines
[SessionStart,
Message(&amp;quot;[18:44]&amp;quot;, &amp;quot;Jane&amp;quot;, &amp;quot;hi&amp;quot;),
Message(&amp;quot;[18:55]&amp;quot;, &amp;quot;Me&amp;quot;, &amp;quot;hey whats up&amp;quot;),
SessionClose]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;looks good, just need to strip out the brackets.
we’ll drop a character at the start and end for that&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let time = time
	|&amp;gt; string.drop_start(1)
	|&amp;gt; string.drop_end(1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;gleam run&lt;&#x2F;code&gt; that, and it looks good&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src&#x2F;parse_aim_log.gleam:14 log lines
[SessionStart,
Message(&amp;quot;18:44&amp;quot;, &amp;quot;Jane&amp;quot;, &amp;quot;hi&amp;quot;),
Message(&amp;quot;18:55&amp;quot;, &amp;quot;Me&amp;quot;, &amp;quot;hey whats up&amp;quot;),
SessionClose]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;let’s do the same for the session start and close.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type LogEntry {
	Message(time: String, author: String, body: String)
	SessionStart(name: String, datetime: String)
	SessionClose(name: String, datetime: String)
}

fn parse_line(line) {
	case line {
		&amp;quot;[&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; todo as &amp;quot;cut out for brevity&amp;quot;
		&amp;quot;Session Start&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; {
			let assert Ok(#(other_data, datetime)) = string.split_once(line, &amp;quot;: &amp;quot;)
			let assert Ok(#(_, name)) = other_data
				|&amp;gt; string.drop_end(1)
				|&amp;gt; string.split_once(&amp;quot;(&amp;quot;)
			SessionStart(name, datetime)
		}
		&amp;quot;Session Close&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; {
			let assert Ok(#(other_data, datetime)) = string.split_once(line, &amp;quot;: &amp;quot;)
			let assert Ok(#(_, name)) = other_data
				|&amp;gt; string.drop_end(1)
				|&amp;gt; string.split_once(&amp;quot;(&amp;quot;)
			SessionClose(name, datetime)
		}
		_ -&amp;gt; panic as &amp;quot;Unkown log entry&amp;quot;
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;start and close are exactly the same
apart from the constructor’s name,
so let’s split that out to a function.
i even created a separate session info type
so that the new function can construct it directly
and then it can be put directly into the session entries,
instead of putting it together manually from tuples&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type LogEntry {
	Message(time: String, author: String, body: String)
	SessionStart(SessionInfo)
	SessionClose(SessionInfo)
}

type SessionInfo {
	SessionInfo(name: String, datetime: String)
}

fn parse_line(line) {
	case line {
		&amp;quot;[&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; todo as &amp;quot;cut out for brevity&amp;quot;
		&amp;quot;Session Start&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; {
			parse_session_info(line) |&amp;gt; SessionStart
		}
		&amp;quot;Session Close&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; {
			parse_session_info(line) |&amp;gt; SessionClose
		}
		_ -&amp;gt; panic as &amp;quot;Unkown log entry&amp;quot;
	}
}

fn parse_session_info(line) -&amp;gt; SessionInfo {
	let assert Ok(#(other_data, datetime)) = string.split_once(line, &amp;quot;: &amp;quot;)
	let assert Ok(#(_, name)) = other_data
		|&amp;gt; string.drop_end(1)
		|&amp;gt; string.split_once(&amp;quot;(&amp;quot;)
	SessionInfo(name:, datetime:)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;starting-with-types&quot;&gt;starting with types&lt;a class=&quot;zola-anchor&quot; href=&quot;#starting-with-types&quot; aria-label=&quot;Anchor link for: starting-with-types&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;i think it’s generally a good idea to think of types,
and then write them out and go from there.&lt;&#x2F;p&gt;
&lt;p&gt;while slinging strings gets some immediate output,
types help solidify our understanding of the problem
and discourage over-using strings and other built-ins,
because then the type system can’t help you as much.
we’ll also have to do less refactoring,
and the gleam lsp will help us a lot&lt;&#x2F;p&gt;
&lt;p&gt;so, we have a look at the sample log&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Session Start (DumbAIMScreenName:Jane): Mon Sep 12 18:44:17 2005
[18:44] Jane: hi
[18:55] Me: hey whats up
Session Close (Jane): Mon Sep 12 18:56:02 2005
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and we see three types of log entries&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type LogEntry {
	Message(time: String, author: String, body: String)
	SessionStart(name, datetime)
	SessionClose(name, datetime)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;we know that having a SessionInfo type is useful,
and we can see that it’s being repeat here,
but it also feels like extra typing at this point,
so i personally wouldn’t have done it,
but i think the lesson is that you should probably
split out repeat info into it’s own type,
because they’ll be handled the same.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type LogEntry {
	Message(time: String, author: String, body: String)
	SessionStart(info: SessionInfo)
	SessionClose(info: SessionInfo)
}

type SessionInfo {
	SessionInfo(name: String, datetime: String)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;from here, it’s best to write a parser for each,
which i prefer over one big function
like we did before with &lt;code&gt;parse_entry&lt;&#x2F;code&gt;.
we can have it delegate to the individual ones&lt;&#x2F;p&gt;
&lt;p&gt;first, i’ll change &lt;code&gt;main&lt;&#x2F;code&gt; a bit
because i like seeing something&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;const test_input =
&amp;quot;Session Start (DumbAIMScreenName:Jane): Mon Sep 12 18:44:17 2005
[18:44] Jane: hi
[18:55] Me: hey whats up
Session Close (Jane): Mon Sep 12 18:56:02 2005&amp;quot;

pub fn main() -&amp;gt; Nil {
	let lines = string.split(test_input, &amp;quot;\n&amp;quot;)
	echo lines
	Nil
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;gleam run&lt;&#x2F;code&gt; that, and we see a list of lines.
cool, let’s start parsing&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pub fn main() -&amp;gt; Nil {
	string.split(test_input, &amp;quot;\n&amp;quot;)
	|&amp;gt; list.map(parse_entry)
	|&amp;gt; echo as &amp;quot;entries&amp;quot;

	Nil
}

fn parse_entry(text: String) -&amp;gt; LogEntry {
	case text {
		&amp;quot;Session Start&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; parse_session_start(text)
		&amp;quot;[&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; parse_message(text)
		&amp;quot;Session Close&amp;quot; &amp;lt;&amp;gt; _ -&amp;gt; parse_session_start(text)
		_ -&amp;gt; {
			echo text as &amp;quot;unkown entry&amp;quot;
			panic
		}
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;gleam run&lt;&#x2F;code&gt; won’t work right now.
it’ll give errors because the functions don’t exist.
we can use the lsp to generate the functions for us,
which is kinda nice&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn parse_session_start(text: String) -&amp;gt; LogEntry {
	todo
}

fn parse_message(text: String) -&amp;gt; LogEntry {
	todo
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;oop, we there’s only two functions,
we copied &lt;code&gt;parse_session_start&lt;&#x2F;code&gt;
and forgot to change it to &lt;code&gt;close&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;alright, we’ll parse session start.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; Session Start (DumbAIMScreenName:Jane): Mon Sep 12 18:44:17 2005
&#x2F;&#x2F; -------------- junk
&#x2F;&#x2F; session info  --------------------------------------------------
fn parse_session_start(text: String) -&amp;gt; LogEntry {
	let assert &amp;quot;Session Start &amp;quot; &amp;lt;&amp;gt; data = text
	parse_session_info(data) |&amp;gt; SessionStart |&amp;gt; echo
}

&#x2F;&#x2F; (DumbAIMScreenName:Jane): Mon Sep 12 18:44:17 2005
&#x2F;&#x2F;                           ------------------------ datetime
&#x2F;&#x2F;                         -- separator
&#x2F;&#x2F; ------------------------ name_parens
&#x2F;&#x2F;  ---------------------- name
fn parse_session_info(text: String) -&amp;gt; SessionInfo {
	let assert Ok(#(name_parens, datetime)) =
		string.split_once(text, &amp;quot;: &amp;quot;)
	let name = name_parens
		|&amp;gt; string.drop_start(1)
		|&amp;gt; string.drop_end(1)
	SessionInfo(name:, datetime:)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;i’m echoing the data in &lt;code&gt;parse_session_start&lt;&#x2F;code&gt;
because the &lt;code&gt;todo&lt;&#x2F;code&gt;s make it crash
before &lt;code&gt;main&lt;&#x2F;code&gt; shows anything.
the extra &lt;code&gt;echo&lt;&#x2F;code&gt; shows us some info
before the crash&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src&#x2F;parse_aim_log.gleam:45
SessionStart(SessionInfo(&amp;quot;DumbAIMScreenName:Jane&amp;quot;, &amp;quot;Mon Sep 12 18:44:17 2005&amp;quot;))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;looks nice. we can parse the message&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; [18:44] Jane: hi
&#x2F;&#x2F;               -- body
&#x2F;&#x2F;             -- separator
&#x2F;&#x2F; ------------ metadata
&#x2F;&#x2F;         ---- name
&#x2F;&#x2F;        - separator
&#x2F;&#x2F; ------- time_brackets
&#x2F;&#x2F;  ----- time
fn parse_message(text: String) -&amp;gt; LogEntry {
	let assert Ok(#(metadata, body)) =
		string.split_once(text, &amp;quot;: &amp;quot;)
	let assert Ok(#(time_brackets, name)) =
		string.split_once(metadata, &amp;quot; &amp;quot;)
	let time = time_brackets
		|&amp;gt; string.drop_start(1)
		|&amp;gt; string.drop_end(1)
	Message(time:, author:, body:) |&amp;gt; echo
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;gleam run&lt;&#x2F;code&gt; output looks nice
(before the crash; &lt;code&gt;parse_session_close&lt;&#x2F;code&gt; is still &lt;code&gt;todo&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src&#x2F;parse_aim_log.gleam:45
SessionStart(SessionInfo(&amp;quot;DumbAIMScreenName:Jane&amp;quot;, &amp;quot;Mon Sep 12 18:44:17 2005&amp;quot;))
src&#x2F;parse_aim_log.gleam:78
Message(&amp;quot;18:44&amp;quot;, &amp;quot;Jane&amp;quot;, &amp;quot;hi&amp;quot;)
src&#x2F;parse_aim_log.gleam:78
Message(&amp;quot;18:55&amp;quot;, &amp;quot;Me&amp;quot;, &amp;quot;hey whats up&amp;quot;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;finally, we parse &lt;code&gt;SessionClose&lt;&#x2F;code&gt;,
copying freely from &lt;code&gt;parse_session_start&lt;&#x2F;code&gt;,
while remembering to change “start” to “close”&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; Session Close (Jane): Mon Sep 12 18:56:02 2005
&#x2F;&#x2F; -------------- junk
&#x2F;&#x2F; session info  --------------------------------------------------
fn parse_session_close(text: String) -&amp;gt; LogEntry {
	let assert &amp;quot;Session Close &amp;quot; &amp;lt;&amp;gt; data = text
	parse_session_info(data) |&amp;gt; SessionClose |&amp;gt; echo
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;gleam run&lt;&#x2F;code&gt; now completes without a crash,
but with all entries shown again at the end&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src&#x2F;parse_aim_log.gleam:45
SessionStart(SessionInfo(&amp;quot;DumbAIMScreenName:Jane&amp;quot;, &amp;quot;Mon Sep 12 18:44:17 2005&amp;quot;))
src&#x2F;parse_aim_log.gleam:78
Message(&amp;quot;18:44&amp;quot;, &amp;quot;Jane&amp;quot;, &amp;quot;hi&amp;quot;)
src&#x2F;parse_aim_log.gleam:78
Message(&amp;quot;18:55&amp;quot;, &amp;quot;Me&amp;quot;, &amp;quot;hey whats up&amp;quot;)
src&#x2F;parse_aim_log.gleam:86
SessionClose(SessionInfo(&amp;quot;Jane&amp;quot;, &amp;quot;Mon Sep 12 18:56:02 2005&amp;quot;))
src&#x2F;parse_aim_log.gleam:13 entries
[SessionStart(SessionInfo(&amp;quot;DumbAIMScreenName:Jane&amp;quot;, &amp;quot;Mon Sep 12 18:44:17 2005&amp;quot;)), Message(&amp;quot;18:44&amp;quot;, &amp;quot;Jane&amp;quot;, &amp;quot;hi&amp;quot;), Message(&amp;quot;18:55&amp;quot;, &amp;quot;Me&amp;quot;, &amp;quot;hey whats up&amp;quot;), SessionClose(SessionInfo(&amp;quot;Jane&amp;quot;, &amp;quot;Mon Sep 12 18:56:02 2005&amp;quot;))]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;incidentally, i noticed one pattern repeated twice,
for stripping the square and round brackets,
which i could pull out into a separate function&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn drop_brackets(text: String) -&amp;gt; String {
	text
	|&amp;gt; string.drop_start(1)
	|&amp;gt; string.drop_end(1)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;we’re relying on the name for this to be used correctly,
and we’re experienced devs so we won’t abuse it
even in a small project like this.
if this ever became bigger
maybe we could check for brackets
and have an error otherwise?
or just not drop anything?
yeah, probably just don’t touch the string
if there’s no brackets&lt;&#x2F;p&gt;
&lt;p&gt;also, we could save the separators in variables,
and it might have the variable names as documentation
in a way?&lt;&#x2F;p&gt;
&lt;p&gt;also-also, gleam doc comments use three slashes,
after which it’s parsed as markdown or djot,
both of which use the same code block syntax,
so we could generate pretty docs with &lt;code&gt;gleam docs&lt;&#x2F;code&gt;.
we also need to make the function &lt;code&gt;pub&lt;&#x2F;code&gt;
to have it show up in the docs&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F;&#x2F; ```
&#x2F;&#x2F;&#x2F; Session Close (Jane): Mon Sep 12 18:56:02 2005
&#x2F;&#x2F;&#x2F; -------------- junk
&#x2F;&#x2F;&#x2F; session info  --------------------------------
&#x2F;&#x2F;&#x2F; ```
pub fn parse_session_close(text: String) -&amp;gt; LogEntry {
	let assert &amp;quot;Session Close &amp;quot; &amp;lt;&amp;gt; data = text
	parse_session_info(data) |&amp;gt; SessionClose |&amp;gt; echo
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;you’ll need to &lt;code&gt;gleam docs build&lt;&#x2F;code&gt; that,
open the link in your browser,
then open the module name,
because it opens the readme by default&lt;&#x2F;p&gt;
&lt;p&gt;welp, that’s about it&lt;&#x2F;p&gt;
&lt;p&gt;kinda fun.
i really do enjoy using gleam&lt;&#x2F;p&gt;
&lt;p&gt;could be fun to add &lt;code&gt;to_string&lt;&#x2F;code&gt;
to reconstruct the plain-text logs
from the parsed &lt;code&gt;LogEntry&lt;&#x2F;code&gt; types.
we’d need it to normalise all the logs anyway&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
        <entry xml:lang="en">
            <title>Connect 4 Gleam</title>
            <published>2025-10-18T01:05:15+00:00</published>
            <updated>2025-10-18T01:05:15+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/connect-4-gleam/"/>
            <id>https://pranabekka.neocities.org/connect-4-gleam/</id>
            <summary type="html">
              Making a little Connect 4 TUI in Gleam.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/connect-4-gleam/">
              &lt;p&gt;Making a little Connect 4 TUI in Gleam.&lt;&#x2F;p&gt;
&lt;p&gt;I like looking for little projects to work on,
though sometimes I guess the scope incorrectly.
Also, I’m prone to overthinking things
and trying to get it perfect,
which means tweaking things and going back and forth
on the smallest details.
For example, how should I model a grid cell?
Is it one of empty, red and yellow,
or is it empty and full, with full containing a piece?
I’m usually inclined towards piece being separate,
but I can’t articulate why,
which makes me a bit uncomfortable.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I was thinking of Ludo a while back,
and I realised setting up the board
would be a lot of work,
so I wondered how I might render it in the terminal.
I never really got around to it,
but one day I remembered Connect 4,
and I realised that’s perfect for a CLI!&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;1 2 3 4 5 6 7
_ _ _ _ _ _ _
_ _ _ _ _ _ _
_ _ _ _ _ _ _
_ _ _ _ O _ _
_ _ _ _ X O _
_ _ _ O X X _
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Connect 4 usually has 7 columns and 6 rows,
and I can use simple letters for the pieces.
I picked X and O from knots and crosses,
though I’ve seen people use emojis,
which is also a fine idea.&lt;&#x2F;p&gt;
&lt;p&gt;I managed to theorise about the perfect
board representation as well, by the way.
I started off with two wide columns,
Rd and Bk for Red and Black pieces,
dashes for empty cells,
and zero padded numbers for the columns.&lt;&#x2F;p&gt;
&lt;p&gt;Yikes.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, the reason I picked Gleam
was because the language is so interesting,
so even though I don’t see any particular use for it,
I felt like implementing a small project in it,
which made Connect 4 seem like a decent idea.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve been hitting roadblocks with
functional programming since then,
partly because I’m trying to get it right.
I probably should have ended it there
and come back later to improve the code,
but here we are, over a month later,
and I still haven’t finished it,
because I think lots and do little.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, well.&lt;&#x2F;p&gt;
&lt;p&gt;What I like about type systems like Gleam
is how easy it is to model things.
I have pieces which can be X or O,
cells which can be empty or filled with a piece,
rows which are a list of cells,
and a grid which is a list of rows.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type Grid = List(Row)

type Row = List(Cell)

type Cell = Option(Piece)

type Piece {
	X
	O
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ahhh, and pipes are so nice.
I was already critical of objects,
but even procedural languages
can’t do pipes like this.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;const height = 6
const width = 7

fn grid_new() -&amp;gt; Grid {
	list.repeat(Empty, width)
	|&amp;gt; list.repeat(height)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I even wrote a test for this,
though I did that… let me look it up
— just 7 days ago.
Huh, it feels like it’s been longer.&lt;&#x2F;p&gt;
&lt;p&gt;Ah, and I used &lt;code&gt;Option(Piece)&lt;&#x2F;code&gt; for the cell.
I’m thinking that’s an odd choice right now.
It really doesn’t matter that much,
but, as I’ve already established,
this is my specialty.
Let me have it.&lt;&#x2F;p&gt;
&lt;p&gt;This feels like a case of primitive obsession.
It’s better to have custom types where possible.
Not using a list for the row and grid
has terrible ergonomics,
but options use the built-in types feature,
so the only difference is importing a general type.
Dang, I must fix it to use a custom type.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type Cell {
	Empty
	Full(Piece)
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well.&lt;&#x2F;p&gt;
&lt;p&gt;I’m sorry! But I simply must overthink this.
I cannot help myself.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t see what benefits the custom type gives.
A cell will always be either empty or full.
It can never be partially full.
The custom type does give a better name though.
Let’s stick with it.&lt;&#x2F;p&gt;
&lt;p&gt;Sorry.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, after making a grid,
we must print the thing.
Initially I put it all into a single function
with lots of case statements,
but as I was implementing it in Rust (what can I say),
I was encouraged to have a string function for each type.
The Rust display trait is weirdly complicated, by the way.
Anyway, I made a string function for each type,
delegating down the chain for each new one.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pub fn grid_string(grid: Grid) -&amp;gt; String {
	list.map(grid, row_string)
	|&amp;gt; string.join(&amp;quot;\n&amp;quot;)
}

pub fn row_string(row: Row) -&amp;gt; String {
	list.map(row, cell_string)
	|&amp;gt; string.join(&amp;quot; &amp;quot;)
}

pub fn cell_string(cell: Cell) -&amp;gt; String {
	case cell {
		Full(piece) -&amp;gt; piece_string(piece)
		Empty -&amp;gt; &amp;quot;_&amp;quot;
	}
}

pub fn piece_string(piece: Piece) -&amp;gt; String {
	case piece {
		X -&amp;gt; &amp;quot;X&amp;quot;
		O -&amp;gt; &amp;quot;O&amp;quot;
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Such nice and pretty little functions.
Did you notice how readable it is
with the pipes and implicit returns?
Mmmm, delicious. Chef’s kiss.&lt;&#x2F;p&gt;
&lt;p&gt;My first stumbling block was here.
I needed to put a piece in the board,
and it must drop all the way down
to the last empty cell in the column.&lt;&#x2F;p&gt;
&lt;p&gt;I was thinking in the imperative style
and spent several hours
browsing the standard library and experimenting
to write the perfect function
to get the correct cell to put the piece.&lt;&#x2F;p&gt;
&lt;p&gt;But Gleam deals with values, not references.
I can’t do &lt;code&gt;a.b.c = X&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I came back a few days later, I think,
after I saw the &lt;code&gt;dict.insert&lt;&#x2F;code&gt; function,
which will replace a value if the key exists.
I got it to work and began to write about it,
but turning a few days into a few words
helped me realise that it was a roundabout way
to do something like &lt;code&gt;a.b.c = X&lt;&#x2F;code&gt;.
It felt like the wrong way to do it.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve put the code using dictionaries below.
While it might look a bit complicated,
it’s actually much easier than figuring out lists.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe I should’ve gone with the dictionary
instead of making my life hard.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, well.&lt;&#x2F;p&gt;
&lt;p&gt;I’ll get into handling lists in another post.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type Grid = Dict(Int, Row)

type Row = Dict(Int, Cell)

fn grid_new() -&amp;gt; Grid {
	let number_update = fn(entry: #(_, _), idx) {
		#(entry.0 + idx, entry.1)
	}

	let row = list.repeat(#(1, Empty), width)
	|&amp;gt; list.index_map(number_update)
	|&amp;gt; dict.from_list
	
	list.repeat(#(1, row), width)
	|&amp;gt; list.index_map(number_update)
	|&amp;gt; dict.from_list
}

fn grid_update(grid: Grid, piece: Piece, column_number: Int) {
	let column = dict.fold(grid, [], fn(column, row_number, row) {
		&#x2F;&#x2F; SAFE: We make sure the user inputs a valid column number.
		let assert Ok(cell) = dict.get(row, column_number)
		[#(row_number, cell), ..column]
	}

	let empty_row_result =
		column
		&#x2F;&#x2F; Column got reversed, so this starts from bottom.
		|&amp;gt; list.find(fn(row) { row.1 == Empty })
	
	case empty_row_result {
		Ok(#(row_number, _)) -&amp;gt; {
			&#x2F;&#x2F; SAFE: The row_number was generated from the grid.
			let assert Ok(old_row) = dict.get(grid, row_number)
			let new_row = dict.insert(old_row, column_number, Full(piece))
			dict.insert(grid, row_number, new_row)
		}
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

            </content>
        </entry>
        
      
      
      
      
      
      
      
        <entry xml:lang="en">
            <title>All you need is pipes and assignment</title>
            <published>2025-06-30T20:02:25+00:00</published>
            <updated>2025-06-30T20:02:25+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/all-you-need-is-pipes-and-assignment/"/>
            <id>https://pranabekka.neocities.org/all-you-need-is-pipes-and-assignment/</id>
            <summary type="html">
              For function composition and clearer mutation.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/all-you-need-is-pipes-and-assignment/">
              &lt;p&gt;For function composition and clearer mutation.&lt;&#x2F;p&gt;
&lt;p&gt;Most modern languages have realised
that you should make references explicit,
but even that can be stripped out.
If you remove references,
then assignment is the only way to mutate,
and you don’t need a second syntax and semantics,
with its own set of keywords and&#x2F;or symbols.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let x = 210
x = double(x)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The main reason references are used
is to prevent expensive copies,
but those have been solved for some time.
The copy-on-write mechanism uses a reference,
until a mutation is performed,
at which point it stores a mutated copy.
Similary, if I’m passing in &lt;code&gt;x&lt;&#x2F;code&gt; and
assigning it back into &lt;code&gt;x&lt;&#x2F;code&gt;,
or I never use &lt;code&gt;x&lt;&#x2F;code&gt; again,
then it can be mutated in place.&lt;&#x2F;p&gt;
&lt;p&gt;Tada! No copies, no references, no performance cost,
and a cleaner language with one obvious way to mutate.&lt;&#x2F;p&gt;
&lt;p&gt;In fact, references have also been lamented by Tony Hoare,
of “billion-dollar mistake” fame.
I found an article by without.boats citing this,
titled “References are like jumps”.
What’s funny is that they didn’t directly say
“References considered harmful”,
but comparing them to jump&#x2F;goto heavily implies that.
Their article is a much better advocation
for removing references in high level languages.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;references-are-like-jumps&#x2F;&quot;&gt;References considered harmful&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Either way,
I think all new languages should adopt this.
If your concern is intermediate variables,
those can also be optimised the same way I suggested,
although the nicer way is piping or method chaining,
with piping as the other feature new languages should adopt.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; Intermediate variables
let metadata = parse_metadata(post)
let authors = get_authors(metadata)
let me = find_author(authors, my_name)

&#x2F;&#x2F; No intermediate variables
let me = post
	.parse_metadata()
	.get_authors()
	.find_author(&amp;quot;Pranab&amp;quot;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So pass-by-value functions enforce
nice piping interfaces
for function composition.&lt;&#x2F;p&gt;
&lt;p&gt;In fact, I was thinking about references because
I was wondering how to make nice functions for piping.
The key to a good piping or method chaining interface
is returning values instead of mutating references.
If either of the above functions mutated their arguments,
then the next function in the chain would get nothing,
and I’d have to do &lt;code&gt;x.bar()&lt;&#x2F;code&gt; on a new line.
The best way to ensure functions return values
is to remove references completely.
And that brings us the happy accident of creating
only one obvious way to mutate.&lt;&#x2F;p&gt;
&lt;p&gt;One benefit of piping over chaining,
is that chaining requires methods,
which requires objects,
which requires mutation,
thus enabling empty return values.
Piping only needs functions,
without any mutation of &lt;code&gt;self&lt;&#x2F;code&gt;.
Simple pass-by-value functions.
And it can be used with any function
that has the right argument type.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let parse_metadata(post: Post) -&amp;gt; Metadata { ... }
let get_authors(metadata: Metadata) -&amp;gt; List(Author) { ... }
let find_author(authors: List(Author), name: String) -&amp;gt; Author { ... }
let me = post
	|&amp;gt; parse_metadata()
	|&amp;gt; get_authors()
	|&amp;gt; find_author(&amp;quot;Pranab&amp;quot;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By the way,
the question about pipe interfaces,
and the answer of removing references,
was actually inspired by Gleam.
It’s such a neat language.
You could learn its features in a day
and the programming style in a week.
If it had native cross-compilation,
I’d never look at Go or Rust.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gleam.run&quot;&gt;Gleam&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>KDL solves</title>
            <published>2025-04-14T00:32:51+00:00</published>
            <updated>2025-04-14T00:32:51+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/kdl-solves/"/>
            <id>https://pranabekka.neocities.org/kdl-solves/</id>
            <summary type="html">
              KDL versus issues with TOML, YAML, and JSON.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/kdl-solves/">
              &lt;p&gt;KDL versus issues with TOML, YAML, and JSON.&lt;&#x2F;p&gt;
&lt;p&gt;For some reason, people don’t seem to know of KDL,
or think of it,
when issues with other related languages pop up.
It’s much newer, but I think it’s pretty great.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kdl.dev&quot;&gt;KDL website&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;img alt=&quot;Unofficial dark KDL logo&quot; data-image-type=&quot;logo&quot; src=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;kdl-logo-dark.svg&quot;&gt;
&lt;h2 id=&quot;brief-intro&quot;&gt;Brief intro&lt;a class=&quot;zola-anchor&quot; href=&quot;#brief-intro&quot; aria-label=&quot;Anchor link for: brief-intro&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;KDL is node-based.
Newlines and semicolons end nodes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;node1
node2; node3
node4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first item is the name of the node,
and the rest are children.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;a-node child1 child2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nodes can have properties mixed in with children.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;node child1 prop1=something child2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Child nodes can be nested using curly braces.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;node a-child {
	nested-child
	nested-child
	nested-child
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Alright, let’s get into it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comments&quot;&gt;Comments&lt;a class=&quot;zola-anchor&quot; href=&quot;#comments&quot; aria-label=&quot;Anchor link for: comments&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For starters, there’s comments.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{ &amp;quot;json&amp;quot;: &amp;quot;conspicuously missing comments&amp;quot; }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; bask in glory, believers
kdl has comments

&#x2F;*
multiline comments
*&#x2F;
kdl has &#x2F;*no*&#x2F; multi-line comments
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In fact, KDL also includes
syntax for commenting out a single node.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; `&#x2F;-` will only comment out `no`
kdl has &#x2F;-no comments

servers {
	&#x2F;&#x2F; uh-oh, banned
	&#x2F;&#x2F; `&#x2F;-` will comment out `north-america { ... }`
	&#x2F;-north-america {
		provider DataCentre&amp;#39;s R Us
		ip &amp;quot;123:456:789:111&amp;quot;
		location Dallas
	}
	india {
		provider BareMetal Inc.
		ip &amp;quot;123:456:789:111&amp;quot;
		location Tiruvanantapuram
	}
	armenia {
		provider iServer
		ip &amp;quot;123:456:789:111&amp;quot;
		location Tsaghkadzor
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Neither multi-line comments, nor node comments,
are present in the others.
If you wanted to comment out one item on a line,
you’d first have to break it up into multiple lines.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# before
yaml: [6, 7, 8, 9, 10]

# after
yaml:
	- 6
	- 7
	- 8
	# - 9
	- 10
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# before
toml = [6, 7, 8, 9, 10]

# after
toml = [
	6,
	7,
	8,
	9,
	# 10,
]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; before
kdl 6 7 8 9 10

&#x2F;&#x2F; after
kdl 6 7 8 &#x2F;-9 10

&#x2F;&#x2F; after (verbose)
kdl 6 7 8 &#x2F;*9*&#x2F; 10
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;simple-nesting&quot;&gt;Simple nesting&lt;a class=&quot;zola-anchor&quot; href=&quot;#simple-nesting&quot; aria-label=&quot;Anchor link for: simple-nesting&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Nesting structured entries in TOML
means typing the same identifier every time.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# uh-oh, banned
# [servers.north-america]
# provider = &amp;quot;DataCentre&amp;#39;s R Us&amp;quot;
# ip = &amp;quot;123:456:789:111&amp;quot;
# location = &amp;quot;Dallas&amp;quot;

[servers.india]
provider = &amp;quot;BareMetal Inc.&amp;quot;
ip = &amp;quot;123:456:789:111&amp;quot;
location = &amp;quot;Tiruvanantapuram&amp;quot;

[servers.armenia]
provider = &amp;quot;iServer&amp;quot;
ip = &amp;quot;123:456:789:111&amp;quot;
location = &amp;quot;Tsaghkadzor&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We already showed this example in KDL,
which doesn’t repeat identifiers when nesting.&lt;&#x2F;p&gt;
&lt;details&gt;&lt;summary&gt;Nesting example in KDL.&lt;&#x2F;summary&gt;
  &lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;servers {
	&#x2F;&#x2F; uh-oh, banned
	&#x2F;-north-america {
		provider DataCentre&amp;#39;s R Us
		ip &amp;quot;123:456:789:111&amp;quot;
		location Dallas
	}
	india {
		provider BareMetal Inc.
		ip &amp;quot;123:456:789:111&amp;quot;
		location Tiruvanantapuram
	}
	armenia {
		provider iServer
		ip &amp;quot;123:456:789:111&amp;quot;
		location Tsaghkadzor
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;details&gt;
&lt;p&gt;A list of structured entries in TOML
will also require you to type in the identifier every time:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[users] # this bit is optional, as far as i know

[[users]]
name = &amp;quot;Alden Thorn&amp;quot;
age = 16
location = &amp;quot;Anesidora&amp;quot;

[[users]]
name = &amp;quot;Ardi Egobar&amp;quot;
age = 18
location = &amp;quot;Metropolis&amp;quot;

[[users]]
name = &amp;quot;Livara Tär Valtteri&amp;quot;
age = 30
location = &amp;quot;Coral Bay&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It’s much simpler in KDL.
Nodes don’t need unique names,
and &lt;code&gt;-&lt;&#x2F;code&gt; is a valid identifier,
used for marking list items.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;users {
- { name Alden Thorn
	age 16
	location Anesidora }
- { name Ardi Egobar
	age 55
	location Metropolis }
- { name Livara Tär Valtteri
	age 30
	location Coral Bay }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here’s a more confusing TOML example
with nested lists and dictionaries:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[products]

[[products.categories]]
name = &amp;quot;Fruits&amp;quot;
description = &amp;quot;Juicy fruits from brands like Yo Mama and more.&amp;quot;

	[[products.categories.items]]
	name = &amp;quot;Apple&amp;quot;
	price = 50

	[[products.categories.items]]
	name = &amp;quot;Banana&amp;quot;
	price = 30

[[products.categories]]
name = &amp;quot;Grain&amp;quot;
description = &amp;quot;The finest waffle-head in existence.&amp;quot;

	[[products.categories.items]]
	name = &amp;quot;Rice&amp;quot;
	quantity = 1000
	unit = &amp;quot;grams&amp;quot;
	price = 100
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;KDL involves much less typing,
and significantly simpler nesting and list rules.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;products {
	categories {
		- {
			name Fruits
			description &amp;quot;&amp;quot;&amp;quot;
				Juicy fruits from brands like Yo Mama and more.
				&amp;quot;&amp;quot;&amp;quot;
			items {
				- name=Apple price=50
				- name=Banana price=30
			}
		}
		- {
			name Grain
			description &amp;quot;&amp;quot;&amp;quot;
				The finest waffle-head in existence.
				&amp;quot;&amp;quot;&amp;quot;
			items {
				- name=Rice quantity=1000 unit=grams price=100
			}
		}
	}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;multi-line-raw-strings&quot;&gt;Multi-line raw strings&lt;a class=&quot;zola-anchor&quot; href=&quot;#multi-line-raw-strings&quot; aria-label=&quot;Anchor link for: multi-line-raw-strings&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Imagine a shell script in a build config:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{
	&amp;quot;fooBarDir&amp;quot;: &amp;quot;echo \&amp;quot;foo\&amp;quot;\necho \&amp;quot;bar\&amp;quot;\ncd C:\\path\\to\\dir&amp;quot;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All the backslashes are why YAML is so popular.
Here’s the KDL equivalent:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fooBarDir #&amp;quot;&amp;quot;&amp;quot;
	echo &amp;quot;foo&amp;quot;
	echo &amp;quot;bar&amp;quot;
	cd C:\path\to\dir
	&amp;quot;&amp;quot;&amp;quot;#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Any indentation matching the closing quotes (&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;#&lt;&#x2F;code&gt;) is removed,
and there’s no need for escapes in a raw string (indicated with &lt;code&gt;#&lt;&#x2F;code&gt;),
which makes the string much more readable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;verbosity&quot;&gt;Verbosity&lt;a class=&quot;zola-anchor&quot; href=&quot;#verbosity&quot; aria-label=&quot;Anchor link for: verbosity&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;KDL uses just a bit of significant whitespace to reduce verbosity,
so that you don’t need to type equal signs or colons for each entry.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{
	&amp;quot;lang&amp;quot;: &amp;quot;json&amp;quot;,
	&amp;quot;author&amp;quot;: &amp;quot;Douglas Crockford&amp;quot;,
	&amp;quot;year&amp;quot;: 2000
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;lang = &amp;quot;TOML&amp;quot;
author = &amp;quot;Tom Preston-Werner&amp;quot;
year = 2013
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;lang: YAML
author: Clark Evans
year: 2001
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;lang KDL
author Kat Marchán
year 2020
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;KDL is all data, no markup —
no commas, equal signs, colons, or quotes!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clearer-types&quot;&gt;Clearer types&lt;a class=&quot;zola-anchor&quot; href=&quot;#clearer-types&quot; aria-label=&quot;Anchor link for: clearer-types&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Anything starting with a number must be a number.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Anything starting with &lt;code&gt;+&lt;&#x2F;code&gt;, &lt;code&gt;-&lt;&#x2F;code&gt;, &lt;code&gt;.&lt;&#x2F;code&gt;, &lt;code&gt;-.&lt;&#x2F;code&gt;, or &lt;code&gt;+.&lt;&#x2F;code&gt;,
followed by a number must also be a number.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Anything starting with &lt;code&gt;0x&lt;&#x2F;code&gt;, &lt;code&gt;0o&lt;&#x2F;code&gt;, or &lt;code&gt;0b&lt;&#x2F;code&gt;
are literals for hexadecimal, octal, and binary, respectively.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If it starts with a &lt;code&gt;#&lt;&#x2F;code&gt;, it’s a special value,
such as raw strings, &lt;code&gt;#true&lt;&#x2F;code&gt;, &lt;code&gt;#false&lt;&#x2F;code&gt;, and &lt;code&gt;#null&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If there’s quotes, it’s a string.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Items need to be quoted
if they have one of &lt;code&gt;[]{}()\&#x2F;#&amp;quot;;=&lt;&#x2F;code&gt; or spaces,
or are one of &lt;code&gt;true&lt;&#x2F;code&gt;, &lt;code&gt;false&lt;&#x2F;code&gt;, &lt;code&gt;null&lt;&#x2F;code&gt;, &lt;code&gt;inf&lt;&#x2F;code&gt;, &lt;code&gt;-inf&lt;&#x2F;code&gt;, or &lt;code&gt;nan&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Everything else is a string.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Any value can be prefixed with a type annotation,
like &lt;code&gt;(date)&amp;quot;2025-04-11&amp;quot;&lt;&#x2F;code&gt;.
This has no special meaning in a KDL document.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can’t accidentally mix up numbers and strings in KDL,
such as when hex codes are used for colours.
Have a look at the following YAML:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;- 1810 # number
- 1910 # number
- 1a10 # string
- 1b10 # string
- 1e999 # number: &amp;#39;e&amp;#39; means &amp;#39;exponent&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;KDL will raise an error if there’s alphabets mixed in:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;- 1810 &#x2F;&#x2F; number
- 1910 &#x2F;&#x2F; number
- 1a10 &#x2F;&#x2F; error: starts with number, but contains a
- 1b10 &#x2F;&#x2F; same error as above
- 1e999 &#x2F;&#x2F; number: &amp;#39;e&amp;#39; means &amp;#39;exponent&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead, you can use strings or hexadecimal literals.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;hex-colours {
	red 0xff0000
	green 0x00ff00
	blue 0x0000ff
}

error-colours {
	red ff0000 &#x2F;&#x2F; string
	green 00ff00 &#x2F;&#x2F; error: &amp;#39;ff&amp;#39; in number
	blue 0000ff &#x2F;&#x2F; error: &amp;#39;ff&amp;#39; in number
}

string-colours {
	red &amp;quot;ff0000&amp;quot;
	green &amp;quot;00ff00&amp;quot;
	blue &amp;quot;0000ff&amp;quot;
}

typed-colours {
	red (colour)0xff0000
	green (colour)0x00ff00
	blue (colour)0x0000ff
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;try-it-out&quot;&gt;Try it out&lt;a class=&quot;zola-anchor&quot; href=&quot;#try-it-out&quot; aria-label=&quot;Anchor link for: try-it-out&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There’s a web playground where you can type KDL
and see the syntax tree for it.
Errors are clearly highlighted,
though you need a mouse to hover and see details.&lt;&#x2F;p&gt;
&lt;p&gt;There’s also implementations in several languages.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kdl.dev&#x2F;play&quot;&gt;KDL playground&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kdl.dev&#x2F;#implementations&quot;&gt;KDL implementations&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
        <entry xml:lang="en">
            <title>Game checklist</title>
            <published>2025-01-24T19:52:47+00:00</published>
            <updated>2025-01-24T19:52:47+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/game-checklist/"/>
            <id>https://pranabekka.neocities.org/game-checklist/</id>
            <summary type="html">
              Things that would make an ideal game for me.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/game-checklist/">
              &lt;p&gt;Things that would make an ideal game for me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;main&quot;&gt;Main&lt;a class=&quot;zola-anchor&quot; href=&quot;#main&quot; aria-label=&quot;Anchor link for: main&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;multiplayer&quot;&gt;Multiplayer&lt;a class=&quot;zola-anchor&quot; href=&quot;#multiplayer&quot; aria-label=&quot;Anchor link for: multiplayer&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I’ve had the most fun with multiplayer games.
Most of the singleplayer games I’ve played
have also been shared experiences.
We used to play games on the same computer,
and even now we play some games on each others computers,
and we watch each other and discuss the game.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;beginner-friendly&quot;&gt;Beginner friendly&lt;a class=&quot;zola-anchor&quot; href=&quot;#beginner-friendly&quot; aria-label=&quot;Anchor link for: beginner-friendly&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I want to play for fun with friends,
and I want to make it accessible for everyone.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;free&quot;&gt;Free&lt;a class=&quot;zola-anchor&quot; href=&quot;#free&quot; aria-label=&quot;Anchor link for: free&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I can’t expect everyone to purchase a game.
Especially when I’m generally broke myself.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;open-sauce&quot;&gt;Open sauce&lt;a class=&quot;zola-anchor&quot; href=&quot;#open-sauce&quot; aria-label=&quot;Anchor link for: open-sauce&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Sounds like a good way to build a community,
in my opinion.
Allows people to play with the internals
and make the game their own.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;additional&quot;&gt;Additional&lt;a class=&quot;zola-anchor&quot; href=&quot;#additional&quot; aria-label=&quot;Anchor link for: additional&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I also have some smaller points
that are mostly derived from the above.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;co-operative-play&quot;&gt;Co-operative play&lt;a class=&quot;zola-anchor&quot; href=&quot;#co-operative-play&quot; aria-label=&quot;Anchor link for: co-operative-play&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Beginners will not have fun
if they’re pitted against higher-skilled players.&lt;&#x2F;p&gt;
&lt;p&gt;This can also be mixed in with PvP
in the form of team-based games,
including battle-royales&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#royale&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;royale&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;See the point on LAN multiplayer, though.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;directional-movement&quot;&gt;Directional movement&lt;a class=&quot;zola-anchor&quot; href=&quot;#directional-movement&quot; aria-label=&quot;Anchor link for: directional-movement&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Directly controlling a character is more immersive.
I think it creates a link between you and the character,
and makes you a part of the world,
instead of ruling over it with clicks and drags.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;non-action-combat-games&quot;&gt;Non-action&#x2F;combat games&lt;a class=&quot;zola-anchor&quot; href=&quot;#non-action-combat-games&quot; aria-label=&quot;Anchor link for: non-action-combat-games&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;“Action”&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#action&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; games are unintuitive for some people,
and can make them immediately lose interest.&lt;&#x2F;p&gt;
&lt;p&gt;Combat games like shooters are also unappealing to some.&lt;&#x2F;p&gt;
&lt;p&gt;Alternatives include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Racing games&lt;&#x2F;li&gt;
&lt;li&gt;Card games like UNO&lt;&#x2F;li&gt;
&lt;li&gt;Board games like ludo&lt;&#x2F;li&gt;
&lt;li&gt;Puzzle games&lt;&#x2F;li&gt;
&lt;li&gt;Matching games like Candy Crush&lt;&#x2F;li&gt;
&lt;li&gt;Deck-building games like Slay the Spire&lt;&#x2F;li&gt;
&lt;li&gt;Word games like Crossword, boggle, and Wordle&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;One point in favour of “action”&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#action&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; games
is that they provide a consistent and repeatable interface
that can be used in a large variety of contexts.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;action&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;action games in the sense of
controlling a character directly
and making it take actions in the world.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;playable-lobby&quot;&gt;Playable lobby&lt;a class=&quot;zola-anchor&quot; href=&quot;#playable-lobby&quot; aria-label=&quot;Anchor link for: playable-lobby&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The waiting room should be a fully playable space.&lt;&#x2F;p&gt;
&lt;p&gt;This way people can do something other than
staring at a menu while they wait for each other.&lt;&#x2F;p&gt;
&lt;p&gt;You can also put gameplay tips and a tutorial area there
so that all players can brush up on the mechanics,
and experienced players can guide beginners through.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2d-movement&quot;&gt;2D movement&lt;a class=&quot;zola-anchor&quot; href=&quot;#2d-movement&quot; aria-label=&quot;Anchor link for: 2d-movement&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Have you ever yelled at someone to “look left”,
then “right!”, then “wait! stop! now slowly turn left!”?&lt;&#x2F;p&gt;
&lt;p&gt;Even if the graphics are 3D, as long as movement is 2D,
it means that directions will always have the same meaning.&lt;&#x2F;p&gt;
&lt;p&gt;This contributes to being beginner friendly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;top-down&quot;&gt;Top-down&lt;a class=&quot;zola-anchor&quot; href=&quot;#top-down&quot; aria-label=&quot;Anchor link for: top-down&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We navigate in the physical world and 3D games
using discrete floors.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, movement in all directions remains consistent.
In a platformer game, jump is much more complex
than simply moving in a given direction
in a top-down game.&lt;&#x2F;p&gt;
&lt;p&gt;This also contributes to being beginner friendly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lan-multiplayer&quot;&gt;LAN multiplayer&lt;a class=&quot;zola-anchor&quot; href=&quot;#lan-multiplayer&quot; aria-label=&quot;Anchor link for: lan-multiplayer&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When I play with friends,
I’m often hanging out with them,
and it’s nice to see and hear reactions in person.&lt;&#x2F;p&gt;
&lt;p&gt;Also, online multiplayer means servers,
although peer-to-peer might help reduce costs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;minigames&quot;&gt;Minigames&lt;a class=&quot;zola-anchor&quot; href=&quot;#minigames&quot; aria-label=&quot;Anchor link for: minigames&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;They’re fun!
They add some variety and extra depth to the game.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mobile-friendly&quot;&gt;Mobile friendly&lt;a class=&quot;zola-anchor&quot; href=&quot;#mobile-friendly&quot; aria-label=&quot;Anchor link for: mobile-friendly&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It’s just easier to get started,
and people carry phones everywhere.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;web-technologies&quot;&gt;Web technologies&lt;a class=&quot;zola-anchor&quot; href=&quot;#web-technologies&quot; aria-label=&quot;Anchor link for: web-technologies&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It’s the easiest way to support several devices,
and distributing iOS apps is really tough.&lt;&#x2F;p&gt;
&lt;p&gt;Could collaborate with iOS users, if they have a Mac,
and you’re working on a game that needs it,
such as something with 3D or higher graphics.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;storage-space-efficient&quot;&gt;Storage space efficient&lt;a class=&quot;zola-anchor&quot; href=&quot;#storage-space-efficient&quot; aria-label=&quot;Anchor link for: storage-space-efficient&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This is a part of making games accessible to more people,
because download sizes for games these days are huge,
which can make people reluctant to download it,
or even unable to, because of unavailable space.&lt;&#x2F;p&gt;
&lt;p&gt;This can be achieved with pixel art,
simple 2D art, or low poly 3D art.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pretty&quot;&gt;“Pretty”&lt;a class=&quot;zola-anchor&quot; href=&quot;#pretty&quot; aria-label=&quot;Anchor link for: pretty&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Aesthetics matter to people,
and they likely won’t try something if
it doesn’t at least look interesting.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;trial-round&quot;&gt;Trial round&lt;a class=&quot;zola-anchor&quot; href=&quot;#trial-round&quot; aria-label=&quot;Anchor link for: trial-round&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If making a party game or something with lots of minigames,
have a way to run a trial round to experience
a round of each minigame.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;in-game-wiki&quot;&gt;In-game wiki&lt;a class=&quot;zola-anchor&quot; href=&quot;#in-game-wiki&quot; aria-label=&quot;Anchor link for: in-game-wiki&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Information about game systems
should be available in the game.&lt;&#x2F;p&gt;
&lt;p&gt;Preferably with images and animations.
These can be made with in-game assets,
and could even be made interactable!&lt;&#x2F;p&gt;
&lt;p&gt;In a top-down 2D game,
this could even be written on the floor,
and the player could move around
or use buttons in the game-world
to change what they’re viewing.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;interactive-tutorial&quot;&gt;Interactive tutorial&lt;a class=&quot;zola-anchor&quot; href=&quot;#interactive-tutorial&quot; aria-label=&quot;Anchor link for: interactive-tutorial&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Don’t force a tutorial
where control is taken away from the player.&lt;&#x2F;p&gt;
&lt;p&gt;In a 2D game, you can achieve this
by having tutorial text and images
on the floor or wall.&lt;&#x2F;p&gt;
&lt;p&gt;You can also use “holographs”
that depict a character or player
taking a specific path,
performing some actions,
or using various controls.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;show-controls&quot;&gt;Show controls&lt;a class=&quot;zola-anchor&quot; href=&quot;#show-controls&quot; aria-label=&quot;Anchor link for: show-controls&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Show the available controls to the player.&lt;&#x2F;p&gt;
&lt;p&gt;on desktop, show the keys and mouse actions in a corner.&lt;&#x2F;p&gt;
&lt;p&gt;on mobile, make the buttons have the expected icons.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
      
      
        <entry xml:lang="en">
            <title>Alden&#x27;s levels</title>
            <published>2024-12-26T00:59:13+00:00</published>
            <updated>2025-02-16T21:41:18+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/aldens-levels/"/>
            <id>https://pranabekka.neocities.org/aldens-levels/</id>
            <summary type="html">
              We have some solid numbers to compare.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/aldens-levels/">
              &lt;p&gt;We have some solid numbers to compare.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;spoiler-severity-warning&quot;&gt;Spoiler severity warning&lt;a class=&quot;zola-anchor&quot; href=&quot;#spoiler-severity-warning&quot; aria-label=&quot;Anchor link for: spoiler-severity-warning&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There are references to information till chapter 189,
which is from 15th December 2024,
but if Alden is back on Earth for you,
I’ve taken care to only have miniscule spoilers.
If he &lt;em&gt;isn’t&lt;&#x2F;em&gt; back on earth, major spoilers ahead.&lt;&#x2F;p&gt;
&lt;p&gt;If you haven’t read the book,
you might want to read it first.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.royalroad.com&#x2F;fiction&#x2F;63759&#x2F;super-supportive&quot;&gt;Super Supportive&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can still read past this point
if you don’t care too much about spoilers.
I feel the biggest reason to read Super Supportive
is all the little details that make up
the world and the characters.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;spoilers-lie-ahead&quot;&gt;Spoilers lie ahead&lt;a class=&quot;zola-anchor&quot; href=&quot;#spoilers-lie-ahead&quot; aria-label=&quot;Anchor link for: spoilers-lie-ahead&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In 156, we learn someone got
an impressive four levels that year,
and in 189, we find out someone else
gets two to three levels a year “like a teenager”.&lt;&#x2F;p&gt;
&lt;p&gt;Before this, we knew his real (nine) levels were epic,
but we had a vague idea even his fake (four) levels were decent.
When he gets back to Earth in 64,
a woman says three levels and a star is impressive,
though she might have cared more about the star,
and in 78, someone said Alden must have hidden
and trained for a year &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#skill&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
to have three levels on his skill.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;skill&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;they should eventually learn that it was half a year.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;156 is the first concrete number we got
to compare Alden’s levelling to,
but we all got distracted by different things.&lt;&#x2F;p&gt;
&lt;p&gt;If you haven’t connected the dots yet,
this is what this post is about.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-meat&quot;&gt;The meat&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-meat&quot; aria-label=&quot;Anchor link for: the-meat&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;To the world, Alden got three levels
in &lt;em&gt;half&lt;&#x2F;em&gt; a year off Earth.&lt;&#x2F;p&gt;
&lt;p&gt;If more people knew his &lt;em&gt;actual&lt;&#x2F;em&gt; level of eight,
mystery-moon-man is going to give people meltdowns.&lt;&#x2F;p&gt;
&lt;p&gt;In 105, we learn Alden has earned two levels in two months,
which means a level a month,
which means six levels in six months,
which means twelve levels in a year. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#calc&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;calc&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Even with a high error margin,
this is closer to the minimum speed for his levelling.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I get tingles just thinking about it.&lt;&#x2F;p&gt;
&lt;p&gt;Even if that’s cut in half for his fake profile,
that means people would see six levels in a year,
though Alden’s plans from 105 suggest
he’ll only increase it by a level in a few months.
Even so, it’s just so exciting to think about
people seeing his fake profile go up six levels a year.&lt;&#x2F;p&gt;
&lt;p&gt;What will people think when they see his actual profile?&lt;&#x2F;p&gt;
&lt;p&gt;What’s Aulia Velra going to do?&lt;&#x2F;p&gt;
&lt;p&gt;Could the knights or other wizards on Anesidora
find out what’s not on his profile? What he is?&lt;&#x2F;p&gt;
&lt;p&gt;What would Gemma “the Gloom” Elber’s perspective be?&lt;&#x2F;p&gt;
&lt;p&gt;What about Morrisson I-hope-the-kid-catches-bullets Waker?&lt;&#x2F;p&gt;
&lt;p&gt;What about Torsten one-skill-is-not-enough Klein?&lt;&#x2F;p&gt;
&lt;p&gt;Even the students are going to learn of his levels.
Poor Mehdi would actually lose his mind.
They’ll all want to know his secrets.&lt;&#x2F;p&gt;
&lt;p&gt;AAAAaaahhhhh!
There’s going to be so much juicy drama!
The tingles simply don’t stop!&lt;&#x2F;p&gt;
&lt;p&gt;I can’t even imagine what the reveal of
his real profile will be like.
When will the cost of “lying” be too much for the system?
Probably quite a bit,
given that he’s basically a Knight
and Artona 1 likes him,
but he’ll eventually have to reveal it.
In 59, he says “At least a year or two”,
so probably within a year to two and a half years.&lt;&#x2F;p&gt;
&lt;p&gt;So much strangeness.
So much tingling in my bones.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;I want to time travel to more chapters &lt;strong&gt;so bad&lt;&#x2F;strong&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;edit-about-that-meat&quot;&gt;Edit: about that meat&lt;a class=&quot;zola-anchor&quot; href=&quot;#edit-about-that-meat&quot; aria-label=&quot;Anchor link for: edit-about-that-meat&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Ending low intensity after “a year or two”
doesn’t necessarily mean the path of highest intensity,
and even high intensity doesn’t mean full intensity.&lt;&#x2F;p&gt;
&lt;p&gt;There are actually possibilities
where Alden’s real profile might never be revealed.
At least it might not be revealed to the general public.&lt;&#x2F;p&gt;
&lt;p&gt;There are basically no possibilities where
the fake profile might gradually build up to the real.
Alden already has a backlog of levels,
and he gets roughly twelve every year.
To catch up to the backlog and overtake the yearly twelve,
he has to announce over twelve levels every year,
which is not a low intensity way of revealing his real power.&lt;&#x2F;p&gt;
&lt;p&gt;The only way he could gradually turn the fake profile real
is if he slowed down his skill development significantly
for several years.
I don’t think Alden could do that.
At the very least summons will make him use his power,
and his free authority will also make him progress.
And the whole Celena North High and University track
will take about eight years,
where he can’t slack off.&lt;&#x2F;p&gt;
&lt;p&gt;He also can’t hide his power forever.
When he first preserved Stu-art’h,
Stu noticed the strength of his authority,
and the Primary also analysed it at the party.
The Primary plans to analyse Alden again
when he’s thirty years old.
So that’s the longest he could hide his real power.&lt;&#x2F;p&gt;
&lt;p&gt;If Alden gains 12 levels a year,
and 4 a year is impressive,
then 3 must be the low intensity Alden wants,
which is a quarter of 12.
The Mother says Knights pay more attentions to this,
so even if most wizards won’t notice,
a Knight will notice he’s 4 times as powerful as his profile.&lt;&#x2F;p&gt;
&lt;p&gt;But even if a Knight finds out,
his profile might still be hidden for a while
because there are some unscrupulous summoners
who might arrange an “accident” for Alden,
even if he has powerful connections.&lt;&#x2F;p&gt;
&lt;p&gt;It likely won’t be hidden for too long
because summoners also have authority sense
and could accidentally notice his authority as well.
Unless Alden is blocked off from Artonan society,
it would be better to reveal his power and status.
Perhaps after a brief training period with the Knights,
and managing some politics behind the scenes,
though the Primary and Quaternary
seem to have no interest in that.&lt;&#x2F;p&gt;
&lt;p&gt;There have also been non-Artonan Knights,
which means there is some place for Alden
in terms of accomodations, services, processes,
and relations with Artonans of all kinds.&lt;&#x2F;p&gt;
&lt;p&gt;Even at that point, resource worlds like Earth
might never learn about it,
because wizards don’t even discuss Knights
with non-wizard Artonans — forget Avowed.
Only the most politically powerful Avowed
might learn a bit about Alden’s power,
and it still wouldn’t mention magic or Knight-hood.&lt;&#x2F;p&gt;
&lt;p&gt;Alden might be The Secret Knight.
(Not really, but it’s fun to imagine.)&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
      
        <entry xml:lang="en">
            <title>Notes on Soupault</title>
            <published>2024-11-20T19:41:56+00:00</published>
            <updated>2024-11-20T19:46:13+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/soupault-notes/"/>
            <id>https://pranabekka.neocities.org/soupault-notes/</id>
            <summary type="html">
              An SSG (static site generator) that understands HTML.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/soupault-notes/">
              &lt;p&gt;An SSG (static site generator) that understands HTML.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&quot;&gt;Soupault&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is what “An introduction to Soupault” was going to be.
For some reason I turned that into a full beginner’s guide.
Maybe because these notes might only make sense in context.
Anyway, if you have the terminal open
and want to start making a website,
that’s what you’re looking for.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;soupault-intro&#x2F;&quot;&gt;An introduction to Soupault&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you just want a brief introduction,
this is what you’re looking for.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;understanding-html&quot;&gt;Understand­ing HTML&lt;a class=&quot;zola-anchor&quot; href=&quot;#understanding-html&quot; aria-label=&quot;Anchor link for: understanding-html&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s what I mean when I say Soupault understands HTML:
it uses CSS selectors to extract and add information.&lt;&#x2F;p&gt;
&lt;p&gt;This means that it turns the HTML into a series of nodes
with attributes and children —
it’s not just arbitrary text being put together.&lt;&#x2F;p&gt;
&lt;p&gt;The way Soupault works is by
configuring everything in a TOML file.
This is where you specify “widgets”,
which are steps in a pipeline that work on a page.
Widgets that interact with the HTML use CSS selectors.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;widgets&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;add-author&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;widget&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;insert_html&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;p&amp;gt;by Pranab&amp;lt;&#x2F;p&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;h1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;action&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;insert_after&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a widget that adds “by Pranab”
under the title of every page in the site.
Here’s how it works:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;add-author&lt;&#x2F;code&gt; is like a comment,
to help you keep track of how your site is made.
Soupault also uses it for logging and debugging.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;widget&lt;&#x2F;code&gt; specifies the type of the widget.
&lt;code&gt;insert_html&lt;&#x2F;code&gt; is a built-in widget type,
which inserts HTML into the page.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;html&lt;&#x2F;code&gt; is the HTML you want &lt;code&gt;insert_html&lt;&#x2F;code&gt; to insert.
I’m inserting a paragraph (&lt;code&gt;&amp;lt;p&amp;gt;&lt;&#x2F;code&gt;) with the text “by Pranab”.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;selector&lt;&#x2F;code&gt; is a CSS selector for the element
where you want to insert the HTML.
I chose to add the HTML near the &lt;code&gt;h1&lt;&#x2F;code&gt; element.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;action&lt;&#x2F;code&gt; provides finer control over where
you want the HTML to be inserted.
The CSS &lt;code&gt;selector&lt;&#x2F;code&gt; can only select an element,
while the action specifies if it must be inserted
after the element, inside it, or instead of it.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;widget-function&quot;&gt;Widget = function&lt;a class=&quot;zola-anchor&quot; href=&quot;#widget-function&quot; aria-label=&quot;Anchor link for: widget-function&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;It helps to think of a widget as a function call.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;widget&lt;&#x2F;code&gt; key specifies the name of the function,
and the rest of the keys are arguments to it.&lt;&#x2F;p&gt;
&lt;p&gt;The widget title is simply a description of
what the widget does:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;widget&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-table z-toml&quot;&gt;&amp;lt;description&amp;gt;]&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;widget&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;type&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-invalid z-illegal z-toml&quot;&gt;&amp;lt;arg1&amp;gt; = &amp;quot;&amp;lt;val1&amp;gt;&amp;quot;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-invalid z-illegal z-toml&quot;&gt;&amp;lt;arg2&amp;gt; = &amp;quot;&amp;lt;val2&amp;gt;&amp;quot;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-invalid z-illegal z-toml&quot;&gt;...&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This, specifically, was the revelation
that made Soupault finally click for me,
and what prompted me to write the first “introduction”,
before it turned into a full beginner’s guide.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;html-and-markup-languages&quot;&gt;HTML and markup languages&lt;a class=&quot;zola-anchor&quot; href=&quot;#html-and-markup-languages&quot; aria-label=&quot;Anchor link for: html-and-markup-languages&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If Soupault works with HTML,
what about all the Markdown?&lt;&#x2F;p&gt;
&lt;p&gt;Well, Soupault first converts your markup to HTML.&lt;&#x2F;p&gt;
&lt;p&gt;You tell it which file extensions should be converted to HTML,
and which shell command to use for conversion.&lt;&#x2F;p&gt;
&lt;p&gt;For example, Cmark is a widely available tool
that converts Markdown to HTML.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s how you’d use it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;settings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;page_file_extensions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;md&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;preprocessors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;cmark --unsafe&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As long as you can convert it to HTML,
you can use any markup language you want.&lt;&#x2F;p&gt;
&lt;p&gt;If you really wanted,
you could author your pages in JSON,
and write a custom CLI tool to convert it to HTML.
Just tell Soupault to use your program.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;settings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;page_file_extensions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;md&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-array z-toml&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;json&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;preprocessors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;cmark --unsafe&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
	&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;my-cli&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If all this didn’t make sense,
maybe the full introduction might be for you:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;soupault-intro&#x2F;&quot;&gt;An introduction to Soupault&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
      
        <entry xml:lang="en">
            <title>Code, comments, data</title>
            <published>2024-09-21T02:03:31+00:00</published>
            <updated>2024-09-21T02:03:31+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/code-comments-data/"/>
            <id>https://pranabekka.neocities.org/code-comments-data/</id>
            <summary type="html">
              You only need these three syntax highlighting faces.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/code-comments-data/">
              &lt;p&gt;You only need these three syntax highlighting faces.&lt;&#x2F;p&gt;
&lt;p&gt;Anything more is redundant and maybe even harmful,
because most syntax is designed with
plain text as a visual medium.&lt;&#x2F;p&gt;
&lt;p&gt;For example, take the asterisk (&lt;code&gt;*&lt;&#x2F;code&gt;)
used for emphasis and bold in markdown:
it was inspired by people using it (the asterisk)
to make some text stand out more than the rest.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, the syntaxes for programming languages
use characters to form symbols and icons
to represent various concepts,
like quotes (&lt;code&gt;&amp;quot;&lt;&#x2F;code&gt;) for “quoting” text (strings),
and &lt;code&gt;|&amp;gt;&lt;&#x2F;code&gt; or &lt;code&gt;-&amp;gt;&lt;&#x2F;code&gt; as arrow symbols
that indicate piping or return values.&lt;&#x2F;p&gt;
&lt;p&gt;So syntax elements are already
visually distinct from each other.&lt;&#x2F;p&gt;
&lt;p&gt;Having a different highlight for every syntax element
makes all syntax elements blend together,
which defeats the purpose of having syntax highlighting.&lt;&#x2F;p&gt;
&lt;p&gt;However, the solution isn’t having a single style,
because comments and data (mainly strings &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#data&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;)
can include the exact same symbols without any meaning.&lt;&#x2F;p&gt;
&lt;p&gt;This makes it important to separate comments and data from code.
And so, you highlight code, comments, and data
as separate objects from each other.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;data&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Structured data like arrays and maps
already use symbols to visually mark them,
so they don’t need syntax highlighting.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

            </content>
        </entry>
        
      
      
      
      
      
      
        <entry xml:lang="en">
            <title>An introduction to Soupault</title>
            <published>2024-08-10T23:26:36+00:00</published>
            <updated>2024-11-20T19:42:33+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/soupault-intro/"/>
            <id>https://pranabekka.neocities.org/soupault-intro/</id>
            <summary type="html">
              A beginner’s guide to making a site in Soupault,
the SSG (static site generator).
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/soupault-intro/">
              &lt;p&gt;A beginner’s guide to making a site in Soupault,
the SSG (static site generator).&lt;&#x2F;p&gt;
&lt;p&gt;What makes Soupault interesting
is that it turns all your markup to HTML,
unless it’s already HTML,
then it works with that HTML as elements (not text).
For example, it uses CSS selectors to
extract metadata from the created HTML,
and even allows you to add and remove elements.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&quot;&gt;Soupault&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This guide is useful if you’re sitting at the terminal,
and intend to make a site right this moment.
Otherwise, I have a higher level overview of Soupault
that covers the core concepts:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;soupault-notes&#x2F;&quot;&gt;Notes on Soupault&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; This is written with Soupault 4.x in mind,
and specifically tested in 4.6.0.&lt;&#x2F;p&gt;
&lt;!-- TODO: test with more versions --&gt;
&lt;!--
  TODO: include checklist of completed and remaining steps
  at the beggining of each section, or end of each step.
  seems like a restructure will be required.
--&gt;
&lt;h2 id=&quot;expected-knowledge&quot;&gt;Expected knowledge&lt;a class=&quot;zola-anchor&quot; href=&quot;#expected-knowledge&quot; aria-label=&quot;Anchor link for: expected-knowledge&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;the CLI&lt;&#x2F;li&gt;
&lt;li&gt;file paths&lt;&#x2F;li&gt;
&lt;li&gt;TOML and&#x2F;or other config files&lt;&#x2F;li&gt;
&lt;li&gt;HTML&lt;&#x2F;li&gt;
&lt;li&gt;CSS selectors&lt;&#x2F;li&gt;
&lt;li&gt;jinja style templates&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;why-this-introduction&quot;&gt;Why this introduction&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-this-introduction&quot; aria-label=&quot;Anchor link for: why-this-introduction&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The official “blog quickstart” introduction is a bit front-loaded,
instead of gradually introducing concepts,
and the reference manual has a decent introduction
in the “Overview” section,
but it comes after extensive build and install instructions,
and is followed by another hefty config example.&lt;&#x2F;p&gt;
&lt;p&gt;This guide is meant to ramp up slowly,
starting with the absolute basics,
and introducing things as they’re required.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;tips-and-tricks&#x2F;quickstart&#x2F;&quot;&gt;Blog quickstart&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#overview&quot;&gt;Overview in reference manual&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;a class=&quot;zola-anchor&quot; href=&quot;#overview&quot; aria-label=&quot;Anchor link for: overview&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Soupault works by breaking down a template
into an HTML element tree,
then it goes through the &lt;code&gt;site&lt;&#x2F;code&gt; folder,
turns each page into HTML,
and if it doesn’t have an &lt;code&gt;&amp;lt;html&amp;gt;&lt;&#x2F;code&gt; element,
it inserts it into the template.
The results are then inserted into the &lt;code&gt;build&lt;&#x2F;code&gt; folder.
Things like images and CSS are copied over as is.&lt;&#x2F;p&gt;
&lt;p&gt;All of these things can be changed.&lt;&#x2F;p&gt;
&lt;p&gt;If you don’t want it to do templates,
then set &lt;code&gt;generator_mode&lt;&#x2F;code&gt; to &lt;code&gt;false&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to change which folder it searches for content,
change the &lt;code&gt;site_dir&lt;&#x2F;code&gt; option.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to change how it defines a complete page&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
change the following option:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;complete_page_selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;html&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;a page that isn’t put into the template.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;If you want to change where it outputs files,
change the &lt;code&gt;build_dir&lt;&#x2F;code&gt; option.&lt;&#x2F;p&gt;
&lt;p&gt;With that said, let’s get started!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;a class=&quot;zola-anchor&quot; href=&quot;#installation&quot; aria-label=&quot;Anchor link for: installation&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Soupault is available to download as a single executable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;install&#x2F;&quot;&gt;Soupault install&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Simply move the executable to a folder in
your &lt;code&gt;PATH&lt;&#x2F;code&gt; environment variable,
or add the folder it’s in to the &lt;code&gt;PATH&lt;&#x2F;code&gt; environment variable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; I’ve included the file structure and contents
at the bottom of the post,
so feel free to read through to understand Soupault
before you install it and play around.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;page-files&quot;&gt;Page files&lt;a class=&quot;zola-anchor&quot; href=&quot;#page-files&quot; aria-label=&quot;Anchor link for: page-files&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;First, we create the &lt;code&gt;soupault.toml&lt;&#x2F;code&gt; configuration file,
and tell it what pages to read and how.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;settings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; &amp;quot;Page files&amp;quot; are recognised by the extension &amp;quot;md&amp;quot;.&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;page_file_extensions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;md&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  
&lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; &amp;quot;Page files&amp;quot; need to be processed into HTML before everything else,&lt;&#x2F;span&gt;
&lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; because Soupault works with HTML.&lt;&#x2F;span&gt;
&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;preprocessors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Markdown is converted to HTML with the `cmark` CLI.&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Remember to install cmark,&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; or use a different markdown CLI.&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;cmark&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;See how Soupault doesn’t depend on Markdown,
or even a specific implementation of Markdown?
As long as you can convert it to HTML,
Soupault can work with it.
You could easily use your preferred Markdown format,
or an entirely different markup format like Djot instead.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.github.io&#x2F;djot-1&#x2F;&quot;&gt;Introduction to Djot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;djot.net&quot;&gt;Djot home page&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-a-template-file&quot;&gt;Create a template file&lt;a class=&quot;zola-anchor&quot; href=&quot;#create-a-template-file&quot; aria-label=&quot;Anchor link for: create-a-template-file&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since “page files” don’t generate complete HTML documents,
we must insert it into a full HTML document.&lt;&#x2F;p&gt;
&lt;p&gt;The default template file is &lt;code&gt;templates&#x2F;main.html&lt;&#x2F;code&gt;,
so that’s where we’ll insert the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; class=&quot;language-html z-code&quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;&lt;span class=&quot;z-meta z-tag z-sgml z-doctype z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-doctype z-html&quot;&gt;DOCTYPE&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-doctype z-html&quot;&gt;html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Generated with Soupault&lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-comment z-block z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-html&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt; content will go here &lt;span class=&quot;z-punctuation z-definition z-comment z-end z-html&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By default, content is added at the end of the &lt;code&gt;body&lt;&#x2F;code&gt; element,
though you can change it with the following options:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;default_content_selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;body&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;default_content_action&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;append_child&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#page-templates&quot;&gt;Page template options&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;your-first-page&quot;&gt;Your first page&lt;a class=&quot;zola-anchor&quot; href=&quot;#your-first-page&quot; aria-label=&quot;Anchor link for: your-first-page&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For Soupault to actually generate a page,
you’ll need to write something.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s create an &lt;code&gt;index.md&lt;&#x2F;code&gt; file in the &lt;code&gt;site&lt;&#x2F;code&gt; folder &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Remember, Soupault reads files from &lt;code&gt;site&lt;&#x2F;code&gt;,
and we’ve asked it to treat &lt;code&gt;md&lt;&#x2F;code&gt; files as pages.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;markdown&quot; class=&quot;language-markdown z-code&quot;&gt;&lt;code class=&quot;language-markdown&quot; data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-block-level z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-heading z-begin z-markdown&quot;&gt;#&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-entity z-name z-section z-markdown&quot;&gt;Index&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-whitespace z-newline z-markdown&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-paragraph z-markdown&quot;&gt;Welcome to the index.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can start generating a site with Soupault.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;generate&quot;&gt;Generate&lt;a class=&quot;zola-anchor&quot; href=&quot;#generate&quot; aria-label=&quot;Anchor link for: generate&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To generate the site, just run &lt;code&gt;soupault&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It will automatically create a build folder,
if there isn’t one already,
and inside it there should be an index.html file.&lt;&#x2F;p&gt;
&lt;p&gt;If you have any issues, run Soupault with
the &lt;code&gt;--debug&lt;&#x2F;code&gt; and&#x2F;or &lt;code&gt;--verbose&lt;&#x2F;code&gt; flags.
I’d recommend you run it like that at least once,
even if you don’t have any issues,
so that you can see what Soupault does.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;preview&quot;&gt;Preview&lt;a class=&quot;zola-anchor&quot; href=&quot;#preview&quot; aria-label=&quot;Anchor link for: preview&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;soupault-intro-preview-no-index.svg&quot; alt=&quot;Home page with heading and welcome paragraph&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To serve your pages for preview, 
you can use a simple web server,
but if you have Python installed,
just use the http.server module.&lt;&#x2F;p&gt;
&lt;details&gt;&lt;summary&gt;Web servers&lt;&#x2F;summary&gt;
  &lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;svenstaro&#x2F;miniserve&quot;&gt;miniserve&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&quot;&gt;Caddy&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;details&gt;
&lt;p&gt;Python http server:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;python3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;m&lt;&#x2F;span&gt; http.server&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;directory&lt;&#x2F;span&gt; build&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running the command will give you an address
which you can open in your browser.&lt;&#x2F;p&gt;
&lt;p&gt;To automatically rebuild the site, use watch:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;watch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;interval&lt;&#x2F;span&gt; 1 &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;soupault&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you’re using Windows instead, just use an infinite loop:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-while z-shell&quot;&gt;while&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-compound z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-compound z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;soupault; sleep 1&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will run &lt;code&gt;soupault&lt;&#x2F;code&gt; every second,
and you only need to reload the page to see your changes.&lt;&#x2F;p&gt;
&lt;p&gt;And that’s it!
You have a basic site up and running!
But Soupault has more powerful features
to help you create the site you really want.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;creating-an-index&quot;&gt;Creating an index&lt;a class=&quot;zola-anchor&quot; href=&quot;#creating-an-index&quot; aria-label=&quot;Anchor link for: creating-an-index&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Soupault doesn’t have any default content model.
It doesn’t require pages to have any specific metadata.
Instead, you tell it what metadata to extract from where,
and what to do with it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;extract-metadata&quot;&gt;Extract metadata&lt;a class=&quot;zola-anchor&quot; href=&quot;#extract-metadata&quot; aria-label=&quot;Anchor link for: extract-metadata&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Because we want the title to show up in the index,
and we want to sort the posts by date,
we’ll define those as the metadata fields.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;h1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  
&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;div#post-date&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;fallback_to_content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-toml&quot;&gt;true&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; get the date from the contents, not attribute&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note how we’re using the “h1” selector for the title.
This is because &lt;code&gt;cmark&lt;&#x2F;code&gt; turns &lt;code&gt;# Index&lt;&#x2F;code&gt; into an &lt;code&gt;h1&lt;&#x2F;code&gt;,
and Soupault runs the &lt;code&gt;preprocessors&lt;&#x2F;code&gt;
before it starts working with the page.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;add-a-page-to-index&quot;&gt;Add a page to index&lt;a class=&quot;zola-anchor&quot; href=&quot;#add-a-page-to-index&quot; aria-label=&quot;Anchor link for: add-a-page-to-index&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Right now, there’s nothing for the index to list,
so let’s create another page (in &lt;code&gt;site&#x2F;&lt;&#x2F;code&gt;).
Maybe &lt;code&gt;hello.md&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And since we’ve specified the date metadata field
as the contents of the &lt;code&gt;div&lt;&#x2F;code&gt; with the &lt;code&gt;post-date&lt;&#x2F;code&gt; id,
we’ll also add that in.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;markdown&quot; class=&quot;language-markdown z-code&quot;&gt;&lt;code class=&quot;language-markdown&quot; data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-block-level z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-heading z-begin z-markdown&quot;&gt;#&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-entity z-name z-section z-markdown&quot;&gt;Hello, world&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-whitespace z-newline z-markdown&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-disable-markdown&quot;&gt;&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;div&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-id z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-id z-html&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-meta z-toc-list z-id z-html&quot;&gt;post-date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  2077-07-07
&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-paragraph z-markdown&quot;&gt;This is a page. Wow.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;allow-html&quot;&gt;Allow HTML&lt;a class=&quot;zola-anchor&quot; href=&quot;#allow-html&quot; aria-label=&quot;Anchor link for: allow-html&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;By default, &lt;code&gt;cmark&lt;&#x2F;code&gt; replaces raw HTML with a comment.
To allow HTML, we need to use the &lt;code&gt;--unsafe&lt;&#x2F;code&gt; option,
which means changing the ‘preprocessor’ for markdown:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;preprocessors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;cmark --unsafe&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;generate-an-index&quot;&gt;Generate an index&lt;a class=&quot;zola-anchor&quot; href=&quot;#generate-an-index&quot; aria-label=&quot;Anchor link for: generate-an-index&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we have the metadata, 
and a page to index,
let’s generate the index.&lt;&#x2F;p&gt;
&lt;!-- TODO?: mix in the views section and put most config there? --&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-toml&quot;&gt;true&lt;&#x2F;span&gt;
  
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; We specified date as one of the index fields&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; in [index.fields.date]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;sort_by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;date&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Treat values as dates&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;sort_type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;calendar&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Use the YYYY-MM-DD format for dates&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;date_formats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%F&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Ensure all dates are valid&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;strict_sort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-toml&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is only the index data though.
We need a place to put this before we turn it into HTML.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;make-space-for-index-html&quot;&gt;Make space for index HTML&lt;a class=&quot;zola-anchor&quot; href=&quot;#make-space-for-index-html&quot; aria-label=&quot;Anchor link for: make-space-for-index-html&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Soupault will need to know where to put the index.
We’ll just add a &lt;code&gt;div&lt;&#x2F;code&gt; with the &lt;code&gt;index&lt;&#x2F;code&gt; id
to the index.md file.
It should look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;markdown&quot; class=&quot;language-markdown z-code&quot;&gt;&lt;code class=&quot;language-markdown&quot; data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-block-level z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-heading z-begin z-markdown&quot;&gt;#&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-entity z-name z-section z-markdown&quot;&gt;Index&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-whitespace z-newline z-markdown&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-paragraph z-markdown&quot;&gt;Welcome to the index.

&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-disable-markdown&quot;&gt;&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;div&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-id z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-id z-html&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-meta z-toc-list z-id z-html&quot;&gt;main-index&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We’ll tell Soupault to put the index in &lt;code&gt;div#main-index&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;insert-index-html&quot;&gt;Insert index HTML&lt;a class=&quot;zola-anchor&quot; href=&quot;#insert-index-html&quot; aria-label=&quot;Anchor link for: insert-index-html&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we have the index data,
and a place to put the index,
we can render it into html.&lt;&#x2F;p&gt;
&lt;p&gt;Before we do that, we must understand views.&lt;&#x2F;p&gt;
&lt;p&gt;Since you might want to have different ways to index data,
such as grouping posts by author or tag,
Soupault lets you define “views”.
Views have an “index_selector” property,
which will put the index HTML
into the element which matches that selector.
This allows you to have multiple index views in the same page.
Yes, we’ve already sorted it by date,
but you can put those options independently for each view,
or use different index rendering options.&lt;&#x2F;p&gt;
&lt;details&gt;&lt;summary&gt;Index views and options links&lt;&#x2F;summary&gt;
  &lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#index-views&quot;&gt;Index views&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#index-view-options&quot;&gt;Index view options&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#ways-to-control-index-rendering&quot;&gt;Index rendering options&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;details&gt;
&lt;p&gt;In our &lt;code&gt;index.md&lt;&#x2F;code&gt; file,
we’re using a div with the id &lt;code&gt;main-index&lt;&#x2F;code&gt;,
so we want an index view that applies to &lt;code&gt;div#main-index&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;views&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Use the main view for divs with the &amp;quot;main-index&amp;quot; id&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;index_selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;div#main-index&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; The html to generate for each item&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;index_item_template&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-triple z-basic z-block z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;
    &amp;lt;h2&amp;gt;
      &amp;lt;a href=&amp;quot;{{url}}&amp;quot;&amp;gt;
        {{title}}
      &amp;lt;&#x2F;a&amp;gt;
    &amp;lt;&#x2F;h2&amp;gt;
    &amp;lt;p&amp;gt;Date: {{date}}&amp;lt;&#x2F;p&amp;gt;
  &lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;{{url}}&lt;&#x2F;code&gt;, &lt;code&gt;{{title}}&lt;&#x2F;code&gt;, and &lt;code&gt;{{date}}&lt;&#x2F;code&gt; tell Soupault
to replace them with the related metadata fields.
The title and date are fields that we defined in &lt;code&gt;[index.fields]&lt;&#x2F;code&gt;,
and the url is a built-in field
that is automatically collected by Soupault.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#built-in-index-fields&quot;&gt;Built-in index fields&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now you can reload the page in the browser
and see your index appear!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;soupault-intro-preview-with-index.svg&quot; alt=&quot;Home page with index&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;widgets&quot;&gt;Widgets!&lt;a class=&quot;zola-anchor&quot; href=&quot;#widgets&quot; aria-label=&quot;Anchor link for: widgets&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Soupault’s power feature is the ability to manipulate HTML.&lt;&#x2F;p&gt;
&lt;p&gt;For this, it uses an extensive set of “widgets”,
though it provides a Lua scripting interface as well,
where you can create your own widgets.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#widgets&quot;&gt;Widgets&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#built-in-widgets&quot;&gt;Built-in widgets&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#plugins&quot;&gt;Lua plugins&#x2F;widgets&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As an example, we’ll use an &lt;code&gt;insert_html&lt;&#x2F;code&gt; widget
to add in the author name:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; add-author is a name *we* choose&lt;&#x2F;span&gt;
&lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; to help keep track of our widgets&lt;&#x2F;span&gt;
&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;widgets&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;add-author&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;

  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Widget type&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;widget&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;insert_html&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Replace &amp;quot;Pranab&amp;quot; with your name&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;p&amp;gt;by Pranab&amp;lt;&#x2F;p&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  
  &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Insert the HTML after the title&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;h1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;action&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;insert_after&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will insert a paragraph with the text “by Pranab” after the h1.
Remember to change “Pranab” to your name.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;soupault-intro-preview-by-pranab.svg&quot; alt=&quot;Home page with “by Pranab” text&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can use this same widget to insert a link to the home page,
as well as a link to some CSS.&lt;&#x2F;p&gt;
&lt;p&gt;Have a look at the built-in widgets as well as the Lua plugins for more.
Plugins are as simple as putting a Lua file
in the (configurable) plugins folder,
and then adding them like a widget to your &lt;code&gt;soupault.toml&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#built-in-widgets&quot;&gt;Built-in widgets&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;#plugins&quot;&gt;Lua plugins reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;plugins&#x2F;&quot;&gt;Available plugins&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-setup&quot;&gt;Final setup&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-setup&quot; aria-label=&quot;Anchor link for: final-setup&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is a summary of what you should end up with.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;folder-structure&quot;&gt;Folder structure&lt;a class=&quot;zola-anchor&quot; href=&quot;#folder-structure&quot; aria-label=&quot;Anchor link for: folder-structure&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;soupault-blog&#x2F;
  soupault.toml
  site&#x2F;
    index.md
    hello.md
  templates&#x2F;
    main.html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;soupault-toml&quot;&gt;&lt;code&gt;soupault.toml&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#soupault-toml&quot; aria-label=&quot;Anchor link for: soupault-toml&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;settings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;page_file_extensions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;md&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;preprocessors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;cmark --unsafe&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-toml&quot;&gt;true&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;sort_by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;date&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;sort_type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;calendar&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;date_formats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%F&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;strict_sort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-toml&quot;&gt;true&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;h1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  
&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;div#post-date&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;fallback_to_content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-toml&quot;&gt;true&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;index&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;views&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;index_selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;div#main-index&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;index_item_template&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-triple z-basic z-block z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;
    &amp;lt;h2&amp;gt;
      &amp;lt;a href=&amp;quot;{{url}}&amp;quot;&amp;gt;
        {{title}}
      &amp;lt;&#x2F;a&amp;gt;
    &amp;lt;&#x2F;h2&amp;gt;
    &amp;lt;p&amp;gt;Date: {{date}}&amp;lt;&#x2F;p&amp;gt;
  &lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;widgets&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;add-author&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;widget&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;insert_html&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;p&amp;gt;by Pranab&amp;lt;&#x2F;p&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;h1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;action&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;insert_after&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;site-index-md&quot;&gt;&lt;code&gt;site&#x2F;index.md&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#site-index-md&quot; aria-label=&quot;Anchor link for: site-index-md&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;markdown&quot; class=&quot;language-markdown z-code&quot;&gt;&lt;code class=&quot;language-markdown&quot; data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-block-level z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-heading z-begin z-markdown&quot;&gt;#&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-entity z-name z-section z-markdown&quot;&gt;Index&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-whitespace z-newline z-markdown&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-paragraph z-markdown&quot;&gt;Welcome to the index.

&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-disable-markdown&quot;&gt;&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;div&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-id z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-id z-html&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-meta z-toc-list z-id z-html&quot;&gt;main-index&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;site-hello-md&quot;&gt;&lt;code&gt;site&#x2F;hello.md&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#site-hello-md&quot; aria-label=&quot;Anchor link for: site-hello-md&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;markdown&quot; class=&quot;language-markdown z-code&quot;&gt;&lt;code class=&quot;language-markdown&quot; data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-block-level z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-heading z-begin z-markdown&quot;&gt;#&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-entity z-name z-section z-markdown&quot;&gt;Hello, world&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-whitespace z-newline z-markdown&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-disable-markdown&quot;&gt;&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;div&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-id z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-id z-html&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-meta z-toc-list z-id z-html&quot;&gt;post-date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  2077-07-07
&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;

&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-paragraph z-markdown&quot;&gt;This is a page. Wow.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;templates-main-html&quot;&gt;&lt;code&gt;templates&#x2F;main.html&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#templates-main-html&quot; aria-label=&quot;Anchor link for: templates-main-html&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;html&quot; class=&quot;language-html z-code&quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;&lt;span class=&quot;z-meta z-tag z-sgml z-doctype z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-doctype z-html&quot;&gt;DOCTYPE&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-doctype z-html&quot;&gt;html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Generated with Soupault&lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-comment z-block z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-html&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt; content will go here &lt;span class=&quot;z-punctuation z-definition z-comment z-end z-html&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
  &lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-structure z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-structure z-any z-html&quot;&gt;html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;learn-more&quot;&gt;Learn more&lt;a class=&quot;zola-anchor&quot; href=&quot;#learn-more&quot; aria-label=&quot;Anchor link for: learn-more&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to see more options to set up your website,
have a look at the official blog quickstart,
as well as the reference manual.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;tips-and-tricks&#x2F;quickstart&quot;&gt;Blog quickstart&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&#x2F;reference-manual&#x2F;&quot;&gt;Reference manual&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
      
        <entry xml:lang="en">
            <title>Light theme toggle</title>
            <published>2024-06-24T19:23:04+00:00</published>
            <updated>2024-06-24T19:23:04+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/light-theme-toggle/"/>
            <id>https://pranabekka.neocities.org/light-theme-toggle/</id>
            <summary type="html">
              A CSS based system/light/dark mode toggle,
with Javascript for fallback and additional functionality.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/light-theme-toggle/">
              &lt;p&gt;A CSS based system&#x2F;light&#x2F;dark mode toggle,
with Javascript for fallback and additional functionality.&lt;&#x2F;p&gt;
&lt;p&gt;Big thanks to Kevin Powell for the core CSS &lt;code&gt;:has()&lt;&#x2F;code&gt; solution.
I simply added some functionality for falling back to Javascript,
and storing and loading your preferences for later.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;codepen.io&#x2F;kevinpowell&#x2F;pen&#x2F;KKEevOp&quot;&gt;Simple light&#x2F;dark example by Kevin Powell&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This implementation does four things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Adds a selector in HTML,&lt;&#x2F;li&gt;
&lt;li&gt;applies the theme using pure CSS,&lt;&#x2F;li&gt;
&lt;li&gt;falls back to applying the theme with Javascript
if the required CSS feature (&lt;code&gt;:has()&lt;&#x2F;code&gt;) isn’t supported,&lt;&#x2F;li&gt;
&lt;li&gt;and saves and loads the theme using Javascript.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;add-the-selector&quot;&gt;Add the selector&lt;a class=&quot;zola-anchor&quot; href=&quot;#add-the-selector&quot; aria-label=&quot;Anchor link for: add-the-selector&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;label&amp;gt;Colour Scheme:
  &amp;lt;select name=&amp;quot;colour-scheme-picker&amp;quot; id=&amp;quot;colour-scheme-picker&amp;quot;&amp;gt;
    &amp;lt;option value=&amp;quot;system&amp;quot;&amp;gt;System&amp;lt;&#x2F;option&amp;gt;
    &amp;lt;option value=&amp;quot;light&amp;quot;&amp;gt;Light&amp;lt;&#x2F;option&amp;gt;
    &amp;lt;option value=&amp;quot;dark&amp;quot;&amp;gt;Dark&amp;lt;&#x2F;option&amp;gt;
  &amp;lt;&#x2F;select&amp;gt;
&amp;lt;&#x2F;label&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The selected theme can be one of &lt;code&gt;system&lt;&#x2F;code&gt;, &lt;code&gt;light&lt;&#x2F;code&gt;, or &lt;code&gt;dark&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;apply-the-theme-in-pure-css&quot;&gt;Apply the theme in pure CSS&lt;a class=&quot;zola-anchor&quot; href=&quot;#apply-the-theme-in-pure-css&quot; aria-label=&quot;Anchor link for: apply-the-theme-in-pure-css&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;system&quot;&gt;System&lt;a class=&quot;zola-anchor&quot; href=&quot;#system&quot; aria-label=&quot;Anchor link for: system&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;@media (prefers-color-scheme: dark) {
  body {
    &#x2F;* dark theme settings *&#x2F;
  }
}

@media (prefers-color-scheme: light) {
  body {
    &#x2F;* light theme settings *&#x2F;
  }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If no specific theme is set,
it will listen to what the browser says.
This default will apply in all cases.&lt;&#x2F;p&gt;
&lt;p&gt;Remember to set default preferences
for when nothing specific is set or shared
by the browser.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;light-and-dark&quot;&gt;Light and dark&lt;a class=&quot;zola-anchor&quot; href=&quot;#light-and-dark&quot; aria-label=&quot;Anchor link for: light-and-dark&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;body:has(#colour-scheme-picker [value=&amp;quot;dark&amp;quot;]:checked) {
  &#x2F;* dark theme settings *&#x2F;
}

body:has(#colour-scheme-picker [value=&amp;quot;light&amp;quot;]:checked) {
  &#x2F;* light theme settings *&#x2F;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If the “Dark” or “Light” option is checked,
it applies the respective settings,
and overrides the default browser settings.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;light-and-dark-javascript-fallback&quot;&gt;Light and dark Javascript fallback&lt;a class=&quot;zola-anchor&quot; href=&quot;#light-and-dark-javascript-fallback&quot; aria-label=&quot;Anchor link for: light-and-dark-javascript-fallback&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Check if the &lt;code&gt;:has()&lt;&#x2F;code&gt; selector is supported:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;const supportsSelectorHas = CSS.supports(&amp;quot;( selector(:has(h1)) )&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Get a reference to the colour scheme picker,
and because we’ll be setting a custom property on the body,
get a reference to the body as well:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;const colourSchemePicker = document.getElementById(&amp;#39;colour-scheme-picker&amp;#39;);
const body = document.querySelector(&amp;#39;body&amp;#39;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If &lt;code&gt;supportsSelectorHas&lt;&#x2F;code&gt; is false,
we add the &lt;code&gt;data-colour-scheme&lt;&#x2F;code&gt; property to the body:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;colourSchemePicker.addEventListener(&amp;#39;change&amp;#39;, () =&amp;gt; {
  if (colourSchemePicker.value != &amp;#39;system&amp;#39;) {
    &#x2F;* save preference *&#x2F;
    if (!supportsSelectorHas) {
      body.dataset.colourScheme = colourSchemePicker.value;
    }
  } else {
    &#x2F;* save preference *&#x2F;
    if (!supportsSelectorHas) {
      delete body.dataset.colourScheme;
    }
  }
});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Normally we’d only add the event listener
if the selector isn’t supported,
but we’ll need to add it anyway to save preferences,
so the check is inside the listener.&lt;&#x2F;p&gt;
&lt;p&gt;Since the ‘system’ theme is the default,
we remove the custom property for that,
but we add it for the other cases
(either ‘light’ or ‘dark’).&lt;&#x2F;p&gt;
&lt;details&gt;&lt;summary&gt;Dataset API and data- attributes&lt;&#x2F;summary&gt;
  &lt;p&gt;The dataset API sets a &lt;code&gt;data-&lt;&#x2F;code&gt; attribute on the element,
and converts &lt;code&gt;camelCase&lt;&#x2F;code&gt; to &lt;code&gt;kebab-case&lt;&#x2F;code&gt;.
So &lt;code&gt;body.dataset.colourScheme&lt;&#x2F;code&gt; converts
&lt;code&gt;colourScheme&lt;&#x2F;code&gt; to &lt;code&gt;colour-scheme&lt;&#x2F;code&gt;,
then sets a &lt;code&gt;data-colour-scheme&lt;&#x2F;code&gt; property on the body.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;HTMLElement&#x2F;dataset&quot;&gt;Dataset property on MDN&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTML&#x2F;Global_attributes&#x2F;data-*&quot;&gt;Custom data attributes on MDN&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;details&gt;
&lt;p&gt;This will need the associated CSS selector
for &lt;code&gt;data-colour-scheme&lt;&#x2F;code&gt;,
which you can combine with the previous &lt;code&gt;:has()&lt;&#x2F;code&gt; selector:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;body:has(#colour-scheme-picker [value=&amp;quot;dark&amp;quot;]:checked),
body[data-colour-scheme=&amp;quot;dark&amp;quot;] { &#x2F;* ADDING THIS *&#x2F;
  &#x2F;* dark theme settings *&#x2F;
}

body:has(#colour-scheme-picker [value=&amp;quot;light&amp;quot;]:checked),
body[data-colour-scheme=&amp;quot;light&amp;quot;] { &#x2F;* ADDING THIS *&#x2F;
  &#x2F;* light theme settings *&#x2F;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;save-and-load-preferences&quot;&gt;Save and load preferences&lt;a class=&quot;zola-anchor&quot; href=&quot;#save-and-load-preferences&quot; aria-label=&quot;Anchor link for: save-and-load-preferences&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To save preferences:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;colourSchemePicker.addEventListener(&amp;#39;change&amp;#39;, () =&amp;gt; {
  if (colourSchemePicker.value != &amp;#39;system&amp;#39;) {

    &#x2F;* ADDING THIS *&#x2F;
    localStorage.setItem(&amp;#39;colourScheme&amp;#39;, colourSchemePicker.value);

    if (!supportsSelectorHas) {
      body.dataset.colourScheme = colourSchemePicker.value;
    }
  } else {

    &#x2F;* ADDING THIS *&#x2F;
    localStorage.removeItem(&amp;#39;colourScheme&amp;#39;);

    if (!supportsSelectorHas) {
      delete body.dataset.colourScheme;
    }
  }
});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the system theme we’re actually deleting it
because that’s the default when nothing is set.&lt;&#x2F;p&gt;
&lt;p&gt;To load the preferences,
we need to check it before the page loads,
and we need to update the selector after the page loads.&lt;&#x2F;p&gt;
&lt;p&gt;Inside your HTML &lt;code&gt;body&lt;&#x2F;code&gt; tag,
add a script tag before anything else:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;body&amp;gt;
  &amp;lt;script&amp;gt;
    if ( localStorage.getItem(&amp;#39;colourScheme&amp;#39;) != null ) {
      const docBody = document.querySelector(&amp;#39;body&amp;#39;);
      docBody.dataset.colourScheme = localStorage.getItem(&amp;#39;colourScheme&amp;#39;);
    }
  &amp;lt;&#x2F;script&amp;gt;

  &amp;lt;!-- the rest of the body --&amp;gt;
&amp;lt;&#x2F;body&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The script has to be inline, and at the beginning of the body,
to load before anything else,
otherwise you’ll see a flickering effect,
where the default theme is loaded before it updates
to the saved user selection.&lt;&#x2F;p&gt;
&lt;p&gt;In your main script, where the rest of the logic is,
check if the colour scheme was stored,
and updated the picker to reflect that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;const storedColourScheme = localStorage.getItem(&amp;#39;colourScheme&amp;#39;);

if (storedColourScheme) {
  colourSchemePicker.value = storedColourScheme;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;HTML:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;body&amp;gt;
  &amp;lt;!-- Load saved colour scheme --&amp;gt;
  &amp;lt;script&amp;gt;
    if ( localStorage.getItem(&amp;#39;colourScheme&amp;#39;) != null ) {
      const docBody = document.querySelector(&amp;#39;body&amp;#39;);
      docBody.dataset.colourScheme = localStorage.getItem(&amp;#39;colourScheme&amp;#39;);
    }
  &amp;lt;&#x2F;script&amp;gt;

  &amp;lt;!-- ... --&amp;gt;

  &amp;lt;!-- Colour scheme picker --&amp;gt;
  &amp;lt;label&amp;gt;Colour Scheme:
    &amp;lt;select name=&amp;quot;colour-scheme-picker&amp;quot; id=&amp;quot;colour-scheme-picker&amp;quot;&amp;gt;
      &amp;lt;option value=&amp;quot;system&amp;quot;&amp;gt;System&amp;lt;&#x2F;option&amp;gt;
      &amp;lt;option value=&amp;quot;light&amp;quot;&amp;gt;Light&amp;lt;&#x2F;option&amp;gt;
      &amp;lt;option value=&amp;quot;dark&amp;quot;&amp;gt;Dark&amp;lt;&#x2F;option&amp;gt;
    &amp;lt;&#x2F;select&amp;gt;
  &amp;lt;&#x2F;label&amp;gt;
  
  &amp;lt;!-- ... --&amp;gt;

&amp;lt;&#x2F;body&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;CSS:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;* {{{ Default browser preferences *&#x2F;
  @media (prefers-color-scheme: dark) {
    body {
      &#x2F;* dark theme settings *&#x2F;
    }
  }

  @media (prefers-color-scheme: light) {
    body {
      &#x2F;* light theme settings *&#x2F;
    }
  }
&#x2F;* end Default browser preferences }}} *&#x2F;

&#x2F;* {{{ User preferences *&#x2F;
  &#x2F;* Selector for pure CSS method *&#x2F;
  body:has(#colour-scheme-picker [value=&amp;quot;dark&amp;quot;]:checked),
  &#x2F;* Selector for Javascript fallback method *&#x2F;
  body[data-colour-scheme=&amp;quot;dark&amp;quot;] {
    &#x2F;* dark theme settings *&#x2F;
  }

  &#x2F;* Selector for pure CSS method *&#x2F;
  body:has(#colour-scheme-picker [value=&amp;quot;light&amp;quot;]:checked),
  &#x2F;* Selector for Javascript fallback method *&#x2F;
  body[data-colour-scheme=&amp;quot;light&amp;quot;] {
    &#x2F;* light theme settings *&#x2F;
  }
&#x2F;* end User preferences }}} *&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Javascript:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;const supportsSelectorHas = CSS.supports(&amp;quot;( selector(:has(h1)) )&amp;quot;);
const storedColourScheme = localStorage.getItem(&amp;#39;colourScheme&amp;#39;);

const colourSchemePicker = document.getElementById(&amp;#39;colour-scheme-picker&amp;#39;);
const body = document.querySelector(&amp;#39;body&amp;#39;);

if (storedColourScheme) {
  colourSchemePicker.value = storedColourScheme;
}

colourSchemePicker.addEventListener(&amp;#39;change&amp;#39;, () =&amp;gt; {
  if (colourSchemePicker.value != &amp;#39;system&amp;#39;) {
    &#x2F;* &amp;#39;light&amp;#39; or &amp;#39;dark&amp;#39; theme *&#x2F;
    localStorage.setItem(&amp;#39;colourScheme&amp;#39;, colourSchemePicker.value);
    if (!supportsSelectorHas) {
      body.dataset.colourScheme = colourSchemePicker.value;
    }
  } else {
    &#x2F;* &amp;#39;system&amp;#39; (default) theme *&#x2F;
    localStorage.removeItem(&amp;#39;colourScheme&amp;#39;);
    if (!supportsSelectorHas) {
      delete body.dataset.colourScheme;
    }
  }
});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Log</title>
            <published>2024-06-24T15:52:46+00:00</published>
            <updated>2025-10-10T20:12:25+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/log/"/>
            <id>https://pranabekka.neocities.org/log/</id>
            <summary type="html">
              Where I add short thoughts, TODO items, links, etc.,
that shouldn’t be a separate page.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/log/">
              &lt;p&gt;Where I add short thoughts, TODO items, links, etc.,
that shouldn’t be a separate page.&lt;&#x2F;p&gt;
&lt;p&gt;I intend to keep adding entries under sub-headings by date,
without deleting old entries.&lt;&#x2F;p&gt;
&lt;p&gt;Somewhat similar to “now” pages
or Sara Joy’s “Weak Notes”.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nownownow.com&#x2F;about&quot;&gt;“Now” pages&lt;&#x2F;a&gt;
(warning: bright white page)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sarajoy.dev&#x2F;basic&#x2F;notes&quot;&gt;“Weak Notes” by Sara Joy&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2025-12-19-the-eye&quot;&gt;2025-12-19 The eye&lt;a class=&quot;zola-anchor&quot; href=&quot;#2025-12-19-the-eye&quot; aria-label=&quot;Anchor link for: 2025-12-19-the-eye&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve always been a bit “edgy”,
though it waxes and wanes,
and I don’t express it all that much.
It feels silly sometimes,
but I also enjoy it.
So.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2025-10-09-a-little-funny-a-little-sigh&quot;&gt;2025-10-09 A little funny, a little sigh&lt;a class=&quot;zola-anchor&quot; href=&quot;#2025-10-09-a-little-funny-a-little-sigh&quot; aria-label=&quot;Anchor link for: 2025-10-09-a-little-funny-a-little-sigh&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Functional programming languages essentially
allow pass around references nearly everywhere,
and you can mutate pretty much anything,
unless you hide it in a module.&lt;&#x2F;p&gt;
&lt;p&gt;That’s the funny.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;You don’t need an accumulator for tail-call optimisation
if the function calls itself only once.&lt;&#x2F;p&gt;
&lt;p&gt;So that’s the other kind of loop
that’s tail-call optimised,
while constructing a value,
without requiring an accumulator.&lt;&#x2F;p&gt;
&lt;p&gt;We could still just teach a simple function like that
followed by something with an accumulator.
Perhaps the difference can be stated as “combining”.
A function calling itself more than once
is for when it needs to combine results, right?
So the accumulator stores a part of the combination,
and the second part is calculated and combined
in the next repetition of the function.&lt;&#x2F;p&gt;
&lt;p&gt;I’m pretty sure that’s it though.&lt;&#x2F;p&gt;
&lt;p&gt;That’s the little sigh.
It’s a bit more complicated than I thought,
but I think we can still avoid teaching
stack frames and tail-call optimisation.
I can’t believe I completely forgot that.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;2025-10-05-accumulator-functions&quot;&gt;2025-10-05 Accumulator functions&lt;a class=&quot;zola-anchor&quot; href=&quot;#2025-10-05-accumulator-functions&quot; aria-label=&quot;Anchor link for: 2025-10-05-accumulator-functions&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I think we can teach functional programming
without teaching tail-call optimisation.&lt;&#x2F;p&gt;
&lt;p&gt;Functions that return nothing are optimised,
because there’s nothing to be done with the return value.&lt;&#x2F;p&gt;
&lt;p&gt;Functions that need to return something
use an accumulator for tail-call optimisation.&lt;&#x2F;p&gt;
&lt;p&gt;Accumulators encourage function designs
that are tail-call optimised,
the same way functional languages
encourage program designs that are
optimised for modularity and composability.&lt;&#x2F;p&gt;
&lt;p&gt;So we can teach accumulation instead
and keep tail-call optimisation as an advanced topic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2025-10-04-not-corrections&quot;&gt;2025-10-04 Not corrections&lt;a class=&quot;zola-anchor&quot; href=&quot;#2025-10-04-not-corrections&quot; aria-label=&quot;Anchor link for: 2025-10-04-not-corrections&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Huh, I thought I’d put up some nonsense about the NoSQL stuff.
I didn’t. There’s nothing strictly wrong there.&lt;&#x2F;p&gt;
&lt;p&gt;The only thing to add is that the general requirements
might be immediately fulfilled by
an embedded document database (engine?).
Maybe an embedded &lt;em&gt;graph&lt;&#x2F;em&gt; database?&lt;&#x2F;p&gt;
&lt;p&gt;The other option, going the plain text route,
is to pick a “configuration and policy” language,
like CUE, KCL, Nickel, Dhall, etc.&lt;&#x2F;p&gt;
&lt;p&gt;I also realised that application code
ideally checks the data before storing it,
so it could use the same checks to import it,
instead of reimplementing types in the database.
So it makes some sense for SQLite to be “untyped”.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I can’t comment on a specific pick.
I’ll get around to it when I actually need it —
spend an innovation token.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2025-10-03&quot;&gt;2025-10-03&lt;a class=&quot;zola-anchor&quot; href=&quot;#2025-10-03&quot; aria-label=&quot;Anchor link for: 2025-10-03&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Oh, hello there.&lt;&#x2F;p&gt;
&lt;p&gt;I keep thinking of this page,
but I never get around to it.
Part of it is because I only edit this at my laptop,
and this is mostly a place for short or idle thoughts
which don’t seem worth the effort.&lt;&#x2F;p&gt;
&lt;p&gt;I’m also working on a few big things,
trying to get them just right,
but in the meantime:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Objects are a bad patch over poor type systems.&lt;&#x2F;p&gt;
&lt;p&gt;Encapsulation is done by modules.
So they might be patching poor module systems as well.&lt;&#x2F;p&gt;
&lt;p&gt;Multiple inheritance is reviled.&lt;&#x2F;p&gt;
&lt;p&gt;Inheritance trees are just variants.&lt;&#x2F;p&gt;
&lt;p&gt;Types associate functions with data.
And as I said, modules to separate them.&lt;&#x2F;p&gt;
&lt;p&gt;Types are just one additional concept,
while objects mean classes, methods,
private fields, private methods, inherited methods,
and more.&lt;&#x2F;p&gt;
&lt;p&gt;What do you think?&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Something mildly inappropriate&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;We don’t need SQL for most projects.
Especially if we’re using ORMs,
but also if our project is something small.
I just don’t know of a good NoSQL database.
Something like SQLite meets MongoDB.
Maybe a binary format,
I don’t mind a text format like KDL.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, CUE is a really interesting option!
It’s like JSON with less typing, adding rules,
generating repeated parts, and more.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kdl.dev&quot;&gt;KDL&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cuetorials.com&#x2F;introduction&#x2F;&quot;&gt;CUE introduction&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I was thinking of having individual log posts,
with a page aggregating them all like this.&lt;&#x2F;p&gt;
&lt;p&gt;I wouldn’t be editing the same post again and again,
possibly forgetting to update the data.&lt;&#x2F;p&gt;
&lt;p&gt;New updates would show up on the home page,
labelled something like “Log 2025-10-03”
to indicate the kind of post it is.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Enjoy my braindump :)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2024-09-21&quot;&gt;2024-09-21&lt;a class=&quot;zola-anchor&quot; href=&quot;#2024-09-21&quot; aria-label=&quot;Anchor link for: 2024-09-21&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Beware the NodeList (and use the console&#x2F;repl often)&lt;&#x2F;p&gt;
&lt;p&gt;Had an issue where I got a list from &lt;code&gt;getElementsByClassName&lt;&#x2F;code&gt;
to copy their contents and delete them from the DOM.
For some reason, it would only delete every other node,
and leave half the nodes untouched.
Turns out it was because a NodeList can update live
to reflect the current contents of the DOM.
Still note sure why it was every other.&lt;&#x2F;p&gt;
&lt;p&gt;It’s not an array, see the &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;NodeList&quot;&gt;MDN docs on NodeList&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I should really get Soupault set up.
(Which means turning my SASS to CSS.)&lt;&#x2F;p&gt;
&lt;p&gt;Had to use JS to do extra stuff
that Zola should’ve let me do at build time.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;2024-08-09&quot;&gt;2024-08-09&lt;a class=&quot;zola-anchor&quot; href=&quot;#2024-08-09&quot; aria-label=&quot;Anchor link for: 2024-08-09&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;i made some character concept art!
it’s cute, simple, and easy to pose&#x2F;animate.
&lt;img src=&quot;&#x2F;concept-art-character-sheep-cat.jpg&quot; alt=&quot;Sheep and cat 2d art&quot; &#x2F;&gt;&lt;&#x2F;li&gt;
&lt;li&gt;how did people let apple get away
with the notch, then the cutout?
it makes the screen shape awkward,
and adds very little extra space.&lt;&#x2F;li&gt;
&lt;li&gt;when treating s-expressions as nodes,
the top-level is a special node with variable args,
and the main nodes in your program feed into it.&lt;&#x2F;li&gt;
&lt;li&gt;also two more draft posts in the works:
good game checklist, and spaceship security!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;2024-08-05-shower-thoughts&quot;&gt;2024-08-05 Shower thoughts&lt;a class=&quot;zola-anchor&quot; href=&quot;#2024-08-05-shower-thoughts&quot; aria-label=&quot;Anchor link for: 2024-08-05-shower-thoughts&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;this might be my shower thoughts place&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;you could use hair ties or wrist bands to mark glasses&lt;&#x2F;li&gt;
&lt;li&gt;s-expression lists are also blocks,
in the mit scratch sort of way&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;2024-08-05-new-log-entry&quot;&gt;2024-08-05 New log entry!&lt;a class=&quot;zola-anchor&quot; href=&quot;#2024-08-05-new-log-entry&quot; aria-label=&quot;Anchor link for: 2024-08-05-new-log-entry&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;had this thought for a while now:&lt;&#x2F;p&gt;
&lt;p&gt;s-expressions are perfect for visual programming.&lt;&#x2F;p&gt;
&lt;p&gt;take &lt;code&gt;(o o o)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;()&lt;&#x2F;code&gt; is a node.&lt;&#x2F;p&gt;
&lt;p&gt;each &lt;code&gt;o&lt;&#x2F;code&gt; is an input for that node.&lt;&#x2F;p&gt;
&lt;p&gt;think of blender shader&#x2F;geometry nodes.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;soupault intro nearly done&lt;&#x2F;p&gt;
&lt;p&gt;just some small edits, and maybe screenshots left&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;should start CSS refactor by using &lt;code&gt;--var: val&lt;&#x2F;code&gt; in SASS&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;:root
  --highlight: var(--yellow)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;almost have switch to soupault figured out.&lt;&#x2F;p&gt;
&lt;p&gt;should write a doc about it.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;2024-06-24-theming-todos&quot;&gt;2024-06-24 Theming TODOs&lt;a class=&quot;zola-anchor&quot; href=&quot;#2024-06-24-theming-todos&quot; aria-label=&quot;Anchor link for: 2024-06-24-theming-todos&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;this became all about theming ¯_(ツ)_&#x2F;¯&lt;&#x2F;p&gt;
&lt;p&gt;TODO:&lt;&#x2F;p&gt;
&lt;p&gt;toggle post is the easiest,
and might be helpful for future implementation,
but css from sass is also important.
the rest are for down the line.&lt;&#x2F;p&gt;
&lt;p&gt;edit: i wrote the post&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;write post on light theme toggle&lt;&#x2F;p&gt;
&lt;p&gt;see &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pranabekka&#x2F;pages&quot;&gt;https:&#x2F;&#x2F;codeberg.org&#x2F;pranabekka&#x2F;pages&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;depends on css for core functionality,
with js fallback where possible.&lt;&#x2F;p&gt;
&lt;p&gt;check the html template to see how stored theme is loaded.
refer also to a lobste.rs discussion on implementing dark mode —
toastal suggests that the script has to be in the html for that.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;s&#x2F;iefspl&#x2F;notes_on_implementing_dark_mode&quot;&gt;lobste.rs discussion on implementing dark mode&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;switch to css from sass.&lt;&#x2F;p&gt;
&lt;p&gt;css has all the features i need,
and the built output is cleaner.
i’m not using any advanced features from sass,
and knowing css better means working with it.&lt;&#x2F;p&gt;
&lt;p&gt;also a precursor to adding more themes
for light mode as well as lower and higher contrast.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;create a light theme&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;add a light theme toggle&lt;&#x2F;p&gt;
&lt;p&gt;see &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pranabekka&#x2F;pages&quot;&gt;https:&#x2F;&#x2F;codeberg.org&#x2F;pranabekka&#x2F;pages&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;check the html template to see how stored theme is loaded.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;create themes for different contrasts&lt;&#x2F;p&gt;
&lt;p&gt;increase default contrast above current minimum AAA compliance,
add lower contrast colours for &lt;code&gt;prefers-contrast: less&lt;&#x2F;code&gt;,
and higher contrast colours for &lt;code&gt;prefers-contrast: more&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;CSS&#x2F;@media&#x2F;prefers-contrast&quot;&gt;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;CSS&#x2F;@media&#x2F;prefers-contrast&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;probably have variables for
&lt;code&gt;--black-full&lt;&#x2F;code&gt;, &lt;code&gt;--black-low&lt;&#x2F;code&gt;, &lt;code&gt;--black-high&lt;&#x2F;code&gt;, etc.&lt;&#x2F;p&gt;
&lt;p&gt;also add a switch, similar to the light theme one&lt;&#x2F;p&gt;
&lt;p&gt;consider full black&#x2F;white toggle for oled screens and e-readers.
maybe call it “full-contrast”.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Clean URLs: bad!</title>
            <published>2024-06-24T15:30:08+00:00</published>
            <updated>2024-06-24T15:30:08+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/clean-urls/"/>
            <id>https://pranabekka.neocities.org/clean-urls/</id>
            <summary type="html">
              “Clean URLs” like site.com/hello/ should not be used.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/clean-urls/">
              &lt;p&gt;“Clean URLs” like &lt;code&gt;site.com&#x2F;hello&#x2F;&lt;&#x2F;code&gt; should not be used.&lt;&#x2F;p&gt;
&lt;p&gt;NOTE: This is a bit of a shower thought,
and the title is a shower thought title —
I don’t actually care all that much,
though the reasoning makes sense to me.&lt;&#x2F;p&gt;
&lt;p&gt;The reward for these is obvious:
clean URLs that are just words separated by slashes.
However, there are several (somewhat conceptual) costs.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Abuse of the index page.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;my-page&#x2F;index.html&lt;&#x2F;code&gt; is not indexing anything.
It’s simply the contents you want to display at &lt;code&gt;my-page&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;index.html&lt;&#x2F;code&gt; clutter.&lt;&#x2F;p&gt;
&lt;p&gt;The file tree is littered with &lt;code&gt;index.html&lt;&#x2F;code&gt; pages
— files that have the same name
and that are not really related.
Not to mention folders with only one item.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Obscure page names.&lt;&#x2F;p&gt;
&lt;p&gt;A page on a specific topic is called &lt;code&gt;index.html&lt;&#x2F;code&gt;
instead of &lt;code&gt;&amp;lt;topic&amp;gt;.html&lt;&#x2F;code&gt;.
It does not reflect the contents of the file.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It might make sense for dynamic server side
and&#x2F;or single page applications (with url rewriting),
but not so much for static files.&lt;&#x2F;p&gt;
&lt;p&gt;The average user will likely not notice
whether the URL ends with &lt;code&gt;.html&lt;&#x2F;code&gt; or not,
and someone who notices will likely know,
and if they don’t know,
they might learn something new.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>SSGs should be libraries</title>
            <published>2024-06-24T15:25:30+00:00</published>
            <updated>2024-08-04T03:39:44+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/ssg-libs/"/>
            <id>https://pranabekka.neocities.org/ssg-libs/</id>
            <summary type="html">
              Hugo (SSG) should’ve been a set of libraries
that the user imported and hooked up.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/ssg-libs/">
              &lt;p&gt;Hugo (SSG) should’ve been a set of libraries
that the user imported and hooked up.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gohugo.io&quot;&gt;Hugo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The basic proposal is that an SSG in Go
should provide a simple core API &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
and a set of libraries to customise and build your site,
similar to how Bevy and its ecosystem works for games.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Or two or three,
starting with a dependency graph, I think,
but I wouldn’t really know.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;go.dev&quot;&gt;Go&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&quot;&gt;Bevy&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You would import the libraries you want,
maybe implement some specific functionality,
and build your site from that.&lt;&#x2F;p&gt;
&lt;p&gt;Given that one of Go’s advantages
is a fast compile&#x2F;feedback cycle,
this approach seems viable,
and perhaps even desired.&lt;&#x2F;p&gt;
&lt;p&gt;It enables better customisation
than trying to program in a templating language,
and you can use the language that you already know.
For those unfamiliar with the language,
it could make a good introduction as well.&lt;&#x2F;p&gt;
&lt;p&gt;Soupault is an interesting reference here:
first, you define your page files and how to convert them to HTML,
then you define things to do with that HTML.
Another cool thing it does is that there’s no content model.
You have to define what metadata to extract and how,
then you decide what to do with it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&quot;&gt;Soupault&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Zine is another interesting reference point.
It’s a work-in-progress SSG
that uses the Zig build system to build your site,
and allows you to swap in components as you need,
though I haven’t looked into it too much.
It also includes structural templating
that’s a superset of HTML,
instead of the string templating you find
in non-Javascript SSGs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;zine-ssg.io&quot;&gt;Zine&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Metadata in Markdown</title>
            <published>2024-06-24T14:41:56+00:00</published>
            <updated>2024-09-20T18:01:53+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/markdown-metadata/"/>
            <id>https://pranabekka.neocities.org/markdown-metadata/</id>
            <summary type="html">
              Alternatives to putting the markdown title in TOML/YAML.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/markdown-metadata/">
              &lt;p&gt;Alternatives to putting the markdown title in TOML&#x2F;YAML.&lt;&#x2F;p&gt;
&lt;p&gt;Because frontmatter breaks Markdown syntax
and puts the title at the same importance as
other metadata like the date and thumbnail.&lt;&#x2F;p&gt;
&lt;p&gt;The title is a primary piece of data for the document,
and it is not on the same level of importance as the date.&lt;&#x2F;p&gt;
&lt;p&gt;With frontmatter, your Markdown (not metadata) document
starts with a level 2 heading and no level 1 heading,
or it has multiple level 1 headings (titles).&lt;&#x2F;p&gt;
&lt;p&gt;Instead, put the document heading at the top
using Markdown syntax,
and add metadata like the date below that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-1-metadata-tag&quot;&gt;Solution 1: metadata tag&lt;a class=&quot;zola-anchor&quot; href=&quot;#solution-1-metadata-tag&quot; aria-label=&quot;Anchor link for: solution-1-metadata-tag&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since Markdown requires extension with HTML,
and is primarily an HTML generation tool,
we could use a ‘metadata’ tag.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# My document title

&amp;lt;metadata
  date=&amp;quot;2024-06-24&amp;quot;
  update=&amp;quot;2024-06-27&amp;quot;
&#x2F;&amp;gt;

post content ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;‘metadata’ could also be shortened to ‘meta’
for the convenience of authors,
but there should ideally be a simple template
and a &lt;code&gt;new&lt;&#x2F;code&gt; command to create a skeleton
and fill in the basic information.&lt;&#x2F;p&gt;
&lt;p&gt;You can also prefix the tag with a ‘namespace’ of sorts,
to avoid potential collisions.
Hugo would call it &lt;code&gt;hugo-metadata&lt;&#x2F;code&gt;,
while Zola might call it &lt;code&gt;zola-metadata&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;my-metadata
  date=&amp;quot;2024-06-24&amp;quot;
  update=&amp;quot;2024-06-27&amp;quot;
&#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It should be easy to use HTML if the tool already uses it,
although XML&#x2F;HTML can be verbose for some people.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-2-metadata-code-block&quot;&gt;Solution 2: metadata “code” block&lt;a class=&quot;zola-anchor&quot; href=&quot;#solution-2-metadata-code-block&quot; aria-label=&quot;Anchor link for: solution-2-metadata-code-block&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Another solution is to author metadata in YAML, TOML,
or whatever format is already used,
by using a code block with the ‘metadata’ language.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;```metadata
date: 2024-06-24
update: 2024-06-27
```
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In addition to the previous ‘meta’ suggestion,
you could also include the metadata format
if multiple formats are available,
with a default format if none is included.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;```metadata&#x2F;toml
date = 2024-06-24
update = 2024-06-24
```
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Specifiers like &lt;code&gt;metadata&#x2F;toml&lt;&#x2F;code&gt; are also used in
HTTP responses as well as HTML &lt;code&gt;link&lt;&#x2F;code&gt; elements.&lt;&#x2F;p&gt;
&lt;p&gt;Most markup formats include code blocks,
and setting the language should be easy.
Plus people tend to like YAML&#x2F;TOML over XML&#x2F;HTML.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>SSG attempt 1 notes</title>
            <published>2024-06-24T13:44:00+00:00</published>
            <updated>2024-06-24T13:44:00+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/ssg-attempt-1/"/>
            <id>https://pranabekka.neocities.org/ssg-attempt-1/</id>
            <summary type="html">
              I made a little progress on creating my own SSG,
but I decided it would take too much time
and I need to work on my base skills first.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/ssg-attempt-1/">
              &lt;p&gt;I made a little progress on creating my own SSG,
but I decided it would take too much time
and I need to work on my base skills first.&lt;&#x2F;p&gt;
&lt;p&gt;One roadblock was Codeberg pages redirects not working properly,
Then I also figured that doing proper builds
would require a lot of work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;a class=&quot;zola-anchor&quot; href=&quot;#goals&quot; aria-label=&quot;Anchor link for: goals&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Before I start, this project was an attempt of two things:
using djot for authoring pages,
and using HTML (manipulation) to glue things.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;codeberg-pages-redirects&quot;&gt;Codeberg pages redirects&lt;a class=&quot;zola-anchor&quot; href=&quot;#codeberg-pages-redirects&quot; aria-label=&quot;Anchor link for: codeberg-pages-redirects&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So, I like my built files to be
in the same directory that I’m working in,
and I see no reason to not build the site on my machine,
since I’m already doing the work.&lt;&#x2F;p&gt;
&lt;p&gt;In light of that, I liked Codeberg’s &lt;code&gt;_redirects&lt;&#x2F;code&gt; file.
It lets you specify something like &lt;code&gt;&#x2F;* &#x2F;build&#x2F;:splat 200&lt;&#x2F;code&gt;,
which serves all requests at the root from the build folder,
without rewriting any URLs.&lt;&#x2F;p&gt;
&lt;p&gt;It just has a few bugs right now.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;Codeberg&#x2F;Community&#x2F;issues&#x2F;1545#issuecomment-2033496&quot;&gt;Issue report on Codeberg&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I could try using worktrees or submodules
with a simple git hook to deploy pages,
but then I’d have to deal with other issues
like managing builds correctly,
not to mention the complexity of git.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;proper-builds&quot;&gt;Proper builds&lt;a class=&quot;zola-anchor&quot; href=&quot;#proper-builds&quot; aria-label=&quot;Anchor link for: proper-builds&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There’s a lot of things to be handled here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Removing stale files&lt;&#x2F;p&gt;
&lt;p&gt;If I delete source files, I need to remove
the corresponding build files.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Depending on the build file&lt;&#x2F;p&gt;
&lt;p&gt;If your build rules change,
then you want (changed) builds to be redone.
If I’m doing a build script in the language,
then everything will need to be redone,
unless I come up with a clever way to structure builds,
or maybe work on a constructed dependency graph.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Dependency graph&lt;&#x2F;p&gt;
&lt;p&gt;A way to manage which items depend on which,
so that individual build jobs can be scheduled.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some of these ideas are from the ninja author’s
notes on ninja and a successor called n2,
which would be good resources for approaching the issue.
The design notes have a lot of useful information,
as well as the links in the project’s README file.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;neugierig.org&#x2F;software&#x2F;blog&#x2F;2022&#x2F;03&#x2F;n2.html&quot;&gt;Design notes on n2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;evmar&#x2F;n2&quot;&gt;n2 (pronounced “into”) on Github&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Using some sort of build library might also be an option,
though that’ll be another dependency to figure out,
which might require me to contort my design,
and they might encounter the pitfalls
recorded in the design notes for n2.&lt;&#x2F;p&gt;
&lt;p&gt;I could try using a simple method of rebuilding everything
and working through all the pages in the contents folder,
but it would probably cause strife,
and I still have to deal with other issues.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;other-issues&quot;&gt;Other issues&lt;a class=&quot;zola-anchor&quot; href=&quot;#other-issues&quot; aria-label=&quot;Anchor link for: other-issues&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I have to figure out the design and code for things like
backlinks, custom components, build hooks, templating, etc.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to that, I have to do a lot of reasearch
to figure out which APIs I can use and how.
I’ve already encountered many little roadblocks.&lt;&#x2F;p&gt;
&lt;p&gt;At a certain scale, I might also want to use Typescript,
but I’m still learning Javascript.&lt;&#x2F;p&gt;
&lt;p&gt;I’m also working on multiple layers of abstraction right now.
In the current project repo,
I have a bunch of custom CSS&#x2F;JS stuff
for handling a dark&#x2F;light mode toggle.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pranabekka&#x2F;pages&quot;&gt;SSG attempt 1 repo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There’s a few more issues
at the end of the design introduction:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;design-introduction&quot;&gt;Design introduction&lt;a class=&quot;zola-anchor&quot; href=&quot;#design-introduction&quot; aria-label=&quot;Anchor link for: design-introduction&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Folder structure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;build&#x2F;
content&#x2F;
  index.djot
  main.js
  main.css
  ...
extra&#x2F;
  template-default.html
_redirects
ssg.js
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;build&lt;&#x2F;code&gt; is where the built site is stored.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;content&lt;&#x2F;code&gt; and &lt;code&gt;extra&lt;&#x2F;code&gt; are the two types of input
for generating the site.
&lt;code&gt;extra&lt;&#x2F;code&gt; contains “extra” data like templates
and maybe some data files to build pages from?
&lt;code&gt;content&lt;&#x2F;code&gt; contains files that will be copied over
with minimal changes, that form the content of the site.
Maybe &lt;code&gt;main.js&lt;&#x2F;code&gt; and &lt;code&gt;main.css&lt;&#x2F;code&gt; shouldn’t be in there —
I probably put them there because I had logic
for copying anything that wasn’t djot files.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;_redirects&lt;&#x2F;code&gt; is something specific to Codeberg pages,
which allows you to specify redirects for your pages.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ssg.js&lt;&#x2F;code&gt; is the build script.&lt;&#x2F;p&gt;
&lt;p&gt;It works by working through all the files in &lt;code&gt;content&#x2F;&lt;&#x2F;code&gt;.
If it’s &lt;em&gt;not&lt;&#x2F;em&gt; a djot file,
it simply copies it over to &lt;code&gt;build&#x2F;&lt;&#x2F;code&gt;,
and if it &lt;em&gt;is&lt;&#x2F;em&gt; a djot file,
then it converts it to HTML,
inserts its contents into the template,
and copies over the resulting page to &lt;code&gt;build&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;few-more-issues&quot;&gt;Few more issues&lt;a class=&quot;zola-anchor&quot; href=&quot;#few-more-issues&quot; aria-label=&quot;Anchor link for: few-more-issues&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This reminds me of a few more issues:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;How do I handle data files that generate pages?&lt;&#x2F;p&gt;
&lt;p&gt;Does the &lt;code&gt;content&lt;&#x2F;code&gt; folder treat data formats
as something special to generate pages from?
(data formats like JSON or whatever I like)&lt;&#x2F;p&gt;
&lt;p&gt;Or do I put data files in &lt;code&gt;extra&lt;&#x2F;code&gt;,
and have a special component or content file
to take in data and spit out a page or more?&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;How do I copy djot or data files verbatim?&lt;&#x2F;p&gt;
&lt;p&gt;This is probably the work of a &lt;code&gt;static&lt;&#x2F;code&gt; folder,
where &lt;code&gt;main.css&lt;&#x2F;code&gt; and &lt;code&gt;main.js&lt;&#x2F;code&gt; should also go.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

            </content>
        </entry>
        
      
      
      
      
      
        <entry xml:lang="en">
            <title>A Bean-troduction</title>
            <published>2024-05-21T18:08:41+00:00</published>
            <updated>2024-05-21T18:08:41+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/bean-troduction/"/>
            <id>https://pranabekka.neocities.org/bean-troduction/</id>
            <summary type="html">
              An introduction to the (currently imaginary)
Bean markup language,
with some comparisons to Markdown.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/bean-troduction/">
              &lt;p&gt;An introduction to the (currently imaginary)
Bean markup language,
with some comparisons to Markdown.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;paragraphs&quot;&gt;Paragraphs&lt;a class=&quot;zola-anchor&quot; href=&quot;#paragraphs&quot; aria-label=&quot;Anchor link for: paragraphs&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Writing a paragraph is roughly the same:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;This is a paragraph.
Multiple consecutive lines belong
to the same paragraph.

Blank lines start a new paragraph.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;headings&quot;&gt;Headings&lt;a class=&quot;zola-anchor&quot; href=&quot;#headings&quot; aria-label=&quot;Anchor link for: headings&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Bean does something a bit different with headings:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#### Document title

### A level 1 heading

## A level 2 heading

# A level 3 heading
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Only three heading levels have syntax sugar,
and the higher the heading level,
the more marks it has —
in order to maintain visual hierarchy.&lt;&#x2F;p&gt;
&lt;p&gt;Bean supports additional heading levels,
but that’s through the generic tag syntax.
If you find yourself requiring those levels,
you might be better served by a list.
(Well, I’m just buying into what Edward Tufte says.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code&quot;&gt;Code&lt;a class=&quot;zola-anchor&quot; href=&quot;#code&quot; aria-label=&quot;Anchor link for: code&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Fences in Bean simply mark an area of text,
either as a span or div.
You must use the &lt;code&gt;code&lt;&#x2F;code&gt; tag, or a &lt;code&gt;:lang&lt;&#x2F;code&gt; attribute
if you want to create a code block.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[code :lang javascript]
```
let markup = &amp;quot;Bean&amp;quot;
```

[:lang javascript]
```
const MARKUP = &amp;quot;Bean&amp;quot;
```
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Bean avoids specialising for code,
though users of markup languages are likely programmers.
I’ll have to see about the decision,
but I think it’s the correct one.&lt;&#x2F;p&gt;
&lt;p&gt;Indented code is not a thing.
In fact, indentation is ignored throughout Bean,
unless a block assigns special meaning to it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lists&quot;&gt;Lists&lt;a class=&quot;zola-anchor&quot; href=&quot;#lists&quot; aria-label=&quot;Anchor link for: lists&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Bean’s list syntax is borrowed from Asciidoc.
It avoids complex list rules and related accidents.&lt;&#x2F;p&gt;
&lt;!-- TODO: write a better example use case --&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;* list item 1
** sub-list item 1
* list item 2.
  * continuation of list item 2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In Markdown, the continuation of list item 2 would require an escape character.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;* list item 1
  * sub-list item 1
* list item 2.
  \* continuation of list item 2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rendered HTML output:&lt;&#x2F;p&gt;
&lt;div class=&quot;sample-block&quot;&gt;
  &lt;ul&gt;
&lt;li&gt;list item 1
&lt;ul&gt;
&lt;li&gt;sub-list item 1&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;list item 2.
* continuation of list item 2&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;tables&quot;&gt;Tables&lt;a class=&quot;zola-anchor&quot; href=&quot;#tables&quot; aria-label=&quot;Anchor link for: tables&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Bean defaults to tables with comma-separated values,
but it also allows you to specify your own separator.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[table]
comma  , separated , values
can be , used for  , tables

[table :sep |]
cell 1 | cell 2 | cell 3
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;extension&quot;&gt;Extension&lt;a class=&quot;zola-anchor&quot; href=&quot;#extension&quot; aria-label=&quot;Anchor link for: extension&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to do anything beyond
the syntax sugar provided by Markdown,
you must rely on HTML.&lt;&#x2F;p&gt;
&lt;p&gt;Bean provides a generic tag syntax
that can be directly translated to HTML or XML,
which you’ve already seen
in the form of the &lt;code&gt;code&lt;&#x2F;code&gt; block.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[details]
[summary]`A summary of this block`
Any ol&amp;#39; content you want to show
when the details block is expanded.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice how the backticks don’t specify code,
but instead mark the boundaries of the tagged (summary) content.&lt;&#x2F;p&gt;
&lt;p&gt;Bean also has some syntax sugar for tags.
To create a div with a specific class,
you can simply use &lt;code&gt;[.class-name]&lt;&#x2F;code&gt;.
The same goes for IDs.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[#div-id.class-name]
content
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;div id=&amp;quot;div-id&amp;quot; class=&amp;quot;class-name&amp;quot;&amp;gt;
  content
&amp;lt;&#x2F;div&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You’ve also seen the attribute syntax
being matched to an appropriate element,
but it can be used to set an attribute for a div.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[:data-value skip]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;div data-value=&amp;quot;skip&amp;quot;&amp;gt;&amp;lt;&#x2F;div&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If&#x2F;when I get this far,
I also intend to implement a scripting interface
to create your own blocks,
maybe with syntax sugar or over-rides included.&lt;&#x2F;p&gt;
&lt;p&gt;For a more comprehensive explanation of Bean,
see my previous post on its syntax and features.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;bean-markup&#x2F;&quot;&gt;Bean markup&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Two random foughts</title>
            <published>2024-05-21T18:01:10+00:00</published>
            <updated>2024-06-24T15:32:34+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/random-foughts-go-ssg-clean-urls/"/>
            <id>https://pranabekka.neocities.org/random-foughts-go-ssg-clean-urls/</id>
            <summary type="html">
              1) Hugo (SSG) should’ve been a set of libraries
that the user imported and hooked up.
2) Clean URLs like site.com/hello/
should not be used.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/random-foughts-go-ssg-clean-urls/">
              &lt;p&gt;1) Hugo (SSG) should’ve been a set of libraries
that the user imported and hooked up.
2) Clean URLs like &lt;code&gt;site.com&#x2F;hello&#x2F;&lt;&#x2F;code&gt;
should not be used.&lt;&#x2F;p&gt;
&lt;p&gt;NOTE: I initially had both posts in this page,
but I’ve moved them to separate pages,
since they are, in fact, separate things.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ssg-libraries-for-go&quot;&gt;SSG libraries for Go&lt;a class=&quot;zola-anchor&quot; href=&quot;#ssg-libraries-for-go&quot; aria-label=&quot;Anchor link for: ssg-libraries-for-go&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;ssg-libs&#x2F;&quot;&gt;SSGs should be libraries&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clean-urls-bad&quot;&gt;Clean URLs: bad!&lt;a class=&quot;zola-anchor&quot; href=&quot;#clean-urls-bad&quot; aria-label=&quot;Anchor link for: clean-urls-bad&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;clean-urls&#x2F;&quot;&gt;Clean URLs: bad!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>My current favourite (web)fiction</title>
            <published>2024-05-09T11:58:53+00:00</published>
            <updated>2025-01-07T10:17:39+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/super-supportive/"/>
            <id>https://pranabekka.neocities.org/super-supportive/</id>
            <summary type="html">
              And also a source of great pain.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/super-supportive/">
              &lt;p&gt;And also a source of great pain.&lt;&#x2F;p&gt;
&lt;p&gt;For the last few months,
I open a tab at least two days a week,
and I refresh it every few minutes or hours,
in the hope that a new release is made,
and I rejoice for every chapter released.
Introducing: Super Supportive by Sleyca.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.royalroad.com&#x2F;fiction&#x2F;63759&#x2F;super-supportive&quot;&gt;Super Supportive on Royal Road&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I’ve been reading it for so long
that I’m not sure I can pinpoint exactly what I felt
when I started reading it,
but I can promise you this:
it’s incredibly well written,
the world is rich, believable, and large,
and the main character is very likable.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;elcy-cassandrian-scuu&#x2F;&quot;&gt;Previous book suggestion (Quod Olim Erat)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Bookmarks</title>
            <published>2024-05-07T10:59:46+00:00</published>
            <updated>2024-05-07T10:59:46+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/bookmarks/"/>
            <id>https://pranabekka.neocities.org/bookmarks/</id>
            <summary type="html">
              List of interesting links with brief introductions.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/bookmarks/">
              &lt;p&gt;List of interesting links with brief introductions.&lt;&#x2F;p&gt;
&lt;p&gt;Previously available at “Links” page (now empty).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;web-sustainability-guidelines&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;w3c.github.io&#x2F;sustyweb#table-of-contents&quot;&gt;Web Sustainability Guidelines&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#web-sustainability-guidelines&quot; aria-label=&quot;Anchor link for: web-sustainability-guidelines&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Multi-faceted and comprehensive guide
to making sustainable web sites&#x2F;products,
with links to research and examples.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godot-engine-docs-getting-started&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;getting_started&#x2F;introduction&#x2F;index.html&quot;&gt;Godot Engine Docs (Getting Started)&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#godot-engine-docs-getting-started&quot; aria-label=&quot;Anchor link for: godot-engine-docs-getting-started&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Explanations of basic godot concepts,
as well as more detailed walkthroughs
and a full reference for nodes, functions, variables,
best practices, and general topics.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nixos-flakes-book&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nixos-and-flakes.thiscute.world&#x2F;&quot;&gt;NixOS &amp;amp; Flakes Book&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nixos-flakes-book&quot; aria-label=&quot;Anchor link for: nixos-flakes-book&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;An (unofficial) introduction to Nix,
which includes flakes (unlike official docs),
and seems more beginner friendly and comprehensive
than the official docs.
Aims to include everything you might need.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;soatok-dhole-moments&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;soatok.blog&quot;&gt;Soatok&#x2F;Dhole Moments&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#soatok-dhole-moments&quot; aria-label=&quot;Anchor link for: soatok-dhole-moments&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Great writing on security,
but also posts on general things,
and a good series on getting jobs
(in tech; called “Furward Momentum”).
The about page has a list of “top posts”.
&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;bookmarks&#x2F;filippo.io&quot;&gt;Filippo Valsorda&lt;&#x2F;a&gt;
is also a good resource for cryptography and security.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lobste-rs&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lobste.rs&quot;&gt;lobste.rs&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#lobste-rs&quot; aria-label=&quot;Anchor link for: lobste-rs&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Well-moderated tech forum.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;marginalia-search&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;search.marginalia.nu&quot;&gt;Marginalia Search&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#marginalia-search&quot; aria-label=&quot;Anchor link for: marginalia-search&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Search engine that tries to be indie, relevant,
and free of corporate marketing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cl-cookbook&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lispcookbook.github.io&#x2F;cl-cookbook&quot;&gt;CL Cookbook&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cl-cookbook&quot; aria-label=&quot;Anchor link for: cl-cookbook&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Handy articles and references for getting stuff done in Common Lisp.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lisp-journey-vindarel&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lisp-journey.gitlab.io&quot;&gt;Lisp Journey&#x2F;Vindarel&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#lisp-journey-vindarel&quot; aria-label=&quot;Anchor link for: lisp-journey-vindarel&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Website by Vindarel — big contributor to Common Lisp
cookbook and community.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ye-olde-blogroll&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blogroll.org&quot;&gt;Ye Olde Blogroll&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ye-olde-blogroll&quot; aria-label=&quot;Anchor link for: ye-olde-blogroll&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Short and curated list of personal and indie blogs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sourcehut&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sr.ht&quot;&gt;Sourcehut&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#sourcehut&quot; aria-label=&quot;Anchor link for: sourcehut&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Indie (ish?) and FOSS source forge
with interesting UI&#x2F;UX and more,
started by drewdevault and company.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;drew-devault&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;drewdevault.com&quot;&gt;Drew Devault&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#drew-devault&quot; aria-label=&quot;Anchor link for: drew-devault&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Articles on FOSS software and community,
and tech in general.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;seirdy&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;seirdy.one&quot;&gt;Seirdy&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#seirdy&quot; aria-label=&quot;Anchor link for: seirdy&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Articles on accessibility, security, privacy, FOSS.
Includes a good one on
&lt;a href=&quot;https:&#x2F;&#x2F;seirdy.one&#x2F;posts&#x2F;2020&#x2F;11&#x2F;23&#x2F;website-best-practices&#x2F;&quot;&gt;accessibility&lt;&#x2F;a&gt;
that’s inspired a fair bit of my UI&#x2F;UX designs,
and some of the design for the current website
(to be fair, the article is a compilation
of various other sources).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;danluu&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;danluu.com&quot;&gt;DanLuu&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#danluu&quot; aria-label=&quot;Anchor link for: danluu&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Well thought out posts on various topics,
especially tech and personal productivity&#x2F;improvement.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;farnam-street-blog&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fs.blog&#x2F;blog&quot;&gt;Farnam Street Blog&lt;&#x2F;a&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#farnam-street-blog&quot; aria-label=&quot;Anchor link for: farnam-street-blog&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Articles on improving yourself.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
        <entry xml:lang="en">
            <title>Detailed military sci-fi book</title>
            <published>2024-05-03T19:20:40+00:00</published>
            <updated>2024-05-03T19:20:40+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/elcy-cassandrian-scuu/"/>
            <id>https://pranabekka.neocities.org/elcy-cassandrian-scuu/</id>
            <summary type="html">
              Quod Olim Erat (Battleship Chronicles #1 on Amazon)
is an incredibly realistic, detailed, believable
and intense take on military sci-fi.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/elcy-cassandrian-scuu/">
              &lt;p&gt;Quod Olim Erat (Battleship Chronicles #1 on Amazon)
is an incredibly realistic, detailed, believable
and intense take on military sci-fi.&lt;&#x2F;p&gt;
&lt;p&gt;As I was imagining what Halo’s
story and depictions could have been,
it kept sounding like Quod Olim Erat,
so I thought I’d give the book
and its sequels a recommendation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.royalroad.com&#x2F;fiction&#x2F;15449&#x2F;quod-olim-erat&quot;&gt;Quod Olim Erat by Lise Eclaire, on Royal Road&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In Quod Olim Erat, and its two sequels,
you follow a ship A.I. that re-enters military service
in a human-like body, after being retired for decades.&lt;&#x2F;p&gt;
&lt;p&gt;The alien wars on both frontiers is still ongoing,
and Elcy has to deal with people keeping secrets,
her own redacted memories,
complex politics surrounding (un)retired ships,
concerns about her going rogue,
and mysterious alien artifacts.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; The books in the series were
published on Amazon and Kindle (around April 22, 2024) &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
which means the Royal Road versions are now stubbed.
You can read the previews for free, and if you like it,
buy it for pretty cheap (that too by Indian standards)
under the “Battleship Chronicles” name.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.royalroad.com&#x2F;fiction&#x2F;15449&#x2F;quod-olim-erat&#x2F;chapter&#x2F;1606159&#x2F;available-on-amazon-and-kindle&quot;&gt;Author’s note on publishing&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

            </content>
        </entry>
        
      
      
        <entry xml:lang="en">
            <title>Bean markup</title>
            <published>2024-03-13T23:56:12+00:00</published>
            <updated>2024-03-13T23:56:12+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/bean-markup/"/>
            <id>https://pranabekka.neocities.org/bean-markup/</id>
            <summary type="html">
              Bean is an extensible markup language,
with generic constructs for delimiting and marking up text,
as well as syntax sugar for commonly used markup,
such as emphasis, lists, and tables.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/bean-markup/">
              &lt;p&gt;Bean is an extensible markup language,
with generic constructs for delimiting and marking up text,
as well as syntax sugar for commonly used markup,
such as emphasis, lists, and tables.&lt;&#x2F;p&gt;
&lt;p&gt;Bean borrows from the tradition of Markdown,
yet is more obviously influenced by djot and AsciiDoc.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;djot.net&quot;&gt;Djot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;asciidoc.org&#x2F;&quot;&gt;AsciiDoc&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.markdownguide.org&#x2F;getting-started&#x2F;&quot;&gt;Markdown&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; Bean doesn’t have an implementation.
This is just an idea in my head right now.&lt;&#x2F;p&gt;
&lt;!--
## Audience

People already familiar with Markdown,
and maybe even other markup languages,
who are interested in plain text markup formats.
--&gt;
&lt;h2 id=&quot;the-other-formats&quot;&gt;The other formats&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-other-formats&quot; aria-label=&quot;Anchor link for: the-other-formats&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Markdown suffers from being a mix of plain-text email conventions
instead of a fully considered specification,
and thus has many complexities,
inconsistencies, and surprises.
The author of CommonMark and djot
has already explained these issues
in ‘Beyond Markdown’.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;johnmacfarlane.net&#x2F;beyond-markdown.html&quot;&gt;Beyond Markdown&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;While I was initially enamoured by AsciiDoc and all its features,
I eventually realised that it has a lot of complex syntax,
which makes it hard to learn and use,
and even harder to port.&lt;&#x2F;p&gt;
&lt;p&gt;Djot is the format I find the most appealing,
though it has made some choices
that I believe could be done better.
Djot’s syntax isn’t &lt;em&gt;completely&lt;&#x2F;em&gt; fixed yet,
but I obviously can’t resist dreaming up my own format.&lt;&#x2F;p&gt;
&lt;p&gt;Typst is another format that I quite like,
although it’s currently made for PDF output,
and includes a whole new scripting language.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;typst.app&quot;&gt;Typst&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;MDX is another format that I like,
but just for the component system,
because it’s still a Markdown dialect.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mdxjs.com&#x2F;&quot;&gt;MDX&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;a class=&quot;zola-anchor&quot; href=&quot;#rationale&quot; aria-label=&quot;Anchor link for: rationale&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The first factor that led me to devise another format
was my desire to create and use custom markup elements
that conform to my preferences.&lt;&#x2F;p&gt;
&lt;p&gt;Bean includes &lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;concise and regular markup,&lt;&#x2F;li&gt;
&lt;li&gt;a general syntax that is equal to XML,
except with reduced tag soup,&lt;&#x2F;li&gt;
&lt;li&gt;convenient syntax sugar for common elements,&lt;&#x2F;li&gt;
&lt;li&gt;plain text readability,&lt;&#x2F;li&gt;
&lt;li&gt;and a way to declare custom elements.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;terms&quot;&gt;Terms&lt;a class=&quot;zola-anchor&quot; href=&quot;#terms&quot; aria-label=&quot;Anchor link for: terms&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I want to clarify some terms before I continue,
which I have borrowed from HTML,
due to my familiarity with it.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Element:&lt;&#x2F;strong&gt;
An abstract ‘part’ of the document,
identified with tags and delimiters.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tag:&lt;&#x2F;strong&gt;
A declaration, within the document,
of an element, its type,
and optional or required attributes.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Delimiter:&lt;&#x2F;strong&gt;
Marker for where an element begins or ends.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Block (Element):&lt;&#x2F;strong&gt;
A ‘block’ level element,
usually delimited by blank lines.
Examples include paragraphs and lists.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Inline (Element):&lt;&#x2F;strong&gt;
An element that usually occurs within a line of text,
such as a link or emphasised text.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;begin&quot;&gt;Begin&lt;a class=&quot;zola-anchor&quot; href=&quot;#begin&quot; aria-label=&quot;Anchor link for: begin&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;paragraphs&quot;&gt;Paragraphs&lt;a class=&quot;zola-anchor&quot; href=&quot;#paragraphs&quot; aria-label=&quot;Anchor link for: paragraphs&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;As in Markdown and the rest,
a block of text delimited by newlines is a paragraph,
with line breaks converted to spaces.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A paragraph.

Another paragraph.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;other-blocks-and-tags&quot;&gt;Other blocks, and tags&lt;a class=&quot;zola-anchor&quot; href=&quot;#other-blocks-and-tags&quot; aria-label=&quot;Anchor link for: other-blocks-and-tags&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Bean uses square brackets to tag a block.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[tagged-block]
This block is tagged as a `tagged-block` element.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tags can also have options for the element,
such as the language for a verbatim block.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[verbatim :language bean]
This block represents Bean markup.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;multi-line-tags&quot;&gt;Multi-line tags&lt;a class=&quot;zola-anchor&quot; href=&quot;#multi-line-tags&quot; aria-label=&quot;Anchor link for: multi-line-tags&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Tags can span multiple lines to aid readability.&lt;&#x2F;p&gt;
&lt;p&gt;All the blocks below produce the same content.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[tag
  :option1 value1
  option2
  :option3 value3]
Block contents

[tag
 :option1 value1
 option2
 :option3 value3
]
Block contents

[tag :option1 value1 option2 :option3 value3]
Block contents

[
  tag
  :option1 value1
  option2
  :option3 value3
]
Block contents
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;nested-blocks&quot;&gt;Nested blocks&lt;a class=&quot;zola-anchor&quot; href=&quot;#nested-blocks&quot; aria-label=&quot;Anchor link for: nested-blocks&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A block-level tag within another block-level tag
indicates that it is nested.
“Within” is defined as not separated by a blank line.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[parent-block]
parent-block content
[child-block]
child-block content

[parent-block]
[child-block]
child-block contents
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;indentation-and-whitespace&quot;&gt;Indentation and whitespace&lt;a class=&quot;zola-anchor&quot; href=&quot;#indentation-and-whitespace&quot; aria-label=&quot;Anchor link for: indentation-and-whitespace&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Bean ignores indentation and extra whitespace,
unless it’s a verbatim block or a list.
Whitespace at the end is stripped,
and line breaks are collapsed into a space,
unless there is a blank line,
which breaks apart blocks.&lt;&#x2F;p&gt;
&lt;p&gt;The two paragraphs in the following example
produce the same content,
regardless of their indentation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A paragraph that I am writing.

  A paragraph that I am writing.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;fenced-blocks&quot;&gt;Fenced blocks&lt;a class=&quot;zola-anchor&quot; href=&quot;#fenced-blocks&quot; aria-label=&quot;Anchor link for: fenced-blocks&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Block elements can also be delimited by
two or more backticks.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[tag]
``
This is a block element.

This is a second block within the block element.
``
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A fenced block defaults to a generic block,
unless there’s a tag specifying otherwise.&lt;&#x2F;p&gt;
&lt;p&gt;Fenced blocks can also be nested.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[fenced-block]
``
  [nested-fenced-block]
  ```
  nested fenced block contents
  ```
``
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fenced blocks can also contain blocks that are not fenced.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[unordered-list]
``
  [list-item]
  First list item

  [list-item]
  Second list item
``
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;inline-tags&quot;&gt;Inline tags&lt;a class=&quot;zola-anchor&quot; href=&quot;#inline-tags&quot; aria-label=&quot;Anchor link for: inline-tags&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Sometimes you want to mark up a part of a paragraph of text.
A single backtick or more is used to do so.
You can use tags within running text to mark inline content.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A paragraph with an inline[tag] element.

A paragraph with an [tag]inline element.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The tag identifies it’s content using whitespace.
If it comes after whitespace,
it will apply to the content after the tag,
if it comes after a non-whitespace character,
it will apply to the content before it,
and if it is surrounded by whitespace on both sides,
it will not apply to any content.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to tag more than a single word,
use backticks to create an inline fence
and put your tag before the opening backtick,
or after the closing backtick.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A paragraph with a
`tagged inline element`[inline-tag].
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These can also use multiple backticks and be nested arbitrarily,
though it is not encouraged.&lt;&#x2F;p&gt;
&lt;p&gt;Similar to block tags,
inline tags can contain attributes for the element.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A paragraph with a `link`[link :target https:&#x2F;&#x2F;example.com].
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;div class=&quot;sample-block&quot;&gt;
  &lt;p&gt;A paragraph with a &lt;a href=&quot;https:&#x2F;&#x2F;example.com&quot;&gt;link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h3 id=&quot;lists&quot;&gt;Lists&lt;a class=&quot;zola-anchor&quot; href=&quot;#lists&quot; aria-label=&quot;Anchor link for: lists&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This is the first of the syntax sugar,
since using tags and fences for lists
would get tedious very quickly.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;* List item
* Another list item

1. First item
2. Second item

. First item
. Second item
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While they appear the same as Markdown at a first glance,
we borrow list syntax from AsciiDoc
and avoid the mistakes and limitations of list syntax
in both Markdown and djot.&lt;&#x2F;p&gt;
&lt;p&gt;Nested list items require extra list item markers
for each level of indentation,
and must share the same indentation
as the first list item.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;* List item
** Nested list item
* Second top-level list item
  * with running text (this is not a list item)
* Third list item

[hr]

1. First item
1.1. Part 1 of first item
1. 2. Second item (automatically numbered 2)
3. Third item
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;div class=&quot;sample-block&quot;&gt;
  &lt;ul&gt;
&lt;li&gt;List item
&lt;ul&gt;
&lt;li&gt;Nested list item&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Second top-level list item * with running text
(this is not a list item)&lt;&#x2F;li&gt;
&lt;li&gt;Third list item&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;ol&gt;
&lt;li&gt;First item
&lt;ol&gt;
&lt;li&gt;Part 1 of first item&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;span&gt;2&lt;&#x2F;span&gt;. Second item &lt;!-- It creates an inline nested list, otherwise --&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Third item&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Notice how the bullet mark doesn’t create a new list item
if it doesn’t have the same indentation as the first list marker.
Djot navigates this by requiring a blank line before a nested list,
while Markdown can cause unexpected issues and requires escaping.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tables&quot;&gt;Tables&lt;a class=&quot;zola-anchor&quot; href=&quot;#tables&quot; aria-label=&quot;Anchor link for: tables&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Tables are another construct that can appear with some regularity.
Bean defaults to comma separated values under a &lt;code&gt;table&lt;&#x2F;code&gt; tag,
but you can specify your own separator.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[table :header :separator ,]
markup   , rating
markdown , 7&#x2F;10
djot     , 9&#x2F;10
asciidoc , 8&#x2F;10
typst    , 9&#x2F;10
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;div class=&quot;tablewrapper&quot;&gt;
  &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;markup&lt;&#x2F;th&gt;&lt;th&gt;rating&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;markdown&lt;&#x2F;td&gt;&lt;td&gt;7&#x2F;10&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;djot&lt;&#x2F;td&gt;&lt;td&gt;9&#x2F;10&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;asciidoc&lt;&#x2F;td&gt;&lt;td&gt;8&#x2F;10&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;typst&lt;&#x2F;td&gt;&lt;td&gt;9&#x2F;10&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;
&lt;h3 id=&quot;headings&quot;&gt;Headings&lt;a class=&quot;zola-anchor&quot; href=&quot;#headings&quot; aria-label=&quot;Anchor link for: headings&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Bean accomodates for the title
and three heading levels by default.
Further heading levels are discouraged
and require explicit heading tags.&lt;&#x2F;p&gt;
&lt;p&gt;The document title uses four ‘#’ signs,
the first heading level uses three,
the second uses two,
and the third uses one.
This is based on the idea
that higher level headings are more important,
and should be more prominent in plain text,
than lower level headings.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#### Document title

An introductory paragraph.

### Level 1 heading

## Level 2 heading

# Level 1 heading
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;emphasis&quot;&gt;Emphasis&lt;a class=&quot;zola-anchor&quot; href=&quot;#emphasis&quot; aria-label=&quot;Anchor link for: emphasis&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;While you could use a generic inline element for emphasis,
bean provides custom delimiters to make it easy.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A paragraph with *emphasised text*.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;div class=&quot;sample-block&quot;&gt;
  &lt;p&gt;A paragraph with &lt;em&gt;emphasised text&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Delimiters for emphasis can also be tagged:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Some *emphasised text*[link :target https:&#x2F;&#x2F;example.com] in the paragraph.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;div class=&quot;sample-block&quot;&gt;
  &lt;p&gt;A paragraph with &lt;a href=&quot;https:&#x2F;&#x2F;example.com&quot;&gt;&lt;em&gt;emphasised text&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h3 id=&quot;openers-and-closers&quot;&gt;Openers and closers&lt;a class=&quot;zola-anchor&quot; href=&quot;#openers-and-closers&quot; aria-label=&quot;Anchor link for: openers-and-closers&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Djot has a neat construct for dealing with
complex and nested delimiters:
delimiters can have braces to indicate
whether they are opening or closing delimiters.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{*Emphasised * text.*}

{`inline ` fence`}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;div class=&quot;sample-block&quot;&gt;
  &lt;p&gt;&lt;em&gt;Emphasised * text.&lt;&#x2F;em&gt; &lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;inline ` fence&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;This way you can explicitly say where the emphasis should end,
instead of having to worry about escaping delimiter characters.&lt;&#x2F;p&gt;
&lt;p&gt;Another cool thing (I think) djot does,
is to use openers and closers with single and double ticks
to specify whether they’re right or left quotes,
though it usually infers them correctly.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{&amp;quot;Hello, world&amp;quot;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;div class=&quot;sample-block&quot;&gt;
  &lt;p&gt;“Hello, world”&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h3 id=&quot;meta-information-tag-s&quot;&gt;Meta-information tag(s)&lt;a class=&quot;zola-anchor&quot; href=&quot;#meta-information-tag-s&quot; aria-label=&quot;Anchor link for: meta-information-tag-s&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A meta tag helps set document-level options and properties,
along with a slightly better alternative to frontmatter. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#f-mtr&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;f-mtr&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Frontmatter introduces a second language to markdown files,
and breaks the usual flow of markdown,
by moving the level 1 heading and even cluttering it a bit.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#### Document title

[meta
  :date 2049-01-01
  :author &amp;quot;Pranab&amp;quot;
]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A summary would be a similarly related element.
It provides meta-information about the document,
while not quite being part of the document contents.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#### Document title

[meta :date 2049-01-01]

[summary]
A summary of the document,
to be used in listings and previews,
but not when displaying the document directly.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;conditional-passthrough&quot;&gt;Conditional passthrough&lt;a class=&quot;zola-anchor&quot; href=&quot;#conditional-passthrough&quot; aria-label=&quot;Anchor link for: conditional-passthrough&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Djot has passthrough blocks that take a format specifier,
so if the export format matches the specifier,
then the contents of the block are passed as is.
This would allow writing raw HTML, for example,
though there should be no need for that in Bean.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Regular indentation&#x2F;spacing.

&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;[passthrough HTML]Indented by four spaces in HTML.

[passthrough HTML]
&amp;lt;ul id=&amp;quot;document-formats&amp;quot;&amp;gt;
  &amp;lt;li&amp;gt;Djot&amp;lt;&#x2F;li&amp;gt;
  &amp;lt;li&amp;gt;AsciiDoc&amp;lt;&#x2F;li&amp;gt;
  &amp;lt;li&amp;gt;Markdown&amp;lt;&#x2F;li&amp;gt;
&amp;lt;&#x2F;ul&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;div class=&quot;sample-block&quot;&gt;
  &lt;p&gt;Regular indentation&#x2F;spacing.&lt;&#x2F;p&gt;
&lt;p&gt;    Indented by four spaces in HTML.&lt;&#x2F;p&gt;
&lt;ul id=&quot;document-formats&quot;&gt;
  &lt;li&gt;Djot&lt;&#x2F;li&gt;
  &lt;li&gt;AsciiDoc&lt;&#x2F;li&gt;
  &lt;li&gt;Markdown&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;waffle&quot;&gt;Waffle&lt;a class=&quot;zola-anchor&quot; href=&quot;#waffle&quot; aria-label=&quot;Anchor link for: waffle&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt;
These are random unorganised and&#x2F;or incomplete bits.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tag-syntax&quot;&gt;Tag syntax&lt;a class=&quot;zola-anchor&quot; href=&quot;#tag-syntax&quot; aria-label=&quot;Anchor link for: tag-syntax&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I’m not a 100% sure about the tag property syntax.
These are the three main options I considered:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[tag option1=value1 option2 option3=value3]

[tag :option1 value1 option2 :option3 value3]

[tag option1 value1 option2 true option3 value3]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The last is the easiest to type,
but I don’t feel like the difference is that big,
plus having an indicator like the colon or equal sign
can be quite helpful, and thus worth the extra character.
I guess the second has the benefit
that you won’t need to escape equal signs?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;classes-and-ids&quot;&gt;Classes and IDs&lt;a class=&quot;zola-anchor&quot; href=&quot;#classes-and-ids&quot; aria-label=&quot;Anchor link for: classes-and-ids&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[.big .red]
Big red paragraph (has &amp;quot;big&amp;quot; and &amp;quot;red&amp;quot; classes)

[#warning]
This paragraph has the &amp;quot;warning&amp;quot; ID
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is another concept that djot has.
I’m not quite sure it’s necessary or even desired,
and it injects a bit of HTML in some ways.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;custom-elements-tags&quot;&gt;Custom elements&#x2F;tags&lt;a class=&quot;zola-anchor&quot; href=&quot;#custom-elements-tags&quot; aria-label=&quot;Anchor link for: custom-elements-tags&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Roughly the same as custom components in MDX,
except you use Bean tags instead of XML&#x2F;HTML.&lt;&#x2F;p&gt;
&lt;p&gt;I guess it would be implementation dependent,
so there’s no real point of examples here,
though if I were to require an extension language,
I’d pick an S-expression language.&lt;&#x2F;p&gt;
&lt;p&gt;I was imagining the API would be something simple like
defining a function that takes in the tag contents
and outputs HTML by manipulating child tags and text content.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bean-as-an-extensible-markup-format&quot;&gt;Bean as an extensible markup format&lt;a class=&quot;zola-anchor&quot; href=&quot;#bean-as-an-extensible-markup-format&quot; aria-label=&quot;Anchor link for: bean-as-an-extensible-markup-format&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Bean is basically the same as HTML and XML,
with some syntax differences,
and a few added conveniences for authoring documents
(such as the syntax sugar for lists).
At a base level, it has
tags, attributes, nested tags, and text content.&lt;&#x2F;p&gt;
&lt;p&gt;An initial Bean compiler can just
use the base tag and block&#x2F;inline rules,
and automatically convert them to HTML&#x2F;XML tags.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s an HTML in Bean example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[ul :id &amp;quot;document-formats&amp;quot;]
[li]Djot
[li]AsciiDoc
[li]Markdown
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looking at that,
I’m almost tempted to remove syntax sugar for lists.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, the basic rules make Bean a decent document&#x2F;data format,
though the syntax will make it more or less suitable
for various uses.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fences-as-code&quot;&gt;Fences as code&lt;a class=&quot;zola-anchor&quot; href=&quot;#fences-as-code&quot; aria-label=&quot;Anchor link for: fences-as-code&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Initially, fences defaulted to code if no tag was given,
but then I thought that shouldn’t be default behaviour
to avoid specialising too much for writing about programming.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cool-features-to-consider&quot;&gt;Cool features to consider&lt;a class=&quot;zola-anchor&quot; href=&quot;#cool-features-to-consider&quot; aria-label=&quot;Anchor link for: cool-features-to-consider&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Namespaces to avoid custom tag collisions.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;import &amp;lt;package&amp;gt; as &amp;lt;nickname&amp;gt;&lt;&#x2F;code&gt; statements
to avoid namespace collisions?
Maybe in the meta tag.&lt;&#x2F;li&gt;
&lt;li&gt;Some sort of package registry and manager?&lt;&#x2F;li&gt;
&lt;li&gt;Default config file for all Bean files within folder.&lt;&#x2F;li&gt;
&lt;li&gt;Comments — probably using the djot method.
Better than adding extra syntax sugar.
Maybe a comment “tag” and&#x2F;or attribute?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;table-wrappers&quot;&gt;Table wrappers&lt;a class=&quot;zola-anchor&quot; href=&quot;#table-wrappers&quot; aria-label=&quot;Anchor link for: table-wrappers&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I really dislike how tables break layouts
if they stretch past the page width,
so I’d like Bean to automatically insert
a &lt;code&gt;div.tablewrapper&lt;&#x2F;code&gt; around them,
either by over-riding the default component,
or creating a custom component.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;details-component&quot;&gt;Details component&lt;a class=&quot;zola-anchor&quot; href=&quot;#details-component&quot; aria-label=&quot;Anchor link for: details-component&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[details]
[summary]This is the summary of this block
Insert any ol&amp;#39; content over here,
which will be displayed when the details element is opened.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;sample-block&quot;&gt;
  &lt;br&gt;
&lt;details&gt;
&lt;summary&gt;This is the summary of this block&lt;&#x2F;summary&gt;
Insert any ol&#x27; content over here,
which will be displayed when the details element is opened.
&lt;&#x2F;details&gt;
&lt;br&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Another option is to use fences,
and make the first block the summary.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[details]
``
This block is the summary

Any other blocks are part of the hidden content.
``
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Trying them out will give the answers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;inline-tag-nesting&quot;&gt;Inline tag nesting&lt;a class=&quot;zola-anchor&quot; href=&quot;#inline-tag-nesting&quot; aria-label=&quot;Anchor link for: inline-tag-nesting&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Later tags should be nested inside earlier tags
when they’re prefixed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[parent-inline-tag][child-inline-tag]content
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But what about suffixed inline tags?
Just reverse the order?&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;content[child-inline-tag?][parent-inline-tag?]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;inline-vs-block-elements-tags&quot;&gt;Inline vs block elements&#x2F;tags&lt;a class=&quot;zola-anchor&quot; href=&quot;#inline-vs-block-elements-tags&quot; aria-label=&quot;Anchor link for: inline-vs-block-elements-tags&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Would it be okay to mark a heading or other block
with a lone inline tag?&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[h4]My heading
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The h2 component would know this is a block,
but how does the surrounding context know this?
How do I prevent it from wrapping it in a paragraph?&lt;&#x2F;p&gt;
&lt;p&gt;What about a suffixed inline tag?&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;`My heading`[h1]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perhaps the wrapper checks its contents
before deciding to be a paragraph, a div,
or whatever the inline tag specifies as a block element.
Or maybe it just errors out?
Like, a paragraph cannot take a block element,
but things like lists can.
So the inline&#x2F;block nature of the tagged element doesn’t quite matter,
but it does matter in the case of a parent element
that disallows block elements inside it.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps, if there is only one child block element,
it swallows the parent element?
That seems like a bad idea.
Simply erroring out is probably best.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;block-link-syntax&quot;&gt;Block link syntax&lt;a class=&quot;zola-anchor&quot; href=&quot;#block-link-syntax&quot; aria-label=&quot;Anchor link for: block-link-syntax&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Similar to that in gemtext:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;=&amp;gt; https:&#x2F;&#x2F;example.com my link text
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gemini.flounder.online&#x2F;docs&#x2F;gemtext.gmi&quot;&gt;Gemtext&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Block links can be increased in size
to improve the experience of tapping or clicking them,
without disrupting any surrounding text.&lt;&#x2F;p&gt;
&lt;p&gt;A dedicated syntax should encourage that.&lt;&#x2F;p&gt;
&lt;p&gt;A details and&#x2F;or aside element
can be used to move large lists of links
out of the way.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;unknown-blocks&quot;&gt;Unknown blocks&lt;a class=&quot;zola-anchor&quot; href=&quot;#unknown-blocks&quot; aria-label=&quot;Anchor link for: unknown-blocks&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Unknown blocks can be rendered with a label at the top,
and the verbatim contents of the block.
It could include a warning inside a prominent box
to say (in the HTML) that it’s unknown.&lt;&#x2F;p&gt;
&lt;p&gt;Probably emit an error and cancel building
if the build is for production,
though allow configuration to disable that.
And log a warning for dev builds.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;attribute-accumulation&quot;&gt;attribute accumulation&lt;a class=&quot;zola-anchor&quot; href=&quot;#attribute-accumulation&quot; aria-label=&quot;Anchor link for: attribute-accumulation&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;djot allows accumulating attributes (for block only?).
maybe using an &amp;amp; block to accumulate instead of nest?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;definition-lists&quot;&gt;definition lists&lt;a class=&quot;zola-anchor&quot; href=&quot;#definition-lists&quot; aria-label=&quot;Anchor link for: definition-lists&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;how does asciidoc do it?&lt;&#x2F;p&gt;
&lt;p&gt;djot requires loose lists for definition lists&lt;&#x2F;p&gt;
&lt;p&gt;maybe this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;: item
- definition?
: item
  continued
- definition?
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;i don’t think hyphens (at beginning of line)
have any other significance.
though maybe i want to keep it for hyphens.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;: item
= definition
: item
  continued
= definition
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;that should work, i think.
and the &lt;code&gt;=&lt;&#x2F;code&gt; sign carries some related meaning,
like &lt;code&gt;item = definition&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
        <entry xml:lang="en">
            <title>Web feed now live!</title>
            <published>2024-02-09T12:26:56+00:00</published>
            <updated>2024-02-09T12:26:56+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/feed-atom/"/>
            <id>https://pranabekka.neocities.org/feed-atom/</id>
            <summary type="html">
              AKA “RSS” feed, or Atom feed.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/feed-atom/">
              &lt;p&gt;AKA “RSS” feed, or Atom feed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;atom.xml&quot;&gt;Link to feed&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-use-a-feed&quot;&gt;Why use a feed?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-use-a-feed&quot; aria-label=&quot;Anchor link for: why-use-a-feed&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Say you follow a few interesting websites,
and they don’t post a flood of content,
not too often, and not even on any schedule.&lt;&#x2F;p&gt;
&lt;p&gt;If you regularly find yourself
checking these sites only to find nothing,
consider using web feeds.&lt;&#x2F;p&gt;
&lt;p&gt;Web feeds allow you to see updates
to your favourite sites in one place,
with the option to view it in the same place,
and even notify you of updates.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-does-it-work&quot;&gt;How does it work?&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-does-it-work&quot; aria-label=&quot;Anchor link for: how-does-it-work&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A feed is a simple link that you
put in a feed reader app,
usually by copying it.&lt;&#x2F;p&gt;
&lt;p&gt;Feed readers have varying degrees of functionality.
At a base level, they should be able to list posts
from all the people that you follow,
with a link to the post on their website.&lt;&#x2F;p&gt;
&lt;p&gt;Additional features include
viewing the post in the app,
which is fairly common,
searching all feeds and posts,
grouping them into categories,
receiving notifications on updates,
and more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-reader-should-i-use&quot;&gt;What reader should I use?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-reader-should-i-use&quot; aria-label=&quot;Anchor link for: what-reader-should-i-use&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s a short list of readers to get started with.
Feel free to research and find your own.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;rssisawesome.com&quot;&gt;RSS is Awesome&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you tend to consume content on a single device,
use this for a free and simple reader
with no sign-up and no ads.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;feedreader.com&#x2F;online&quot;&gt;Feed Reader&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Sign up to sync across devices,
so that you can check your feed anywhere,
without ads of any kind.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;feedly.com&quot;&gt;Feedly&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Feedly is quite big and well known,
with apps for multiple platforms,
at the cost of ads, sponsored content,
and other limitations for free accounts.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Ironically, I hammered out the feed
after I read a post by someone who doesn’t like feeds,
despite not caring for them myself,
just because I could.&lt;&#x2F;p&gt;
&lt;p&gt;I even went through the effort of styling it with XSL,
which was the main draw for me, honestly.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gkeenan.co&#x2F;avgb&#x2F;rss-readers-make-me-want-to-jump-into-a-vat-of-acid&quot;&gt;Why someone doesn’t like feeds&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Try djot instead of markdown</title>
            <published>2024-02-03T19:34:38+00:00</published>
            <updated>2024-04-13T19:38:19+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/djot-1/"/>
            <id>https://pranabekka.neocities.org/djot-1/</id>
            <summary type="html">
              Djot is a pretty cool markup format
that contains the lessons learnt by the author
of the CommonMark spec and implementation.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/djot-1/">
              &lt;p&gt;Djot is a pretty cool markup format
that contains the lessons learnt by the author
of the CommonMark spec and implementation.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve mentioned it here and there,
and thought I might as well write about it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;generic-blocks-and-attributes&quot;&gt;Generic blocks and attributes&lt;a class=&quot;zola-anchor&quot; href=&quot;#generic-blocks-and-attributes&quot; aria-label=&quot;Anchor link for: generic-blocks-and-attributes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One of the coolest features is generic blocks,
which are called “divs” and “spans” in the spec&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
as well as a method to add attributes to any element.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;htmlpreview.github.io&#x2F;?https:&#x2F;&#x2F;github.com&#x2F;jgm&#x2F;djot&#x2F;blob&#x2F;master&#x2F;doc&#x2F;syntax.html&quot;&gt;spec&#x2F;syntax description&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;::: class-name
A paragraph inside the div
:::
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Markdown would require HTML to do anything like this.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to divs and spans,
attributes can be attached to &lt;em&gt;anything&lt;&#x2F;em&gt; using curly braces.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Warning{.big .red data-type=&amp;quot;warning&amp;quot;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above markup will create a span with the “big red” class
and the &lt;code&gt;data-type=&amp;quot;warning&amp;quot;&lt;&#x2F;code&gt; attribute.&lt;&#x2F;p&gt;
&lt;p&gt;Again, markdown would require HTML to do anything of the sort.&lt;&#x2F;p&gt;
&lt;p&gt;Now, when I say attributes can be attached to anything,
I mean &lt;em&gt;anything&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{#custom-section-id}
## My heading

{.important}
An important paragraph,
likely styled with big text.

*some bold text that&amp;#39;s also red*{.red}

{lang=&amp;#39;javascript&amp;#39;}
```
var answer = &amp;#39;42&amp;#39;;
```
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;comments&quot;&gt;Comments&lt;a class=&quot;zola-anchor&quot; href=&quot;#comments&quot; aria-label=&quot;Anchor link for: comments&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Comments are solved in a very clever way.&lt;&#x2F;p&gt;
&lt;p&gt;Attributes can have comments inside them:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{.big .red % comment: red for warning % .important}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The text between the percent signs is a comment.&lt;&#x2F;p&gt;
&lt;p&gt;To have an independent comment,
simply remove any other content from the attribute block.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{% This is a comment %}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;raw-blocks&quot;&gt;Raw blocks&lt;a class=&quot;zola-anchor&quot; href=&quot;#raw-blocks&quot; aria-label=&quot;Anchor link for: raw-blocks&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Another useful construct is raw blocks,
which allow you to pass something into the final output as is,
depending on the export format you select,
without any escaping or processing.&lt;&#x2F;p&gt;
&lt;p&gt;If I were exporting to HTML,
and I wanted to have some specific HTML markup in the output,
I could do the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;``` =html
&amp;lt;my-html-tag-soup &#x2F;&amp;gt;
```
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The inline version of the same is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Some `&amp;lt;my-tag-soup &#x2F;&amp;gt;`{=html} inline
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;try-it-out&quot;&gt;Try it out&lt;a class=&quot;zola-anchor&quot; href=&quot;#try-it-out&quot; aria-label=&quot;Anchor link for: try-it-out&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Overall it’s a really cool format,
and you can try it out now in the live sandbox!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;djot.net&#x2F;playground&#x2F;&quot;&gt;Live sandbox&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you like it, you can see
if one of the implementations listed in the home page
might suit your purposes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;djot.net&quot;&gt;Djot home page&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
        <entry xml:lang="en">
            <title>Flatpak</title>
            <published>2024-01-29T20:55:13+00:00</published>
            <updated>2024-01-29T20:55:13+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/flatpak/"/>
            <id>https://pranabekka.neocities.org/flatpak/</id>
            <summary type="html">
              Low network speeds and limited availability
are a fact of life for me.
I update my devices every 7 days,
and the size of a single Flatpak package
(around 350mb on the lower side)
is often larger than the regular apt updates,
if not comparable to updates that include
Firefox, Chrome, Inkscape, and/or Linux.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/flatpak/">
              &lt;p&gt;Low network speeds and limited availability
are a fact of life for me.
I update my devices every 7 days,
and the size of a &lt;em&gt;single&lt;&#x2F;em&gt; Flatpak package
(around 350mb on the lower side)
is often larger than the regular apt updates,
if not comparable to updates that include
Firefox, Chrome, Inkscape, and&#x2F;or Linux.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps it’s not fair to compare them,
but these are my needs,
and it’s a pain every time a developer
chooses to release their package only on Flatpak.
I will likely not use it,
and certainly not update it for weeks or months.&lt;&#x2F;p&gt;
&lt;p&gt;The team behind Flatpaks could have instead
worked on tooling to smooth out publishing packages.
Perhaps documentation for how updates are handled.
Maybe include permissions&#x2F;capabilities in package descriptions.
They could have worked with maintainers.
Instead they got nerdsniped into creating a whole
package format and ecosystem that still suffers.&lt;&#x2F;p&gt;
&lt;p&gt;They have to contend with managing permissions,
poking holes through their sandbox,
making sure people can’t poke through the sandbox,
making it easy to build and publish packages,
documenting all of these things, and more.
Including relying on developers
to maintain dependencies and security.&lt;&#x2F;p&gt;
&lt;p&gt;I appreciate GNOME design otherwise,
even though I use the terminal and tiling WMs,
but this frustrates me.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
      
      
      
      
      
      
      
        <entry xml:lang="en">
            <title>Ceci n&#x27;est pas Wordle devlog</title>
            <published>2023-12-18T14:00:16+00:00</published>
            <updated>2023-12-18T14:00:16+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/not-wordle/"/>
            <id>https://pranabekka.neocities.org/not-wordle/</id>
            <summary type="html">
              Bonjour!
Welcome to devlog 1 of 1:
why I made a Wordle clone
(and then another),
as well as some tips and design choices.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/not-wordle/">
              &lt;p&gt;Bonjour!
Welcome to devlog 1 of 1:
why I made a Wordle clone
(and then another),
as well as some tips and design choices.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;not-wordle-v1.png&quot; alt=&quot;screenshot of v1&quot; &#x2F;&gt;
(Version 1, with a static grid and a single input field
for typing out your guess)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;not-wordle-v2.png&quot; alt=&quot;screenshot of v2&quot; &#x2F;&gt;
(Version 2, with a grid of input cells,
so you can type in letters directly in the grid)&lt;&#x2F;p&gt;
&lt;p&gt;Try &lt;a href=&quot;&#x2F;not-wordle-v2.html&quot;&gt;Ceci n’est pas Wordle&lt;&#x2F;a&gt;! (version 2)&lt;&#x2F;p&gt;
&lt;p&gt;Here’s why I made it:
basically, I was mad at a friend,
and I didn’t want to just rant at him —
I had to curse him in a &lt;em&gt;nice&lt;&#x2F;em&gt; way.
After racking my brain for a day or two,
I figured it out —
I’d make him find out exactly what he was
(a f***er, if you must know,
since other words would be too long).&lt;&#x2F;p&gt;
&lt;p&gt;After that I couldn’t resist sharing it with other people
(I obviously changed the word),
because it’s quite fun to share something I made,
plus I could pick a funny or silly word
that referenced the day we had,
or a random conversation or event.&lt;&#x2F;p&gt;
&lt;p&gt;(Btw, “ceci n’est pas” means “this is not”)&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, here’s some little things I learnt
as I worked on my clone(s),
in rough order of usefulness.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;consider-a-custom-keyboard-or-a-single-input&quot;&gt;Consider a custom keyboard or a single input&lt;a class=&quot;zola-anchor&quot; href=&quot;#consider-a-custom-keyboard-or-a-single-input&quot; aria-label=&quot;Anchor link for: consider-a-custom-keyboard-or-a-single-input&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When using the current (v2) design,
it requires adding in some special handling for some keys,
so that the focussed input automatically switches back and forth,
which can cause issues,
because some keyboards (on Android, at least)
don’t like sharing what keys have been pressed.&lt;&#x2F;p&gt;
&lt;p&gt;The default keyboards work though (even on iOS).&lt;&#x2F;p&gt;
&lt;p&gt;So if you’re facing issues with handling input,
or if you want to make it really robust,
either you make a custom keyboard with divs,
or you use a single input with a ‘submit’ button.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-letters-or-less&quot;&gt;5 letters (or less)&lt;a class=&quot;zola-anchor&quot; href=&quot;#5-letters-or-less&quot; aria-label=&quot;Anchor link for: 5-letters-or-less&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Longer than that starts to become quite hard to guess,
and then your friends and family will just feel bad.
It’s fine if you’re around to monitor and give hints though.&lt;&#x2F;p&gt;
&lt;p&gt;One reason is that when you think of a word,
you need to count out the letters,
and it becomes harder as you go.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t think it’s that longer words are inherently harder,
since they can give a chance to reveal more letters,
but that might also contribute to the problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;show-letters-in-the-grid&quot;&gt;Show letters in the grid&lt;a class=&quot;zola-anchor&quot; href=&quot;#show-letters-in-the-grid&quot; aria-label=&quot;Anchor link for: show-letters-in-the-grid&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My first design had an input element
for people to enter their guess
and then it would add their guess to the grid above.
This would cause confusion by having no response
when trying to submit a guess, because
it was hard to see that there were too few letters.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s how it looked:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;not-wordle-v1.png&quot; alt=&quot;screenshot of v1&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;While there’s a counter at the bottom,
it would either get covered up by the keyboard,
or people would not think or realise that it updated.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the benefits of the design:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;See your guess in context, before submitting.&lt;&#x2F;li&gt;
&lt;li&gt;Immediately see which letters are missing, and how many.&lt;&#x2F;li&gt;
&lt;li&gt;Fill in the letters you know.
&lt;ul&gt;
&lt;li&gt;Don’t delete the whole word to change your guess.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Use less space on the grid.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;set-height-and-width-for-cells&quot;&gt;Set height and width for cells&lt;a class=&quot;zola-anchor&quot; href=&quot;#set-height-and-width-for-cells&quot; aria-label=&quot;Anchor link for: set-height-and-width-for-cells&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This applies more to my initial design,
which used &lt;code&gt;div&lt;&#x2F;code&gt; elements instead of input fields.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re using divs to show the grid,
then empty cells just disappear.&lt;&#x2F;p&gt;
&lt;p&gt;Set a height and width anyway,
so that it looks nice and consistent,
instead of the (quite ugly) default style,
which is too wide, and quite small
(even if you increase base font size —
you’ll have to change that as well).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;add-a-start-button&quot;&gt;Add a start button&lt;a class=&quot;zola-anchor&quot; href=&quot;#add-a-start-button&quot; aria-label=&quot;Anchor link for: add-a-start-button&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A start button at the bottom is nice,
so that you can start the game
without having to reach to the top of the screen,
which is always awkward.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-add-a-border-for-keyboard-references&quot;&gt;Don’t add a border for keyboard references&lt;a class=&quot;zola-anchor&quot; href=&quot;#don-t-add-a-border-for-keyboard-references&quot; aria-label=&quot;Anchor link for: don-t-add-a-border-for-keyboard-references&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There’s a minor issue in my version 2 screenshot:
the keyboard references for the ‘enter’ key
look like buttons,
so some people try pressing those instead
of the enter button on their keyboard.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-design&quot;&gt;Final design&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-design&quot; aria-label=&quot;Anchor link for: final-design&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;not-wordle-v2.png&quot; alt=&quot;screenshot of v1&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Give &lt;a href=&quot;&#x2F;not-wordle-v2.html&quot;&gt;Ceci n’est pas Wordle&lt;&#x2F;a&gt; a try!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;make-your-own&quot;&gt;Make your own&lt;a class=&quot;zola-anchor&quot; href=&quot;#make-your-own&quot; aria-label=&quot;Anchor link for: make-your-own&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can just copy the HTML, change the &lt;code&gt;WORD&lt;&#x2F;code&gt; variable &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
and then share it with someone!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;not-wordle-v2.html&quot; download&gt;Download Wordle clone&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Remember to pick a 5 letter word or less,
unless you’re there to give hints.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;look for &lt;code&gt;const WORD = &#x27;&amp;lt;a-word&amp;gt;&#x27;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>UI&#x2F;UX Design Principles</title>
            <published>2023-11-07T14:52:17+00:00</published>
            <updated>2023-11-07T14:52:17+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/design-principles/"/>
            <id>https://pranabekka.neocities.org/design-principles/</id>
            <summary type="html">
              Some of the choices behind most of my designs.
I can sometimes sacrifice these, based on context,
but I adhere to them most of the time.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/design-principles/">
              &lt;p&gt;Some of the choices behind most of my designs.
I can sometimes sacrifice these, based on context,
but I adhere to them most of the time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mobile-first&quot;&gt;Mobile first&lt;a class=&quot;zola-anchor&quot; href=&quot;#mobile-first&quot; aria-label=&quot;Anchor link for: mobile-first&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Most users of any digital product are on mobile.
Especially if it’s a website —
even users of a desktop application
will visit a website on mobile.&lt;&#x2F;p&gt;
&lt;p&gt;Designing for mobile also helps figure out
what is most important in a product.&lt;&#x2F;p&gt;
&lt;p&gt;Also, it’s easier to spread out content
from a mobile layout to a desktop layout,
than to try to fit in the contents of
a desktop layout into a mobile screen.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;interactive-area-in-lower-half&quot;&gt;Interactive area in lower half&lt;a class=&quot;zola-anchor&quot; href=&quot;#interactive-area-in-lower-half&quot; aria-label=&quot;Anchor link for: interactive-area-in-lower-half&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Having interactive elements in the top half
requires users to move a hand to the top of the phone,
or to make awkward reaches with their thumb.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, I put buttons
at the middle of the screen or lower.
If the user scrolls down,
buttons will also move up the screen.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;large-fonts&quot;&gt;Large fonts&lt;a class=&quot;zola-anchor&quot; href=&quot;#large-fonts&quot; aria-label=&quot;Anchor link for: large-fonts&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I use large fonts to accomodate for
conditions with hampered vision,
such as age, moving vehicles, walking, etc.&lt;&#x2F;p&gt;
&lt;p&gt;This usually means 14pt or 16pt for body text.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clear-labels&quot;&gt;Clear labels&lt;a class=&quot;zola-anchor&quot; href=&quot;#clear-labels&quot; aria-label=&quot;Anchor link for: clear-labels&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Icons can often have multiple meanings,
which might not be obvious to some users,
or might even have no meaning to some people.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;large-interactive-areas&quot;&gt;Large interactive areas&lt;a class=&quot;zola-anchor&quot; href=&quot;#large-interactive-areas&quot; aria-label=&quot;Anchor link for: large-interactive-areas&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I make interactive areas roughly 44 pixels by 44 pixels or larger,
usually with a minimum of 8 pixel gaps between them.&lt;&#x2F;p&gt;
&lt;p&gt;This makes it easier to target for users,
without accidentally selecting the wrong element.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;consistent-interactive-element-style&quot;&gt;Consistent interactive element style&lt;a class=&quot;zola-anchor&quot; href=&quot;#consistent-interactive-element-style&quot; aria-label=&quot;Anchor link for: consistent-interactive-element-style&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I try to have a distinctive style for buttons and links
so that users immediately know
what elements can be interacted with,
and what elements are safe to select.&lt;&#x2F;p&gt;
&lt;p&gt;Modern UIs nowadays often have a dozen different button styles,
some of which even look like plain text.
It sometimes feels like there is no system
for what constitutes a button versus images or text.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dark-mode&quot;&gt;Dark mode&lt;a class=&quot;zola-anchor&quot; href=&quot;#dark-mode&quot; aria-label=&quot;Anchor link for: dark-mode&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Using a website at night time, or in a dark environment,
shouldn’t subject the viewer to (sudden) brightness,
which can negatively affect
their vision, their sleep, and more.&lt;&#x2F;p&gt;
&lt;p&gt;For the same reason, I try to use warm colours&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
though people generally expect blue for interactions,
and red for negative interactions.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Night light filters do the same,
because of something to do with white or blue-ish colours.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;slightly-lowered-contrast&quot;&gt;Slightly lowered contrast&lt;a class=&quot;zola-anchor&quot; href=&quot;#slightly-lowered-contrast&quot; aria-label=&quot;Anchor link for: slightly-lowered-contrast&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;100% white text on a 100% black background
can cause a “halation” effect for some users,
which means it looks like a light pointed at your eyes,
where the edges are blurry and hard to see.&lt;&#x2F;p&gt;
&lt;p&gt;There might be some other issues with full contrast,
but this is a good enough reason to lower it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lightweight&quot;&gt;Lightweight&lt;a class=&quot;zola-anchor&quot; href=&quot;#lightweight&quot; aria-label=&quot;Anchor link for: lightweight&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Websites should be usable with low network conditions,
such as being underground, or in a building.&lt;&#x2F;p&gt;
&lt;p&gt;This can be achieved
by only including necessary content,
and optimising images and videos.&lt;&#x2F;p&gt;
&lt;p&gt;For images, I compare file sizes for different formats.
Generally, I use SVGs for simple graphics and illustrations,
and PNGs or JPGs for photographs,
though the AVIF format is supposed to be the best.&lt;&#x2F;p&gt;
&lt;p&gt;A related idea is progressive enhancement,
where you ensure a basic version of the main content
is actually usable as is,
and then build better UI&#x2F;UX on top of that.
This requires some understanding of HTML,
and interacting with the developer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;content-first&quot;&gt;Content first&lt;a class=&quot;zola-anchor&quot; href=&quot;#content-first&quot; aria-label=&quot;Anchor link for: content-first&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The content of the page should stand out.&lt;&#x2F;p&gt;
&lt;p&gt;You can see it in my site design:
in each page, the title is highlighted,
and then it continues on into the body of the post.
I even sacrificed the navigation bar on top
so that the content had more space&#x2F;prominence
when the user first loads a page.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clarity-over-cleverness&quot;&gt;Clarity over cleverness&lt;a class=&quot;zola-anchor&quot; href=&quot;#clarity-over-cleverness&quot; aria-label=&quot;Anchor link for: clarity-over-cleverness&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I try to avoid clever designs,
because some users will simply be confused.
For example, it’s not really that obvious
that you must scroll up (on mobile)
to show a hidden navigation bar.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;design-annotations&quot;&gt;Design Annotations&lt;a class=&quot;zola-anchor&quot; href=&quot;#design-annotations&quot; aria-label=&quot;Anchor link for: design-annotations&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;On screen buttons aren’t the only method of interaction.
Keyboard shortcuts and touch gestures
are not obvious from designs.
Designs should include annotations for these things.&lt;&#x2F;p&gt;
&lt;p&gt;While I don’t actually annotate things,
that’s mostly because of no particular need,
and I do consider them and explain them in writing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;accessibility-for-everyone&quot;&gt;Accessibility for everyone&lt;a class=&quot;zola-anchor&quot; href=&quot;#accessibility-for-everyone&quot; aria-label=&quot;Anchor link for: accessibility-for-everyone&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This ties into many of the points above:
Everyone has “disabilities” of some variety
at one point or the other.&lt;&#x2F;p&gt;
&lt;p&gt;Injuries can reduce dexterity in the hands,
moving vehicles can hamper vision and reading,
and crowded environments impact hearing.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Oh! That&#x27;s cold!</title>
            <published>2023-10-30T20:53:19+00:00</published>
            <updated>2023-10-31T14:34:35+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/oh-thats-cold-microfiction/"/>
            <id>https://pranabekka.neocities.org/oh-thats-cold-microfiction/</id>
            <summary type="html">
              Low sci-fi speculative micro-fiction
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/oh-thats-cold-microfiction/">
              &lt;p&gt;Low sci-fi speculative micro-fiction&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Oh! That’s cold!&lt;&#x2F;p&gt;
&lt;p&gt;I suddenly felt little cold spots on my face.&lt;&#x2F;p&gt;
&lt;p&gt;It was you, and you asked me to trust you.&lt;&#x2F;p&gt;
&lt;p&gt;My gear is now off.&lt;&#x2F;p&gt;
&lt;p&gt;Now we’re sitting outside, silently,
thoughts racing, or blanking out,
our hands intertwined;
and this is nice, but I’m not sure if I’d do it again.&lt;&#x2F;p&gt;
&lt;p&gt;It took a while to adjust after taking off the wear.
My eyes aren’t watering anymore,
but it still feels weird.
Everything does — a bit.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t think I could do this again.&lt;&#x2F;p&gt;
&lt;p&gt;I love you.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The basic concept is a society
where headgear is a thing,
and people live completely
in virtual&#x2F;augmented space.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
      
        <entry xml:lang="en">
            <title>Ekkas&#x27;</title>
            <published>2023-10-17T21:38:26+00:00</published>
            <updated>2023-10-17T21:38:26+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/ekkas/"/>
            <id>https://pranabekka.neocities.org/ekkas/</id>
            <summary type="html">
              Bridal accessories website design and live concept.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/ekkas/">
              &lt;p&gt;Bridal accessories website design and live concept.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;ekkas.html&quot;&gt;See Live Concept&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When I showed &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;dymes&#x2F;&quot;&gt;Dyme’s&lt;&#x2F;a&gt; to my mum and aunts,
it turned out they’d been talking about a little
bridal accessories business the other day,
so we discussed it a little bit,
and I just mocked up another website in the same vein.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;ekkas.png&quot; alt=&quot;Screenshot of website on mobile. The website title says “Ekkas’”, and subtitle says “We make tasteful bridal accessories.” Below the subtitle are three icons: a head with a veil on it, a basket, and a set of flowers. Under the icons is the text “Veils, flower baskets, and bouquets.” Further below are two buttons for Call and Message, with the Call button more prominent, and a placeholder number (8765487654) below them. Under that you can see an image of a bouquet, and further below is cut off text saying “Pricing” in larger bold font (a heading).&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Like &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;dymes&#x2F;&quot;&gt;Dyme’s&lt;&#x2F;a&gt;,
I tried to make something simple and easily achievable.
The CTA here encourages calling
because the deliverables are more complex,
and it makes sense to work out everything.
I also show the contact information separately,
so that people can share it easily.
The final versions of the two websites (this and Dyme’s)
could use a separate share button as well.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;portfolio&#x2F;&quot;&gt;More Projects (Portfolio)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Dyme&#x27;s</title>
            <published>2023-10-15T09:43:48+00:00</published>
            <updated>2023-10-15T09:43:48+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/dymes/"/>
            <id>https://pranabekka.neocities.org/dymes/</id>
            <summary type="html">
              My aunt’s cooking is better than the restaurants
I’ve eaten from in Ranchi and Khunti
(perhaps excepting Radison Blu).
So I thought that her food should be shared with people,
and this website design is a result of that idea.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/dymes/">
              &lt;p&gt;My aunt’s cooking is better than the restaurants
I’ve eaten from in Ranchi and Khunti
(perhaps excepting Radison Blu).
So I thought that her food should be shared with people,
and this website design is a result of that idea.&lt;&#x2F;p&gt;
&lt;p&gt;I even made an actual webpage
that you should check out :D&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;dymes.html&quot;&gt;See Live Concept&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;dymes.png&quot; alt=&quot;Website screen mockup&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;dymes-light.png&quot; alt=&quot;Website screen mockup&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I worked especially to make the idea achievable,
instead of a fancy restaurant menu or dashboard.&lt;&#x2F;p&gt;
&lt;p&gt;You can get a better understanding
if you scroll through the &lt;a href=&quot;&#x2F;dymes.html&quot;&gt;website concept&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The site design is super simple,
things are operated by email,
and I put a lot of thought into the overall system,
such as the number of seats and the waitlist.
I’ll probably write about it in more detail in a separate post.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;portfolio&#x2F;&quot;&gt;More Projects (Portfolio)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Links</title>
            <published>2023-10-06T11:44:15+00:00</published>
            <updated>2024-05-07T11:00:39+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/links/"/>
            <id>https://pranabekka.neocities.org/links/</id>
            <summary type="html">
              The contents of this page have been moved to “Bookmarks”.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/links/">
              &lt;p&gt;The contents of this page have been moved to “Bookmarks”.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;bookmarks&#x2F;&quot;&gt;Bookmarks&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The term better conveys what the page is,
and avoids confusion with Linktree-style ‘bio’ links.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>About</title>
            <published>2023-09-26T14:46:13+00:00</published>
            <updated>2024-01-04T18:46:51+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/about/"/>
            <id>https://pranabekka.neocities.org/about/</id>
            <summary type="html">
              A brief introduction to me and the site,
including tips on how to use it (the site, not me).
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/about/">
              &lt;p&gt;A brief introduction to me and the site,
including tips on how to use it (the site, not me).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;about-me&quot;&gt;About Me&lt;a class=&quot;zola-anchor&quot; href=&quot;#about-me&quot; aria-label=&quot;Anchor link for: about-me&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Where me = “Pranab” (he&#x2F;him).&lt;&#x2F;p&gt;
&lt;p&gt;I have a formal education in design,
with my current focus on UI&#x2F;UX design,
but I’ve also had an interest in computers since school,
starting with Scratch and the like.&lt;&#x2F;p&gt;
&lt;p&gt;Some of my interests include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Reading: especially (science) fiction,
but I read a lot of blog posts on various subjects,
though I find good tech blogs the easiest to find.&lt;&#x2F;li&gt;
&lt;li&gt;UI&#x2F;UX Design: I’ve been looking into accessibility lately,
and I quite enjoy a brutalist&#x2F;swiss&#x2F;functional style
that relies more on text,
though I try to infuse some popular aesthetics into it
and play around with other styles.&lt;&#x2F;li&gt;
&lt;li&gt;Writing:
that’s how I maintain this blog ;)
I can write nonsense about whatever’s going on in my head,
but also notes on things I read or ideas I have,
as well as short snippets of fiction.
I might write a book someday.&lt;&#x2F;li&gt;
&lt;li&gt;Shell Scripting: I’m fairly proficient
in using the (Fish) shell and scripting,
and I have a few small utilities I use here and there.&lt;&#x2F;li&gt;
&lt;li&gt;Programming: I have a decent grasp of most concepts,
and I can navigate code well enough,
even if I don’t know the language,
but I haven’t written or maintained
a decently sized codebase.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;contact&quot;&gt;Contact&lt;a class=&quot;zola-anchor&quot; href=&quot;#contact&quot; aria-label=&quot;Anchor link for: contact&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You can reach me via email or Mastodon&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Email: &lt;a href=&quot;mailto:pranabekka@gmail.com&quot;&gt;pranabekka@gmail.com&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Mastodon: &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@pranabekka&quot;&gt;@pranabekka@mastodon.social&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Mastodon is a twitter-like social media,
except anyone can create a copy of it for their community,
and all copies can talk to each other.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;about-the-site&quot;&gt;About the Site&lt;a class=&quot;zola-anchor&quot; href=&quot;#about-the-site&quot; aria-label=&quot;Anchor link for: about-the-site&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Built Using &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&quot;&gt;Zola&lt;&#x2F;a&gt;
(Static Site Generator)&lt;&#x2F;p&gt;
&lt;p&gt;Custom theme made by me.
See choices below.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;“zettelkasten”-like
&lt;ul&gt;
&lt;li&gt;no categories
&lt;ul&gt;
&lt;li&gt;could add tags in the future?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;backreferences
&lt;ul&gt;
&lt;li&gt;posts link to each other&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;flat structure&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;8px gap between interactive elements (where possible)
to reduce chances of tapping adjacent element&lt;&#x2F;li&gt;
&lt;li&gt;large-ish font size for people with poor eyesight&lt;&#x2F;li&gt;
&lt;li&gt;no “flashbang”: dark theme
&lt;ul&gt;
&lt;li&gt;“flashbang” is when you suddenly load a bright page&lt;&#x2F;li&gt;
&lt;li&gt;might make a light theme eventually&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;avoid full black&#x2F;white to reduce glare effect (halation).
not sure what other issues it might cause&lt;&#x2F;li&gt;
&lt;li&gt;low contrast, while preserving AAA contrast compliance,
to accomodate users affected by high contrast,
and to be dimmer for night time users (like me).
i need to add a check and control to increase contrast.&lt;&#x2F;li&gt;
&lt;li&gt;show all posts in single page to make basic search easy&lt;&#x2F;li&gt;
&lt;li&gt;three heading levels
&lt;ul&gt;
&lt;li&gt;inspired by edward tufte&lt;&#x2F;li&gt;
&lt;li&gt;not a hard rule, but easy to stick to&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;number headings to match list of contents (“table” of contents)&lt;&#x2F;li&gt;
&lt;li&gt;rounded inline code to show start and end,
especially when spanning multiple lines (on mobile)&lt;&#x2F;li&gt;
&lt;li&gt;higher contrast for smaller areas
&lt;ul&gt;
&lt;li&gt;highlight colour is brighter when used in underlines,
than the colour used in the title&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;“logo” in header and tab title to make pages from site apparent&lt;&#x2F;li&gt;
&lt;li&gt;no custom fonts (imports) to save on page size and loading time&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pranabekka&#x2F;pranabekka.github.io&quot;&gt;Site source&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;usage-tips&quot;&gt;Usage Tips&lt;a class=&quot;zola-anchor&quot; href=&quot;#usage-tips&quot; aria-label=&quot;Anchor link for: usage-tips&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;index is a good place to search the site&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;it shows &lt;em&gt;all&lt;&#x2F;em&gt; posts, though only title and first paragraph&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;search using the following snippet in your search provider
(remember to replace &lt;code&gt;&amp;lt;search term&amp;gt;&lt;&#x2F;code&gt;
with what you’re looking for).&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;site:pranabekka.github.io &amp;lt;search term&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This works with all major search providers.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;references to current page appear at the bottom&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;other related pages appear in the body&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;page source can be used to view history.
if you’re unfamiliar with github,
select the history icon near the top left.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Now Playing</title>
            <published>2023-09-22T23:38:47+00:00</published>
            <updated>2023-09-22T23:38:47+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/ku-lo-sa/"/>
            <id>https://pranabekka.neocities.org/ku-lo-sa/</id>
            <summary type="html">
              KU LO SA by Oxlade and Camila Cabello
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/ku-lo-sa/">
              &lt;p&gt;KU LO SA by Oxlade and Camila Cabello&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;music.youtube.com&#x2F;watch?v=kquPJC4cq7o&quot;&gt;Listen on YouTube Music&lt;&#x2F;a&gt;
(You’ll have to search for other platforms)&lt;&#x2F;p&gt;
&lt;p&gt;I’ve been into whatever this genre is lately:
Nigerian hip hop, I guess.&lt;&#x2F;p&gt;
&lt;p&gt;It started with Wetin by Yarden,
followed by KOLO by Ice Prince and Oxlade (amongst others),
though I’ve liked Jamaican Patois for a while,
and I’ve been listening to African-origin rappers
from the US and UK for even longer.
I even enjoyed the Patois bits from Top Boy a lot.&lt;&#x2F;p&gt;
&lt;p&gt;My favourite bit is the chorus at the end.
Makes me just play the song again.
It’s simply so upbeat and makes me want to dance
even while I’m walking along in front of other people.&lt;&#x2F;p&gt;
&lt;p&gt;If you liked KU LO SA,
you can also check out these songs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Wetin by Yarden&lt;&#x2F;li&gt;
&lt;li&gt;Toast by Koffee&lt;&#x2F;li&gt;
&lt;li&gt;soso by Omah Lay&lt;&#x2F;li&gt;
&lt;li&gt;KOLO by Ice Prince and Oxlade&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Expose Product Team to Users</title>
            <published>2023-09-18T20:42:10+00:00</published>
            <updated>2023-09-18T20:42:10+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/user-exposure/"/>
            <id>https://pranabekka.neocities.org/user-exposure/</id>
            <summary type="html">
              Designers should be directly exposed to users
(as opposed to only relying on reports
from a dedicated user research team).
Notes on article by Center Centre.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/user-exposure/">
              &lt;p&gt;Designers should be directly exposed to users
(as opposed to only relying on reports
from a dedicated user research team).
Notes on article by Center Centre.&lt;&#x2F;p&gt;
&lt;p&gt;Original article:
&lt;a href=&quot;https:&#x2F;&#x2F;articles.centercentre.com&#x2F;user_exposure_hours&quot;&gt;Fast Path to a Great UX – Increased Exposure Hours&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Amount of time spent with a user&#x2F;users
is more important than the number of research participants.&lt;&#x2F;p&gt;
&lt;p&gt;At least two hours every six weeks is best,
since it reinforces learnings.&lt;&#x2F;p&gt;
&lt;p&gt;All team members (not just designers and developers)
should be exposed to users to get the whole team on board.&lt;&#x2F;p&gt;
&lt;p&gt;Field visits are especially helpful for initial exposure.
Usability tests can be made based on pain points recorded from field visits.
Don’t rely completely on remote testing.
Observing users with competing products is also helpful.&lt;&#x2F;p&gt;
&lt;p&gt;Field visits, as defined:
“interview the user, uncover their goals and objectives,
and then ask them to use the product or service to accomplish those.”&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Design Takeaways from Fabricio Teixeira</title>
            <published>2023-08-17T11:47:33+00:00</published>
            <updated>2023-08-17T11:47:33+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/lessons-design/"/>
            <id>https://pranabekka.neocities.org/lessons-design/</id>
            <summary type="html">
              These are my takeaways from
“The musings of a designer and what he loves
about design and what he’s learned along the way” (2023)
by Fabricio Teixeira.
I found it full of practical and actionable advice and
I recommend you read the whole article yourself:
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/lessons-design/">
              &lt;p&gt;These are my takeaways from
“The musings of a designer and what he loves
about design and what he’s learned along the way” (2023)
by Fabricio Teixeira.
I found it full of practical and actionable advice and
I recommend you read the whole article yourself:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lessons.design&#x2F;&quot;&gt;lessons.design&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;a class=&quot;zola-anchor&quot; href=&quot;#takeaways&quot; aria-label=&quot;Anchor link for: takeaways&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I don’t quite understand what frameworks is about,
and I understand and appreciate
the points on simplicity and consistency a fair bit,
but my biggest takeaway is on framing:&lt;&#x2F;p&gt;
&lt;p&gt;You should present your idea
as a starting quote, image, video, metaphor,
or &lt;em&gt;something&lt;&#x2F;em&gt; to introduce the idea to your audience.
See the emphasised points under
&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;lessons-design&#x2F;#framing&quot;&gt;the section on framing&lt;&#x2F;a&gt; for more.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;framework&quot;&gt;framework&lt;a class=&quot;zola-anchor&quot; href=&quot;#framework&quot; aria-label=&quot;Anchor link for: framework&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;have a model&#x2F;framework  for the
product. to represent and understand the
subject of the product. this should not
change as the product evolves, and
should keep the product consistent&lt;&#x2F;li&gt;
&lt;li&gt;identify and emphasise the core
differentiating factor  of your
framework. make it incredibly obvious&lt;&#x2F;li&gt;
&lt;li&gt;don’t stick to preconceived notions of
the problem&#x2F;subject area&lt;&#x2F;li&gt;
&lt;li&gt;test concepts by making prototypes
with exaggerated differences&lt;&#x2F;li&gt;
&lt;li&gt;make frameworks and get inspiration
from beyond design&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;simplicity&quot;&gt;simplicity&lt;a class=&quot;zola-anchor&quot; href=&quot;#simplicity&quot; aria-label=&quot;Anchor link for: simplicity&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;if two things are similar, bring them
closer, merge them, or separate them
further&lt;&#x2F;li&gt;
&lt;li&gt;whitespace is for the eyes to rest and
absorb things&lt;&#x2F;li&gt;
&lt;li&gt;descriptions with “and” or “also”
suggest that the product is doing too
much&lt;&#x2F;li&gt;
&lt;li&gt;words and writing can merge things
together, make them shorter, make them
less generic&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;framing&quot;&gt;framing&lt;a class=&quot;zola-anchor&quot; href=&quot;#framing&quot; aria-label=&quot;Anchor link for: framing&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you read the article a second time,
you’ll see that he uses these ideas
at the beginning of the page,
as well at the beginning of every chapter.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;frame the product such that you
present your reasoning and make it
apparent to people&lt;&#x2F;li&gt;
&lt;li&gt;learn to see the rationale behind
designs, to learn how to frame your own&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;you can frame a product with a
conceptual word, an image, an animation,
a video, a short sentence, a metaphor,
a drawing, a framework, a datapoint, a
quote&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;don’t just describe the layout of the
product (which is already visible).
describe how it will benefit users, how
it reaches business goals, the reasoning
behind it&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;framing gives people time, context and
insight about the design, which makes
it easier to understand&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;consistency&quot;&gt;consistency&lt;a class=&quot;zola-anchor&quot; href=&quot;#consistency&quot; aria-label=&quot;Anchor link for: consistency&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;consistency means designing for the
future — not just for present delight
or use&lt;&#x2F;li&gt;
&lt;li&gt;consistency helps users as well as
creators (team)&lt;&#x2F;li&gt;
&lt;li&gt;double check work to ensure quality,
consistency&lt;&#x2F;li&gt;
&lt;li&gt;don’t pursue consistency in the face
of context&lt;&#x2F;li&gt;
&lt;li&gt;the people you work with will last
longer than the products you work on.
joy in that is what lasts&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Significant Whitespace Lisp Syntax</title>
            <published>2023-07-11T04:39:16+00:00</published>
            <updated>2023-07-11T04:39:16+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/whitespace-lisp-syntax/"/>
            <id>https://pranabekka.neocities.org/whitespace-lisp-syntax/</id>
            <summary type="html">
              I was browsing the web when I came upon
the Rhombus language by the Racket team,
and I couldn’t help but have
a few thoughts of my own for a Lisp syntax
with significant whitespace.
The key difference in my idea
is that it works quite transparently with s-expressions,
and has some extra sugar and rules
to help with parentheses elision.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/whitespace-lisp-syntax/">
              &lt;p&gt;I was browsing the web when I came upon
the Rhombus language by the Racket team,
and I couldn’t help but have
a few thoughts of my own for a Lisp syntax
with significant whitespace.
The key difference in my idea
is that it works quite transparently with s-expressions,
and has some extra sugar and rules
to help with parentheses elision.&lt;&#x2F;p&gt;
&lt;p&gt;NOTE: Some knowledge of Lisp is assumed.&lt;&#x2F;p&gt;
&lt;p&gt;NOTE: Elision (removal) rules only mean that there are ways
for the computer to infer the position of parentheses.
You can still use parentheses, as demonstrated later.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;function-calls&quot;&gt;Function Calls&lt;a class=&quot;zola-anchor&quot; href=&quot;#function-calls&quot; aria-label=&quot;Anchor link for: function-calls&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The first word (symbol) in a line is a function call,
and the rest are arguments, subject to variable expansion.
This is an example of parentheses elision:
you can elide (remove) the parentheses,
since their position is inferred
at the beginning and end of a line
(not quite, see next point).&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;my-func arg1 arg2

; turns into:

(my-func arg1 arg2)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;sub-expressions-blocks-functions-as-arguments&quot;&gt;Sub-Expressions&#x2F;Blocks (Functions as Arguments)&lt;a class=&quot;zola-anchor&quot; href=&quot;#sub-expressions-blocks-functions-as-arguments&quot; aria-label=&quot;Anchor link for: sub-expressions-blocks-functions-as-arguments&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;An indented line starts a sub-expression
in the form immediately above it in the “indentation hierarchy”.
So the automatic placement of parentheses
is slightly more complicated —
if the next line (expression) is indented,
then the closing parenthesis is held off
until a line with less indentation is encountered
(or the end of the file).&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fun1 arg-x
  fun2 arg-n

; turns into

(fun1 arg-x
  (fun2 arg-n))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fun3
  fun4
  fun5

; turns into

(fun3 (fun4) (fun5))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;inline-syntax&quot;&gt;Inline Syntax&lt;a class=&quot;zola-anchor&quot; href=&quot;#inline-syntax&quot; aria-label=&quot;Anchor link for: inline-syntax&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The above rules with significant whitespace
might also be called “block syntax”,
since it necessarily requires blocks
that span both dimensions.
The parentheses syntax may also be called “inline syntax”,
since it can be written in a single line
without changing the meaning
(although it severely impacts readability).&lt;&#x2F;p&gt;
&lt;p&gt;The two syntaxes can be mixed together
to create more complicated forms.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let (
    variable value
  )
  my-fun variable

; turns into

(let (
    (variable value)
  )
  (my-fun variable))

; which is the same as

(let ((variable value))
  (my-fun variable))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(You need not write it as shown above.)&lt;&#x2F;p&gt;
&lt;p&gt;The following also achieves the same thing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let (
    variable value )
  my-fun variable
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;sugar-for-list-of-lists&quot;&gt;Sugar: &lt;code&gt;[]&lt;&#x2F;code&gt; (for List of Lists)&lt;a class=&quot;zola-anchor&quot; href=&quot;#sugar-for-list-of-lists&quot; aria-label=&quot;Anchor link for: sugar-for-list-of-lists&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To help create a list of lists,
there will also be a &lt;code&gt;[]&lt;&#x2F;code&gt; reader macro
(used like a function)
that wraps its arguments into a list.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let
  []
    variable value
  my-fun variable

; turns into:

(let
  (
    (variable value))
  (my-fun variable))

; which is the same as:

(let ((variable value))
  (my-fun variable))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here’s another example with a lambda.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[]
  lambda (x)
    func x
  arg1

; turns into:

(
  (lambda (x)
    (func x))
  arg1)

; which is the same as:

((lambda (x) (func x)) arg1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;splitting-arguments-across-lines&quot;&gt;Splitting Arguments Across Lines&lt;a class=&quot;zola-anchor&quot; href=&quot;#splitting-arguments-across-lines&quot; aria-label=&quot;Anchor link for: splitting-arguments-across-lines&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you must split arguments into multiple lines,
a “splice” (reader) macro is available.
(Another name might be more suitable,
given the pre-existing splice macro
— in Common Lisp, at least.)&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;my-func arg1 arg2 arg3
      @ arg4 arg5 arg6

; is equivalent to

(my-func arg1 arg2 arg3
         arg4 arg5 arg6)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Without the “splice” macro
it would try to call &lt;code&gt;arg4&lt;&#x2F;code&gt; as a function
with the arguments &lt;code&gt;arg5&lt;&#x2F;code&gt; and &lt;code&gt;arg6&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;!--
You can also mix up the `[]` and `@` macros.

```
[]
  @ item1 item2 item3
  @ item4 item5 item6

; turns into

(item1 item2 item3
 item4 item5 item6)
```
--&gt;
&lt;h2 id=&quot;infix-syntax&quot;&gt;Infix Syntax&lt;a class=&quot;zola-anchor&quot; href=&quot;#infix-syntax&quot; aria-label=&quot;Anchor link for: infix-syntax&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;While this goes a long way towards
making lisp more palatable for some people,
(maybe even appealing)
there are two places where
programmers from other languages expect infix syntax.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;math&quot;&gt;Math&lt;a class=&quot;zola-anchor&quot; href=&quot;#math&quot; aria-label=&quot;Anchor link for: math&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The first place infix syntax is often used is for (simple) math,
for which the &lt;code&gt;$&lt;&#x2F;code&gt; macro is provided.
The &lt;code&gt;$&lt;&#x2F;code&gt; symbol was chosen because
it is used for indicating math in markup languages
like LaTeX, Typst, and Kramdown
(a feature-ful flavour of markdown).&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ 1 + 2 + var &#x2F; 7

; turns into:

(+ 1 2 (&#x2F; var 7))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;comparison&quot;&gt;Comparison&lt;a class=&quot;zola-anchor&quot; href=&quot;#comparison&quot; aria-label=&quot;Anchor link for: comparison&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The second place where other languages use infix syntax
is for comparisons in conditionals and loops.
The &lt;code&gt;check&lt;&#x2F;code&gt; or &lt;code&gt;?&lt;&#x2F;code&gt; macro can be used for this.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;? my-var != your-var

; turns into:

(? my-var != your-var)

; which is the same as:

(not (eq my-var your-var))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Maybe infix math could also be allowed here?
— just to make things easier
for the kinds of people this syntax might appeal to.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;benefits-over-other-significant-whitespace-syntaxes&quot;&gt;Benefits Over Other Significant Whitespace Syntaxes&lt;a class=&quot;zola-anchor&quot; href=&quot;#benefits-over-other-significant-whitespace-syntaxes&quot; aria-label=&quot;Anchor link for: benefits-over-other-significant-whitespace-syntaxes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This syntax might even be more appealing to some people
over other syntaxes with significant whitespace
for several reasons.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Only spaces to separate arguments.&lt;&#x2F;li&gt;
&lt;li&gt;Only spaces to separate function from arguments&lt;&#x2F;li&gt;
&lt;li&gt;No colon for indented blocks&lt;&#x2F;li&gt;
&lt;li&gt;Consistent syntax (for both block and inline)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Getting rid of commas means that
you no longer need to balance them.
Lots of recent languages have taken to
allowing trailing commas just to deal with that issue.
Having no commas makes it easier to move things around.
Furthermore, commas repeated the work
that spaces were already doing.
If whitespace is significant,
then you might as well lean into it.
Signifcant whitespace ++.&lt;&#x2F;p&gt;
&lt;p&gt;All languages (that I know of)
treat the first word as a (special) function call,
and the rest are just keywords or arguments
for that function call,
so the surrounding parentheses for the arguments
are largely unecessary.
The command-line does this beautifully.
We have now rid ourselves of all the superfluous parentheses
(that a host of other languages also have, might I add),
and made whitespace even more significant.&lt;&#x2F;p&gt;
&lt;p&gt;In Python, a colon is required at the end of some forms
like &lt;code&gt;if&lt;&#x2F;code&gt;, &lt;code&gt;else&lt;&#x2F;code&gt;, and &lt;code&gt;for&lt;&#x2F;code&gt;.
This is despite the fact that
the content of these forms is already indented.
So the colon is repeating work
that is already being achieved by indentation.
Furthermore, having tried some Python,
I know for a fact that I would get
annoying syntax errors for missing a colon in various forms.&lt;&#x2F;p&gt;
&lt;p&gt;This syntax also has very simple and consistent rules,
such that even if they are not explicitly mentioned,
a user should get a grasp of them
much sooner than other languages
that have special forms and exceptions of all kinds.
Essentially all language features reduce to
“functions” and lists describing various things.
(I say “functions” in quotes,
because there are special functions and macros as well.)
Only Lisp syntax is simpler and more consistent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We have a syntax with (even more!) significant whitespace,
consistent rules, infix syntax and easy inline syntax,
that should be more palatable to users of other languages,
and easy for existing Lispers to learn and share.
It might even reduce strain on Lispers’ pinkies.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>I Discovered Skribilo!</title>
            <published>2023-06-29T10:19:10+00:00</published>
            <updated>2023-06-29T10:19:10+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/discovered-skribilo/"/>
            <id>https://pranabekka.neocities.org/discovered-skribilo/</id>
            <summary type="html">
              Skribilo is a way to interleave markup and scheme code,
with very similar semantics to what I was envisioning
in Lispy Templates:
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/discovered-skribilo/">
              &lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.nongnu.org&#x2F;skribilo&#x2F;&quot;&gt;Skribilo&lt;&#x2F;a&gt; is a way to interleave markup and scheme code,
with very similar semantics to what I was envisioning
in &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;lispy-templates&#x2F;&quot;&gt;Lispy Templates&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It uses &lt;code&gt;,(&lt;&#x2F;code&gt; to evaluate code inside a markup block.&lt;&#x2F;li&gt;
&lt;li&gt;It uses square brackets (‘[…]’)for content blocks instead of quotes.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Skribilo actually supports multiple types of syntax,
since it’s more of a framework for defining your own syntax.
The syntax it uses by default is the Skribe syntax,
which has its origins in LAML roughly as far back as 1999,
as per &lt;a href=&quot;https:&#x2F;&#x2F;people.cs.aau.dk&#x2F;~normark&#x2F;laml&#x2F;papers&#x2F;laml-retrospective-paper.pdf&quot;&gt;this paper&lt;&#x2F;a&gt; by Kurt Nørmark.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;www.nongnu.org&#x2F;skribilo&#x2F;&quot;&gt;Skribilo page&lt;&#x2F;a&gt; also mentions a lot of prior art
and similar projects at the bottom,
which might be interesting to look at.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s an example of a Skribe document:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;scheme&quot; class=&quot;language-scheme z-code&quot;&gt;&lt;code class=&quot;language-scheme&quot; data-lang=&quot;scheme&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;(define (skribilo . body)
  (ref :url &amp;quot;https:&#x2F;&#x2F;www.nongnu.org&#x2F;skribilo&#x2F;&amp;quot; :text body))

(document :title [I Discovered Skribilo!]
          :draft #t
          :date (make-date 0 0 28 10 29 06 2023 0) ;(nanosecond second minute hour day month year timezone-offset)

  (p [,(skribilo [Skribilo]) is a way to interleave markup and scheme code,
with very similar semantics to what I was envisioning in
,(ref &amp;quot;@&#x2F;lispy-templates.skribe&amp;quot; &amp;quot;Lispy Templates&amp;quot;).]))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At this stage, I think all it needs
is a way to define syntax sugar (like &lt;code&gt;# title&lt;&#x2F;code&gt; or &lt;code&gt;- list item&lt;&#x2F;code&gt;),
and it would be roughly on par with typst.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>PubNotes</title>
            <published>2023-06-25T15:50:07+00:00</published>
            <updated>2023-09-26T08:36:05+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/pubnotes/"/>
            <id>https://pranabekka.neocities.org/pubnotes/</id>
            <summary type="html">
              Superpowered “notes”:
imagine sticky notes,
and then imagine if you could add fancy things
like images, links, videos, games, and more.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/pubnotes/">
              &lt;p&gt;Superpowered “notes”:
imagine sticky notes,
and then imagine if you could add fancy things
like images, links, videos, games, and more.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the most basic version of a PubNotes app,
where notes are called stories,
and they just contain some text.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;pubnotes-anonymous.png&quot; alt=&quot;A mobile screen with the title “World Wide Whispers”, the subtitle “Enabling millions to share their stories without fear.”, a button labelled “Share Your Story”, and a list of notes with only the (placeholder) text “This is an anonymous note, without any additional information. This could be used for people to anonymously share real life stories.” The notes also have different colours like yellow, green,and blue.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Then PubNotes can add advanced things
like the author, time and date, replies, and more!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;pubnotes-microblogging.png&quot; alt=&quot;A list of notes with some placeholder text, a timestamp, comments icon, mentions icon, and tags icon displayed at the bottom of each note. Each icon has a count next to it. The background is white with a grey background for notes. The placeholder text says “This is a post with just some plain text and a #tag or #two. I didn’t even add any section titles or anything. I’m rambling and that’s all this is. Micro-blogging at its finest!”&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now the notes include when you wrote the “note”,
a count of replies to it,
a list of who it was addressed to,
and a list of what topics (tags) it belongs to.&lt;&#x2F;p&gt;
&lt;p&gt;Basically, PubNotes is incredibly flexible.
It’s like a piece of paper,
along with any pen, pencil, or paints that you might need.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine you had a piece of paper:
If you’re writing to yourself,
you just write the core message,
similar to the first example.
If you were writing to someone else,
you write their name at the top
and your name at the bottom.
If you saw something nice,
you’d put an image on the paper.
PubNotes allows you to do that and way more.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;pubnotes-microblogging-actions.png&quot; alt=&quot;A mobile screen with a list of notes divided into sections using titles. The first title is “PubNotes”, meant as the name of the app or website. Under is a note with the (placeholder) title “Hello and Welcome!”, followed by some text. The second title is “Recent Notes”. The notes under it have arbitrary placeholder text. All notes have extra information at the bottom, such as the author, timestamp, icons with counts for comments, mentions, and tags, and icons to bookmark the note, expand it, or reply to it. The screen has a dark theme with a serif font and coloured notes. At the bottom is a navigation bar with icons for search, user profile, home, and messages.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This example is basically
a social media application or forum!&lt;&#x2F;p&gt;
&lt;p&gt;As you can see, PubNotes can be easily themed.
And you can add even more things,
like a title,
a preview with only the first 80 words or so,
the name of the author,
bookmarks,
and more.&lt;&#x2F;p&gt;
&lt;p&gt;We could even turn it all into a video sharing platform:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;pubnotes-video-sharing.png&quot; alt=&quot;A screen with the title “PubNotes”, where the inside of the P looks like a play button, and the s has a volume icon after it. Below it is a list of notes. Each note has a grey rectangle as a video placeholder with video controls inside it, followed by a title. All notes have extra information at the bottom, such as the author, timestamp, icons with counts for comments, mentions, and tags, and icons to bookmark the note, expand it, or reply to it. The screen has a dark theme, with coloured notes. At the bottom is a navigation bar with icons for search, user profile, home, and messages.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We even removed the like button to enable better discourse!
Just kidding ;)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;&#x2F;strong&gt;: PubNotes is &lt;em&gt;not&lt;&#x2F;em&gt; limited to mobile,
even though it’s not shown in the examples.&lt;&#x2F;p&gt;
&lt;p&gt;PubNotes has a lot more potential
that I haven’t yet mocked up or explained,
in an effort to keep the introduction simple.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;&#x2F;strong&gt;: &lt;em&gt;No more images beyond this point.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You could create a platform for publishing and discussing books.
Use tags to indicate the genre of the books.
Use a different note for each chapter.
Each new chapter could be a reply to the old one,
to keep them all linked together,
or you could create a more specific linking system.
The rest is super easy to use.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve already displayed a social media&#x2F;forum example,
though I didn’t really explain much.
PubNotes has all the features a forum might need.
In fact, this whole thing began with
the idea of making super-charged forums.
Forum administrators can pin notes to the home page,
and make categories that can also be pinned.
In the example, “Hello and Welcome!” is a pinned note,
and “Recent Notes” is a pinned category of sorts
(It’s a special type of category).
Users can organise notes into threads on specific topics,
and they could even split them or interweave them.
There’s a lot of potential!&lt;&#x2F;p&gt;
&lt;p&gt;You could even put games into PubNotes.
A simple example is knots and crosses.
One user adds it to their note,
make the first move,
and sends it over to their friend.
The friend replies to it,
which automatically adds knots and crosses to their note,
then they make their move and send it back.
They just repeat this until one of them wins.
The same framework could also be used for
chess, dots and boxes, and other turn based games.
Maybe you could put something like Pokemon!
Imagine a whole monster collecting community
built into a small social media platform.
People would discuss all kinds of things,
have melodramatic roleplay,
maybe solve puzzle notes to gather monsters,
perhaps create their own monsters and add them to the platform
(with the help of moderators), and more.
They could have topics threads
for different types of monsters or weight classes.&lt;&#x2F;p&gt;
&lt;p&gt;I’ll add more ideas as I come up with them
or find them in my notes.
Feel free to &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;about&#x2F;#contact&quot;&gt;share&lt;&#x2F;a&gt; your own ideas as well!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;portfolio&#x2F;&quot;&gt;More Projects (Portfolio)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>More on Noon-Flower (Game Idea)</title>
            <published>2023-06-22T12:03:17+00:00</published>
            <updated>2023-06-23T21:32:14+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/noon-flower-2/"/>
            <id>https://pranabekka.neocities.org/noon-flower-2/</id>
            <summary type="html">
              Just a summary of my motivations, inspiration,
and the origin of the name (it’s random).
See my first post on Noon-Flower for an introduction.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/noon-flower-2/">
              &lt;p&gt;Just a summary of my motivations, inspiration,
and the origin of the name (it’s random).
See &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;noon-flower&#x2F;&quot;&gt;my first post on Noon-Flower&lt;&#x2F;a&gt; for an introduction.&lt;&#x2F;p&gt;
&lt;p&gt;(Noon-Flower was previously called Wijo)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;motivations&quot;&gt;Motivations&lt;a class=&quot;zola-anchor&quot; href=&quot;#motivations&quot; aria-label=&quot;Anchor link for: motivations&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Multiplayer&lt;&#x2F;strong&gt;: For me, the main deciding factor for playing a game
is if I get to play it with other people.
The only one I play right now is Call of Duty on mobile,
simply because I’m able to easily get online with friends.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Co-op&lt;&#x2F;strong&gt;: I also don’t want to get into the highly competitive PvP games,
because while it feels cool to dominate,
it requires practice that takes a lot of time
and their nature can often exclude people.
I used to play Valorant and League at one point, for example,
and I was at the point where I would do target practice every day.
PvP is still alright, of course, but not the exclusive focus.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Depth&lt;&#x2F;strong&gt;: While it’s nice to play Call of Duty with friends,
I want something a little more varied sometimes.
That’s why my concept is heavily influenced by Minecraft.
I’d like exploration, crafting, NPCs, some building, and maybe quests.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Extensible&lt;&#x2F;strong&gt;: I think the reason Minecraft is so compelling
is that it allows you to create your own game,
and it allows this along a smooth gradient.
It can be as easy as creating a small base for yourself,
or you could go on to make a large adventure game
with custom dungeons, loot and gameplay mechanics.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Free&lt;&#x2F;strong&gt;: My options for multiplayer games with friends
can be quite limited,
because I can’t expect anyone to buy games.
Also, a Libre&#x2F;Open Source game should allow
further participation from the community.
Frankly, that would be really cool.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2D, Pixel Art&lt;&#x2F;strong&gt;: This simply makes the game possible to create.
2D pixel art is easier to create,
but also easy to mock up, sketch, prototype, and reason about.
It’s effects on even generating ideas for a game
should be exponential.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inspiration&quot;&gt;Inspiration&lt;a class=&quot;zola-anchor&quot; href=&quot;#inspiration&quot; aria-label=&quot;Anchor link for: inspiration&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Minecraft&lt;&#x2F;strong&gt;: I’ve mentioned Minecraft under
the motivation points on Depth and Extensibility,
but Minecraft is basically a game engine.
It allows you to realise (a version of)
nearly any game idea you have.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;CrossCode&lt;&#x2F;strong&gt;: I found the mechanical depth of CrossCode really cool,
as well as some of the RPG elements,
like the quests and characters&#x2F;story beats.
Their movement and parkour system is really cool,
and I find the overall combat system quite good as well,
even if I select upgrades pseudo-randomly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-noon-flower&quot;&gt;Why Noon-Flower?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-noon-flower&quot; aria-label=&quot;Anchor link for: why-noon-flower&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;It’s simple to pronounce and remember,
and doesn’t have any specific meaning,
which means I’m not bound to anything specific.
Like, Minecraft is so much more than mining or crafting
— it’s more building or auto-farming than mining
for lots of people.&lt;&#x2F;p&gt;
&lt;p&gt;While it’s supposed to be random and meaningless,
I did imagine the game and it’s (potential) community
developing a random obsession with some item called the Noon Flower.
I was picturing bases, custom maps, maybe some magic,
lore, art, and stories about some mythical&#x2F;magical item.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Noon-Flower (Game Idea)</title>
            <published>2023-06-22T11:23:16+00:00</published>
            <updated>2023-06-22T11:23:16+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/noon-flower/"/>
            <id>https://pranabekka.neocities.org/noon-flower/</id>
            <summary type="html">
              Imagine if Minecraft
were 2D — and top-down,
instead of sidescrolling (Terraria, Starbound).
Something like CrossCode,
but with building and more emergent gameplay.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/noon-flower/">
              &lt;p&gt;Imagine if &lt;a href=&quot;https:&#x2F;&#x2F;www.minecraft.net&#x2F;en-us&quot;&gt;Minecraft&lt;&#x2F;a&gt;
were 2D — and top-down,
instead of sidescrolling (Terraria, Starbound).
Something like &lt;a href=&quot;http:&#x2F;&#x2F;cross-code.com&#x2F;en&#x2F;home&quot;&gt;CrossCode&lt;&#x2F;a&gt;,
but with building and more emergent gameplay.&lt;&#x2F;p&gt;
&lt;p&gt;(Noon-Flower was previously called Wijo)&lt;&#x2F;p&gt;
&lt;p&gt;There are two core ideas behind this:
It must be compelling, and it must be tractable.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A compelling game is something multiplayer
that I can play with friends.
Something that allows different kinds of gameplay.
Something that allows you to own it.
Something accessible.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A tractable game is something that can be achieved,
even if I don’t have the skills (right now or ever).
2D pixel art should speed up ideating, prototyping,
and the “final” implementation.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I think the key reason Minecraft is so successful
is that it enables a gradient of game to game engine.
You can just play the game as is,
or you switch some of the toggles
to make certain parts easier or harder.
Maybe you add a few nice to have features to the game.
Or maybe you &lt;a href=&quot;https:&#x2F;&#x2F;ctmrepository.com&#x2F;index.php?action=viewMap&amp;amp;id=469&quot;&gt;change the game entirely&lt;&#x2F;a&gt;
— you add grand structures, limit exploration,
add new items with different effects,
add new creatures with different abilities,
and add a new magic system.
That’s the power of Minecraft.&lt;&#x2F;p&gt;
&lt;p&gt;So at an overall view, I want a base game,
along with a system for scripting and adding custom content.
You should be able to implement a puzzle game, a PvP game,
maybe a shooter, an RPG, an MMO game (?), a roguelike, and more.
Maybe a simple farming simulator as well.&lt;&#x2F;p&gt;
&lt;p&gt;The base game will be open world,
with procedurally generated terrain.
I imagine people exploring and creating bases together.
I imagine them visiting villages, towns and cities
populated by new and interesting races.
I imagine them raiding dungeons
and fighting terrible creatures.
I imagine players meeting creatures and
accepting quests for interesting rewards.&lt;&#x2F;p&gt;
&lt;p&gt;I recommend everyone to try out
&lt;a href=&quot;http:&#x2F;&#x2F;cross-code.com&#x2F;en&#x2F;home&quot;&gt;CrossCode&lt;&#x2F;a&gt;’s free demo,
to see an example of compelling 2D gameplay
that’s actually quite 3 dimensional.
They have a very interesting parkour system,
as well as a nice combat system.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Ivy</title>
            <published>2023-06-22T10:26:27+00:00</published>
            <updated>2023-06-22T10:26:27+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/ivy/"/>
            <id>https://pranabekka.neocities.org/ivy/</id>
            <summary type="html">
              
I thought that I was dreaming,
when you said you love me.
The start of nothing.
I had no chance to prepare.
I couldn’t see you coming.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/ivy/">
              &lt;blockquote&gt;
&lt;p&gt;I thought that I was dreaming,&lt;br &#x2F;&gt;
when you said you love me.&lt;br &#x2F;&gt;
The start of nothing.&lt;br &#x2F;&gt;
I had no chance to prepare.&lt;br &#x2F;&gt;
I couldn’t see you coming.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Listen to the cover by Indigo De Souza.
While you’re at it,
you could also listen to Kill Me.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Started from nothing&lt;br &#x2F;&gt;
Oooh…&lt;br &#x2F;&gt;
I could hate you now&lt;br &#x2F;&gt;
It’s alright to hate me now&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Better Markup Headings</title>
            <published>2023-06-19T09:50:55+00:00</published>
            <updated>2023-06-19T09:50:55+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/better-markup-titles/"/>
            <id>https://pranabekka.neocities.org/better-markup-titles/</id>
            <summary type="html">
              Lightweight markup languages are designed in such a way
that the markup looks like what is intended.
Bulleted lists use asterisks or hyphens
and emphasised text has asterisks or underscores around it.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/better-markup-titles/">
              &lt;p&gt;Lightweight markup languages are designed in such a way
that the markup &lt;em&gt;looks&lt;&#x2F;em&gt; like what is intended.
Bulleted lists use asterisks or hyphens
and emphasised text has asterisks or underscores around it.&lt;&#x2F;p&gt;
&lt;p&gt;The headings, however, have a structure
that highlights lower level headings
over higher level headings.
Instead, in a markdown file,
the highest level heading should have the most hashes (‘#’),
while the lowest level heading should have the least.
Other lightweight markup languages should do the same
with whatever character they use for headings.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;###### Heading Level 1 (Document Title)

This is the introductory paragraph of your document.

##### Heading Level 2 (Section Heading)

This is the content of the first section.

#### Heading Level 3 (Sub-Section Heading)

This is the content of Section 1.1.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Plain Text Data Structures</title>
            <published>2023-06-18T20:29:28+00:00</published>
            <updated>2023-06-18T20:29:28+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/plain-text-data-structures/"/>
            <id>https://pranabekka.neocities.org/plain-text-data-structures/</id>
            <summary type="html">
              This is a wild one,
which stems from my education as a visual designer,
as well as a regular terminal user.
The gist of my idea is that there are many ways
of representing data in plain text for easy use.
This is especially useful in a terminal based workflow,
but even basic users can adopt some of this in
something like Notepad or any simple text editor.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/plain-text-data-structures/">
              &lt;p&gt;This is a wild one,
which stems from my education as a visual designer,
as well as a regular terminal user.
The gist of my idea is that there are many ways
of representing data in plain text for easy use.
This is especially useful in a terminal based workflow,
but even basic users can adopt some of this in
something like Notepad or any simple text editor.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;an-example&quot;&gt;An Example&lt;a class=&quot;zola-anchor&quot; href=&quot;#an-example&quot; aria-label=&quot;Anchor link for: an-example&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Around two or three years ago,
I had a colleague trying to balance some accounts
and she had a discrepancy between two different reports
of the same accounts.
I helped her by opening Notepad
and just listing down the costs
with each report in a different line.
Then we just had to line up the matching costs
and the odd ones out were easy to pick out.
Here’s an example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;1050 | 100 | 250 | 320     | 1200 | 3200 | 80 | 20 20 20 |
1050 |     | 250 | 120 200 | 1200 | 3200 | 80 | 60       |
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here you can see that some costs
were given as a single entry in one report
but were split into multiple entries in the other,
which made it quite hard to organise.
Furthermore, the ordering of the entries also had to be matched up.
Using this method it was easy to see what was missing,
and she used it later on as well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-plain-text&quot;&gt;Why Plain Text&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-plain-text&quot; aria-label=&quot;Anchor link for: why-plain-text&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You might ask why Notepad, or plain text in general.
The answer is manifold:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Editors for spreadsheets and rich text documents
require several seconds or minutes to start up,
which breaks your flow.&lt;&#x2F;li&gt;
&lt;li&gt;These editors also bog down slower computers further.
Especially if you have several reports already open
on a low-budget work computer.
This also breaks your flow.&lt;&#x2F;li&gt;
&lt;li&gt;These editors have complex controls for aligning data.&lt;&#x2F;li&gt;
&lt;li&gt;Most of their features have no use for you,
and in fact interfere with your work.&lt;&#x2F;li&gt;
&lt;li&gt;Monospaced text makes it easier to align and compare data.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Basically, you get everything you need, and nothing you don’t.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;data-structures&quot;&gt;Data Structures&lt;a class=&quot;zola-anchor&quot; href=&quot;#data-structures&quot; aria-label=&quot;Anchor link for: data-structures&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;notes-and-draft-personal-documents&quot;&gt;Notes and (Draft&#x2F;Personal) Documents&lt;a class=&quot;zola-anchor&quot; href=&quot;#notes-and-draft-personal-documents&quot; aria-label=&quot;Anchor link for: notes-and-draft-personal-documents&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When you’re just writing down your thoughts,
or a draft of your final document,
write normal paragraphs as continuous lines,
separate paragraphs with a blank line,
and use a marker like ‘#’ or ‘=’ for titles.
You can also use the other data structures in this page,
to represent other kinds of data.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Note&#x2F;Draft Title

This is a normal paragraph
that wraps across multiple lines.

This is another paragraph, that also continues
across multiple lines.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Try out &lt;a href=&quot;https:&#x2F;&#x2F;www.markdownguide.org&#x2F;cheat-sheet&#x2F;&quot;&gt;Markdown&lt;&#x2F;a&gt;,
and &lt;a href=&quot;https:&#x2F;&#x2F;www.markdownguide.org&#x2F;tools&#x2F;&quot;&gt;the various applications&lt;&#x2F;a&gt;
that can make note taking incredibly fast and easy
across any device that you like.
You can write and view these documents without any special app,
and most of these apps (if not all)
open in the blink of an eye.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tables&quot;&gt;Tables&lt;a class=&quot;zola-anchor&quot; href=&quot;#tables&quot; aria-label=&quot;Anchor link for: tables&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When representing table-like data,
use a delimiter to separate each column
and a new line to separate each row.
The delimiter can be spaces and&#x2F;or vertical bars,
like the example above,
or any other character,
such as commas, tabs, colons, and more.
Use spaces or tabs to align the columns properly.&lt;&#x2F;p&gt;
&lt;p&gt;Choose your delimiter character based on
what is least likely to appear in your actual data.
In the above example it was just numbers,
so I used spaces because there’s a huge spacebar
to easily add spaces and visually separate the numbers.
If you’re going to be using commas and spaces,
try semicolons (“;”).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lists&quot;&gt;Lists&lt;a class=&quot;zola-anchor&quot; href=&quot;#lists&quot; aria-label=&quot;Anchor link for: lists&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Use a dash to mark the beginning of each entry,
maybe with a blank line in between.
Indent sub-lists to indicate that they belong
to a parent item.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;- List Item 1
  - List Item 1.1
  - List Item 1.2
- List Item 2
- List Item 3
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;task-lists&quot;&gt;Task Lists&lt;a class=&quot;zola-anchor&quot; href=&quot;#task-lists&quot; aria-label=&quot;Anchor link for: task-lists&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Task lists can often benefit from additional information.
Mark done tasks with a ‘.’ to make them less prominent,
or use an ‘x’ if that feels more intuitive.
Mark important tasks with an ‘@’ or ‘#’ symbol,
simply because they’re large and more prominent.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;- Normal task to do
. Finished task
@ Important task
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can add date stamps at the beginning of a task
to indicate when it should be completed,
or when you created it,
or when it was completed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;- () No completion date
. (Jan 15, 23) Completed on 15th Jan 2023
@ (Jul 21) Complete by 21st July!
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Have a look at &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;todotxt&#x2F;todo.txt&quot;&gt;todo.txt&lt;&#x2F;a&gt;
for even more ideas and features.
The benefit of it is that there are
a bunch of applications that can
make it easy to manipulate your data across devices.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;choosing-a-representation&quot;&gt;Choosing a Representation&lt;a class=&quot;zola-anchor&quot; href=&quot;#choosing-a-representation&quot; aria-label=&quot;Anchor link for: choosing-a-representation&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Lists are actually very similar to tables.
Take the following table for example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Chef&amp;#39;s Special? | Name                     | Spiciness | Description                                   | Cost
No              | Dragon-Glaze Salmon      | Medium    | Sweet and spicy glazed salmon topped with ... | 200
No              | Fried Shrimp             | Low       | Crispy shrimp with cocktail sauce. Served ... | 300
No              | Parmesan-Crusted Chicken | Low       | Grilled all-natural chicken, creamy white ... | 250
No              | Crispy Chicken Tenders   | Low       | Served with coleslaw, seasoned fries and H... | 320
Yes             | Simply Grilled Salmon    | Low       | Seasoned with hickory-smoked sea salt and ... | 500
No              | Fish &amp;amp; Chips             | Low       | Battered golden cod fillets served with se... | 300
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The descriptions are so long they’re basically unusable
(I’ve truncated them to avoid typing it all),
and some columns take up more space than they need.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, you could represent it like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Item Name
Chef&amp;#39;s Special?
Spice
Price
Description
...

Dragon-Glaze Salmon
-
Medium Spice
200
Sweet and spicy glazed salmon
topped with ...

Fried Shrimp
-
Low Spice
300
Crispy shrimp with cocktail sauce.
Served ...

Parmesan-Crusted Chicken
-
Low Spice
250
Grilled all-natural chicken,
creamy white ...

Crispy Chicken Tenders
-
Low Spice
320
Served with coleslaw,
seasoned fries and H...

Simply Grilled Salmon
Chef&amp;#39;s Special
Low Spice
500
Seasoned with hickory-smoked sea salt
and ...

Fish &amp;amp; Chips
Low Spice
300
Battered golden cod fillets
served with se...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, each row is separated by a blank line,
and each column is separated by a new line.
Empty fields are marked with a simple -,
and additional lines before the blank line
are part of the item description.
You can also use a list,
but this saves you a lot of typing,
because you don’t have to add the dashes for each item
and the spaces for indenting item information
(price, description, etc).
In fact, this is a sort of hybrid of lists and tables,
and you can see how one can be transformed into the other.&lt;&#x2F;p&gt;
&lt;p&gt;You can also mix it up with headings:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# The Grill

Dragon-Glaze Salmon
-
Medium Spice
200
Sweet and spicy glazed salmon
topped with ...

...

# Drinks
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Basically, you should think about how you’re using the data.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the basic list format, if you were curious:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;- Dragon-Glaze Salmon
  - Not Special
  - Medium Spice
  - 200
  - Sweet and spicy glazed salmon
    topped with ...
- Fried Shrimp
  - Not Special
  - Low Spice
  - 300
  - Crispy shrimp with cocktail sauce.
    Served ...
...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It requires a dash for each row and column,
as well as two extra spaces for each column.
Additionally, it’s harder to scan quickly,
because all the items are squeezed up next to each other —
in the blank line delimited format (tables use delimiters!) 
you just skip to the line after every empty line
to get the name of the item.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-about-json-yaml-etc&quot;&gt;What About JSON, YAML, etc&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-about-json-yaml-etc&quot; aria-label=&quot;Anchor link for: what-about-json-yaml-etc&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;JSON is too verbose for typing out manually.
In fact, YAML is quite verbose as well.
These are primarly formats for transmitting data,
and are more computer friendly than reading&#x2F;writing friendly.&lt;&#x2F;p&gt;
&lt;p&gt;If you expect to be using this data in a lot of places,
and you don’t want to write a custom parser,
then you can of course go with a more popular format.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you’re going to be typing out stuff for yourself,
maybe for a small use case,
then try using one of these formats,
and&#x2F;or even changing them for your own use case.&lt;&#x2F;p&gt;
&lt;p&gt;If you have programming knowledge,
you can also write simple parsers for them,
which will allow you to manipulate them easily
and even export them to other formats.&lt;&#x2F;p&gt;
&lt;p&gt;Learn
&lt;a href=&quot;https:&#x2F;&#x2F;kakoune.org&quot;&gt;Kakoune&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;&quot;&gt;(Neo)Vim&lt;&#x2F;a&gt;
or &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;&quot;&gt;Emacs&lt;&#x2F;a&gt;
if you want even more power out of these plain text formats.
They can allow you to &lt;em&gt;interactively&lt;&#x2F;em&gt; transform the data,
instead of writing a parser the traditional way,
and can enhance your general text writing and editing as well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;credits&quot;&gt;Credits&lt;a class=&quot;zola-anchor&quot; href=&quot;#credits&quot; aria-label=&quot;Anchor link for: credits&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Menu items copied from &lt;a href=&quot;https:&#x2F;&#x2F;www.pinterest.com&#x2F;pin&#x2F;458733912047759557&#x2F;&quot;&gt;How to Make a Better Restaurant Menu (Pinterest)&lt;&#x2F;a&gt;
only for use as examples.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Typst Syntax</title>
            <published>2023-06-17T11:26:09+00:00</published>
            <updated>2023-06-17T11:26:09+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/typst-syntax/"/>
            <id>https://pranabekka.neocities.org/typst-syntax/</id>
            <summary type="html">
              I’ve mentioned Typst here and there,
but I just thought I should give it a proper mention.
They’ve done a lot of interesting things
to make it easy to write large documents.
For this post, I just want to talk about the syntax.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/typst-syntax/">
              &lt;p&gt;I’ve mentioned &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;typst-syntax&#x2F;typst.app&quot;&gt;Typst&lt;&#x2F;a&gt; here and there,
but I just thought I should give it a proper mention.
They’ve done a lot of interesting things
to make it easy to write large documents.
For this post, I just want to talk about the syntax.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; Typst is currently in Beta,
and the things I mention might change in the future,
although the general architecture should be the same.&lt;&#x2F;p&gt;
&lt;p&gt;Typst has three types of syntax (&lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;reference&#x2F;syntax&#x2F;&quot;&gt;modes&lt;&#x2F;a&gt;):
content, math, and code.
Content is a lot like &lt;a href=&quot;https:&#x2F;&#x2F;www.markdownguide.org&#x2F;getting-started&#x2F;&quot;&gt;Markdown&lt;&#x2F;a&gt;,
with headings, paragraphs, lists, links, and so on.
Math is a way to enter formulae with all kinds of special symbols.
Code is a little bit like &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;TeX&quot;&gt;TeX&lt;&#x2F;a&gt;’s macros,
except they’re actually full-fledged functions
in a specially created programming language.
There’s a function to describe macros as well.&lt;&#x2F;p&gt;
&lt;p&gt;When you start writing a Typst document,
you’re in content mode.
To enter math mode, you type a dollar sign
and write out your formulae using math mode syntax.
To enter code mode you use an octothorpe (‘#’)
followed by the name of the function,
and the arguments to the function.
For example, &lt;code&gt;#heading(level: 1, [Heading Level 1])&lt;&#x2F;code&gt;
calls the heading function asking for
a level 1 heading with the text “Heading Level 1”.&lt;&#x2F;p&gt;
&lt;p&gt;Typst’s syntax is actually built completely on code.
When you write out special syntax in content mode,
it gets converted into code.
Continuing the heading example,
when you write &lt;code&gt;= My Document&lt;&#x2F;code&gt;,
it gets transformed into &lt;code&gt;#heading(level: 1, [My Document])&lt;&#x2F;code&gt;.
When you write a paragraph of text,
it implicitly calls &lt;code&gt;#para([Paragraph Content])&lt;&#x2F;code&gt;.
When you write math like &lt;code&gt;$ x + y $&lt;&#x2F;code&gt;,
it gets converted into &lt;code&gt;#equation([x + y])&lt;&#x2F;code&gt; (I think).&lt;&#x2F;p&gt;
&lt;p&gt;And that’s the coolest thing about Typst’s syntax.
This programming language allows you to do lots of exciting things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;reference&#x2F;types&#x2F;function&#x2F;#definitions&quot;&gt;Create custom functions&lt;&#x2F;a&gt;
that you can use in your documents.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;reference&#x2F;styling&#x2F;#show-rules&quot;&gt;Create&#x2F;override syntax&lt;&#x2F;a&gt;
that implicitly calls your functions, or any other Typst function.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;reference&#x2F;scripting&#x2F;#modules&quot;&gt;Import&lt;&#x2F;a&gt;
other Typst files, both content and functions.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;reference&#x2F;data-loading&#x2F;&quot;&gt;Import arbitrary files&lt;&#x2F;a&gt;,
such as JSON, CSV, or any plain text file.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;reference&#x2F;visualize&#x2F;&quot;&gt;Draw&lt;&#x2F;a&gt; arbitrary shapes.
Functions for plotting and diagrams are also being worked on.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Typst’s biggest current limitation (for me)
is that it only supports PDF output,
but HTML output is in the works and should be ready in a few months.
Along with that, I think they’ll include exporting an intermediate format,
such that you can use Typst to calculate most of the layout and results,
then get a structured representation of the resulting content,
so that you can transform it into whatever you like.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, Typst is not out of Beta,
so things change nearly every month or so.
However, you can already do exciting stuff with it,
and I would encourage you to try it out.
Start with the tutorial at &lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;tutorial&quot;&gt;typst.app&#x2F;docs&#x2F;tutorial&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Portfolio</title>
            <published>2023-06-01T21:17:40+00:00</published>
            <updated>2023-10-15T16:03:33+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/portfolio/"/>
            <id>https://pranabekka.neocities.org/portfolio/</id>
            <summary type="html">
              Hi! My portfolio is currently available as a PDF.
You can reach out if you’d like to know more about any project.
I’ll be including some of them on the website over time.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/portfolio/">
              &lt;p&gt;Hi! My portfolio is currently available as a PDF.
You can reach out if you’d like to know more about any project.
I’ll be including some of them on the website over time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;svg class=&quot;icon&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
     viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot;&gt;
  &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;
        d=&quot;M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021
        18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
Download: &lt;a href=&quot;&#x2F;pranabekka-portfolio-2023-06-23-public.pdf&quot;&gt;Portfolio (PDF)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;svg class=&quot;icon&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
     viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot;&gt;
  &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;
        d=&quot;M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0
        01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0
        00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25
        2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
Email: &lt;a href=&quot;mailto:pranabekka@gmail.com&quot;&gt;pranabekka@gmail.com&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;svg class=&quot;icon&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
     viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot;&gt;
  &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;
        d=&quot;M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125
        1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25
        0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125
        1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
Resumé: &lt;a href=&quot;&#x2F;resume&quot;&gt;pranabekka.github.io&#x2F;resume&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;!-- see &quot;portfolio.html&quot; template for &quot;Online Projects&quot; section --&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>More Ideas on CL SSG</title>
            <published>2023-05-31T21:50:57+00:00</published>
            <updated>2023-05-31T21:50:57+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/cl-ssg-2/"/>
            <id>https://pranabekka.neocities.org/cl-ssg-2/</id>
            <summary type="html">
              Following up on my initial post
(CL SSG — Common Lisp Static Site Generator),
Coleslaw didn’t really work out (more below).
Instead, I’m imagining a static site generator based on
a build system,
a typst-inspired language,
and a simple server.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/cl-ssg-2/">
              &lt;p&gt;Following up on my initial post
(&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;cl-ssg&#x2F;&quot;&gt;CL SSG — Common Lisp Static Site Generator&lt;&#x2F;a&gt;),
Coleslaw didn’t really work out (more below).
Instead, I’m imagining a static site generator based on
a build system,
a typst-inspired language,
and a simple server.&lt;&#x2F;p&gt;
&lt;p&gt;Regarding Coleslaw,
I had some bugs that I didn’t feel like going through,
plus it loaded a lot of modules I wasn’t interested in
(but not the incrememental build one?),
and I didn’t feel like learning all about it.
Even the preview didn’t work properly.
So I just let it be.
Zola gives me most of what I need anyway.
I might give Coleslaw a try again later.&lt;&#x2F;p&gt;
&lt;p&gt;I did look up some Common Lisp libraries, however.&lt;&#x2F;p&gt;
&lt;p&gt;Overlord seems to be a good build system.
It should get me incrememental and parallel builds.&lt;&#x2F;p&gt;
&lt;p&gt;For the authoring and templating,
I want to use a typst-like language.
Templates will simply be functions that wrap
the rest of the content.
I wonder how I’d extract metadata.
Perhaps a metadata function?&lt;&#x2F;p&gt;
&lt;p&gt;Hunchentoot seems to be the most popular server,
and it should be more than good enough.
I simply need to serve pages locally,
and it should be well documented,
with enough guides and references.&lt;&#x2F;p&gt;
&lt;p&gt;The first step is to start messing with cl-typst.
Should be as simply as evaluating anything starting with &lt;code&gt;,(&lt;&#x2F;code&gt;
and simply passing along anything else as regular text.
Then figure out a system for sharing state or environment?
Or should I strive to keep it functional?
Oh, well. Get the parser-evaluator figured out first.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Minecraft Activate the Monument</title>
            <published>2023-05-21T20:07:42+00:00</published>
            <updated>2023-05-21T20:07:42+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/minecraft-activate-the-monument/"/>
            <id>https://pranabekka.neocities.org/minecraft-activate-the-monument/</id>
            <summary type="html">
              I was watching the 9th devlog of Space64 (WIP name)
by FireDragon04, and as he talked about activating
the doorway by enabling beacons,
I thought about Minecraft beacons, and a spin on
the Minecraft CTM (Complete the Monument) formula
where you activate beacons instead of fetching wool
and returning it to the monument.
A Minecraft ATM. (Activate the Monument. Hah.)
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/minecraft-activate-the-monument/">
              &lt;p&gt;I was watching the 9th devlog of Space64 (WIP name)
by FireDragon04, and as he talked about activating
the doorway by enabling beacons,
I thought about Minecraft beacons, and a spin on
the Minecraft CTM (Complete the Monument) formula
where you activate beacons instead of fetching wool
and returning it to the monument.
A Minecraft ATM. (Activate the Monument. Hah.)&lt;&#x2F;p&gt;
&lt;p&gt;I’d say the main difference is that
loosing a monument key is now impossible,
since they don’t exist.
This is usually solved by regenerating the keys,
or making ways to keep your inventory,
or preventing your items from despawning,
which is no longer required.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps it will feel like less of a fetch quest?&lt;&#x2F;p&gt;
&lt;p&gt;I know I want to recreate FireDragon04’s game
in Minecraft, at least a general vibe.
I’m a fan of Halo, sci-fi, brutalism,
and grand buildings.
I can just imaging the whole thing
as a &lt;del&gt;Complete the Monument&lt;&#x2F;del&gt; Activate the Monument.
I even have vague ideas of progression, dungeons,
gameplay, grand architecture and the ending in mind.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Todo Formatting</title>
            <published>2023-05-21T00:03:47+00:00</published>
            <updated>2023-05-21T00:03:47+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/todo-formatting/"/>
            <id>https://pranabekka.neocities.org/todo-formatting/</id>
            <summary type="html">
              A way of visually organising your tasks 
to suggest which one is currently actionable,
which one can be acted upon next,
and which tasks depend upon which.
This can be used to create UIs,
organise tasks in a todo app,
or to organise tasks in a simple text file.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/todo-formatting/">
              &lt;p&gt;A way of visually organising your tasks 
to suggest which one is currently actionable,
which one can be acted upon next,
and which tasks depend upon which.
This can be used to create UIs,
organise tasks in a todo app,
or to organise tasks in a simple text file.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First, write titles for projects.&lt;&#x2F;p&gt;
&lt;p&gt;Projects can be of any size.
Clearing out your desk could be a project.&lt;&#x2F;p&gt;
&lt;p&gt;All tasks go under a project.
One off tasks can go under a “more” title.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Two, write the very next action you can perform on a project.&lt;&#x2F;p&gt;
&lt;p&gt;Think of an action and write it down,
then think of what you need to get that done
and write that down.
Repeat that until you can’t reasonably break it down further.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Put the next actionable step at the top of the project list.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Indent dependent tasks below their blocker tasks.&lt;&#x2F;p&gt;
&lt;p&gt;If action B requires action A to be complete
before you can do action B,
then put action B below action A and indent it.&lt;&#x2F;p&gt;
&lt;p&gt;Tasks that depend on the same parent task,
but not on each other,
will go below that parent task and will have
the same amount of indentation as each other.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here’s an example,
where i have to clean up my desktop folder:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;desktop clean-up
  - copy list of files to notes
    - list possible actions under each item for
      where to put it or what to do with it
      - choose best action for each file
        - perform best action for each file
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don’t yet know how to model tasks that depend on
two or more tasks —
a possible method could be to put one parent task below the other,
even though it might not depend on the other parent task,
and then put the dependent task under both of them.&lt;&#x2F;p&gt;
&lt;p&gt;In my todo file, I replace the hyphen (&lt;code&gt;-&lt;&#x2F;code&gt;) with a simple &lt;code&gt;@&lt;&#x2F;code&gt; sign
to indicate tasks that are urgent or important to me.
Try to limit them to 5 or less.
I aim to make it more GTD compatible as it grows,
adding in project tags and actions lists,
or maybe I try writing a tool to extract tasks instead,
since moving items around will either create duplication
or mess up the dependency order.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>CL SSG (Common Lisp Static Site Generator)</title>
            <published>2023-05-18T23:03:39+00:00</published>
            <updated>2023-05-18T23:03:39+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/cl-ssg/"/>
            <id>https://pranabekka.neocities.org/cl-ssg/</id>
            <summary type="html">
              Writing so much about Static Site Generators,
I want nothing other than to implement one in Common Lisp.
I get full configurability, really nice templates,
programmatic css, awesome scripting,
and anything else I might desire.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/cl-ssg/">
              &lt;p&gt;Writing so much about Static Site Generators,
I want nothing other than to implement one in Common Lisp.
I get full configurability, really nice templates,
programmatic css, awesome scripting,
and anything else I might desire.&lt;&#x2F;p&gt;
&lt;p&gt;I wonder how long the build times would be, however,
if I used a shell script instead?&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, I could always try &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coleslaw-org&#x2F;coleslaw&quot;&gt;Coleslaw&lt;&#x2F;a&gt;.
But why Roswell.
Oh, well. I had to use it someday anyway.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Scripting (SSG Edition)</title>
            <published>2023-05-17T20:16:04+00:00</published>
            <updated>2023-05-18T12:11:46+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/scripting-ssg-edition/"/>
            <id>https://pranabekka.neocities.org/scripting-ssg-edition/</id>
            <summary type="html">
              A lot of applications that are meant for creating media
benefit from some sort of scripting,
including SSGs (static site generators).
All of the Javascript ones seem to use Javascript,
but Hugo and Zola rely on templates to do everything,
which can be quite cumbersome, limited and generally painful.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/scripting-ssg-edition/">
              &lt;p&gt;A lot of applications that are meant for creating media
benefit from some sort of scripting,
including SSGs (static site generators).
All of the Javascript ones seem to use Javascript,
but Hugo and Zola rely on templates to do everything,
which can be quite cumbersome, limited and generally painful.&lt;&#x2F;p&gt;
&lt;p&gt;However, it should be relatively easy to add scripting to them,
since Go and Rust have several scripting languages
that are designed to be easily embedded.
You can have a look at &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dbohdan&#x2F;embedded-scripting-languages&quot;&gt;this (Github) page on embedded scripting languages&lt;&#x2F;a&gt;
for a full list,
but some interesting options include
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rhaiscript&#x2F;rhai&quot;&gt;Rhai (Github)&lt;&#x2F;a&gt;
for Rust, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;d5&#x2F;tengo&quot;&gt;Tengo (Github)&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mattn&#x2F;anko&#x2F;&quot;&gt;Anko (Github)&lt;&#x2F;a&gt;
for Go.&lt;&#x2F;p&gt;
&lt;p&gt;The most interesting options, however, are
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bazelbuild&#x2F;starlark&quot;&gt;Starlark(Github)&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;scripting-ssg-edition&#x2F;github.com&#x2F;tweag&#x2F;nickel&quot;&gt;Nickel (Github)&lt;&#x2F;a&gt;,
both of which are designed for configuring
build systems and related tools.&lt;&#x2F;p&gt;
&lt;p&gt;I think they’re quite suitable
because they’re designed with a very specific use case
instead of some abstract theory,
and that specific use case happens to be build systems,
which are what static site generators essentially are.&lt;&#x2F;p&gt;
&lt;p&gt;Starlark has implementations in both Go and Rust,
while Nickel is implemented in Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;benefits&quot;&gt;Benefits&lt;a class=&quot;zola-anchor&quot; href=&quot;#benefits&quot; aria-label=&quot;Anchor link for: benefits&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As stated earlier, full fledged scripting languages
make it easier to write complex and reusable code.&lt;&#x2F;p&gt;
&lt;p&gt;They can also be used to make a more intuitive
and integrated templating system,
by using the same language in the templating system.
I’ve included a templating example with Starlark below,
but it can also be used to implement metadata
(or “frontmatter”) with a simple function call
like &lt;code&gt;{{ meta(&amp;quot;2022-03-05&amp;quot;, draft) }}&lt;&#x2F;code&gt;
at the top of your markdown file.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;starlark&quot;&gt;Starlark&lt;a class=&quot;zola-anchor&quot; href=&quot;#starlark&quot; aria-label=&quot;Anchor link for: starlark&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Starlark is a Python-like scripting language
designed for build systems,
and static site generators are basically specialised build systems.
It’s designed to be parallel (for fast builds),
safe (for executing untrusted code) and simple.
Honestly, sounds perfect for a static site generator.
The one downside might be randomness,
but that could be provided by the application (Zola or Hugo).
The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;facebook&#x2F;buck2&#x2F;&quot;&gt;Buck2 build system (Github)&lt;&#x2F;a&gt;
for example, provides an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;facebook&#x2F;buck2&#x2F;blob&#x2F;main&#x2F;docs&#x2F;benefits.md#benefits-for-rule-authors&quot;&gt;API (Github)&lt;&#x2F;a&gt;
that can be accessed by scripts.&lt;&#x2F;p&gt;
&lt;p&gt;You could even embed it inside the template language.
As an example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;h1&amp;gt;{{ page.title }}&amp;lt;&#x2F;h1&amp;gt;
&amp;lt;ul&amp;gt;
{%
  for page in pages:
    &amp;quot;&amp;quot;&amp;quot;
    &amp;lt;li&amp;gt;
      &amp;lt;a href={{page.permalink}}&amp;gt;{{ page.title }}&amp;lt;&#x2F;a&amp;gt;
    &amp;lt;&#x2F;li&amp;gt;
    &amp;quot;&amp;quot;&amp;quot;
%}
&amp;lt;&#x2F;ul&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; I’m not 100% sure about Starlark syntax and features,
and I’m not really a Python user either,
so this might not be correct.
Although, you could probably add additional features
through the app, such as a custom string format (I think).&lt;&#x2F;p&gt;
&lt;p&gt;This enables you to write more complex scripts directly,
instead of writing them in the (imho) awkward template syntax.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;def page_list(pages):
  &amp;quot;&amp;quot;&amp;quot;create a list of pages&amp;quot;&amp;quot;&amp;quot;
  result = &amp;quot;&amp;lt;ul&amp;gt;&amp;quot;
  for page in pages:
    result += &amp;quot;&amp;quot;&amp;quot;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{page.permalink}&amp;quot;&amp;gt;{page.title}&amp;lt;&#x2F;a&amp;gt;&amp;lt;&#x2F;li&amp;gt;&amp;quot;&amp;quot;&amp;quot;
  result += &amp;quot;&amp;lt;&#x2F;ul&amp;gt;&amp;quot;
  return result
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That example is not so bad in the templating language,
but ending all your statements with &lt;code&gt;end-&amp;lt;statement&amp;gt;&lt;&#x2F;code&gt;
and scripting more complex logic can get quite annoying.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nickel&quot;&gt;Nickel&lt;a class=&quot;zola-anchor&quot; href=&quot;#nickel&quot; aria-label=&quot;Anchor link for: nickel&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Another language that could be used is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tweag&#x2F;nickel&quot;&gt;Nickel&lt;&#x2F;a&gt;.
It’s designed with the Nix build&#x2F;configuration system in mind,
and is inspired by the Nix language.&lt;&#x2F;p&gt;
&lt;p&gt;One advantage over Starlark is gradual typing and contracts.
(Contracts are basically like assertions.)
This is especially helpful when writing scripts
that expect data in a specific form,
but would otherwise return incorrect results
which you might find several weeks later.
You can also use it to ensure that your configuration
conforms to a certain type or contract,
instead of causing errors later on.
Contracts, for example, can ensure properties
about your strings, such as what they can contain,
what they can start or end with, and so on.
As a simple example, you can do&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let dateToString : Date -&amp;gt; String
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another is easier multiline strings —
in the Starlark&#x2F;Python example above,
it would preserve the indentation of the text
(quite unintuitively, might I add).
Here’s how it looks in Nickel:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;let it&amp;#39;s-a-multiline-string = m%&amp;quot;
  This isn&amp;#39;t indented.
    This is indented.
  This isn&amp;#39;t indented.
&amp;quot;%
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Yes, examples imply it allows hyphens
and single quotes in its identifiers.)&lt;&#x2F;p&gt;
&lt;p&gt;While most configuration languages try to avoid
turing completeness, Nickel is Turing-complete,
with restricted accessibility to side-effects.
This can allow things like reading file contents
and updating backlinks, which are quite useful.&lt;&#x2F;p&gt;
&lt;p&gt;Nickel can also import and reuse YAML, TOML and JSON,
which allows gradually migrating to it,
instead of completely invalidating older (site) configurations.&lt;&#x2F;p&gt;
&lt;p&gt;Have a look at the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tweag&#x2F;nickel&#x2F;blob&#x2F;master&#x2F;RATIONALE.md&quot;&gt;Rationale (Github)&lt;&#x2F;a&gt;
to understand their design choices and
how it compares to other languages, including Starlark.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Lispy Templates</title>
            <published>2023-05-15T20:32:10+00:00</published>
            <updated>2023-05-15T20:32:10+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/lispy-templates/"/>
            <id>https://pranabekka.neocities.org/lispy-templates/</id>
            <summary type="html">
              Lisp makes a pretty great system for templating all kinds of material.
Simply let people write lisp code directly in their files
and evaluate it in the context of the document,
while blocking features unsuitable for templating.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/lispy-templates/">
              &lt;p&gt;Lisp makes a pretty great system for templating all kinds of material.
Simply let people write lisp code directly in their files
and evaluate it in the context of the document,
while blocking features unsuitable for templating.&lt;&#x2F;p&gt;
&lt;p&gt;In the most basic form treat &lt;code&gt;,&amp;lt;anything&amp;gt;&lt;&#x2F;code&gt;
as a call to evaluate &lt;code&gt;&amp;lt;anything&amp;gt;&lt;&#x2F;code&gt;.
So &lt;code&gt;,var&lt;&#x2F;code&gt; expands to the variable &lt;code&gt;var&lt;&#x2F;code&gt;,
and &lt;code&gt;,(func arg1)&lt;&#x2F;code&gt; expands to the function &lt;code&gt;func&lt;&#x2F;code&gt;
with the argument &lt;code&gt;arg1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The next step after this is to create content blocks.
If you need to wrap some content inside a function
(such as a loop),
you wouldn’t want to worry about escaping all the quotes.
For that purpose, use square brackets
(Borrowed from &lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;reference&#x2F;types&#x2F;content&#x2F;&quot;&gt;Typst&lt;&#x2F;a&gt;.
This allows you to write
&lt;code&gt;(link [Link to article called &amp;quot;Hello, World&amp;quot;])&lt;&#x2F;code&gt;
without worrying about escaping the quotes or using single quotes.
You still have to escape closing square brackets,
but that’s not as big a problem in my opinion.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to representing flat data,
s-expressions can easily model nested data structures as well,
which is where their power truly shines.
HTML is a common format that represents nested data.
All you need is custom functions to create various HTML elements,
which allows you to write something like the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;,(:para
   [This is some content with a 
     ,(:link [link text] &amp;quot;example.com&amp;quot;)
    in it])
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The coolest part is that you don’t need to
embed a scripting language.
You just re-use the lisp programming language!&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;;; definitions

,(define fn1
   (:footnote [I am but a Lisp newbie]))

,(define fn2
   (:footnote
     (:link [CommonMark specification] &amp;quot;commonmark.org&amp;quot;)))

,(define fn3
   (:footnote
     (:link [LaTeX Website] &amp;quot;latex-project.org&amp;quot;)))

;; html content

&amp;lt;h2&amp;gt; ,next-steps &amp;lt;&#x2F;h2&amp;gt;

&amp;lt;p&amp;gt;I have yet to see or implement this ,fn1 ,
but imagine using it in regular prose
as a Markdown ,fn2 or LaTeX ,fn3 alternative?&amp;lt;&#x2F;p&amp;gt;

&amp;lt;p&amp;gt;It would probably require being able to define
custom syntax, since it would be tedious to type
&amp;lt;code&amp;gt;,(:link [This is my title])&amp;lt;&#x2F;code&amp;gt;
every time you wanted to insert a link,
for example.&amp;lt;&#x2F;p&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A lot of these ideas were inspired by &lt;a href=&quot;https:&#x2F;&#x2F;typst.app&quot;&gt;Typst&lt;&#x2F;a&gt;, by the way.
Check it out.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Drawing and Writing</title>
            <published>2023-05-15T04:56:14+00:00</published>
            <updated>2023-05-15T04:56:14+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/drawing-writing/"/>
            <id>https://pranabekka.neocities.org/drawing-writing/</id>
            <summary type="html">
              Drawing and writing are essential tools for thinking.
Because they are loose and unstructured,
they allow you to capture thoughts with the least friction;
and capturing thoughts quickly and smoothly is essential for
completing, developing, and refining ideas.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/drawing-writing/">
              &lt;p&gt;Drawing and writing are essential tools for thinking.
Because they are loose and unstructured,
they allow you to capture thoughts with the least friction;
and capturing thoughts quickly and smoothly is essential for
completing, developing, and refining ideas.&lt;&#x2F;p&gt;
&lt;p&gt;You can write and draw with a notebook and pen,
or you could use your smartphone.
You could use a tablet if you want to capture
a lot of sketches digitally, and enable easy
reorganisation and search of text and other material.
Use a physical keyboard if you’re writing a lot,
since keyboards can capture words faster than pens.&lt;&#x2F;p&gt;
&lt;p&gt;This applies to most endeavours.
You might be thinking of a new piece of furniture,
or a topic you want to compile material on,
or figuring out how to organise something,
or designing the interface for an application.&lt;&#x2F;p&gt;
&lt;p&gt;These are all creative pursuits, by the way.
A mathematician exploring new principles and ideas
is just as creative as a painter exploring
new brushes and subject materials.&lt;&#x2F;p&gt;
&lt;p&gt;This might all be feeling like an epiphany to me
purely because I’m a little sleep deprived.
Oh, well.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Github Forks</title>
            <published>2023-05-13T21:10:13+00:00</published>
            <updated>2023-05-13T21:10:13+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/github-forks/"/>
            <id>https://pranabekka.neocities.org/github-forks/</id>
            <summary type="html">
              “Forks” in Github should probably be called “clones”.
That’s basically what they are.
Other related terms are “remotes” and “mirrors”.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/github-forks/">
              &lt;p&gt;“Forks” in Github should probably be called “clones”.
That’s basically what they are.
Other related terms are “remotes” and “mirrors”.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-forks-stand-for&quot;&gt;What “Forks” Stand For&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-forks-stand-for&quot; aria-label=&quot;Anchor link for: what-forks-stand-for&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Outside of Github, a “fork” is a project
that takes the code of one project
and seeks to establish itself as its own project,
with a different name and branding,
as well as different features and code fixes.&lt;&#x2F;p&gt;
&lt;p&gt;In Github parlance, a “fork” is used to mean
a clone of a repository to which you’ve made some changes,
before you can send those changes forward via pull requests.
It’s not meant to be an independent project,
simply a mirror of your personal copy of the project.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reasoning-and-conclusion&quot;&gt;Reasoning and Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#reasoning-and-conclusion&quot; aria-label=&quot;Anchor link for: reasoning-and-conclusion&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I guess Github was worried about the difference between
cloning it onto your machine versus your Github space.
In that case, call it a “Github Clone” or “Remote Clone”?
“Clones” is the more accurate term
because you’re &lt;code&gt;git clone&lt;&#x2F;code&gt;-ing a repo to create a personal copy to mess with.&lt;&#x2F;p&gt;
&lt;p&gt;The git term “remote” is meant for other locations of a repository.
Technically, it’s not a remote —
your copy is not (automatically) a remote to the original copy,
although the original project should be a remote of your copy.
But it is a clone on a (Github) remote.&lt;&#x2F;p&gt;
&lt;p&gt;So ‘Remote Clone’.&lt;&#x2F;p&gt;
&lt;p&gt;I wonder what the process is for (remote) git interfaces like
Sourcehut, Gogs (and descendants like Gitea and Forgejo),
and any other interactive ones.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>GNOME Appreciation</title>
            <published>2023-05-11T16:34:15+00:00</published>
            <updated>2023-05-11T16:34:15+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/gnome-appreciation/"/>
            <id>https://pranabekka.neocities.org/gnome-appreciation/</id>
            <summary type="html">
              I frequently see people annoyed with GNOME,
but I personally like a lot of GNOME’s decisions,
even if I don’t use it.
This post is about those decisions that make GNOME great.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/gnome-appreciation/">
              &lt;p&gt;I frequently see people annoyed with GNOME,
but I personally like a lot of GNOME’s decisions,
even if I don’t use it.
This post is about those decisions that make GNOME great.&lt;&#x2F;p&gt;
&lt;p&gt;In summary, it’s simple, pretty and approachable for new users,
and its overview screen is in a class of its own.&lt;&#x2F;p&gt;
&lt;!-- TODO?: add screenshots&#x2F;gifs? --&gt;
&lt;h2 id=&quot;super-power-the-overview&quot;&gt;Super Power (The Overview)&lt;a class=&quot;zola-anchor&quot; href=&quot;#super-power-the-overview&quot; aria-label=&quot;Anchor link for: super-power-the-overview&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;See what I did there?
The ‘Super’ button is a name for the main shortcut button,
which is ‘Windows’ on most keyboards
and ‘Command’ on Apple keyboards.&lt;&#x2F;p&gt;
&lt;p&gt;In GNOME, the ‘Super’ button simply gives you so much power
with the press of just a single button.&lt;&#x2F;p&gt;
&lt;p&gt;You can open the overview with the ‘Super’ key,
or a three finger swipe up on the touchpad,
or clicking on the Activities button,
or even just flicking your mouse to the top left
(to where the activities button is).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;video src=&quot;&#x2F;gnome-overview.mp4&quot;
       poster=&quot;&#x2F;gnome-overview.jpg&quot;
       alt=&quot;GNOME Overview&quot;
       playsinline controls muted&gt;&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;p&gt;(Video copied from &lt;a href=&quot;https:&#x2F;&#x2F;forty.gnome.org&quot;&gt;forty.gnome.org&lt;&#x2F;a&gt;:
shows swiping up to view overview, then again to view all apps)&lt;&#x2F;p&gt;
&lt;p&gt;You then get, at your fingertips:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The current workspace.&lt;&#x2F;li&gt;
&lt;li&gt;All the apps open on the current workspace.&lt;&#x2F;li&gt;
&lt;li&gt;Any other workspaces and its apps.&lt;&#x2F;li&gt;
&lt;li&gt;Your pinned applications.&lt;&#x2F;li&gt;
&lt;li&gt;A search bar to access absolutely &lt;em&gt;all&lt;&#x2F;em&gt; of your apps,
files and folders. &lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
And you only need to start typing.
No extra clicks or keys required.&lt;&#x2F;li&gt;
&lt;li&gt;Smooth animations to highlight
the spatial relationships between all elements.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All the other desktops require
several different shortcuts or buttons for this.
You can have an applications menu,
but it might not have a search bar.
Or you might, but it only searches applications.
Then it needs a separate shortcut
to search through files and folders.&lt;&#x2F;p&gt;
&lt;p&gt;And you’ll never get a desktop overview
with all your apps (launchers) available.
Picture this:
you’re in the all apps view,
with two desktop thumbnails up top.
You drag the calculator to the first,
then the browser to the second,
then GNOME will create a third workspace for you,
then you drag the messaging and email apps to the third,
and then you start typing ‘Finan’,
when GNOME suggests ‘Financial Report.xlsx’
and you just hit ‘Enter’ to open
your spreadsheet app on the first workspace
— and just like that, you’re off to the races!&lt;&#x2F;p&gt;
&lt;p&gt;Frankly, the overview makes GNOME
the smoothest and slickest DE implementation
that I’ve ever seen —
not just in terms of looks,
but also the consistent spatial layout&#x2F;relation of things,
as well as all the &lt;em&gt;power&lt;&#x2F;em&gt; that it presents
in such a simple package.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simplicity&quot;&gt;Simplicity&lt;a class=&quot;zola-anchor&quot; href=&quot;#simplicity&quot; aria-label=&quot;Anchor link for: simplicity&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The GNOME DE and apps focus a lot on simplicity.
It’s all about doing the things that you need to do
and avoiding unecessary clutter.&lt;&#x2F;p&gt;
&lt;p&gt;Advanced features are reserved for other apps or plugins
unless&#x2F;until they come up with a more thought out design.&lt;&#x2F;p&gt;
&lt;p&gt;This creates a great environment for new users
to get their work done
without making mistakes,
or worrying about making mistakes,
or getting distracted.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;theming&quot;&gt;Theming&lt;a class=&quot;zola-anchor&quot; href=&quot;#theming&quot; aria-label=&quot;Anchor link for: theming&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;GNOME apps use a fairly modern and “trendy” UI,
with flat design and plenty of white space,
which is another thing that makes it approachable to new users.&lt;&#x2F;p&gt;
&lt;p&gt;While this is not for everyone
and might not be objectively beautiful,
it is familiar and in keeping with current designs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;responsiveness&quot;&gt;Responsiveness&lt;a class=&quot;zola-anchor&quot; href=&quot;#responsiveness&quot; aria-label=&quot;Anchor link for: responsiveness&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A lot of GNOME apps and components automatically
adapt to smaller sizes.&lt;&#x2F;p&gt;
&lt;p&gt;This makes it feasible to open lots of apps in the same window,
and to use the same apps on mobiles and tablets.
Wooooo convergence!&lt;&#x2F;p&gt;
&lt;p&gt;You should see the GNOME mobile shell (Phosh).
It basically uses the same apps and UI as the desktop,
with minor tweaks to fit the form factor.
The consistency and careful design
just leaves me speechless.&lt;&#x2F;p&gt;
&lt;p&gt;Short demo videos available in these two articles by articles by Jonas Dressler:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blogs.gnome.org&#x2F;shell-dev&#x2F;2022&#x2F;05&#x2F;30&#x2F;towards-gnome-shell-on-mobile&#x2F;&quot;&gt;Towards GNOME Shell on mobile&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blogs.gnome.org&#x2F;shell-dev&#x2F;2022&#x2F;09&#x2F;09&#x2F;gnome-shell-on-mobile-an-update&#x2F;&quot;&gt;GNOME Shell on mobile: An update&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;flaws&quot;&gt;Flaws&lt;a class=&quot;zola-anchor&quot; href=&quot;#flaws&quot; aria-label=&quot;Anchor link for: flaws&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now, GNOME isn’t perfect.&lt;&#x2F;p&gt;
&lt;p&gt;There are some things that I don’t quite agree with,
and some things that bother other users.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;centre-app-bar&quot;&gt;Centre App Bar&lt;a class=&quot;zola-anchor&quot; href=&quot;#centre-app-bar&quot; aria-label=&quot;Anchor link for: centre-app-bar&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;My biggest nitpick,
which I noticed when Windows 11 made the same mistake,
is apps aligned along the centre.
When you open a lot of apps,
your pinned apps are no longer where you expect them to be,
so you now have to be more careful.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, a button in the corner is much easier to click
since you can’t overshoot it with quick movements,
which prevents accidentally clicking on something else.
GNOME gets this right with the ‘Activities’ button,
but not with the app bar.&lt;&#x2F;p&gt;
&lt;p&gt;It might not be a big deal,
and it would certainly be difficult to solve,
but I just feel like it’s objectively wrong.
Perhaps the solution is a combined app and status bar,
but I can’t say,
since it’s advantageous to have
a narrow status bar that’s always visible.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;flatpaks&quot;&gt;Flatpaks&lt;a class=&quot;zola-anchor&quot; href=&quot;#flatpaks&quot; aria-label=&quot;Anchor link for: flatpaks&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Another thing that annoys me
is their insistence on using Flatpak.&lt;&#x2F;p&gt;
&lt;p&gt;Despite an established culture of
maintainers and packagers in the Linux world,
they think it’s a great idea to push
additional responsibilities on app developers.
This also indirectly suggests that
developers silo themselves and ignore maintainers.&lt;&#x2F;p&gt;
&lt;p&gt;Furthermore, it hampers performance for apps,
especially on lower grade hardware,
and as a new technology it prevents some affordances
that are available with normally installed apps.
I mean, one of the reasons I first switched to Linux
was precisely because my laptop struggled a lot.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bleeding-edge&quot;&gt;Bleeding Edge&lt;a class=&quot;zola-anchor&quot; href=&quot;#bleeding-edge&quot; aria-label=&quot;Anchor link for: bleeding-edge&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;While it doesn’t bother me specifically
(probably because I don’t use GNOME),
GNOME sometimes breaks things for existing users,
and often despite large backlash,
which makes users feel hurt or offended,
which can lead to the actions and resulting tension
that accompany high running emotions
between the core team and users&#x2F;contributors.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;missing-features&quot;&gt;Missing Features&lt;a class=&quot;zola-anchor&quot; href=&quot;#missing-features&quot; aria-label=&quot;Anchor link for: missing-features&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Because of their focus on simplicity,
they take a while to work through features,
such as the background app statuses,
which were recently added after several years.&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully, GNOME has a decent plugin ecosystem.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Function Design Recipe</title>
            <published>2023-05-11T12:36:29+00:00</published>
            <updated>2023-05-11T12:36:29+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/function-recipe/"/>
            <id>https://pranabekka.neocities.org/function-recipe/</id>
            <summary type="html">
              How to Design Programs (HtDP)
specifies a simple method of designing programs,
called a recipe,
which they call the Function Design Recipe,
introduced in the preface.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/function-recipe/">
              &lt;p&gt;How to Design Programs (HtDP)
specifies a simple method of designing programs,
called a recipe,
which they call the Function Design Recipe,
introduced in the preface.&lt;&#x2F;p&gt;
&lt;p&gt;It’s a fairly simple practice,
and it helped me hammer out some 2048 code
that I’ve been chipping away at off an on for several months.
One help is my growing familiarity with the language, of course,
but the function recipe did a lot of work
in clarifying the design
and letting me know how and where to put my efforts.
This &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=1SlGgCxJa3w&quot;&gt;video (YouTube)&lt;&#x2F;a&gt;
presents a story of why it is useful
in a broader example.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;The idea is to take things step by step.
At the level of the team in the video
the steps are on a grander scale,
but at the level of beginners
it’s very useful to follow the steps
of the Function Design Recipe.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;You can find it at &lt;a href=&quot;https:&#x2F;&#x2F;htdp.org&#x2F;2023-3-6&#x2F;Book&#x2F;part_preface.html&quot;&gt;htdp.org&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
I recommend you go through the book if you’re
a new or intermediate programmer.
The preface is a good place to start.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;The book seems to be updated with some frequency.
If you see the URL, you’ll see &lt;code&gt;2023-3-6&lt;&#x2F;code&gt;,
which suggests it was updated on 6th March 2023.
I recommend starting at &lt;a href=&quot;https:&#x2F;&#x2F;htdp.org&quot;&gt;htdp.org&lt;&#x2F;a&gt;
and clicking the book title to open the index,
so that you have the latest edition.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-recipe&quot;&gt;The Recipe&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-recipe&quot; aria-label=&quot;Anchor link for: the-recipe&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; This is not strictly the recipe.
I’ve borrowed basic ideas from it,
and managed to use it quite successfully.&lt;&#x2F;p&gt;
&lt;p&gt;The first step is to figure out the shape of the data
that you’ll be working on.
You’re recommended to do this using comments.&lt;&#x2F;p&gt;
&lt;p&gt;The next step is a signature and description
of the primary function and its purpose.
The signature says what inputs it requires,
and then what kind of output it spits out.
You can model this as simple data types,
also using the comments.
The purpose follows right after,
stating what the function is meant to do.&lt;&#x2F;p&gt;
&lt;p&gt;Then you create a template of the function,
based on the signature,
also using comments.
Feel free to use &lt;code&gt;...&lt;&#x2F;code&gt; for unknown parts.
My templates simply had a function name
and a list of arguments.
The tests will be run later to verify your code.&lt;&#x2F;p&gt;
&lt;p&gt;The next step is to write some tests for the code.
Write down the test input and the expected output using code.
Think of some edge cases and what their output should be.
These tests will be executed later to validate the program.
I skipped these for my 2048 code
because the game uses random input,
which is easier for me to test visually
than to write test cases for,
especially at the scale I’m working on.
It’s probably a good habit though.
I might try to write tests further along,
with more complicated tests to check the random input.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, you flesh out your template into complete code
and then run your tests on it.
This step took some time,
because I had to look up documentation
and play around with some functions
to see how they might suit my needs.
This is partially because I like to work without the internet,
in order to increase my capability of working offline,
with just the repl and the documentation.&lt;&#x2F;p&gt;
&lt;p&gt;As I mentioned above,
this is my loose interpretation of the steps,
meant to provide a gist of how it works.
Please reference the &lt;a href=&quot;https:&#x2F;&#x2F;htdp.org&quot;&gt;book&lt;&#x2F;a&gt; if you’re interested
— click on the book title to open the index. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;The book seems to be updated with some frequency.
If you see the URL, you’ll see &lt;code&gt;2023-3-6&lt;&#x2F;code&gt;,
which suggests it was updated on 6th March 2023.
I recommend starting at &lt;a href=&quot;https:&#x2F;&#x2F;htdp.org&quot;&gt;htdp.org&lt;&#x2F;a&gt;
and clicking the book title to open the index,
so that you have the latest edition.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>DIY (Fish) Shell Templating</title>
            <published>2023-05-07T14:07:52+00:00</published>
            <updated>2023-05-11T13:26:57+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/shell-templating/"/>
            <id>https://pranabekka.neocities.org/shell-templating/</id>
            <summary type="html">
              If you’ve seen my note on creating a
Static Site Build Tool,
you might’ve seen the link to pp,
and that I lament the syntax and the fact that it uses ash/dash.
Turns out it’s quite easy to implement in fish,
along with a syntax I prefer!
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/shell-templating/">
              &lt;p&gt;If you’ve seen my note on creating a
&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;static-site-build-tool&#x2F;&quot;&gt;Static Site Build Tool&lt;&#x2F;a&gt;,
you might’ve seen the link to &lt;a href=&quot;https:&#x2F;&#x2F;adi.onl&#x2F;pp.html&quot;&gt;pp&lt;&#x2F;a&gt;,
and that I lament the syntax and the fact that it uses ash&#x2F;dash.
Turns out it’s quite easy to implement in fish,
along with a syntax I prefer!&lt;&#x2F;p&gt;
&lt;p&gt;It started with me just going about my day,
when I remembered the &lt;code&gt;eval&lt;&#x2F;code&gt; command
and I started thinking of the pieces I might need
to create a parser&#x2F;state machine of sorts in fish.
I tinkered a bit with some of the commands
I was thinking of,
and I managed to get it working quite well!&lt;&#x2F;p&gt;
&lt;p&gt;I haven’t made a way of putting in variables
or reading and writing from a file,
and I haven’t thought of too many edge cases,
but the basic functionality is there.&lt;&#x2F;p&gt;
&lt;p&gt;If I run &lt;code&gt;.&#x2F;parser.fish &amp;quot;the date is {{ date -I }}&amp;quot;&lt;&#x2F;code&gt;
it will give me the output &lt;code&gt;the date is 2023-05-07&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I’ve pasted in the whole thing,
as it currently is,
at the end,
if you’re curious.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it Works&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-it-works&quot; aria-label=&quot;Anchor link for: how-it-works&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The basic way it works,
is it uses a variable to figure out
if it’s reading normal text or command text.
If it’s reading normal text,
it simply passes it along to stdout,
and if it’s reading command text,
it gathers that into a string,
then runs &lt;code&gt;eval&lt;&#x2F;code&gt; on it,
which spits out its output to stdout.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-work&quot;&gt;Future Work&lt;a class=&quot;zola-anchor&quot; href=&quot;#future-work&quot; aria-label=&quot;Anchor link for: future-work&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I want to be able to parse files
instead of just strings.
The answer might be somewhere in &lt;code&gt;string join \n $fileContents&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;When parsing files,
it would be useful to provide variables for substitution.
Perhaps it could be done by specifying environment variables
in the same line as the command.
Something like &lt;code&gt;VAR=val fish-template str &amp;quot;{{ echo $VAR }}&lt;&#x2F;code&gt;.
Another way would be a syntax for keys and values.
Perhaps &lt;code&gt;--variables &amp;quot;key1: val1; key2: val2&amp;quot;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A short syntax for variable expansion might also be nice.
Something like &lt;code&gt;{{ $var }}&lt;&#x2F;code&gt; or &lt;code&gt;{$ var $}&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It would be cool to have a way to limit its scope,
depending on where it’s being called from.
Include a list to allow certain commands,
as well as one to block some.
If the first the command isn’t in the allow list,
or is present in the block list,
then raise an error instead of evaluating it.&lt;&#x2F;p&gt;
&lt;p&gt;In a similar vein, providing additional commands would be great.
A simple way is to create commands in a &lt;code&gt;bin&#x2F;&lt;&#x2F;code&gt; directory
and then run them with &lt;code&gt;{{ .&#x2F;bin&#x2F;my-command }}&lt;&#x2F;code&gt;,
but a shorter syntax would be quite useful.
Perhaps use the &lt;code&gt;bin&#x2F;&lt;&#x2F;code&gt; directory
with a syntax like &lt;code&gt;{{ @my-command }}&lt;&#x2F;code&gt;?
Or simply &lt;code&gt;{{ my-command }}&lt;&#x2F;code&gt;,
such that if &lt;code&gt;my-command&lt;&#x2F;code&gt; is not installed,
it would look in the bin directory.&lt;&#x2F;p&gt;
&lt;p&gt;It is ideal that the template evaluation
takes place from a specific directory.
Especially if relying on file operations
or something like a &lt;code&gt;.&#x2F;bin&#x2F;&lt;&#x2F;code&gt; directory.
When calling the command on a template file,
ensure the current working directory
is the same as the file’s parent directory,
unless specified otherwise.
Changing directories in the script
sounds like a potential footgun,
since it’s implicit behaviour that people will not be aware of.
An easy flag, then,
to execute in the context of the template file’s folder.
So &lt;code&gt;--dir &amp;lt; current | file-dir | &amp;lt;path&amp;gt; &amp;gt;&lt;&#x2F;code&gt;,
where &lt;path&gt; is relative (starting with &lt;code&gt;.&#x2F;&lt;&#x2F;code&gt;) or absolute.&lt;&#x2F;p&gt;
&lt;p&gt;It would also be great to have all commands in the file&#x2F;template
evaluate in the same context.
This way a variable declared at the top
could be used in a command further down.
Currently, it spawns subshells using the &lt;code&gt;eval&lt;&#x2F;code&gt; command.
Maybe it could use &lt;code&gt;source&lt;&#x2F;code&gt; or a flag in &lt;code&gt;eval&lt;&#x2F;code&gt;?
Another approach might be to gather content
as an &lt;code&gt;echo $content&lt;&#x2F;code&gt; command
along with the other commands in the given sequence,
then calling all the echo and other commands
using a single &lt;code&gt;eval&lt;&#x2F;code&gt; command at the end.
Use &lt;code&gt;string escape&lt;&#x2F;code&gt; to prevent unwanted expansions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code&quot;&gt;Code&lt;a class=&quot;zola-anchor&quot; href=&quot;#code&quot; aria-label=&quot;Anchor link for: code&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;fish&quot; class=&quot;language-fish z-code&quot;&gt;&lt;code class=&quot;language-fish&quot; data-lang=&quot;fish&quot;&gt;&lt;span class=&quot;z-source z-shell z-fish&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;normal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;argv&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brackets z-index-expansion z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-begin z-fish&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-fish&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-end z-fish&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-pipe z-stdout z-implicit z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-pipe z-fish&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-while z-fish&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;while&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;read&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-option z-short z-fish&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-option z-short z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-numeric z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-fish&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;char&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;  &lt;span class=&quot;z-meta z-block z-switch z-fish&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;switch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;char&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;normal {&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;open-brace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;open-brace {&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;command-mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;open-brace *&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;normal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;printf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;{%s&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;char&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;command-mode }&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;close-brace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;close-brace }&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;normal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-comment z-line z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-fish&quot;&gt;#&lt;&#x2F;span&gt; echo \&amp;#39;$command\&amp;#39;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;eval&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;close-brace *&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;\}&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;char&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;command-mode &lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-comment z-line z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-fish&quot;&gt;#&lt;&#x2F;span&gt; newline creates &amp;#39;&amp;#39; when read
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; ; &lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;command-mode #&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;comment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;comment &lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-comment z-line z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-fish&quot;&gt;#&lt;&#x2F;span&gt; newline creates &amp;#39;&amp;#39; when read
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;parserMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;command-mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; ; &lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;command-mode *&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;command&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;char&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;normal &lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-comment z-line z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-fish&quot;&gt;#&lt;&#x2F;span&gt; newline creates &amp;#39;&amp;#39; when read
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;printf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;&lt;span class=&quot;z-constant z-character z-escape z-fish&quot;&gt;\n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;
    &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-path z-fish&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;normal *&lt;span class=&quot;z-punctuation z-definition z-string z-end z-fish&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;      &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-variable z-function z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;printf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-process-expansion z-other z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-process z-fish&quot;&gt;%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-fish&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-parameter z-argument z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;&lt;span class=&quot;z-meta z-variable-expansion z-fish&quot;&gt;&lt;span class=&quot;z-variable z-other z-fish&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-fish&quot;&gt;$&lt;&#x2F;span&gt;char&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;  &lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-name z-fish&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-fish&quot;&gt;&lt;span class=&quot;z-meta z-string z-unquoted z-fish&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-operator z-control z-fish&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Do More in Your Minecraft Worlds</title>
            <published>2023-05-06T01:38:56+00:00</published>
            <updated>2023-05-06T01:38:56+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/minecraft-enhanced/"/>
            <id>https://pranabekka.neocities.org/minecraft-enhanced/</id>
            <summary type="html">
              
It’s hard to get things done in a Minecraft world,
because you often don’t have time,
and you can’t achieve the things that you dream of,
especially the cool things you see from other people,
and maybe prototype in your creative worlds.
This is a set of rules to help you do cool things
in your Minecraft worlds,
including singleplayer,
as well as small multiplayer worlds with friends.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/minecraft-enhanced/">
              &lt;!--
TODO: link to &#x2F;fill and &#x2F;clone command use
--&gt;
&lt;p&gt;It’s hard to get things done in a Minecraft world,
because you often don’t have time,
and you can’t achieve the things that you dream of,
especially the cool things you see from other people,
and maybe prototype in your creative worlds.
This is a set of rules to help you do cool things
in your Minecraft worlds,
including singleplayer,
as well as small multiplayer worlds with friends.&lt;&#x2F;p&gt;
&lt;p&gt;There’s also a bonus solution at the end
to make the game more accessible
(in a looser sense of the word),
similar to the accessibility options of games like
&lt;a href=&quot;https:&#x2F;&#x2F;celeste.ink&#x2F;wiki&#x2F;Assist_Mode&quot;&gt;Celeste (Celeste Wiki)&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;araisegamer.com&#x2F;rusted-moss-how-to-fly&#x2F;&quot;&gt;Rusted Moss (Article on Flying)&lt;&#x2F;a&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;You can see the other options in the screenshots.
The basic instructions apply to those as well.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; A lot of this is trust based,
and might not scale so well.
It works best with friends and acquaintances.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-problem&quot; aria-label=&quot;Anchor link for: the-problem&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can’t build large things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Not enough time&lt;&#x2F;li&gt;
&lt;li&gt;Not enough materials&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can’t accumulate enough materials from your farms:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Not enough time&lt;&#x2F;li&gt;
&lt;li&gt;Can’t AFK because you can’t run Minecraft
while doing other work.
It slows your computer.&lt;&#x2F;li&gt;
&lt;li&gt;Can’t AFK because you can’t keep your computer on.
Possible reasons: high energy bills,
having to carry your laptop around,
unable to monitor computer,
power cutoffs.&lt;&#x2F;li&gt;
&lt;li&gt;Can’t AFK because of poor networks.&lt;&#x2F;li&gt;
&lt;li&gt;Can’t AFK because you host a server from a personal computer,
in which case the previous considerations apply.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-solution&quot; aria-label=&quot;Anchor link for: the-solution&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Offline Hours:
When you’re not playing on the server
you build up a sort of currency called “Offline Hours”.
While the name says hours,
you can time it down to minutes, half hours, or quarters.
This currency can be spent on certain actions
which have varying costs.&lt;&#x2F;li&gt;
&lt;li&gt;AFK Simulation Rule:
If you have an automatic farm of some kind,
measure its output for 5–10 minutes and record it.
You can now spend your “Offline Hours”
and get the materials you would get for that amount of time
by multiplying it with your measurements.&lt;&#x2F;li&gt;
&lt;li&gt;Build Grind Rule:
You can also establish an average baseline for
how many blocks can be placed per minute,
and spend your “Offline Hours”
to fill&#x2F;copy large amounts of blocks
based on that amount.
This can be used to copy repeated elements of a build,
such as a large patterned wall,
or to clear out a large area,
for example.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;bonus-rule-additional-accessibility&quot;&gt;Bonus Rule: Additional Accessibility&lt;a class=&quot;zola-anchor&quot; href=&quot;#bonus-rule-additional-accessibility&quot; aria-label=&quot;Anchor link for: bonus-rule-additional-accessibility&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; I’m using “accessibility” in a looser sense of the word,
not in the sense of a11y &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. &lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Computer_accessibility&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This rule derives from my own frustrations with lag,
but they apply to any player
who might be disadvantaged in any way.
For example, they might not be hardcore gamers,
or they play with special hardware.
Other disadvantages include lag and rubberbanding.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Accessibility Rule:
Players with disadvantages have reduced penalties,
or buffs to deal with their disadvantages.
For example, they might keep their inventory whenever they die,
or they could have extra health,
or they could have permanent regeneration&#x2F;resistance,
or they could have other special items and&#x2F;or abilities,
such as flying
or fire spells that damage hostiles in a given radius.
See what the frustrations and needs of your players are.
The rule need not apply at all times.
For example, network effects can be temporary.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; The other rules are also about accessibility —
they’re about making certain parts of the game
more accessible to everyday players
who might not have enough time
to achieve the big builds they dream of.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementation-and-caveats&quot;&gt;Implementation and Caveats&lt;a class=&quot;zola-anchor&quot; href=&quot;#implementation-and-caveats&quot; aria-label=&quot;Anchor link for: implementation-and-caveats&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is a largely trust based system.&lt;&#x2F;p&gt;
&lt;p&gt;The easiest way to run it,
is to calculate your Offline Hours, etc.,
and then use commands according to the rules.
The AFK rule can be achieved by using &lt;code&gt;&#x2F;give&lt;&#x2F;code&gt;
after calculating how many items you should get.
The build rule can be achieved by using
the &lt;code&gt;&#x2F;fill&lt;&#x2F;code&gt; or &lt;code&gt;&#x2F;clone&lt;&#x2F;code&gt; commands.
Make sure to use the destroy option,
so that you get any blocks that are replaced (or “broken”).
This is also the most flexible and powerful system.&lt;&#x2F;p&gt;
&lt;p&gt;Make sure to take regular backups
if you’re relying on players to use the commands.
Maybe before each command,
or before you start up the server
(this is the same as backing up after closing the server).&lt;&#x2F;p&gt;
&lt;p&gt;People who are unfamiliar with the commands
can either learn to use them with some tutorials,
or they can rely on other people to run it for them.
If you’re applying this to a server,
it would be ideal for the server admin to know them,
since they should be available when the server is up.&lt;&#x2F;p&gt;
&lt;p&gt;To make it easier for people who don’t know commands,
you could set up trigger commands for them.
Trigger commands won’t be able to do everything,
but they should let players do some things on their own.&lt;&#x2F;p&gt;
&lt;p&gt;If you have Minecraft modding experience,
that would be really cool —
you could implement it
and share it with people who are
uncomfortable with commands.
Some additional accesibility features
are best achieved through mods, in fact.
However, try to not make them too invasive.&lt;&#x2F;p&gt;
&lt;p&gt;If people build up “too many” Offline Hours,
you can put a limit on how many they can make.
Make the decision based on the situation.&lt;&#x2F;p&gt;
&lt;p&gt;If you find yourself abusing commands in other ways,
you could create a process
which makes you take it more seriously.&lt;&#x2F;p&gt;
&lt;p&gt;For example, in a singleplayer world,
you can simply create a note,
and every time you use a command,
you put it into that note
with the time, the command,
and why you’re allowed to use it
(number of Offline Hours, any other reasoning).
That note could also include how many Offline Hours you have.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re in a multiplayer world,
you can create a way to submit requests
and get them approved by at least on or two other members.
The admin or other operators could then fulfil these requests,
or you could trust players to responsibly fulfil them
once their request has been approved.
You can make it more or less strict as required.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Make a simple set of rules for achieving things
without requiring prohibitive amounts of work.
The rules should reflect the costs and rewards
that you (and&#x2F;or your players) find
reasonable and enjoyable.&lt;&#x2F;p&gt;
&lt;p&gt;Remember to fine tune the rules and rewards
according to your (or others’) needs.
You don’t want to make the game too easy,
or it won’t be as rewarding,
nor do you want to make it too strict.
You must also communicate this to your players
and discuss matters with them
to create a fun environment for everyone.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>A New (Top-Down, 3D) Game</title>
            <published>2023-05-05T11:05:57+00:00</published>
            <updated>2023-05-05T11:05:57+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/a-new-game/"/>
            <id>https://pranabekka.neocities.org/a-new-game/</id>
            <summary type="html">
              I like coming up with game ideas all the time.
Well, I come up with bizarre ideas of any kind.
Here’s my rambling about a game idea I had last night:
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/a-new-game/">
              &lt;p&gt;I like coming up with game ideas all the time.
Well, I come up with bizarre ideas of any kind.
Here’s my rambling about a game idea I had last night:&lt;&#x2F;p&gt;
&lt;p&gt;This one was prompted by me watching a compilation
of several sci-fi&#x2F;cyberpunk (indie?) games.
I liked the story bits in some of them,
in the sense of your actions building up over time,
and contributing to a larger narrative.
The only game I play right now is a battle royale
with some friends.
It would be nice to have a co-op experience.&lt;&#x2F;p&gt;
&lt;p&gt;But then I fear they may get bored soon.
There’s only so much story content you can add to a game.
Perhaps you could make emergent behaviour using complex systems,
but there’s just something else about competitive multiplayer games.
That’s a whole different universe of emergent behaviour.&lt;&#x2F;p&gt;
&lt;p&gt;So, that means a multiplayer element as well.
And why not.
Why can’t you have an interesting top down multiplayer experience.
Some already exist, in fact.
Furthermore, it would be more performant and flexible
than the higher resolution first-person&#x2F;third-person 3D games.&lt;&#x2F;p&gt;
&lt;p&gt;Ah, yes. The 3D was also a decision to manage appeal,
even though I personally enjoy pixel art a lot.
Imagine the game in low-poly 3D!&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, some top-down games are already in the popular market,
and some of them are even battle royales.
So we could implement some fun mechanisms
for various weapons and items,
as well as environment interactions.&lt;&#x2F;p&gt;
&lt;p&gt;A fog of war system (?) for limiting vision
to a certain distance and through certain materials.
Imagine blasting open doors
and hitting people in the face with it.
Imagine spells, perhaps.
Imagine camouflage items, flamethrowers,
mines, drills, missiles — the whole gamut!
Melee combat of all kinds as well!
You could have a character class
that’s simply larger and stronger than others
who just slams other people.&lt;&#x2F;p&gt;
&lt;p&gt;I think people would appreciate the art style of Xenowerk.
As a more varied PvP and PvE experience.&lt;&#x2F;p&gt;
&lt;p&gt;A 3D character also creates more interesting UI opportunities,
such as a rotating model in your character selection screen.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;My note from last night:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Any story based game
will eventually run out of gameplay,
unless it has the foundations for making your own games,
as well as content updates.&lt;&#x2F;p&gt;
&lt;p&gt;And multiplayer modes with unpredictable outcomes,
with some requirement of skill.&lt;&#x2F;p&gt;
&lt;p&gt;Top down is best to include mobile users as well.&lt;&#x2F;p&gt;
&lt;p&gt;Test out mechanics for multiplayer as well
and maybe tweak the balance for pve modes.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Skeu&amp;shy;morphism</title>
            <published>2023-04-28T17:31:56+00:00</published>
            <updated>2023-04-28T17:31:56+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/skeumorphism/"/>
            <id>https://pranabekka.neocities.org/skeumorphism/</id>
            <summary type="html">
              The gear icon for settings. 
The envelope icon for email. 
The paper plane icon for sending a message. 
The bell for notifications. 
The pages in the world wide web. 
The desktop, and the windows on it.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/skeumorphism/">
              &lt;p&gt;The gear icon for settings. &lt;br &#x2F;&gt;
The envelope icon for email. &lt;br &#x2F;&gt;
The paper plane icon for sending a message. &lt;br &#x2F;&gt;
The bell for notifications. &lt;br &#x2F;&gt;
The pages in the world wide web. &lt;br &#x2F;&gt;
The desktop, and the windows on it.&lt;&#x2F;p&gt;
&lt;p&gt;Skeumorphism isn’t gone,
but maybe we’ve reached the point where
there’s nothing left to take away.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Organising Your Files</title>
            <published>2023-04-24T12:55:31+00:00</published>
            <updated>2023-04-24T12:55:31+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/file-organisation/"/>
            <id>https://pranabekka.neocities.org/file-organisation/</id>
            <summary type="html">
              This is a pretty simple file storage method,
revolving around two folders and links.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/file-organisation/">
              &lt;p&gt;This is a pretty simple file storage method,
revolving around two folders and links.&lt;&#x2F;p&gt;
&lt;p&gt;The two folders here are your ‘Archive’ and ‘Inbox’.
The ‘Archive’ folder is where your organised files stay,
and the ‘Inbox’ folder is where new files come in.
The ‘Inbox’ folder is also where you place
files and folders that you are currently working on
— using links, not copying.&lt;&#x2F;p&gt;
&lt;p&gt;Links are special files that point to another
file or folder on your computer.
If you link to a file instead of copying it,
whenever you edit a file
it will actually edit the original file,
and the links will continue to point to the same file
along with the edits you made.
I believe links are known as ‘shortcuts’ in Windows
and ‘aliases’ in MacOS.
There are a few more things to know about links,
which I’ve mentioned further below.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-archive-and-project-folders&quot;&gt;The Archive and Project Folders&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-archive-and-project-folders&quot; aria-label=&quot;Anchor link for: the-archive-and-project-folders&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The ‘Archive’ folder is where your files will always end up,
in a clean and organised format.&lt;&#x2F;p&gt;
&lt;p&gt;The basic way to organise your files is to
keep them in project folders.
That is, files that are part of the same effort
are put into the same folder.
And if you have files that are used in multiple projects,
then you put them in a separate folder and use links.&lt;&#x2F;p&gt;
&lt;p&gt;You only need a project folder if that project has multiple files.
However, if there will soon be multiple files for that project,
or if you will be sharing that project (see ‘Public’ folders),
then you should just create a folder for it.&lt;&#x2F;p&gt;
&lt;p&gt;Here are a few examples:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Files that are about filing taxes go into the ‘tax-filing’ folder.&lt;&#x2F;li&gt;
&lt;li&gt;A report goes into a folder with the name of that report.
If you do multiple reports,
then you could either create a ‘reports’ folder,
or you could add ‘report’ to the beginning of the file name.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;sub-projects&quot;&gt;Sub-Projects&lt;a class=&quot;zola-anchor&quot; href=&quot;#sub-projects&quot; aria-label=&quot;Anchor link for: sub-projects&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Within a project, there are often subprojects,
or sub-tasks.
Usually, you have a single file for each section,
but if it grows enough,
simply create a sub-project folder within the project folder,
and put those additional files in there.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;public&quot;&gt;Public&lt;a class=&quot;zola-anchor&quot; href=&quot;#public&quot; aria-label=&quot;Anchor link for: public&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When you have projects that require you to edit files
before you share them with other people
(such as generating a PDF from your Word file)
you create a ‘Public’ folder within the project folder
and store the exported files in here.&lt;&#x2F;p&gt;
&lt;p&gt;You can even change the end of the file name
to reflect who or what it’s for.
The most frequent use case is when
you remove personal or company information from these files
before you share them with other people.&lt;&#x2F;p&gt;
&lt;p&gt;One example is when you share something for internal review,
and then share another copy to send outside for printing.
In this instance, some printers will want the images
and fonts to be given along with the file,
or they may want it in a different format,
so you’ll have ‘project.png’ file for internal review,
and a ‘project-print&#x2F;’ folder for the printer.&lt;&#x2F;p&gt;
&lt;p&gt;Another example is presentation slides
that are presented to multiple people,
or at different conferences —
you wouldn’t want your slides to say
‘Welcome Mumbai’ for a talk that you’re
presenting at New Delhi.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;new-new-report-final-pdf&quot;&gt;New-new-report-final.pdf&lt;a class=&quot;zola-anchor&quot; href=&quot;#new-new-report-final-pdf&quot; aria-label=&quot;Anchor link for: new-new-report-final-pdf&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A simple way to mitigate this is to add ‘v1’
at the end of the file name,
and change the number every time
you create a new version.&lt;&#x2F;p&gt;
&lt;p&gt;Another way is to add the date at the end,
and if you have more than one version on the same date,
then you add a 1, 2, etc on the end.&lt;&#x2F;p&gt;
&lt;p&gt;If there are a lot of versions,
and you’re struggling to keep track of them,
you can create a changelog.md file,
and write down the important versions,
and the differences between them.&lt;&#x2F;p&gt;
&lt;p&gt;If the project is currently active,
then you will place these new versions inside
the same folder,
but if you’re continuing the project after a long time
or redoing the project completely,
then you create a new project folder
using the version or date scheme.
That is, ‘project-v2&#x2F;’ for your new version.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-inbox-and-active-files-folders&quot;&gt;The Inbox and Active Files&#x2F;Folders&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-inbox-and-active-files-folders&quot; aria-label=&quot;Anchor link for: the-inbox-and-active-files-folders&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The ‘Inbox’ is where unorganised and currently used files sit.
Currently used files are files&#x2F;folders that are organised,
but which you’re currently using.
Instead of moving them or keeping them in the ‘Inbox’ folder,
you link to the actual files in the ‘Archive’ folder:&lt;&#x2F;p&gt;
&lt;p&gt;First, go to the ‘Archive’ folder,
and right click on the file&#x2F;folder you’re working with.
Then, if you’re on Windows, select ‘Create Shortcut’,
or if you’re on MacOS, select ‘Create Alias’,
and select the ‘Inbox’ folder or
move the newly created link to the ‘Inbox’ folder yourself.&lt;&#x2F;p&gt;
&lt;p&gt;When you’re done with a link,
you simply delete the link,
and your actual files will remain in the ‘Archive’ folder.&lt;&#x2F;p&gt;
&lt;p&gt;One example for active files is your taxes folder:
it will remain in the ‘Archive’ folder for most of the year,
except when you start doing your taxes.
When that time comes around,
you link to it in the ‘Inbox’ a few days or weeks in advance,
and start working on your taxes for the year.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inbox-to-archive&quot;&gt;Inbox to Archive&lt;a class=&quot;zola-anchor&quot; href=&quot;#inbox-to-archive&quot; aria-label=&quot;Anchor link for: inbox-to-archive&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You have to take care to periodically
go through your inbox and organise your files.&lt;&#x2F;p&gt;
&lt;p&gt;If the file&#x2F;folder doesn’t have any more use,
then simply put it in the trash bin.&lt;&#x2F;p&gt;
&lt;p&gt;If it’s a link to a folder in the archive
and you’re no longer using it,
then delete the link.
Your actual files will still be there in the ‘Archive’ folder.&lt;&#x2F;p&gt;
&lt;p&gt;If the file&#x2F;folder belongs to an existing project,
put it into that project folder.
Don’t just dump it in, but name it properly,
and put it into a sub-folder if required.&lt;&#x2F;p&gt;
&lt;p&gt;If the file&#x2F;folder doesn’t belong to any project
that you can think of,
then create a new folder for it,
or simply rename it according to that project.&lt;&#x2F;p&gt;
&lt;p&gt;Ideally, you should do this every day
and set a reminder for a specific time.
If you did very little file juggling work today,
then that’s great — it will only take you 5 minutes.
If you have a lot of files to organise,
then you should do it today,
before the pile gets larger.
If you’re especially tired today,
then you can postpone your reminder to the next day,
or for a different time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;integration-with-system-file-manager&quot;&gt;Integration with System&#x2F;File Manager&lt;a class=&quot;zola-anchor&quot; href=&quot;#integration-with-system-file-manager&quot; aria-label=&quot;Anchor link for: integration-with-system-file-manager&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I recommend deleting your ‘Downloads’, ‘Videos’,
‘Pictures’ and ‘Desktop’ folders,
and creating them anew as links to the ‘Inbox’ folder.
There are two main reasons for this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First, the ‘Downloads’, ‘Pictures’ and ‘Videos’ folder
frequently get new and unorganised files dumped into them
from various apps such as the browser and screenshot tool.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Second, it’s easier to access active files&#x2F;folders
from the desktop or any of the other folders,
because lots of file picker dialogues will default to these.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Also, if you use desktop icons
you’ll have them easily accessible,
or you could skip that if you don’t like them.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Similarly, I recommend deleting the ‘Documents’ folder
and creating a new link pointing to the ‘Archive’ folder.
You’ll be able to quickly select it in any file choosers,
and it will appear at the top of your main folders list
in the file manager.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;easy-backup-and-transfer&quot;&gt;Easy Backup and Transfer&lt;a class=&quot;zola-anchor&quot; href=&quot;#easy-backup-and-transfer&quot; aria-label=&quot;Anchor link for: easy-backup-and-transfer&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One easy benefit of this system is that you know,
in a general sense, where all your files are,
and you only need to backup&#x2F;copy these two folders
to get all your files wherever you want.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;links-for-various-platforms&quot;&gt;Links for Various Platforms&lt;a class=&quot;zola-anchor&quot; href=&quot;#links-for-various-platforms&quot; aria-label=&quot;Anchor link for: links-for-various-platforms&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.digitalcitizen.life&#x2F;how-create-shortcuts&#x2F;#ftoc-heading-7&quot;&gt;Windows (11)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you use ‘Send to Desktop (create shortcut)’,
remember to link the ‘Desktop’ to your ‘Inbox’ folder.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;support.apple.com&#x2F;en-in&#x2F;guide&#x2F;mac-help&#x2F;mchlp1046&#x2F;mac&quot;&gt;macOS&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Try the Option-Command with drag method.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;askubuntu.com&#x2F;a&#x2F;941711&quot;&gt;Linux - GNOME Files (Nautilus)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I’ve confirmed that the alt+release method works in version 42.2.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Linux - KDE Dolphin&lt;&#x2F;p&gt;
&lt;p&gt;It appears you can simply right click on empty space,
and select ‘Create New’ then ‘Link’.&lt;&#x2F;p&gt;
&lt;p&gt;Source: &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;kde&#x2F;comments&#x2F;mpz1rc&#x2F;dolphin_convenient_way_to_create_a_symlink&#x2F;&quot;&gt;r&#x2F;kde&lt;&#x2F;a&gt;
(See the comment by throwaway6560192, and the reply by Trollw00t)&lt;&#x2F;p&gt;
&lt;p&gt;Let me know if you find or know any other ways.
Dolphin might also have a drag+alt option
to automatically create links.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.geeksforgeeks.org&#x2F;ln-command-in-linux-with-examples&#x2F;&quot;&gt;Linux - Terminal&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, you can have a look at &lt;code&gt;man ln&lt;&#x2F;code&gt;.
The basic form is &lt;code&gt;ln -s &amp;lt;file&#x2F;folder&amp;gt; &amp;lt;new link&amp;gt;&lt;&#x2F;code&gt;.
Remember to use single quotes around the file&#x2F;folder and new link names.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Resumé</title>
            <published>2023-04-23T16:37:40+00:00</published>
            <updated>2024-05-23T13:24:29+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/resume/"/>
            <id>https://pranabekka.neocities.org/resume/</id>
            <summary type="html">
              Hi! I try out (or note down) design concepts almost daily,
and I love reading books, as well as learning about new things.
Streamlining systems and making things work
(or theorising how to) is what I enjoy most.
Paired with my knowledge of software engineering,
this makes me an ideal candidate for working with
software teams.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/resume/">
              &lt;p&gt;Hi! I try out (or note down) design concepts almost daily,
and I love reading books, as well as learning about new things.
Streamlining systems and making things work
(or theorising how to) is what I enjoy most.
Paired with my knowledge of software engineering,
this makes me an ideal candidate for working with
software teams.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;svg class=&quot;icon&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
     viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot;&gt;
  &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;
        d=&quot;M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159
           5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909
           2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0
           00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5
           1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75
           0 .375.375 0 01.75 0z&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
Portfolio: &lt;a href=&quot;&#x2F;portfolio&quot;&gt;pranabekka.github.io&#x2F;portfolio&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;svg class=&quot;icon&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
     viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot;&gt;
  &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;
        d=&quot;M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0
        01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0
        00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25
        2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
Email: &lt;a href=&quot;mailto:pranabekka@gmail.com&quot;&gt;pranabekka@gmail.com&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;svg class=&quot;icon&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
     viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot;&gt;
  &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;
        d=&quot;M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021
        18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
Download: &lt;a href=&quot;&#x2F;resume-pranab-dasgupta-2023-06-01-public.pdf&quot;&gt;Resumé (PDF)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;skills&quot;&gt;Skills&lt;a class=&quot;zola-anchor&quot; href=&quot;#skills&quot; aria-label=&quot;Anchor link for: skills&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;div class=&quot;pipgrid&quot;&gt;
  &lt;div class=&quot;pip-display&quot;&gt;
  Figma, Adobe XD, Penpot
  &lt;div class=&quot;pips&quot; aria-description=&quot;5 filled pills out of 5 (5&#x2F;5 skill)&quot;&gt;
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

  &lt;div class=&quot;pip-display&quot;&gt;
  Illustrator, Inkscape
  &lt;div class=&quot;pips&quot; aria-description=&quot;5 filled pills out of 5 (5&#x2F;5 skill)&quot;&gt;
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

  &lt;div class=&quot;pip-display&quot;&gt;
  Wireframing, Sketching
  &lt;div class=&quot;pips&quot; aria-description=&quot;4 filled pills out of 5 (4&#x2F;5 skill)&quot;&gt;
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

  &lt;div class=&quot;pip-display&quot;&gt;
  Photoshop, GIMP
  &lt;div class=&quot;pips&quot; aria-description=&quot;3 filled pills out of 5 (3&#x2F;5 skill)&quot;&gt;
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

  &lt;div class=&quot;pip-display&quot;&gt;
  Premiere Pro
  &lt;div class=&quot;pips&quot; aria-description=&quot;3 filled pills out of 5 (3&#x2F;5 skill)&quot;&gt;
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

  &lt;div class=&quot;pip-display&quot;&gt;
  Blender
  &lt;div class=&quot;pips&quot; aria-description=&quot;3 filled pills out of 5 (3&#x2F;5 skill)&quot;&gt;
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

  &lt;div class=&quot;pip-display&quot;&gt;
  HTML, CSS
  &lt;div class=&quot;pips&quot; aria-description=&quot;3 filled pills out of 5 (3&#x2F;5 skill)&quot;&gt;
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

  &lt;div class=&quot;pip-display&quot;&gt;
  Javascript
  &lt;div class=&quot;pips&quot; aria-description=&quot;1 filled pills out of 5 (1&#x2F;5 skill)&quot;&gt;
    
      
        &lt;div class=&quot;pip full&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
      
        &lt;div class=&quot;pip&quot;&gt;&lt;&#x2F;div&gt;
      
    
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;work-experience&quot;&gt;Work Experience&lt;a class=&quot;zola-anchor&quot; href=&quot;#work-experience&quot; aria-label=&quot;Anchor link for: work-experience&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul class=&quot;cards&quot;&gt;
&lt;!--
&lt;li class=&quot;card&quot;&gt;
  &lt;h3 class=&quot;smalltitle&quot;&gt;@@@&lt;&#x2F;h3&gt;
  &lt;p class=&quot;subtitle&quot;&gt;@@@&lt;br&gt;@@@&lt;&#x2F;p&gt;
  &lt;p&gt;@@@&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;

--&gt;
&lt;li class=&quot;card&quot;&gt;
  &lt;h3 class=&quot;smalltitle&quot;&gt;UI Designer&amp;#x2F;Graphic Designer&lt;&#x2F;h3&gt;
  &lt;p class=&quot;subtitle&quot;&gt;Organic Kitchen, Gurugram&lt;br&gt;February 2021 - May 2022&lt;&#x2F;p&gt;
  &lt;p&gt;Along with various design work,
including website and app screens and assets,
I took the initiative to completely revamp
the UX and UI of their primary subscription offering
(see portfolio for more).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li class=&quot;card&quot;&gt;
  &lt;h3 class=&quot;smalltitle&quot;&gt;Packaging&amp;#x2F;Graphic Designer&lt;&#x2F;h3&gt;
  &lt;p class=&quot;subtitle&quot;&gt;Stylo Media, Kolkata&lt;br&gt;February 2020 - June 2020&lt;&#x2F;p&gt;
  &lt;p&gt;Designed packaging and graphics for ITC,
using feedback and discussions with key stakeholders.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li class=&quot;card&quot;&gt;
  &lt;h3 class=&quot;smalltitle&quot;&gt;Junior Designer&lt;&#x2F;h3&gt;
  &lt;p class=&quot;subtitle&quot;&gt;NewsClick, New Delhi&lt;br&gt;June 2019 - July 2019&lt;&#x2F;p&gt;
  &lt;p&gt;Designed video thumbnails and edited footage for YouTube.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;education&quot;&gt;Education&lt;a class=&quot;zola-anchor&quot; href=&quot;#education&quot; aria-label=&quot;Anchor link for: education&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul class=&quot;cards&quot;&gt;
&lt;li class=&quot;card&quot;&gt;
  &lt;h3 class=&quot;smalltitle&quot;&gt;B.A. in Visual Communication Design&lt;&#x2F;h3&gt;
  &lt;p class=&quot;subtitle&quot;&gt;Whistling Woods International&lt;br&gt;July 2017 - July 2020&lt;&#x2F;p&gt;
  &lt;p&gt;Excelled in the UI&#x2F;UX and Web Design courses,
and topped the Typography subjects,
due to my eye for detail and my software skills.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;extra-curricular&quot;&gt;Extra-Curricular&lt;a class=&quot;zola-anchor&quot; href=&quot;#extra-curricular&quot; aria-label=&quot;Anchor link for: extra-curricular&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul class=&quot;cards&quot;&gt;
&lt;li class=&quot;card&quot;&gt;
  &lt;h3 class=&quot;smalltitle&quot;&gt;Co-Lead Designer&lt;&#x2F;h3&gt;
  &lt;p class=&quot;subtitle&quot;&gt;WWI Cricket League (May) 2018&lt;br&gt;Whistling Woods International, Mumbai&lt;&#x2F;p&gt;
  &lt;p&gt;Took on leadership of design team
and helped junior volunteers
with using software to effectively complete their work.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li class=&quot;card&quot;&gt;
  &lt;h3 class=&quot;smalltitle&quot;&gt;Co-Lead Designer&lt;&#x2F;h3&gt;
  &lt;p class=&quot;subtitle&quot;&gt;Celebrate Cinema (September) 2018&lt;br&gt;Whistling Woods International, Mumbai&lt;&#x2F;p&gt;
  &lt;p&gt;Shared leadership and bulk of design work with fellow design student
for inter-college event with outside visitors.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li class=&quot;card&quot;&gt;
  &lt;h3 class=&quot;smalltitle&quot;&gt;Designer&lt;&#x2F;h3&gt;
  &lt;p class=&quot;subtitle&quot;&gt;Celebrate Cinema (September) 2017&lt;br&gt;Whistling Woods International, Mumbai&lt;&#x2F;p&gt;
  &lt;p&gt;Joined the small team to help with graphics and installations.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;mailto:pranabekka@gmail.com&quot;&gt;Get in touch!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>djot</title>
            <published>2023-04-23T15:35:14+00:00</published>
            <updated>2024-02-04T09:28:09+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/djot/"/>
            <id>https://pranabekka.neocities.org/djot/</id>
            <summary type="html">
              EDIT: Whoa! Inane mind dump ahead!
Just check out the post on why I like djot.
I’m keeping this link for something to at least laugh at,
and to build a habit of not breaking links.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/djot/">
              &lt;p&gt;EDIT: &lt;em&gt;Whoa! Inane mind dump ahead!&lt;&#x2F;em&gt;
Just check out the &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;djot-1&#x2F;&quot;&gt;post on why I like djot&lt;&#x2F;a&gt;.
I’m keeping this link for something to at least laugh at,
and to build a habit of not breaking links.&lt;&#x2F;p&gt;
&lt;p&gt;I was reading an article by &lt;a href=&quot;https:&#x2F;&#x2F;matklad.github.io&quot;&gt;matklad&lt;&#x2F;a&gt;
and I realised the formatting looked a lot like
the default Asciidoctor output,
so I went hunting around for how he built his site
and found an &lt;a href=&quot;https:&#x2F;&#x2F;matklad.github.io&#x2F;2022&#x2F;10&#x2F;28&#x2F;elements-of-a-great-markup-language.html&quot;&gt;article on markup formats&lt;&#x2F;a&gt;.
Turns out &lt;a href=&quot;https:&#x2F;&#x2F;djot.net&quot;&gt;djot&lt;&#x2F;a&gt; is a really nice format,
which includes some interesting ideas
from asciidoc as well as markdown.&lt;&#x2F;p&gt;
&lt;p&gt;Sadly, the tooling around it is quite limited.
Current implementations include one in Javascript,
another in Lua, and a third in Rust.
And the syntax reference link at &lt;a href=&quot;https:&#x2F;&#x2F;djot.net&quot;&gt;djot.net&lt;&#x2F;a&gt; seems broken.&lt;&#x2F;p&gt;
&lt;p&gt;The Javascript implementation is the current focus,
while the Lua one is the first (that may be phased out),
and the Rust one is unofficial,
with a single link in the &lt;a href=&quot;https:&#x2F;&#x2F;djot.net&quot;&gt;djot.net&lt;&#x2F;a&gt; page
and no other mention.&lt;&#x2F;p&gt;
&lt;p&gt;I think all three allow for creating an ast,
so it should be easy to work them in with other tools,
but it’s still a fair bit of work (for me)
to set up a static site or generate other documents from it.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe it’s a good reason to really get into Javascript
(Rust is a bit overkill),
although the hexo static site generator has an extension for it,
and other Javascript ones like 11ty
should also be able to easily plug it in.&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, just use the cli given by djot.js
to output the ast and manipulate it in any language,
then feed it back into djot.js or pandoc.
Even the html output can act as an ast of sorts
if you’re already familiar with it.
Maybe I’ll try that,
but it’s still a lot of work (as a non-programmer) to replicate
everything that static site generators and other tools
can do for you.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Again, sorry for that.
Please check out the post with &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;djot-1&#x2F;&quot;&gt;some actual content&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Static Site Build Tool</title>
            <published>2023-04-20T23:34:47+00:00</published>
            <updated>2023-10-29T14:54:00+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/static-site-build-tool/"/>
            <id>https://pranabekka.neocities.org/static-site-build-tool/</id>
            <summary type="html">
              I’ve just been thinking of what it would be like
to have a static site build script.
You would have
dependency management,
parallelisation,
task runners/commands,
and access to all sorts of (cli) tools
(including your own scripts and binaries).
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/static-site-build-tool/">
              &lt;p&gt;I’ve just been thinking of what it would be like
to have a static site build script.
You would have
dependency management,
parallelisation,
task runners&#x2F;commands,
and access to all sorts of (cli) tools
(including your own scripts and binaries).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;EDIT:&lt;&#x2F;strong&gt; &lt;a href=&quot;https:&#x2F;&#x2F;soupault.app&quot;&gt;soupault.app&lt;&#x2F;a&gt;
might be the way to go.
It lets you run any cli tool
and use it in your site building,
as well as a few other cool things.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prior-art&quot;&gt;Prior Art&lt;a class=&quot;zola-anchor&quot; href=&quot;#prior-art&quot; aria-label=&quot;Anchor link for: prior-art&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Some similar tools already exist
in the form of &lt;a href=&quot;https:&#x2F;&#x2F;mkws.sh&quot;&gt;mkws.sh&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kmaasrud&#x2F;sss&quot;&gt;sss&lt;&#x2F;a&gt; (inspired by mkws), 
but my idea is a bit different —
you use a build tool to stitch everything together,
as opposed to a shell script,
which can easily track which files need to be rebuilt,
gives you simple commands to run,
can (usually) easily perform parallel computation,
and is quite easy to extend.
Plus, I discovered you can use python as the shell in make.
And I wouldn’t really want to use &lt;a href=&quot;https:&#x2F;&#x2F;adi.onl&#x2F;pp.html&quot;&gt;pp&lt;&#x2F;a&gt; —
it’s a bit cumbersome.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;templating&quot;&gt;Templating&lt;a class=&quot;zola-anchor&quot; href=&quot;#templating&quot; aria-label=&quot;Anchor link for: templating&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I’d prefer it if pp used a cleaner syntax like &lt;code&gt;{{ shell }}&lt;&#x2F;code&gt;,
which makes inlining so much cleaner,
and it handles indenting better as well,
which some file formats really care about.
I’d also like to have the option to customise which shell to use,
since I’m more familiar with fish shell —
there is absolutely no reason to use (d)ash for a personal site.
Update: turns out it’s quite easy to make your own
&lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;shell-templating&#x2F;&quot;&gt;templating engine in fish shell&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Otherwise, you could always use
a cli templating engine like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kolypto&#x2F;j2cli&quot;&gt;j2cli&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Going through the Pop!_OS package repository,
there are a lot of cli html templating engines,
such as ace, amber, cl-lml2, and aft.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;build-tools&quot;&gt;Build Tools&lt;a class=&quot;zola-anchor&quot; href=&quot;#build-tools&quot; aria-label=&quot;Anchor link for: build-tools&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The build tool can also be anything that you like —
I like something like make, &lt;a href=&quot;https:&#x2F;&#x2F;gittup.org&#x2F;tup&#x2F;&quot;&gt;tup&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;static-site-build-tool&#x2F;the-apenwarr-link&quot;&gt;redo&lt;&#x2F;a&gt;
since they integrate with the shell pretty well,
and there’s a lot of file management in there,
plus the shell makes excellent glue code.
Otherwise you could use something like
&lt;a href=&quot;https:&#x2F;&#x2F;mesonbuild.com&quot;&gt;meson&#x2F;ninja&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;shakebuild.com&quot;&gt;shake&lt;&#x2F;a&gt;,
if you want something &lt;em&gt;really&lt;&#x2F;em&gt; powerful.
Actually, shake might be a good bet if you know haskell,
since (I think) you can plug in other libraries for each step,
to make a much more cohesive and well-integrated program.
There’s even &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ruricolist&#x2F;overlord&quot;&gt;overlord&lt;&#x2F;a&gt; for a (common) lisp build system,
or &lt;a href=&quot;https:&#x2F;&#x2F;buck2.build&#x2F;&quot;&gt;buck2&lt;&#x2F;a&gt; if you want somethind industrial grade&lt;sup&gt;TM&lt;&#x2F;sup&gt;
(that’s a joke).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; If you’re using make,
the &lt;code&gt;.ONESHELL&lt;&#x2F;code&gt; directive runs the steps in a command
in the same shell instance,
otherwise make runs each one in a separate shell.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authoring&quot;&gt;Authoring&lt;a class=&quot;zola-anchor&quot; href=&quot;#authoring&quot; aria-label=&quot;Anchor link for: authoring&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can use any file format you want for authoring,
including the dialect of whatever markup language you choose.
Some interesting languages are &lt;a href=&quot;https:&#x2F;&#x2F;typst.app&quot;&gt;typst&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jgm&#x2F;djot&quot;&gt;djot&lt;&#x2F;a&gt;,
although typst doesn’t have HTML output yet
(as of the time of writing this article;
if you look at the design of typst, the pdf output,
and the github issues, however,
you can be sure that it’ll be really solid).
I used to really like [asciidoc][asciidoc],
but the tooling around it is a bit limited,
so you need to know ruby&#x2F;java to extend it,
which is why I didn’t get around to having a blog for bloody ages.
Use a common static site generator if this is your first time,
and read through the docs, examples and discussion —
you can do almost anything you want and more.
It might help to start with a test blog,
where you just write down random thoughts and articles,
without actually deploying it anywhere.
Anyway, rant aside, the point is that
there’s some really cool markup languages out there.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;front-matter&quot;&gt;Front Matter&lt;a class=&quot;zola-anchor&quot; href=&quot;#front-matter&quot; aria-label=&quot;Anchor link for: front-matter&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You could use a different front matter format,
or no front matter at all!
Let your site builder handle the rest automatically!
Maybe read it out from the file system.
Maybe with a git hook that gets dates from git.
Maybe some other step that creates file hashes
and stores dates in a db?
Maybe a prompt for metainformation about unknown files
that gets saved in a db.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;content-layout&quot;&gt;Content Layout&lt;a class=&quot;zola-anchor&quot; href=&quot;#content-layout&quot; aria-label=&quot;Anchor link for: content-layout&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You could adopt a structure where
you dump everything into the content directory,
and if there’s a build step for that file (type)
it gets processed according to the build step,
else it’s copied directly to the build directory.&lt;&#x2F;p&gt;
&lt;p&gt;Some (most?) build systems even prioritise specificity
when it comes to applying a build step,
so you can set certain files
(or classes of files, based on the file name)
to use custom processing&#x2F;templating.
You could just rely on ordering, otherwise —
simply place the more specific ones higher up,
and the files it doesn’t match will get passed along
to the more general rules,
while the ones you want to treat specially
are caught by the more specific rule at the top.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;development-and-testing&quot;&gt;Development and Testing&lt;a class=&quot;zola-anchor&quot; href=&quot;#development-and-testing&quot; aria-label=&quot;Anchor link for: development-and-testing&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For serving the pages live while you develop and test,
you can plug in something like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;svenstaro&#x2F;miniserve&quot;&gt;miniserve&lt;&#x2F;a&gt;
(to serve files on your device and local network),
with &lt;a href=&quot;https:&#x2F;&#x2F;eradman.com&#x2F;entrproject&quot;&gt;entr&lt;&#x2F;a&gt; (to automatically rebuild on file change)
and &lt;a href=&quot;https:&#x2F;&#x2F;livejs.com&quot;&gt;live.js&lt;&#x2F;a&gt;
(injected into your html pages for auto-reload).&lt;&#x2F;p&gt;
&lt;p&gt;You’ll need to set up your site builder
to use relative paths
or set the url to be the local ip
used by miniserve &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#mini-ip&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; or your preferred dev server
in order to preview the links locally,
otherwise it would take you to your production site.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;mini-ip&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;miniserve displays a list of ips,
but you could also find out by running
&lt;code&gt;ifconfig | grep 192&lt;&#x2F;code&gt;.
If you use &lt;code&gt;ifconfig&lt;&#x2F;code&gt; use the second ip
starting with &lt;code&gt;192.168&lt;&#x2F;code&gt; and add &lt;code&gt;:8080&lt;&#x2F;code&gt; at the end.
miniserve tends to use 8080,
but you might need to change it if it says something else.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;You could even use &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;caddy&lt;&#x2F;a&gt;
or some other server thing.
There’s actually plenty of them —
especially in the Go and Rust space.
You can even use a python one-liner —
I &lt;em&gt;think&lt;&#x2F;em&gt; it’s &lt;code&gt;python3 -m http.server&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In fact, caddy seems to have markdown rendering
and template evaluation.
Dang.
That makes a great development environment,
although it might be a bit overkill,
and it will probably cause some config duplication.&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, you could write your own tool to
create a file server that works as expected —
it would automatically serve index.html files from directories,
and edit the base url in internal pages
to point to the local network.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;image-optimisation&quot;&gt;Image Optimisation&lt;a class=&quot;zola-anchor&quot; href=&quot;#image-optimisation&quot; aria-label=&quot;Anchor link for: image-optimisation&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can add build steps for most images,
where they are optimised for file size
and converted to multiple (display) sizes.
Multiple display sizes directly affect resolution
and therefore the final file size,
and the browser can often decide which one to pick
if you simply list all of them in a figure tag
(or something like that).&lt;&#x2F;p&gt;
&lt;p&gt;Using this entire system gives you the freedom
to plug in all sorts of things
and create a system that aligns with your workflow,
instead of tying you to the assumptions
(such as markdown authoring)
of the static site generator.&lt;&#x2F;p&gt;
&lt;p&gt;You will, of course, have to edit your templates
to use the processed images.
You can use &lt;code&gt;srcset&lt;&#x2F;code&gt; attributes in &lt;code&gt;img&lt;&#x2F;code&gt; tags,
or use a figure element,
and the browser will automatically pick
the most appropriate image.&lt;&#x2F;p&gt;
&lt;p&gt;See the mdn web docs
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Learn&#x2F;HTML&#x2F;Multimedia_and_embedding&#x2F;Responsive_images&quot;&gt;article on responsive images&lt;&#x2F;a&gt;
for a comprehensive guide.&lt;&#x2F;p&gt;
&lt;p&gt;CSS-Tricks also has a great
&lt;a href=&quot;https:&#x2F;&#x2F;css-tricks.com&#x2F;a-guide-to-the-responsive-images-syntax-in-html&#x2F;#using-srcset&quot;&gt;article on reponsive images&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;content-templates&quot;&gt;Content Templates&lt;a class=&quot;zola-anchor&quot; href=&quot;#content-templates&quot; aria-label=&quot;Anchor link for: content-templates&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can make content file templates
that you can instantiate with a simple &lt;code&gt;new&lt;&#x2F;code&gt; command.
This is especially useful
if you’re using custom front matter or special pages,
which you might forget about.
For example, if you’re authoring files in markdown,
then you could store some template markdown files,
like blog.md and tutorial.md,
and then use &lt;code&gt;build-tool new blog&lt;&#x2F;code&gt;
or &lt;code&gt;build-tool new tutorial&lt;&#x2F;code&gt;
to create a new post using the given template.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;html-processing&quot;&gt;HTML Processing&lt;a class=&quot;zola-anchor&quot; href=&quot;#html-processing&quot; aria-label=&quot;Anchor link for: html-processing&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You might want to edit the generated HTML for your pages,
even to a small degree where you replace a span with a div,
or the other way around.&lt;&#x2F;p&gt;
&lt;p&gt;One tool I’ve found &lt;a href=&quot;http:&#x2F;&#x2F;xmlstar.sourceforge.net&quot;&gt;xmlstarlet&lt;&#x2F;a&gt;,
which can structurally edit xml files,
and has some amount of praise around the internet.&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, xml2 &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#xml2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; converts XML&#x2F;HTML to line-oriented formats
that can be manipulated with the usual Unix tools,
which frankly sounds exciting.
(A very similar tool for json is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tomnomnom&#x2F;gron&quot;&gt;gron&lt;&#x2F;a&gt;.
You should check it out if you already know the unix tools.)
Additionally, a github user called dbohdan maintains a list of
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dbohdan&#x2F;structured-text-tools#xml-html&quot;&gt;structured text tools&lt;&#x2F;a&gt;,
which includes some xml tools that could be useful.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;xml2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;See xml2 in the Ubuntu package repositories.
Website available on &lt;a href=&quot;https:&#x2F;&#x2F;pranabekka.neocities.org&#x2F;static-site-build-tool&#x2F;web.archive.org&#x2F;web&#x2F;20160719191401&#x2F;http:&#x2F;&#x2F;ofb.net&#x2F;~egnor&#x2F;xml2&quot;&gt;archive.org&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;You could also use a mardown converter
that lets you hook into it’s HTML generator
and create custom HTML output.
I don’t know of any such tool yet,
but it could expose the parts of the structure as variables,
which you could feed into a template.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;documentation-and-help&quot;&gt;Documentation and Help&lt;a class=&quot;zola-anchor&quot; href=&quot;#documentation-and-help&quot; aria-label=&quot;Anchor link for: documentation-and-help&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Getting this method to really work for people
would require some good documentation and examples to accompany it,
because it’s all about customisability and control,
which will require a lot of research and experimentation
that could prohibit people from developing the site they want
if the information is not available up front.
This includes
a list of tools,
how to use them,
best practices,
common issues,
a public forum or chat (like Zulip &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#zulip&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;),
and more.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;zulip&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Zulip allows you to make some chats
visible to everyone on the internet,
regardless of whether they’re signed up
and part of your organisation or not.
I believe this is a very important step for
reducing friction for new users.
See the &lt;a href=&quot;https:&#x2F;&#x2F;oilshell.org&quot;&gt;oilshell&#x2F;oils-for-unix&lt;&#x2F;a&gt; project
for an example.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;A good documentation project around this system
should allow anyone to easily create their own site builder
in a programming language of their choice
(except, perhaps, for a good parallel build system).
And then they could contribute further to the documentation.
Maybe.
Is there a general website
covering different static site generators
and how they work?
That might be the place for such documentation.
Maybe link to good shell scripting practices as well.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>How Static Site Generators Work ft. Zola</title>
            <published>2023-04-19T00:26:05+00:00</published>
            <updated>2023-04-19T00:26:05+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/how-ssgs-work/"/>
            <id>https://pranabekka.neocities.org/how-ssgs-work/</id>
            <summary type="html">
              
This is a general guide about how static site generators work,
using the Zola static site generator as an example,
with a sprinkling of why they are organised this way.
Other static site generators have the same requirements,
and generally use the same ideas and structure,
so this knowledge should help you get started with
any static site generator.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/how-ssgs-work/">
              &lt;!--
TODO: clarify where to use terminal commands.
TODO: mention template engine
--&gt;
&lt;p&gt;This is a general guide about how static site generators work,
using the Zola static site generator as an example,
with a sprinkling of why they are organised this way.
Other static site generators have the same requirements,
and generally use the same ideas and structure,
so this knowledge should help you get started with
any static site generator.&lt;&#x2F;p&gt;
&lt;p&gt;This post will be easier to digest if you understand
the difference between static and dynamic sites,
HTML and CSS, text editors, and the terminal.
Also, follow the Zola &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;getting-started&#x2F;installation&#x2F;&quot;&gt;installation instructions&lt;&#x2F;a&gt;
so that you can follow along with the examples.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; Please don’t write the files as presented in this post
for an actual blog&#x2F;website for others.
One reason is that I’m only putting partial HTML
(it works, but it’s a good way to make a terrible site),
and I’ve also skipped on some other more advanced topics.
This post only explains how a static site generator
brings everything together.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;structure&quot;&gt;Structure&lt;a class=&quot;zola-anchor&quot; href=&quot;#structure&quot; aria-label=&quot;Anchor link for: structure&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s get right into it.
The basic folders a static site generator needs are as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;content&lt;&#x2F;li&gt;
&lt;li&gt;static&lt;&#x2F;li&gt;
&lt;li&gt;templates&lt;&#x2F;li&gt;
&lt;li&gt;public&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The &lt;code&gt;content&lt;&#x2F;code&gt; folder is meant for the posts you write.
Zola and other popular generators use &lt;a href=&quot;https:&#x2F;&#x2F;spec.commonmark.org&#x2F;dingus&#x2F;&quot;&gt;markdown&lt;&#x2F;a&gt; for writing,
and then these posts are processed
before being placed in the &lt;code&gt;public&lt;&#x2F;code&gt; folder,
using roughly the same file and folder structure.
They usually also include some more advanced features
that go beyond markdown.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;static&lt;&#x2F;code&gt; folder is for files that are to be served as is,
without any modifications.
This includes images and CSS files.
These files and folders are copied directly to the &lt;code&gt;public&lt;&#x2F;code&gt; directory.
You can duplicate the folder structure from your &lt;code&gt;content&lt;&#x2F;code&gt; folder
and the files will then be placed in the same places
under the &lt;code&gt;public&lt;&#x2F;code&gt; directory,
next to the processed files from the &lt;code&gt;content&lt;&#x2F;code&gt; folder,
if they have the same relative path.
i.e. if you have the files &lt;code&gt;content&#x2F;posts&#x2F;post1.md&lt;&#x2F;code&gt;
and &lt;code&gt;static&#x2F;posts&#x2F;post2.html&lt;&#x2F;code&gt;
then your &lt;code&gt;public&lt;&#x2F;code&gt; folder will have &lt;code&gt;post1.html&lt;&#x2F;code&gt;
(remember, files from &lt;code&gt;content&lt;&#x2F;code&gt; are processed)
and &lt;code&gt;post2.html&lt;&#x2F;code&gt; under &lt;code&gt;public&#x2F;posts&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;templates&lt;&#x2F;code&gt; folder includes a bunch of html
files that are processed along with
a markdown file from the &lt;code&gt;content&lt;&#x2F;code&gt; folder
whenever you tell the markdown file to use that template,
or according to some special rules
so that you don’t have to specify it every time.
Templates allow you to do things like
putting a list of important links on every page,
or creating a list of all your pages.
To do this, they allow some special codes in them
to access the contents of the folders and files
in the &lt;code&gt;content&lt;&#x2F;code&gt; folder.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, the &lt;code&gt;public&lt;&#x2F;code&gt; folder is where all the processed content
is finally output for the “public” to view.
This is where the “static” from “static site generator” comes in —
they’re simply a bunch of static files,
served as-is to anyone who visits your site.&lt;&#x2F;p&gt;
&lt;p&gt;Most generators also include a &lt;code&gt;theme&lt;&#x2F;code&gt; folder
where you can place “themes” from other people,
which include custom styling (css) and templates
to do most of the heavy lifting —
all you have to do is write your markdown posts.&lt;&#x2F;p&gt;
&lt;p&gt;Other files and folders can also be included for various things.
The config file is a common one, placed with the other folders,
to control things like your website name, url, theme, etc.
The website url is used when generating the paths for links,
amongst other places.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;a class=&quot;zola-anchor&quot; href=&quot;#getting-started&quot; aria-label=&quot;Anchor link for: getting-started&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The easiest way to get started in Zola is to create an &lt;code&gt;index.html&lt;&#x2F;code&gt;
file within the &lt;code&gt;templates&lt;&#x2F;code&gt; folder.
All you would need to put is &lt;code&gt;&amp;lt;h1&amp;gt;Hello, world&amp;lt;&#x2F;h1&amp;gt;&lt;&#x2F;code&gt;,
and you’re done.&lt;&#x2F;p&gt;
&lt;p&gt;If you run &lt;code&gt;zola build&lt;&#x2F;code&gt; and check the &lt;code&gt;public&lt;&#x2F;code&gt; directory,
you’ll see the &lt;code&gt;index.html&lt;&#x2F;code&gt; file, which is copied as-is.
Open it in your web browser to see what it looks like
(kind of ugly, unless that’s your taste).
Open it in your editor to check that
it’s actually copied &lt;code&gt;templates&#x2F;index.html&lt;&#x2F;code&gt; as-is.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;templates&#x2F;index.html&lt;&#x2F;code&gt; file is required because
every website needs an index file to start,
and markdown files can’t be processed without a template.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;_index.md&lt;&#x2F;code&gt; file is not required
because there’s no reason to edit it often,
which means that there’s little benefit to writing it in markdown,
so Zola simply assumes it exists.&lt;&#x2F;p&gt;
&lt;p&gt;A cleaner way would have been to accept
an &lt;code&gt;index.html&lt;&#x2F;code&gt; file in the &lt;code&gt;static&lt;&#x2F;code&gt; folder,
since you only need Zola to copy it as-is,
but Zola has (rightly) assumed
that there is no reason to do that,
so they never check for it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authoring-pages&quot;&gt;Authoring Pages&lt;a class=&quot;zola-anchor&quot; href=&quot;#authoring-pages&quot; aria-label=&quot;Anchor link for: authoring-pages&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Like I said above, a markdown file requires a template
for it to be processed.
Zola automatically applies the &lt;code&gt;templates&#x2F;index.html&lt;&#x2F;code&gt; file
to the (automatically created) &lt;code&gt;content&#x2F;_index.md&lt;&#x2F;code&gt; file,
and any other pages are usually assigned the &lt;code&gt;page.html&lt;&#x2F;code&gt; template,
unless you specify otherwise.&lt;&#x2F;p&gt;
&lt;p&gt;So, the first thing to do is to create a &lt;code&gt;page.html&lt;&#x2F;code&gt; file
inside the &lt;code&gt;templates&#x2F;&lt;&#x2F;code&gt; folder.
Within that file, we enter the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; class=&quot;language-html z-code&quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;{{ page.title }}&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
{{ page.content }}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The text between the braces (&lt;code&gt;{{ }}&lt;&#x2F;code&gt;) are the special codes
that I mentioned earlier.&lt;&#x2F;p&gt;
&lt;p&gt;When the &lt;code&gt;page.html&lt;&#x2F;code&gt; file is processed with a markdown file,
it is given access to parts of the markdown file using
the &lt;code&gt;page&lt;&#x2F;code&gt; variable.
The &lt;code&gt;page&lt;&#x2F;code&gt; variable has fields called &lt;code&gt;title&lt;&#x2F;code&gt; and &lt;code&gt;content&lt;&#x2F;code&gt;.
Our &lt;code&gt;page.html&lt;&#x2F;code&gt; template file puts the page title inside a heading tag,
then dumps the rest of the page under that.&lt;&#x2F;p&gt;
&lt;p&gt;Now, we can write our first page in the &lt;code&gt;content&lt;&#x2F;code&gt; folder.
Choose a name for your file.
We’ll choose &lt;code&gt;first-post.md&lt;&#x2F;code&gt;,
and within it, we’ll write some text:&lt;&#x2F;p&gt;
&lt;p&gt;Try to write your own title and text,
so that you can see Zola respond to your wishes.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;md&quot; class=&quot;language-md z-code&quot;&gt;&lt;code class=&quot;language-md&quot; data-lang=&quot;md&quot;&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-markdown&quot;&gt;+++
title = &amp;quot;My First Post&amp;quot;
date = 2023-04-19
+++

&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-paragraph z-markdown&quot;&gt;Hi, this is my first post!
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The section between the two sets of plus symbols (&lt;code&gt;+++&lt;&#x2F;code&gt;)
is known as the frontmatter.
Different sites use different styles for frontmatter.
The frontmatter is used to specify basic information about your post,
including some custom information you can pick for yourself.
The title field is what is accessed by &lt;code&gt;{{ page.title }}&lt;&#x2F;code&gt;
in your &lt;code&gt;page.html&lt;&#x2F;code&gt; template,
and everything outside the frontmatter is the content,
accessed by &lt;code&gt;{{ page.content }}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you run &lt;code&gt;zola build&lt;&#x2F;code&gt;,
and open the &lt;code&gt;public&lt;&#x2F;code&gt; folder,
you’ll see a &lt;code&gt;first-post&#x2F;&lt;&#x2F;code&gt; folder,
within which is an &lt;code&gt;index.html&lt;&#x2F;code&gt; file.
This is done because opening &lt;code&gt;first-post.html&lt;&#x2F;code&gt;
would show the &lt;code&gt;.html&lt;&#x2F;code&gt; at the end of the url,
which people might find ugly
because they’re not used to seeing it,
and it’s something that a visitor to your site
doesn’t need to know.
It works because whenever the browser opens a folder on a server,
it automatically shows any &lt;code&gt;index.html&lt;&#x2F;code&gt; file within that folder.
This will not work when opening a folder on your computer.
In that case the browser shows a list of files in that folder.&lt;&#x2F;p&gt;
&lt;p&gt;If you open &lt;code&gt;first-post&#x2F;index.html&lt;&#x2F;code&gt; in your editor,
you’ll see the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; class=&quot;language-html z-code&quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;My First Post&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-constant z-character z-entity z-named z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-html&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;lt&lt;span class=&quot;z-punctuation z-terminator z-entity z-html&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;p&lt;span class=&quot;z-constant z-character z-entity z-named z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-html&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;gt&lt;span class=&quot;z-punctuation z-terminator z-entity z-html&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Hi! This is my first post.&lt;span class=&quot;z-constant z-character z-entity z-named z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-html&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;lt&lt;span class=&quot;z-punctuation z-terminator z-entity z-html&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-entity z-hexadecimal z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-html&quot;&gt;&amp;amp;#x&lt;&#x2F;span&gt;2F&lt;span class=&quot;z-punctuation z-terminator z-entity z-html&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;p&lt;span class=&quot;z-constant z-character z-entity z-named z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-html&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;gt&lt;span class=&quot;z-punctuation z-terminator z-entity z-html&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Open the file in your browser to see exactly what it’s doing.
&lt;code&gt;page.content&lt;&#x2F;code&gt; has basically created the text
&lt;code&gt;&amp;lt;p&amp;gt;Hi! This is my first post&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;code&gt;,
and Zola makes sure by default that random text
is not converted into HTML elements,
otherwise it might mess up your page.&lt;&#x2F;p&gt;
&lt;p&gt;To correct the issue, edit your &lt;code&gt;page.html&lt;&#x2F;code&gt; file
in the &lt;code&gt;templates&lt;&#x2F;code&gt; folder.
Change &lt;code&gt;{{ page.content }}&lt;&#x2F;code&gt; to &lt;code&gt;{{ page.content | safe }}&lt;&#x2F;code&gt;.
The safe command tells Zola that page.content
(or whatever comes before the &lt;code&gt;|&lt;&#x2F;code&gt;)
is properly formatted HTML,
and is thus safe to show as is.&lt;&#x2F;p&gt;
&lt;p&gt;Run &lt;code&gt;zola build&lt;&#x2F;code&gt; again and check the file
in your editor and the browser
to make sure that everything is working.
Your editor should now show the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; class=&quot;language-html z-code&quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;My First Post&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Hi! This is my first post.&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Feel free to create a second post to test it out further.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;static-files&quot;&gt;Static Files&lt;a class=&quot;zola-anchor&quot; href=&quot;#static-files&quot; aria-label=&quot;Anchor link for: static-files&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;em&gt;static&lt;&#x2F;em&gt; folder is a good place to put your &lt;code&gt;style.css&lt;&#x2F;code&gt;.
Just put &lt;code&gt;body { background: cyan; }&lt;&#x2F;code&gt; to test it out.&lt;&#x2F;p&gt;
&lt;p&gt;Remember to edit your template file
so that it links to the CSS file:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; class=&quot;language-html z-code&quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;z-text z-html z-basic&quot;&gt;&lt;span class=&quot;z-meta z-tag z-inline z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-inline z-any z-html&quot;&gt;link&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html&quot;&gt;rel&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;stylesheet&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-attribute-with-value z-html&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html&quot;&gt;href&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-html&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;..&#x2F;style.css&lt;span class=&quot;z-punctuation z-definition z-string z-end z-html&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;{{ page.title }}&lt;span class=&quot;z-meta z-tag z-block z-any z-html&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-block z-any z-html&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
{{ page.content | safe }}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Run &lt;code&gt;zola build&lt;&#x2F;code&gt; and refresh the browser page to review your changes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;actually-using-zola&quot;&gt;Actually Using Zola&lt;a class=&quot;zola-anchor&quot; href=&quot;#actually-using-zola&quot; aria-label=&quot;Anchor link for: actually-using-zola&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I explained things using the slightly cumbersome way
so you could see the things I explain for yourself,
and I omitted several other features that were
not necessary to explain the main components.&lt;&#x2F;p&gt;
&lt;p&gt;The first thing to know is that &lt;code&gt;zola serve&lt;&#x2F;code&gt;
creates a local url that you can open in your browser,
and whenever you save changes to any of your files,
Zola will refresh the page
and serve any new pages that you create.
You don’t have to run &lt;code&gt;zola build&lt;&#x2F;code&gt; and manually refresh the page,
so you can focus on simply editing your website
while Zola does the rest of the work.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
      
        <entry xml:lang="en">
            <title>Kinds of Magic</title>
            <published>2023-04-18T15:45:50+00:00</published>
            <updated>2023-06-12T22:42:22+00:00</updated>
            <author>
              <name>
                Pranab
              </name>
            </author>
            <link rel="alternate" type="text/html" href="https://pranabekka.neocities.org/kinds-of-magic-apenwarr/"/>
            <id>https://pranabekka.neocities.org/kinds-of-magic-apenwarr/</id>
            <summary type="html">
              This is a musing about apenwarr’s post
on AI and magic, and related things.
It’s more of an idea I had related to it.
            </summary>
            <content type="html" xml:base="https://pranabekka.neocities.org/kinds-of-magic-apenwarr/">
              &lt;p&gt;This is a musing about &lt;a href=&quot;https:&#x2F;&#x2F;apenwarr.ca&#x2F;log&#x2F;?m=202304&quot;&gt;apenwarr’s post&lt;&#x2F;a&gt;
on AI and magic, and related things.
It’s more of an idea I had related to it.&lt;&#x2F;p&gt;
&lt;p&gt;As I was going about my day, I just thought:
I thought “this is about interfaces”.
There are good interfaces, and there are bad interfaces.
And so, there are good kinds of magic, and there are bad kinds.
Sometimes, the magic will transport you back home from work
in the blink of an eye.
Inside a wall. Not good.
But there is good magic as well, so it’s okay.&lt;&#x2F;p&gt;

            </content>
        </entry>
        
</feed>
