Shreyas Minocha’s Wiki

Welcome to my wiki.

At the moment, it contains mostly programming-related stuff.

Some pages may be empty (save for a heading). These pages serve as placeholders for future content.



Computer Science


Linear Algebra


  • Physics Student
    • Arrows with direction and magnitude
    • Can freely be panned in space without changing their meaning
  • CS Student
    • Lists
  • Math Student
    • Support the operations:
      • Vector addition
      • Multiplication of a vector by a scalar
    • Abstract



Single Variable Calculus


Hosting an onion mirror

Mining onions

Install eschalot.

./eschalot -t4 -v -p prefix
  • 4 threads
  • verbose
  • prefix prefix


Not anonymous

Place the private key generated by eschalot in secrets.d/a2s3c4d5e6f7g8h9.key, replacing a2s3c4d5e6f7g8h9 with the domain found by eschalot.

Create a2s3c4d5e6f7g8h9.conf:

set project project-name
hardmap secrets.d/a2s3c4d5e6f7g8h9.key
eotk config a2s3c4d5e6f7g8h9.conf
eotk start project-name

nginx must be installed and in PATH.

The user running eotk must be the owner of secrets.d and a2s3c4d5e6f7g8h9.conf

See also: The Onion Diaries


Bourne-Again Shell

for DATE in "2020-06-22 2020-06-27 2020-07-02 2020-07-17"; do
	echo "$DATE"


minute / hour / dOM / month / dOW


  • * — any value

  • , — set of values

  • - — value range

  • minute

    • 159
  • hour

    • 023
  • dOM

    • 131
  • month

    • 112
    • JANDEC
  • dOW

    • 06
    • SUNSAT
# For scripts that don't need root privileges
crontab -e
# For scripts that need to be run as root
sudo crontab -e 
0 0 * * * command
0 0 1 * * certbot renew




Make list items wrap vertically

Use column-count.

.container {
    column-count: 8;


#container {
    display: grid;
    	"left header header"
        "left content content"
        "footer footer footer";

header { grid-area: header; }
aside { grid-area: left; }
main { grid-area: content; }
footer { grid-area: footer; }

Center things

.hero {
    display: grid;
    place-items: center;


# identical to `date +%Y-%m-%d`
date +%F


Deploying a container

docker pull foo/bar
docker run -p <host>:<container> -d foo/bar
docker run -p <host>:<container> -e x='y' -e port='9000' -d foo/bar
docker ps
docker logs a344d52bc2f2
docker stop a344d52bc2f2

Creating a container

docker build -t foo/bar .


npm i -g @11ty/eleventy
  • .eleventy.js

  • .eleventyignore

  • dir

    • input
    • output
    • includes
    • layouts
    • data
    static: '/'

Setting a layout for a collection

If the collection is collection/, set common keys in collection/collection.json:

    "tags": "collection",
    "layout": "../layouts/collection.pug"

Frontmatter keys in layout files

They’re globals.

name: Foo
chairperson: bar
extends /layouts/base.pug

block content



for file in *.txt;
    echo "$file";
while read word;
    echo "$word"
end < /usr/share/dict/words
while test -f foo;


if test $status -ne 0;
    echo "oop—"
  • -eq
  • -ne
  • -gt
  • -ge
  • -lt
  • -le
  • -f
  • -d
if ...;
    echo something
else if ...;
    echo something_else
    echo something_else_altogether


set foo hi
  • -l — scoped local to the current block
  • -g — global scope
  • -x — environment variable

Command Substitution

set total (math "$total+1")



Commit case-change file renames

git mv -f

GPG sign commits

    email =
    signingkey = 00000000

Verify commits

git verify-commit c567d83

Rename branches

git branch -m old new


Executing local hooks from global hooks

#!/usr/bin/env bash

if [ -e ./.git/hooks/commit-msg ]; then
    ./.git/hooks/commit-msg "$@"


Hooks won’t work

chmod +x?

Push to upstream by default

Just set your push.default to upstream to push branches to their upstreams (which is the same that pull will pull from […]), rather than pushing branches to ones matching in name (which is the default setting for push.default — matching).

Brian Campbell on Stack Overflow

    default = upstream

Useful for easily pushing to a remote branch with a name different from that of the local branch. Long-form method:

git push origin local-branch:remote-branch


Generating patches

git format-patch --to head~..head

Applying patches

git apply 0001-Example.patch
git am 0001-Example.patch


    smtpserver =
    smtpuser = foo
    smtpencryption = tls
    smtpserverport = 587
    from =
    confirm = auto
git send-email --to '~sircmpwn/' head^
git send-email --annotate -v2 head^

Subdirectory filter

See Move files from one repository to another, preserving git history.

Git Internals

Git is not magic.

Git is fundamentally a content-addressable filesystem with a VCS user interface written on top of it.

“Porcelain” — Higher-level, more user-friendly commands.

“Plumbing” — Lower-level commands meant for interfacing with the VCS toolkit.

$ ls -F1 .git
  • config — project-specific configuration
  • index — git stores staging index information in this file
  • HEAD — points to the currently checked-out branch
  • hooks/ — client-side and server-side hooks
  • info/ — global exclude file
  • objects/ — stores content
  • refs/ — “stores pointers into commit objects in that data (branches, tags, remotes and more)”


[A]t the core of Git is a simple key-value data store. What this means is that you can insert any kind of content into a Git repository, for which Git will hand you back a unique key you can use later to retrieve that content.


Git is similar to the UNIX file system in some ways. However, git was designed to work with files that don’t change often. File content is saved as a “blob” in git. Two files with the same content anywhere in the world will be stored as the same blob by git. The blob does not store metadata such as the file’s name or mode.

git hash-object takes a file, optionally writes it to the database (with -w), and prints the 40-character SHA checksum hash by which it will be identified. The checksum itself is a checksum of the file contents along with a header.

$ echo 'foo' > a.txt
$ echo 'foo' > b.txt
$ git init

$ git hash-object -w a.txt

$ git hash-object -w b.txt
$ find .git/objects -type f

The above lists “files” in .git/objects. For example, .git/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99. 25 are the first two characters of the hash, 7cc5642cb1a054f08cc83f2d943e56fd3ebe99 are the other 38. Git presumably does this subdirectory-thing to avoid constraints imposed by some filesystems on the maximum number of files in a directory.

$ git cat-file -t 257cc5642cb1a054f08cc83f2d943e56fd3ebe99
$ git cat-file blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99

$ git cat-file -p 257cc5642cb1a054f08cc83f2d943e56fd3ebe99


Trees group blobs and store the metadata associated with the blobs. They correspond loosely with the concept of directories in the UNIX filesystem.

$ git cat-file -p 'master^{tree}'
100644 blob 664e5860e5a29097e673e14639dbae33d71098f4    .eslintignore   [
100644 blob 0d20ca61dfe1a9ad35862d403aa3e582c21cda51    .eslintrc.yml
100644 blob d124b533c0893da4a15aa5447bf4d5a5583a9fec    .gitignore
100644 blob 8a4cf69715b929acd1683ad1fb6af4c5cbd2ff64    .stylelintrc.yml
040000 tree 7c73db8e4c875dbb9c75e54139048f3ce763c89b    archetypes
100644 blob b82eeb6841cf2a466ee3c7fcf05cbf829a6a2ca7    config.yml
040000 tree e395cf748a2199479e1d8e835c6fe90066983adb    content
100644 blob 8feae855aeb0f392eaad037cf3534fe22a26a525    gulpfile.js
040000 tree 8f4aa58a3fa460e1a52c40f55f8a4749e8ace81f    layouts
100644 blob dd85817db646256ba284950fda7ecffd541a42ad    package-lock.json
100644 blob 5abbb73bc45270fff66606f0edf0e4bce35c6197    package.json
100644 blob 0c576833121dc7ff51f73b3ad399e2a6ea9b2235
040000 tree 6a1072a6112e0903cc8ab48373234bbee4e4acf9    static

Directories are stored as trees.

Git normally creates a tree by taking the state of the index (staging area) and writing a series of tree objects from it. To create a tree manually, we must first set up an index by staging some files.

$ git update-index --add --cacheinfo 100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 b.txt

Git’s modes are based on UNIX’s, but are much stricter. The following are the valid modes for files:


git write-tree writes the staging area to a tree.

$ git write-tree
$ git cat-file -t b6643bc0af3fefb3ea606e41cee107ec08fbbed8
$ git cat-file -p b6643bc0af3fefb3ea606e41cee107ec08fbbed8
100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99    b.txt

See also

Git on a server

SSH daemon must be running, of course and git must be installed and on the PATH.

Create a git user.

Add ssh public keys to their .ssh/authorized_keys 1

Change the git user’s shell to git-shell, lest they may wreak havoc.

Optionally, set up:

  • git-http-backend

  • gitweb, gitlist, … whatever you fancy

  • 1

    Consider adding no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty

Permissions after pushes

core.sharedRepository: group, all, or octal permission bits.

git init --bare --shared[=all]



Haskell is a purely functional programming language.

Disclaimer: I’m no Haskell expert. These are just notes I’m compiling as I learn Haskell and as such, they may be prone to inaccuracies or glaring errors.

“Functional languages excel at wholemeal programming, a term coined by Geraint Jones. Wholemeal programming means to think big: work with an entire list, rather than a sequence of elements; develop a solution space, rather than an individual solution; imagine a graph, rather than a single path. The wholemeal approach often offers new insights or provides new perspectives on a given problem. It is nicely complemented by the idea of projective programming: first solve a more general problem, then extract the interesting bits and pieces by transforming the general program into more specialised ones.”

—Ralf Hinze

There is no precise, accepted meaning for the term “functional”. But when we say that Haskell is a functional language, we usually have in mind two things:

  • Functions are first-class, that is, functions are values which can be used in exactly the same ways as any other sort of value.
  • The meaning of Haskell programs is centered around evaluating expressions rather than executing instructions.

CIS194 by UPenn



  • is statically typed.
  • has type inference.
  • is lazy.
  • is cool and unique (for people used to OO languages).


BTW functions (and lots of other stuff) in Haskell are immutable. FP is different from imperative languages in that it doesn’t have the concept of state.


Comments begin with -- and run till the end of the line.

Basic operators


  • +
  • -
  • *
  • / (float division)


  • &&
  • ||
  • not


  • ==
  • /= — “≠”
  • >
  • <
  • >=
  • <=


  • : — “cons” operator. Adds something to the beginning of a list
  • ++ — concatenation operator
  • !! — list indexing operator. e.g. [1, 2, 3] !! 2 gives 3

Basic in-built functions

  • succ — “successor”

  • pred — “predecessor”

  • min

  • max

  • head — first element of a list

  • tail — all but first element of a list

  • last — last element of a list

  • init — all but last element of a list

  • length

  • null — checks if a list is empty, that is, if it is []

  • reverse — reverses a list

  • taketake x y returns the first x elements of list y

  • dropdrop x y removes and returns the first x elements of list y

  • maximum — returns the largest element of a list

    minimummaximums brother

  • sum — ∑ over a list

  • products — ∏ over a list

  • elem — whether an element is in a list

  • modmod x y is the remainder when y is divided by x

  • even

  • odd

  • div — integer division.

Functions can also be called in the infix form. For example, elem 2 [1, 2, 3] is equivalent to 2 `elem` [1, 2, 3].


ƒ x y = x*y creates a function ƒ that “takes two parameters x and y“ and returns their product. Quoting to indicate this is not exactly accurate, but suffices for the time-being.

Pattern matching

Pattern matching consists of specifying patterns to which some data should conform and then checking to see if it does and deconstructing the data according to those patterns. When defining functions, you can define separate function bodies for different patterns.


factorial 0 = 1
factorial n = n * factorial (n - 1)
addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
length' [] = 0
length' (_:rest) = 1 + length' rest
capital "" = "Empty string"
capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]

While matching against an expression that uses ++ might be intuitive in some cases, this just can’t be done.


bmiTell bmi
    | bmi <= 18.5 = "Underweight"
    | bmi <= 25.0 = "Normal"
    | bmi <= 30.0 = "Overweight"
    | otherwise = "Obese"
bmiTell weight height
    | weight / (height ^ 2) <= 18.5 = "Underweight"
    | weight / (height ^ 2) <= 25.0 = "Normal"
    | weight / (height ^ 2) <= 30.0 = "Overweight"
    | otherwise   = "Obese"

Guards can be written inline (often at the cost of readability).


bmiTell weight height
    | bmi <= 18.5 = "Underweight"
    | bmi <= 25.0 = "Normal"
    | bmi <= 30.0 = "Overweight"
    | otherwise   = "Obese"
    where bmi = weight / (height ^ 2)

where bindings must be aligned neatly as follows:

bmiTell weight height
    | bmi <= thin = "Underweight"
    | bmi <= normal = "Normal"
    | bmi <= fat = "Overweight"
    | otherwise   = "Obese"
    where bmi = weight / (height ^ 2)
          thin = 18.5
          normal = 25.0
          fat = 30.0

where bindings are scoped to the function. where bindings can also be used to pattern match. where bindings can be nested.

letin expression

let <binding> in <expression>

These are similar to where bindings in many respects. where bindings are syntactic constructs while letin are expressions (that evaluate to the expression after in) themselves. Which to use when is often a stylistic choice.

let expressions are very versatile.

4 * (let a = 9 in a + 1) + 2
[let square x = x * x in (square 5, square 3, square 2)]
(let (a,b,c) = (1,2,3) in a+b+c) * 100
calcBmis pair = [bmi | (w, h) <- pair, let bmi = w / h ^ 2]

When we want to bind several variables on the same line, we separate the bindings with ;.

ifthenelse expressions

case expressions

They are … expressions!

case <expression> of <pattern> -> <result>
                     <pattern> -> <result>
                     <pattern> -> <result>


[1..20] is a list with elements 1 to 20. Similarly, ['a'..'f'] is a list with characters 'a' through 'z'. [2,4..20] is a list of all even numbers from 2 to 20. Haskell range-step specifying capabilities don’t extend beyond simple arithmetic progressions. [20,19..1] will work as expected, but [20..1] will not. Using floating points in ranges is not a good idea.

Haskell’s cool in that you can create infinite lists. For example, let x = [1,2..] creates and stores an infinite list of natural numbers. Since Haskell is lazy, it does not evaluate the list until it needs to. take 29 x and take 500 x return the first 29 and 500 natural numbers respectively.

  • cycle — cycles a list into an infinite list
  • repeatrepeat x returns an infinite list containing infinite xs.

List comprehensions


  • let perfectSquares = [x^2 | x <- [0..]] — an infinite list of perfect squares
  • let evenNumbers = [x | x <- [0..], x `mod` 2 == 0] — a relatively ugly way of producing an infinite list of even numbers

Filtering is a common pattern in FP.

  • [x*y | x <- [2,5,10], y <- [8,10,11]] — multiplies all pairs (x, y) where x is an element of [2,5,10] and y is an element of [8,10,11].

Here are a few more examples:

let nouns = ["hobo","frog","pope"]
let adjectives = ["lazy","grouchy","scheming"]

let combos = [adjective ++ " " ++ noun | adjective <- adjectives, noun <- nouns]
length' list = sum [1 | _ <- list]

-- `_` indicates that we don't care about what the element we derive from `list` actually is. We sum a list which is equivalent to a list with as many `1`s as the number of elements in `list`.
stripSpaces str = [chr | chr <- str, chr /= ' ']

BTW nested list comprehensions are possible on nested lists.



  • are immutable
  • are typed — (Int, Char) is incompatible with (Int, String). Also, (Int, Int) is incompatible with (Int, Int, Int)
  • are not “cons-able”

Functions on tuples:

  • fst — returns the first element of a tuple
  • snd — returns the second element of a tuple

Some people advise against using tuples with > 2 elements.

Types and Typeclasses

As mentioned earlier, Haskell is statically typed. It has a powerful and “expressive” type system.

Haskell has type inference, but explicit types annotations have several benefits:

  • Serve as a form of documentation.
  • Some run-time errors wil now be compile-time errors.

Common types

  • Int — bounded. 32 or 64 bits depending on the machine.
  • Integer — not bounded. BigInteger of sorts
  • Float
  • Double
  • Bool
  • Char


A typeclass is an interface of sorts that implements certain defined behaviour. If a type is a part of a typeclass, it will implement the behaviour that the typeclass defines.

The prefix :t can be used to examine the type of an expression in GHCi.

Common typeclasses

  • Eq — support equality testing
  • Ord — types whose values can be ordered. Ordering is a type that can be GT, LT or EQ.
  • Show — can be represented as strings, that is, they can be converted to strings.
  • Read — can be converted from strings
  • Enum — sequentially ordered types. Can be used in list ranges. Have succs and preds.
  • Bounded — have upper and lower bounds
  • Num — “numeric”. Can behave like numbers.
  • Integral — “integers”. Implements Num.
  • Floating — “floating point numbers”. Also implements Num.

Relevant functions

  • compare
  • read
  • show

The following are not functions, but polymorphic constants:

  • minBound — For example, minBound :: Int
  • maxBound — For example, maxBound :: Int

Whole numbers are also polymorphic constants — 20 :: Float.

Type annotations

count :: Int
count = 0

:: is to be read as “has the type”.

isPrime :: Int -> Bool
isPrime num = …

isPrime takes an Int as a parameter and returns a Bool.

contains :: [Int] -> Int -> Bool
contains arr elem = …

contains takes a list of Int and an Int and returns a Bool. The reason for this slightly unintuitive syntax for functions that take more than one parameter has a very good reason that will come up later.

Names of types begin with uppercase letters.

Type variables

Class constraints


Recursion is an important pattern in FP. While the fibonacci sequence, factorial etc are cliché examples of recursion, many more functions can be written with recursion.

  • maximum
  • replicate
  • reverse
  • zip
  • sum
  • product

Obligatory cliché Haskell quicksort:

quicksort (pivot:rest) =
    let lessThan = quicksort [x | x <- rest, x <= pivot]
        greaterThan = quicksort [x | x <- rest, x > pivot]
    in lessThan ++ [pivot] ++ greaterThan

A successful Haskell programmer must think in haskell.

Higher order functions

Currying, Partial Applications

Maps, filters



Function application with $

Function composition



  • client establishes TCP connection with server
  • client sends a request
  • server sends a response with a status code and, optionally, a body

Request Methods

  • GET — retrieve resource
  • POST — submit an entity and cause side-effects on the server
  • PUT — replace the target resource with the payload
  • PATCH — partial modifications to a resource
  • DELETE — delete resource
  • HEADGET response sans the response body
  • OPTIONS — list of possible request methods for a resource


When a response contains the Set-Cookie header, a cookie is set on the client.

HTTP/2.0 200 OK
Set-Cookie: foo=bar
Set-Cookie: baz=baj

With subsequent requests, the client will include the foo and baz cookies in the Cookie header.

GET /path HTTP/2.0
Cookie: foo=bar; baz=baj


Set-Cookie: foo=bar; Expires=Wed, 21 Oct 2021 07:28:00 GMT;

the time and date set is relative to the client


  • Secure — cookie sent only with HTTPS
  • HttpOnly — inaccessible via JavaScript. only sent and modified by requests and responses respectively



for … of loops through the items of an iterable.

for … in loops through the keys of an object.

Using for … in is discouraged.

- for (const key in obj) {
+ for (const key of Object.keys(obj)) {



  • filter
  • reduce(callback, init)callback: (acc, current, idx, array)
  • map
  • forEach
  • some
  • every


['foo', 'bar', 'baz'].includes('bar')
// true

[{ id: 2 }, { id: 3 }, { id: 9 }].find((item) => === 3);
// { id: 3 }



Copy the values of all of the enumerable own properties from one or more source objects to a target object. Returns the target object.

Object.assign(defaults, passed); // Mutates `defaults`
const options = Object.assign({}, defaults, passed); // Doesn't mutate `defaults`


toLocalDateString(locales?, options?)


  • weekday
    • long
    • short
    • narrow
  • era
    • long
    • short
    • narrow
  • year
    • numeric
    • 2-digit
  • month
    • numeric
    • 2-digit
    • long
    • short
    • narrow
  • day
    • numeric
    • two-digit
  • hour, minute, second
    • numeric
    • two-digit
  • timeZoneName
    • long
    • short
const options = { weekday: "short", day: "numeric", month: "short" };
const today = new Date();
console.log(today.toLocaleDateString(undefined, options)); // Tue, Jun 2


npm install --save-dev ava
mkdir test
import test from "ava";

test("should foo", (t) => {
  • t.pass
  • t.assert | t.truthy
  • t.falsy
  • t.true
  • t.false
  • t.not
  • t.deepEqual
  • t.notDeepEqual
  • t.throws
  • t.notThrows
  • t.throwsAsync
  • t.notThrowsAsync
  • t.regex
  • t.notRegex
  • test
  • test.skip
  • test.failing
  • test.todo


npm i got
import got from "got";
await got("");
  • got.get
  • got.put
  • got.patch
  • got.delete
  • got.head

Don’t forget the await

Using response body

const response = await got("");
const body = JSON.parse(response.body);

Search parameters

await got.get("", {
    searchParams: {
        sort: "ascending",
        items: 100,
        page: 2,


await got("", {
    headers: {
        "user-agent": "got v1.0.0",


const api = got.extend({
    prefixUrl: "",

await api.get("/foo");
await api.delete("/foo");

POST requests

await"", {
    json: {
        name: "John",
    responseType: "json",


  • toBe
  • toEqual
  • toBeNull
  • toBeDefined
  • toBeUndefined
  • toBeCloseTo
  • toBeTruthy
  • toBeFalsy
  • toBeGreaterThan
  • toBeGreaterThanOrEqual
  • toBeLessThan
  • toBeLessThanOrEqual
  • toMatch
  • toContain
  • toHaveLength
  • toHaveProperty
  • toThrow
  • toBeInstanceOf


JSONPath is a syntax to query json structures.


An incomplete set of examples of using JSON path follows.

Example Data:

    "name": "Super hero squad",
    "homeTown": "Metro City",
    "formed": 2016,
    "secretBase": "Super tower",
    "active": true,
    "members": [
            "name": "Molecule Man",
            "age": 29,
            "secretIdentity": "Dan Jukes",
            "powers": [
                "Radiation resistance", "Turning tiny", "Radiation blast"
            "name": "Madame Uppercut",
            "age": 39,
            "secretIdentity": "Jane Wilson",
            "powers": [
                "Million tonne punch", "Damage resistance", "Superhuman reflexes"
            "name": "Eternal Flame",
            "age": 1000000,
            "secretIdentity": "Unknown",
            "powers": [
                "Immortality", "Heat Immunity", "Inferno", "Teleportation", "Interdimensional travel"


            name: "Molecule Man",
            age: 29,
            secretIdentity: "Dan Jukes",
            powers: ["Radiation resistance", "Turning tiny", "Radiation blast"],
            name: "Madame Uppercut",
            age: 39,
            secretIdentity: "Jane Wilson",
            powers: [
                "Million tonne punch",
                "Damage resistance",
                "Superhuman reflexes",
            name: "Eternal Flame",
            age: 1000000,
            secretIdentity: "Unknown",
            powers: [
                "Heat Immunity",
                "Interdimensional travel",


        name: "Molecule Man",
        age: 29,
        secretIdentity: "Dan Jukes",
        powers: ["Radiation resistance", "Turning tiny", "Radiation blast"],
        name: "Madame Uppercut",
        age: 39,
        secretIdentity: "Jane Wilson",
        powers: [
            "Million tonne punch",
            "Damage resistance",
            "Superhuman reflexes",
        name: "Eternal Flame",
        age: 1000000,
        secretIdentity: "Unknown",
        powers: [
            "Heat Immunity",
            "Interdimensional travel",


Values of all keys name. .. is called the recursive descendant operator.

["Super Hero Squad", "Molecule Man", "Madame Uppercut", "Eternal Flame"];


Values of the name key of all members

["Molecule Man", "Madame Uppercut", "Eternal Flame"];


Element at index 2 of the array members.

    "name": "Eternal Flame",
    "age": 1000000,
    "secretIdentity": "Unknown",
    "powers": [
        "Immortality", "Heat Immunity", "Inferno", "Teleportation",
        "Interdimensional travel"

Also valid:

  • $.members[:2]: First two elements of members
  • $.members[0,2]: Elements at indices 0 and 2


[all values of the JSON structure]

Formal syntax


$The root object/element
@The current object/element
.Child member operator
..Recursive descendant operator; JSONPath borrows this syntax from E4X
*Wildcard matching all objects/elements regardless their names
[]Subscript operator
[,]Union operator for alternate names or array indices as a set
[start:end:step]Array slice operator borrowed from ES4 / Python
?()Applies a filter (script) expression via static evaluation
()Script expression via static evaluation


import knex from 'knex';

const db = knex({
    client: 'mysql',
    connection: {
        host: process.env.DB_HOST,
        user: process.env.DB_USER,
        password: process.env.DB_PASSWORD,
        database: process.env.DB_DB
db('table').insert({ name: 'Foo' });


Koa is a minimal web framework for node.js.

Only methods that are common to nearly all HTTP servers are integrated directly into Koa’s small ~570 SLOC codebase. This includes things like content negotiation, normalization of node inconsistencies, redirection, and a few others.

Koa is not bundled with any middleware.

This is quite unlike express.

There is an ecosystem of npm modules around koa that implement all sorts of useful middleware.

Koa leverages async functions, allowing us to avoid callback hell and implement error handling with greater ease.

Koa is awesome [citation needed].

Useful modules

Minimal Koa app

import Koa from "koa";
import Router from "koa-router";

const app = new Koa();
const router = new Router();

router.get("/", async (ctx) => {
    ctx.body = "response";


app.listen(process.env.PORT || 3000);

Local Storage

const storage = window.localStorage;

storage.setItem(key, val);



  • \alpha, \Alpha
  • \beta, \Beta
  • \sin, \cos, \tan, …

Subscripts — a_1 a_{n+1}

Superscripts — a^2 a^{n+1}




  • \sum_{x=1}^{\infty} \frac{1}{x}
  • \sum_{init}^{limit} term


\int_{lower}^{upper} term \mathrm{d}x

Big operators

  • \sum
  • \prod
  • \int


  • Roman — \mathrm
  • Italic — \mathit
  • Bold — \mathbf
  • Calligraphic — \mathcal
  • Double-lined — \mathbb


  • \leq, \geq
  • \subset, \supset, \subseteq, \supseteq
  • \therefore, \because
  • \pm, \mp
  • \times, \div, \cdot
  • \cap, \cup
  • \exists, \nexists, \forall
  • \neg, \land, \lor
  • \subset, \supset, \in, \notin
  • \dots, \cdots, \vdots, \ddots

Linux from Scratch

Version 9.1 (March 1st, 2020)




  • libz



bzip2, bunzip2 primarily.

Also bz{cat,cmp,diff,egrep,fgrep,grep,less,more} among others.

  • libbz2



lzma, unlzma, xz, unxz primarily.



  • liblzma


determine filetypes of files


  • libmagic — magic number recognition


command-line editing and history

  • libreadline — commands for repl input manipulation
  • libhistory — handle command-line history lines


macro processor



arbitrary precision number processing

bc, dc (rpn)


linker, assembler, and other stuff for handling object files


math libs

  • libgmp — math functions
  • libgmpxx — math functions, but for C++


arbitrary precision math



complex number math



file extended attributes

attr, {get,set}fattr



access control lists. fine-grained file/dir access control

  • chacl — “change ACL”
  • {get,set}facl



tools to securely handle passwords







gnu compiler collection

c compiler



gcov{,-dump,-tool} — coverage testing tool



“libraries for terminal-independent handling of character screens”


“capabilities” (aka privileges)


stream editor. find-replace



display info about running processes


data for network services|protocols

Installs /etc/protocols and /etc/services


parser generator

  • bison — given rules generates parser code
  • yacc (”yet another compiler compiler”)
  • liby


kinda like bison?

flex, flex++, …



find with regex


e: extended

f: “fixed strings”



bash, bashbug


generic library for consistent shared library support


GNU DB Manager

database utils. key-value stores. crud.


“generates a perfect hash function from a key set”


parse XML with C

xmlwf. xml well-formed?



networking tools

  • dnsdomainname
  • {,t}ftp
  • hostname
  • ifconfig
  • ping{,6}
  • talk
  • telnet
  • traceroute


Practical Extraction and Report Language

perl{,bug,doc,ivp,thanks,5.30.1}, pod{…} (documentation format), …


perl interface to expat


i18n tool to extract translatable strings from source files

intltoolize, intltool-{extract,merge,prepare,update}


creates shell scripts to auto-configure source code



kernel modules



Libelf from Elfutils-0.178

executable and linked files





simple build system


another simple build system


buncha random unix-ey tools




diff and siblings



finding files and things


document processing


grand unified bootloader












build systems


apply patches (typically) created via diff


man pages.



info pages. man pages, except longer.





MDX allows using JSX components within markdown. This means it’s possible to import powerful components like charts, interactive playgrounds etc and use them within markdown.

I love markdown as an authoring format, but it’s limitations can get real, making it unsuitable for anything beyond vanilla content. MDX breaks this barrier.

MDX has no runtime, all compilation occurs during the build stage.

Deployment Options



Engine X

location modifier pattern {


  • (none) — prefix match
  • = — exact match
  • ~ — case-sensitive regex
  • ~* — case-insensitive regex
  • ^~ — non-regex
client_max_body_size 25M;
add_header x-header "value";


log_format minimal '[$time_local] $status "$request" $body_bytes_sent bytes'
access_log path minimal;
error_log path severity;

Default severity: error

Port 80 traffic → Port 443

server {
    listen 80;

    return 301 https://$host$request_uri;

Clean URLs

try_files $uri $uri.html $uri/index.html =404;

rewrite ^/index(?:\.html|/)?$ / permanent;
rewrite ^/(.*)/index(?:\.html|/)?$ /$1 permanent;
rewrite ^/(.*)(?:\.html|/)$ /$1 permanent;

URLs Without Trailing Slash or Extension


Server-side includes

		ssi on;



Subdirectory → subdomain mapping

    server_name ~^(?<sub>.+)\.mirrors\.example\.com$;
    root /var/www/mirrors/$sub;


Indentation-based. Indentation must be consistent.

doctype html
		li: a(href="") Example
		li: a(href="") One
		li: a(href="") One

li: a … is shorthand for:

.main //- <div class="main">

#this //- <div id="this">
	… //- <button class="link button">


if followers.length == 0
	p No followers


	each user in activeUsers
		li: img(src=`/img/{}`)
each val, key in {1: 'one', 2: 'two', 3: 'three'}
each val, index in ['zero', 'one', 'two']






if low <= num <= high: # this works!
from itertools import product as cartesian_product

print(cartesian_product(['a', 'f', 'd'], [3, 4, 5]))
from functools import reduce
from operators import mul

print(reduce(mul, [5, 9, 2, 10, 4]))


Flask is a web framework for python. If Django is the Express of the python world, Flask is the Koa (these analogies aren’t perfectly accurate, but analogies never are).

Hello world

from flask import Flask

app = Flask(__name__)

def hello_world():
    return 'Hello world!'
  • Set FLASK_APP to the name of the file containing the app.
  • Set FLASK_ENV to development if in dev environment.

Run flask run to run the app.

Path parameters

def user_profile(username):
    return 'User profile for {}'.format(username)
def user_profile(username):
    return 'User profile for {}'.format(username)


  • string
  • int
  • float
  • path
  • uuid

Checking HTTP method

from flask import request

@app.route('/resource/<id>', methods=['GET', 'PUT'])
def resource(id):
    return resource.method

Trailing slash vs no trailing slash

In the following example, the canonical URL is /path/. /path will redirect to /path/


The opposite is true in the following example.


URL building

from flask import url_for
def index():

def dashboard():

def profile():

url_for('index') # '/'
url_for('dashboard', page='2') # '/dashboard?page=2'
url_for('profile', username='ansh') # '/user/ansh'

Static files

In production, web server software should serve static files. In development, flask is configured to automatically serve files in static under /static.

Regular Expressions


Scalable Vector Graphics

     viewbox="0 0 100 100"
     width="100" height="100"
     version="1.1" xmlns=""

Strokes are centered across paths by default. This may complicate width and coordinate calculation.

stroke-alignment := "inside" | "outside" | "center"



<rect x="0" y="0" width="100" height="100" stroke="black" />


<line x1="0" y1="0" x2="100" y2="100" stroke="black" />


<polyline points="0,0, 0,20 20,20 20,0 0,0" stroke="black" />

Each of the points defined are connected by lines.


(+ 5 6)
(+ (* 4 6) (/ 1 2))
(quote (1 2 3 4 5))
(quote (a b c))
(quote (+ a b c))

'(1 2 3 4 5)
'(a b c)
'(+ a b c)




My S-Q-L

mysql -u root -p


Create user

 create user 'someuser' identified by 'password';

Create DB

create database somedb;
grant all privileges on somedb.* to 'someuser';
flush privileges;

Change user password

 alter user 'someuser' identified by 'password';

Export and Import

mysqldump -u someuser --password somedb > somedb.sql
mysql -u someuser --password somedb < somedb.sql



Client does not support authentication protocol

alter user 'user'@'localhost' identified by 'new_pwd'; 
alter user 'user'@'localhost' identified with mysql_native_password BY 'new_pwd';



SQL Queries

Some illustrative examples follow. Usually it will be obvious what the query is doing.

select a, b, c from table;
select * from table;
select distinct city from table;
select distinct city, country from table;
select first_name, last_name from students where marks > 80;
select first_name, last_name from students where marks != 42;
select first_name, last_name from students where marks between 80 and 90;
select city from table where amount > 5000 and tax < 50;
select score from table where name == "Shreyas" or name == "Sister";
select score from table where name in ("Shreyas", "Sister");
select score from table where name in (select first_name from family);
select customer_name, commodity, price from commodities order by price desc, customer, commodity asc;
select name from customers where phone_number is not null;
update customers set bonus_points = 0, redeemed_points = 0 where id = 25;

If you omit the where clause in an update statement, ALL records will be updated!

delete from customers where first_name="Jeff";

If you omit the where clause in a delete statement, ALL records will be deleted!

delete from customers;
select first_name, city from customers limit 50;`

The limit syntax is MySQL-specific.

select employee_id, max(shipping_fee) from orders;
select min(price) from inventory;
select max(price) from inventory;
select avg(price) from inventory;
select sum(price) from inventory;


Svelte is a “framework-less framework”.

  • No virtual DOM
  • Single-file components
  • Templating-like syntax


let subject = "world";

<span>Hello {subject}</span>

Styles are component-scoped.


{#if condition}
{#if condition}
{#if condition}
{:else if other}
{#each array as element}
{#each array as element, index}
{#each array as {a, b, c}}


    let num = 1;
    $: let double = num * 2;
    $: let triple = num * 3;

<input type="range" bind:value={num}>

<li>x: {num}</li>
<li>2x: {double}</li>
<li>3x: {triple}</li>

$: means “re-run whenever these values change”


  • on:click
  • on:mousemove
  • on:submit
  • |once
  • |preventDefault


  • bind:value
    let name;

<input bind:value={name} placeholder="John Doe">

    Hi {name}
  • bind:checked
  • bind:group


The Pragmatic Programmer

All of this is quoted from The Pragmatic Programmer‘s appendices.


1. Care About Your Craft

Why spend your life developing software unless you care about doing it well?

2. Think! About Your Work

Turn off the autopilot and take control. Constantly critique and appraise your work.

3. Provide Options, Don’t Make Lame Excuses

Instead of excuses, provide options. Don’t say it can’t be done; explain what can be done.

4. Don’t Live with Broken Windows

Fix bad designs, wrong decisions, and poor code when you see them.

5. Be a Catalyst for Change

You can’t force change on people. Instead, show them how the future might be and help them participate in creating it.

6. Remember the Big Picture

Don’t get so engrossed in the details that you forget to check what’s happening around you.

7. Make Quality a Requirements Issue

Involve your users in determining the project’s real quality requirements.

8. Invest Regularly in Your Knowledge Portfolio

Make learning a habit.

9. Critically Analyze What You Read and Hear

Don’t be swayed by vendors, media hype, or dogma. Analyze information in terms of you and your project.

10. It’s Both What You Say and the Way You Say It

There’s no point in having great ideas if you don’t communicate them effectively.

11. DRY—Don’t Repeat Yourself

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

12. Make It Easy to Reuse

If it’s easy to reuse, people will. Create an environment that supports reuse.

13. Eliminate Effects Between Unrelated Things

Design components that are self-contained, independent, and have a single, well-defined purpose.

14. There Are No Final Decisions

No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change.

15. Use Tracer Bullets to Find the Target

Tracer bullets let you home in on your target by trying things and seeing how close they land.

16. Prototype to Learn

Prototyping is a learning experience. Its value lies not in the code you produce, but in the lessons you learn.

17. Program Close to the Problem Domain

Design and code in your user’s language.

18. Estimate to Avoid Surprises

Estimate before you start. You’ll spot potential problems up front.

19. Iterate the Schedule with the Code

Use experience you gain as you implement to refine the project time scales.

20. Keep Knowledge in Plain Text

Plain text won’t become obsolete. It helps leverage your work and simplifies debugging and testing.

21. Use the Power of Command Shells

Use the shell when graphical user interfaces don’t cut it.

22. Use a Single Editor Well

The editor should be an extension of your hand; make sure your editor is configurable, extensible, and programmable.

23. Always Use Source Code Control

Source code control is a time machine for your work—you can go back.

24. Fix the Problem, Not the Blame

It doesn’t really matter whether the bug is your fault or someone else’s—it is still your problem, and it still needs to be fixed.

25. Don’t Panic When Debugging

Take a deep breath and THINK! about what could be causing the bug.

26. “select” Isn’t Broken

It is rare to find a bug in the OS or the compiler, or even a third-party product or library. The bug is most likely in the application.

27. Don’t Assume It—Prove It

Prove your assumptions in the actual environment—with real data and boundary conditions.

28. Learn a Text Manipulation Language

You spend a large part of each day working with text. Why not have the computer do some of it for you?

29. Write Code That Writes Code

Code generators increase your productivity and help avoid duplication.

30. You Can’t Write Perfect Software

Software can’t be perfect. Protect your code and users from the inevitable errors.

31. Design with Contracts

Use contracts to document and verify that code does no more and no less than it claims to do.

32. Crash Early

A dead program normally does a lot less damage than a crippled one.

33. Use Assertions to Prevent the Impossible

Assertions validate your assumptions. Use them to protect your code from an uncertain world.

34. Use Exceptions for Exceptional Problems

Exceptions can suffer from all the readability and maintainability problems of classic spaghetti code. Reserve exceptions for exceptional things.

35. Finish What You Start

Where possible, the routine or object that allocates a resource should be responsible for deallocating it.

36. Minimize Coupling Between Modules

Avoid coupling by writing “shy” code and applying the Law of Demeter.

37. Configure, Don’t Integrate

Implement technology choices for an application as configuration options, not through integration or engineering.

38. Put Abstractions in Code, Details in Metadata

Program for the general case, and put the specifics outside the compiled code base.

39. Analyze Workflow to Improve Concurrency

Exploit concurrency in your user’s workflow.

40. Design Using Services

Design in terms of services—independent, concurrent objects behind well-defined, consistent interfaces.

41. Always Design for Concurrency

Allow for concurrency, and you’ll design cleaner interfaces with fewer assumptions.

42. Separate Views from Models

Gain flexibility at low cost by designing your application in terms of models and views.

43. Use Blackboards to Coordinate Workflow

Use blackboards to coordinate disparate facts and agents, while maintaining independence and isolation among participants.

44. Don’t Program by Coincidence

Rely only on reliable things. Beware of accidental complexity, and don’t confuse a happy coincidence with a purposeful plan.

45. Estimate the Order of Your Algorithms

Get a feel for how long things are likely to take before you write code.

46. Test Your Estimates

Mathematical analysis of algorithms doesn’t tell you everything. Try timing your code in its target environment.

47. Refactor Early, Refactor Often

Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem.

48. Design to Test

Start thinking about testing before you write a line of code.

49. Test Your Software, or Your Users Will

Test ruthlessly. Don’t make your users find bugs for you.

50. Don’t Use Wizard Code You Don’t Understand

Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project.

51. Don’t Gather Requirements—Dig for Them

Requirements rarely lie on the surface. They’re buried deep beneath layers of assumptions, misconceptions, and politics.

52. Work with a User to Think Like a User

It’s the best way to gain insight into how the system will really be used.

53. Abstractions Live Longer than Details

Invest in the abstraction, not the implementation. Abstractions can survive the barrage of changes from different implementations and new technologies.

54. Use a Project Glossary

Create and maintain a single source of all the specific terms and vocabulary for a project.

55. Don’t Think Outside the Box—Find the Box

When faced with an impossible problem, identify the real constraints. Ask yourself: “Does it have to be done this way? Does it have to be done at all?”

56. Start When You’re Ready

You’ve been building experience all your life. Don’t ignore niggling doubts.

57. Some Things Are Better Done than Described

Don’t fall into the specification spiral—at some point you need to start coding.

58. Don’t Be a Slave to Formal Methods

Don’t blindly adopt any technique without putting it into the context of your development practices and capabilities.

59. Costly Tools Don’t Produce Better Designs

Beware of vendor hype, industry dogma, and the aura of the price tag. Judge tools on their merits.

60. Organize Teams Around Functionality

Don’t separate designers from coders, testers from data modelers. Build teams the way you build code.

61. Don’t Use Manual Procedures

A shell script or batch file will execute the same instructions, in the same order, time after time.

62. Test Early. Test Often. Test Automatically

Tests that run with every build are much more effective than test plans that sit on a shelf.

63. Coding Ain’t Done ’Til All the Tests Run

’Nuff said.

64. Use Saboteurs to Test Your Testing

Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them.

65. Test State Coverage, Not Code Coverage

Identify and test significant program states. Just testing lines of code isn’t enough.

66. Find Bugs Once

Once a human tester finds a bug, it should be the last time a human tester finds that bug. Automatic tests should check for it from then on.

67. English is Just a Programming Language

Write documents as you would write code: honor the DRY principle, use metadata, MVC, automatic generation, and so on.

68. Build Documentation In, Don’t Bolt It On

Documentation created separately from code is less likely to be correct and up to date.

69. Gently Exceed Your Users’ Expectations

Come to understand your users’ expectations, then deliver just that little bit more.

70. Sign Your Work

Craftsmen of an earlier age were proud to sign their work. You should be, too.


✔ Languages to Learn

Tired of C, C++, and Java? Try CLOS, Dylan, Eiffel, Objective C, Prolog, Smalltalk, or TOM. Each of these languages has different capabilities and a different “flavor.” Try a small project at home using one or more of them.

✔ The WISDOM Acrostic

  • What do you want them to learn?
  • What is their interest in what you’ve got to say?
  • How sophisticated are they?
  • How much detail do they want?
  • Whom do you want to own the information?
  • How can you motivate them to listen to you?

✔ How to Maintain Orthogonality

  • Design independent, well-defined components. Keep your code decoupled.
  • Avoid global data.
  • Refactor similar functions.

✔ Things to prototype

  • Architecture
  • New functionality in an existing system
  • Structure or contents of external data Third-party tools or components
  • Performance issues
  • User interface design

✔ ArchitecturalQuestions

  • Are responsibilities well defined?
  • Are the collaborations well defined?
  • Is coupling minimized?
  • Can you identify potential duplication?
  • Are interface definitions and constraints accept- able?
  • Can modules access needed data—when needed?

✔ Debugging Checklist

  • Is the problem being reported a direct result of the underlying bug, or merely a symptom?
  • Is the bug really in the compiler? Is it in the OS? Or is it in your code?
  • If you explained this problem in detail to a coworker, what would you say?
  • If the suspect code passes its unit tests, are the tests complete enough? What happens if you run the unit test with this data?
  • Do the conditions that caused this bug exist anywhere else in the system?

✔ Law of Demeter for Functions

An object’s method should call only methods belonging to:

  • Itself
  • Any parameters passed in
  • Objects it creates
  • Component objects

✔ How to Program Deliberately

  • Stay aware of what you’re doing.
  • Don’t code blindfolded.
  • Proceed from a plan.
  • Rely only on reliable things.
  • Document your assumptions.
  • Test assumptions as well as code.
  • Prioritize your effort.
  • Don’t be a slave to history.

✔ When to Refactor

  • You discover a violation of the DRY principle.
  • You find things that could be more orthogonal.
  • Your knowledge improves.
  • The requirements evolve.
  • You need to improve performance.

✔ Cutting the Gordian Knot

When solving impossible problems, ask yourself:

  • Is there an easier way?
  • Am I solving the right problem?
  • Why is this a problem?
  • What makes it hard?
  • Do I have to do it this way?
  • Does it have to be done at all?

✔ Aspects of Testing

  • Unit testing
  • Integration testing
  • Validation and verification
  • Resource exhaustion, errors, and recovery Performance testing
  • Usability testing
  • Testing the tests themselves

The Twelve-Factor App


One codebase tracked in revision control, many deploys

  • Always use a VCS
  • x codebases = x apps
  • “Multiple apps sharing the same code is a violation of twelve-factor.” Create modules and use those instead.
  • A deploy is a running instance of the app.
  • “There is only one codebase per app, but there will be many deploys of the app.”


Explicitly declare and isolate dependencies

  • Never rely on implicit existence of system-wide packages or system tools. If necessary, vendor the tool in question into the app.
  • Explicitly declare dependencies via a dependency declaration manifest.
  • Use a dependency isolation tool.


Store config in the environment

An app’s config is everything that is likely to vary between deploys (staging, production, developer environments, etc).

  • Twelve-factor requires strict separation of config from code.
  • The twelve-factor app stores config in environment variables.
  • Grouping config into named groups is not recommended since it does not scale well.

In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly […].

Backing services

Treat backing services as attached resources

A backing service is any service the app consumes over the network as part of its normal operation.


  • Databases
  • SMTP services
  • Logging services
  • Caching systems
  • API-accessible consumer services

Keep in mind that:

  • The code for a twelve-factor app makes no distinction between local and third party services.
  • Each backing services is a resource. These attached services are loosely coupled with the deploy they are associated with.
  • It should be possible to attach and detach resources from deploys at will.

Build, release, run

Strictly separate build and run stages


Execute the app as one or more stateless processes

Port binding

Export services via port binding


Scale out via the process model


Maximize robustness with fast startup and graceful shutdown

Dev/prod parity

Keep development, staging, and production as similar as possible


Treat logs as event streams

Admin processes

Run admin/management tasks as one-off processes


Type annotations

Intended contract of a variable/function.

let foo: string;
function bar(a: string, b?: number): void {
(foo: string) => boolean
let primes: number[];


interface Rule {
    readonly message: string,
    readonly test?: (commitMessage: string) => boolean;

Type aliases


enum Day {
enum Result {
    pass = 'type',
    fail = 'fail',
    info = 'info'


Unix CLI Tools

Disks and drives

Wipe empty space

sudo dd if=/dev/zero of=out bs=1M count=1024
shred -n 5 --remove out

Bootable drive

sudo dd if=Downloads/os.iso of=/dev/disk3 bs=4m && sync



date +"%Y-%m-%d"
date +%s



sed 's/foo/bar/g' file
sed 's#foo#bar#g' file
sed --in-place='' 's/foo/bar/g' file



shred --remove file
find <dir> -type f -exec shred --remove {} \;

Access control


groupadd foo


useradd \
	-s /bin/bash \
	-g foo \
	-m \



Encrypt files

gpg --encrypt --recipient DEADBEEF file.pdf
gpg --encrypt --recipient '' file.pdf
gpg --encrypt --recipient DEADBEEF --trust-model always file.pdf

Decrypt files

gpg --decrypt file.pdf.gpg > file.pdf

Verifying signatures

gpg --verify

Import keys

curl | gpg --import
gpg --import key.asc

Trust levels

  • Ultimate — it’s your own key
  • Full — you’ve verified the identity of the key owner and signed their public key
  • Marginal — enough to make the key show up as “valid”


HTTP Security Headers

  • X-Content-Type-Options

    • nosniff
  • X-Frame-Options

  • X-XSS-Protection

    • 1; mode-block
  • Strict-Transport-Security

    • max-age=31536000; includeSubDomains
  • Referer-Policy

    • same-origin
  • Content-Security

    • default-src: 'self'

    Some directives:

    • default-src
    • script-src object-src
    • style-src img-src media-src font-src
    • frame-src
    • connect-src
    • form-action


    • (Possibly incomplete) Domains
      • Wildcards permitted for some parts
    • 'none'
    • 'self' — doesn’t include subdomains
    • 'unsafe-inline' — Inline JS and CSS
    • 'unsafe-eval'
  • Feature-Policy


JSON Web Tokens

Auth mechanism.

  • Backend

    • has a secret key
  • Frontend

    • sends a request with a header and a payload
  • Backend

    • signs the header+payload with the secret key
      • using the algorithm specified in the header
    • returns the token to the frontend
  • Frontend

    • must send the token with every request to protected routes.

      Authorization: Bearer <token>
  • Backend

    • then independently computes the signature of the header+payload.
      • If it matches the signature in the token, access is granted.

Since the frontend doesn’t know the secret key, it cannot create signatures that will check out at the backend. Thus, the frontend cannot successfully tamper with the payload.

Can be used for stateless auth!


  • header
  • payload
  • signature


Screenshot from the JWT debugger with two parts—’Encoded’ and ‘Decoded’


    "alg": "HS256",
    "typ": "JWT"

Base64 Encode.


Contains claims.

    "sub": "9234",
    "username": "john",
    "admin": false

Base64 Encode.

Payload is tamper-proof, but publically visible.

Signature verification

    const computedSignature = HMACSHA256(
        base64UrlEncode(token.header) + "." +

    if (token.signature === computedSignature) {
        return true;

    return false;



sudo ufw allow 3000
sudo ufw status [numbered]
sudo ufw reload
sudo ufw delete 4

Don’t accidentally block the SSH port