mirror of
https://github.com/youwen5/blog.git
synced 2024-11-24 18:03:50 -08:00
Compare commits
8 commits
68c5b1a9e3
...
540cfd1310
Author | SHA1 | Date | |
---|---|---|---|
|
540cfd1310 | ||
9caa25dec0 | |||
b20e4a981d | |||
7600335b4d | |||
4803c2d68e | |||
394718bcd4 | |||
c708ab504f | |||
|
87c7f1f18d |
12 changed files with 56 additions and 244 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
@ -46,7 +46,7 @@ jobs:
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
if: success()
|
if: success()
|
||||||
uses: crazy-max/ghaction-github-pages@v4.0.0
|
uses: crazy-max/ghaction-github-pages@v4.1.0
|
||||||
with:
|
with:
|
||||||
build_dir: result
|
build_dir: result
|
||||||
target_branch: gh-pages
|
target_branch: gh-pages
|
||||||
|
|
10
README.md
10
README.md
|
@ -1,4 +1,4 @@
|
||||||
# gradient ascent - yet another developer blog
|
# conditional finality - yet another developer blog
|
||||||
|
|
||||||
This repository hosts the source code for my blog, written in Haskell and
|
This repository hosts the source code for my blog, written in Haskell and
|
||||||
powered by [hakyll](https://jaspervdj.be/hakyll/) and
|
powered by [hakyll](https://jaspervdj.be/hakyll/) and
|
||||||
|
@ -14,7 +14,7 @@ you know what you are doing.
|
||||||
|
|
||||||
Allow the `.envrc`:
|
Allow the `.envrc`:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
direnv allow
|
direnv allow
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ Here's how to do it locally.
|
||||||
|
|
||||||
First, we need to build the site. Run
|
First, we need to build the site. Run
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
hakyll-site build
|
hakyll-site build
|
||||||
|
|
||||||
# sometimes, we need to ignore the cache if things aren't working
|
# sometimes, we need to ignore the cache if things aren't working
|
||||||
|
@ -51,7 +51,7 @@ In the directory, there is a `node_modules` symlink to
|
||||||
`result/lib/node_modules`. If we build the `nodeDeps` package, the
|
`result/lib/node_modules`. If we build the `nodeDeps` package, the
|
||||||
`node_modules` will be made available at this path. So, run the following:
|
`node_modules` will be made available at this path. So, run the following:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
nix build .#nodeDeps
|
nix build .#nodeDeps
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ need to re-run the above command or else node_modules will not be accessible.
|
||||||
|
|
||||||
Finally, run the following to generate the bundled CSS and JS files.
|
Finally, run the following to generate the bundled CSS and JS files.
|
||||||
|
|
||||||
```
|
```bash
|
||||||
rollup -c
|
rollup -c
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
description = "gradient ascent";
|
description = "conditional finality";
|
||||||
|
|
||||||
nixConfig = {
|
nixConfig = {
|
||||||
allow-import-from-derivation = "true";
|
allow-import-from-derivation = "true";
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
|
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
.external-link {
|
.external-link {
|
||||||
@apply dark:text-violet-500 text-indigo-600 hover:bg-indigo-200 pr-3 rounded-sm dark:hover:bg-violet-950 transition-colors duration-300 relative;
|
@apply underline decoration-solid decoration-2 underline-offset-2 hover:text-love-light dark:hover:text-love-dark decoration-love-light decoration-love-dark;
|
||||||
}
|
}
|
||||||
.external-link::after {
|
.external-link-muted {
|
||||||
@apply absolute top-1 right-[6px] w-2 h-2 border-2 border-indigo-600 dark:border-violet-600 rounded-full translate-x-1/2 -translate-y-1/2;
|
@apply underline decoration-solid decoration-2 underline-offset-2 hover:text-love-light dark:hover:text-love-dark decoration-accent-light decoration-accent-dark;
|
||||||
content: "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.small-caps {
|
.small-caps {
|
||||||
font-variant: all-small-caps;
|
font-variant: all-small-caps;
|
||||||
}
|
}
|
||||||
|
|
BIN
src/images/conditional-finality.png
Normal file
BIN
src/images/conditional-finality.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
Binary file not shown.
Before Width: | Height: | Size: 19 KiB |
|
@ -18,7 +18,7 @@ title: "youwen wu"
|
||||||
<div class="rounded-md p-2">
|
<div class="rounded-md p-2">
|
||||||
<a
|
<a
|
||||||
href=".$url$"
|
href=".$url$"
|
||||||
class="w-fit dark:group-hover:text-muted-dark group-hover:text-muted-light transition-colors"
|
class="w-fit dark:group-hover:text-iris-dark group-hover:text-iris-light transition-colors"
|
||||||
>
|
>
|
||||||
<h3 class="text-2xl">$title$</h3>
|
<h3 class="text-2xl">$title$</h3>
|
||||||
<p
|
<p
|
||||||
|
@ -30,7 +30,7 @@ title: "youwen wu"
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<hr
|
<hr
|
||||||
class="max-w-[200px] border-0 h-1 dark:bg-accent-dark bg-accent-light rounded-lg px-2 group-hover:max-w-[250px] dark:group-hover:bg-secondary-dark group-hover:bg-secondary-light transition-all duration-400"
|
class="max-w-[200px] border-0 h-1 dark:bg-accent-dark bg-accent-light rounded-lg px-2 group-hover:max-w-[250px] dark:group-hover:bg-iris-dark group-hover:bg-iris-light transition-all duration-400"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
$endfor$
|
$endfor$
|
||||||
|
|
|
@ -2,25 +2,21 @@
|
||||||
author: "Youwen Wu"
|
author: "Youwen Wu"
|
||||||
authorTwitter: "@youwen"
|
authorTwitter: "@youwen"
|
||||||
desc: "a purely functional...blog?"
|
desc: "a purely functional...blog?"
|
||||||
image: "./images/gradient-ascent.jpg"
|
image: "./images/conditional-finality.png"
|
||||||
keywords: "haskell, blog, functional programming"
|
keywords: "haskell, blog, functional programming"
|
||||||
lang: "en"
|
lang: "en"
|
||||||
title: "why I made my blog in haskell"
|
title: "a haskellian blog"
|
||||||
updated: "2024-05-25T12:00:00Z"
|
updated: "2024-05-25T12:00:00Z"
|
||||||
---
|
---
|
||||||
|
|
||||||
Welcome! This is the first post on _gradient ascent_ and also one that tests all
|
Welcome! This is the first post on _conditional finality_ and also one that tests all
|
||||||
of the features.
|
of the features.
|
||||||
|
|
||||||
<img
|
<img
|
||||||
alt="gradient ascent"
|
alt="conditional finality"
|
||||||
src="./images/gradient-ascent.jpg"
|
src="./images/conditional-finality.png"
|
||||||
style="height: 200px; width: 100%; object-fit: cover"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
I'll be writing about computers, code, math, video games, and whatever else
|
|
||||||
here.
|
|
||||||
|
|
||||||
> A monad is just a monoid in the category of endofunctors, what's the problem?
|
> A monad is just a monoid in the category of endofunctors, what's the problem?
|
||||||
|
|
||||||
## haskell?
|
## haskell?
|
||||||
|
@ -59,11 +55,6 @@ The code highlighting is also generated by hakyll.
|
||||||
Haskell is a purely functional language with no mutable state. Its syntax
|
Haskell is a purely functional language with no mutable state. Its syntax
|
||||||
actually makes it pretty elegant for declaring routes and "rendering" pipelines.
|
actually makes it pretty elegant for declaring routes and "rendering" pipelines.
|
||||||
|
|
||||||
I originally wanted to build this entire blog myself. I had a working version
|
|
||||||
with the Svelte framework, complete with GFM rendering, table of contents, KaTeX
|
|
||||||
math, code highlighting, static generation, and other goodies. However, it
|
|
||||||
seemed like a little too much work to maintain. I switched to hakyll because
|
|
||||||
|
|
||||||
1. Haskell is cool.
|
1. Haskell is cool.
|
||||||
2. It comes with enough features that I don't feel like I have to build
|
2. It comes with enough features that I don't feel like I have to build
|
||||||
everything from scratch.
|
everything from scratch.
|
||||||
|
@ -77,7 +68,7 @@ seemed like a little too much work to maintain. I switched to hakyll because
|
||||||
### speaking of math
|
### speaking of math
|
||||||
|
|
||||||
We can have math inline, like so:
|
We can have math inline, like so:
|
||||||
$\int_\infty^\infty \, e^{-x^2}\,dx = \sqrt{\pi}$. This site ships semantic
|
$\int_{-\infty}^\infty \, e^{-x^2}\,dx = \sqrt{\pi}$. This site ships semantic
|
||||||
MathML math with its HTML, and the MathJax script to the client.
|
MathML math with its HTML, and the MathJax script to the client.
|
||||||
|
|
||||||
It'd be nice if MathML could just be used and supported across all browsers, but
|
It'd be nice if MathML could just be used and supported across all browsers, but
|
||||||
|
|
|
@ -1,197 +0,0 @@
|
||||||
---
|
|
||||||
author: "Youwen Wu"
|
|
||||||
authorTwitter: "@youwen"
|
|
||||||
desc: "and the future of operating systems"
|
|
||||||
image: "./images/gradient-ascent.jpg"
|
|
||||||
keywords: "nix, nixos, functional programming, linux, unix"
|
|
||||||
lang: "en"
|
|
||||||
title: "a retrospective on NixOS"
|
|
||||||
updated: "2024-05-25T12:00:00Z"
|
|
||||||
---
|
|
||||||
|
|
||||||
Many people more knowledgeable than me have already written at length about the
|
|
||||||
virtues of NixOS and _declarative configuration_ and _immutability_ and such. I
|
|
||||||
doubt what I have to say is particularly novel to those already familiar with
|
|
||||||
Nix, but I'd like to discuss precisely what brings people to NixOS in the first
|
|
||||||
place.
|
|
||||||
|
|
||||||
Many people will introduce NixOS by first introducing the Nix package manager,
|
|
||||||
and immediately jumping into terms like _derivation_ and _immutability_ and
|
|
||||||
_reproducibility_ and whatnot. And while these are important concepts for
|
|
||||||
understanding the system at large, it's not very convincing for people looking
|
|
||||||
to try out the system. After all, most people don't (or at least shouldn't!)
|
|
||||||
choose their tools based on hype or purported benefits, but based the problems
|
|
||||||
that they help them solve.
|
|
||||||
|
|
||||||
Instead of immediately evangelizing about the virtues of Nix and NixOS, I'll
|
|
||||||
first motivate the reasons for why I chose a tool with exactly its properties
|
|
||||||
(but not to worry, the evangelizing will come later).
|
|
||||||
|
|
||||||
Essentially: allow me to introduce you to the
|
|
||||||
origins of the [NixOS God
|
|
||||||
Complex](https://www.reddit.com/r/NixOS/comments/kauf1m/dealing_with_post_nixflake_god_complex/).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
My goals for my system are as follows:
|
|
||||||
|
|
||||||
- Allow my computing environment to exist on different computers at the same
|
|
||||||
time (essentially, sync up configurations between machines)
|
|
||||||
- Precisely control the software and services on my machine. I should be able
|
|
||||||
to obtain binaries of most things to save time, but be able to step into the
|
|
||||||
source and apply patches or configuration as desired
|
|
||||||
- For the OS to be absolutely unbreakable
|
|
||||||
- Never configure the system twice; once I solve a problem, I should have a
|
|
||||||
reproducible solution that solves it permanently
|
|
||||||
- Be able to backup my system configuration and quickly redeploy it whenever
|
|
||||||
needed
|
|
||||||
- Avoid janky solutions to these problems that introduce tech debt. I don't
|
|
||||||
want to have to rely on disk images or backups, I want to be able to create
|
|
||||||
fresh installations quickly
|
|
||||||
|
|
||||||
Essentially, I want to synchronize the configuration of my entire system across
|
|
||||||
multiple machines while maintaining a stable and usable system I'm not worried
|
|
||||||
will inadvertently fall apart with a routine system update. When I tweak and
|
|
||||||
mess with some settings on my desktop, I should be able to push to a `git`
|
|
||||||
repository and pull it down on my laptop and have the tweaks carried over. This
|
|
||||||
even includes system-level configuration like the applications installed,
|
|
||||||
system daemons, and other core system services.
|
|
||||||
|
|
||||||
I want a source and binary based distribution simultaneously. And I want a
|
|
||||||
self-documenting reproducible system where every tiny tweak is
|
|
||||||
deterministically applied. And I want to be able to install my configurations
|
|
||||||
onto a new computer, from scratch, in an installer, effectively creating my own
|
|
||||||
custom Linux distribution.
|
|
||||||
|
|
||||||
Oh, and I also want to solve the "works on my machine" problem, and never have
|
|
||||||
trouble using software someone else packaged and claims works on their end, but
|
|
||||||
fails on my computer.
|
|
||||||
|
|
||||||
All or even just a few of these goals seem unattainable to the typical Linux
|
|
||||||
user (not to mention those still on Windows and macOS $\dots$ _oh, the
|
|
||||||
horror!_). But I was in fact able to achieve all of them.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
To begin, let's examine how one might try to approach these problems with the
|
|
||||||
common solutions.
|
|
||||||
|
|
||||||
Let's talk about sharing configuration among multiple computers first, which
|
|
||||||
can be thought of as some form of "settings sync".
|
|
||||||
|
|
||||||
Most people have encountered solutions to sychronizing configuration in two
|
|
||||||
ways: either the entire service is ran in the cloud, so it's really the _same_
|
|
||||||
environment accessed from multiple places (eg. Google Docs), or it's some often
|
|
||||||
half baked opaque solution involving you making an account and sending all your
|
|
||||||
settings to a sync server (eg. Mozilla Firefox).
|
|
||||||
|
|
||||||
The more technically minded may instead opt to create a "dotfiles" repository,
|
|
||||||
holding their vast collection of meticulously crafted configuration files.
|
|
||||||
These repos often come with a janky `install.sh` script that does its best to
|
|
||||||
install all the files into the correct place. This usually works the first
|
|
||||||
time, but trying to keep the installed dotfiles in sync with a central
|
|
||||||
repository is a whole other problem.
|
|
||||||
|
|
||||||
There are also dotfile manager like `chezmoi` or GNU Stow. I have not tried
|
|
||||||
these so I make no judgements on their utility for their intended purpose.
|
|
||||||
These dotfile management solutions may work well for managing configuration
|
|
||||||
files, but they both have the same issue: you also need to install the software
|
|
||||||
you're configuring!
|
|
||||||
|
|
||||||
The software and the configuration are fundamentally tied together; these are
|
|
||||||
not concerns to be separated. If the software is installed, it almost always
|
|
||||||
needs to be configured anyways. If the configuration exists, the software
|
|
||||||
should be installed. So a sane solution needs to both put the configuration in
|
|
||||||
the right place, _and_ set up the system's programs along with all their
|
|
||||||
dependencies!
|
|
||||||
|
|
||||||
So, the most obsessive *nix hackers reach for tools like
|
|
||||||
[Ansible](https://www.ansible.com/), that promise automatic configuration of
|
|
||||||
entire systems. Though Ansible was initially designed to deploy cloud servers
|
|
||||||
quickly through the Infrastructure-as-Code approach, some people opt to use it
|
|
||||||
for deploying and managing their systems quickly as well. I have not personally
|
|
||||||
tried it beyond playing with a few examples The consensus seems to be that it
|
|
||||||
seems to work fine for simple use cases but gets quite unwieldy for more
|
|
||||||
complex purposes (especially for personal systems, which aren't expected to be
|
|
||||||
as ephemeral as servers).
|
|
||||||
|
|
||||||
A system like Ansible combined with a system to manage configuration files
|
|
||||||
might be able to achieve a few of our goals. We can keep configuration in sync
|
|
||||||
between computers and we can quickly redeploy our system. But anyone who has
|
|
||||||
tried this will tell you that it's incredibly uncomfortable to use; our
|
|
||||||
existing operating systems are simply not designed to be managed in this
|
|
||||||
manner. Inevitably you will experience desynchronization between the
|
|
||||||
configuration and the actual state of the machine.
|
|
||||||
|
|
||||||
Also, this does not solve some of our other problems. We'll still need tools
|
|
||||||
like Docker to reproducibly build software and figure out a way to keep our
|
|
||||||
system stable.
|
|
||||||
|
|
||||||
If you agree with the premises I've laid out up to this point, that none of
|
|
||||||
these solutions provide a satisfying solution to our computing woes, you might
|
|
||||||
come to the conclusion that I've made. We need a solution that does _all of
|
|
||||||
it_. A unified tool for reliably deploying software and managing your system
|
|
||||||
configuration. And it must necessarily be declarative and reproducible, because
|
|
||||||
that is the only sane way to manage a system. Imagine working on a programming
|
|
||||||
project where recompiling with the same source code would non-deterministically
|
|
||||||
produce different results based on the environment! We should be able to write
|
|
||||||
files that declaratively and precisely specify the state of whole system, and
|
|
||||||
then be able to revert these files or tweak them with deterministic results
|
|
||||||
that don't leave behind any broken programs or files.
|
|
||||||
|
|
||||||
Well, [Nix](https://nixos.org/) is the _purely functional_ package manager
|
|
||||||
(i.e. declarative, reproducible), and NixOS is a Linux distribution that is
|
|
||||||
managed entirely by Nix. Essentially, Nix provides a solution to the problem of
|
|
||||||
_software deployment_, and in fact was purpose built to do so in Eelco
|
|
||||||
Dolstra's seminal [PhD
|
|
||||||
thesis](https://edolstra.github.io/pubs/phd-thesis.pdf). It effectively solves
|
|
||||||
the problem of "works on my machine" by _forcing_ the user to actually specify
|
|
||||||
all required dependencies. This makes it a little harder to write the initial
|
|
||||||
build configurations due to the strictness imposed. But the reward is that if a
|
|
||||||
piece of software builds on one machine, it's guaranteed to build on another.
|
|
||||||
|
|
||||||
NixOS is a system that takes the power of Nix and applies it to declaratively
|
|
||||||
configure an _entire Linux system_. All of the installed software and activated
|
|
||||||
services can be specified precisely using the Nix expression language, a purely
|
|
||||||
functional DSL used by Nix. And alongside the software, it also configures it,
|
|
||||||
effectively acting as a dotfile manager. Indeed, many core NixOS services and a
|
|
||||||
wide range of programs can be set up through _NixOS modules_, where the program
|
|
||||||
is installed and configured in the same place. (and many programs like `fzf`,
|
|
||||||
`btop`, etc have similar corresponding `home-manager` modules).
|
|
||||||
|
|
||||||
NixOS is also _immutable_, which means that the system cannot be modified after
|
|
||||||
it is built from the Nix files that declare it. How do you make changes to the
|
|
||||||
system then? Obviously, we just create a new system where the changed programs
|
|
||||||
and files are included, and the old ones are removed. But they are not deleted
|
|
||||||
from the hard drive, they still exist in the _Nix store_. So, the system can
|
|
||||||
provide precise atomic rollbacks between each "generation" of itself. Broke
|
|
||||||
your GRUB configuration so your system won't boot? Messed up your kernel
|
|
||||||
settings? Just select an older working generation from the boot menu and you
|
|
||||||
instantly have a working system again. You never worry about breaking things
|
|
||||||
during either routine or massive system updates.
|
|
||||||
|
|
||||||
And because the system is fully declarative, and modifying the system is done
|
|
||||||
only through modifying its Nix configuration files, you can version and sync
|
|
||||||
them up with Git. This solves the problem of keeping system environments in
|
|
||||||
sync; now, you truly only have to keep one repository of all your configuration
|
|
||||||
in sync, and all the software installation and deployment is handled for you by
|
|
||||||
a system designed precisely for that purpose.
|
|
||||||
|
|
||||||
This makes it possible for me to share common configuration between a multitude
|
|
||||||
of entirely distinct machines, including an `x86_64` desktop, an `x86_64`
|
|
||||||
laptop, an Apple Silicon Macbook running NixOS `aarch64` using [Asahi
|
|
||||||
Linux](https://asahilinux.org/), and the same Macbook running macOS with
|
|
||||||
`nix-darwin`, sharing `home-manager` configuration with NixOS. Specific
|
|
||||||
configuration necessary to adjust hardware-specific details between each
|
|
||||||
machines are isolated to the [hosts](./hosts) directory.
|
|
||||||
|
|
||||||
This works exceptionally well, evidenced by the fact that I have (almost) the
|
|
||||||
exact same environment across three separate machines, spanning two entirely
|
|
||||||
distinct CPU architectures.
|
|
||||||
|
|
||||||
In essence, the primary failure of deployment scripts, Ansible and the like is
|
|
||||||
that they are _imperative_ - they must specify precisely _how_ to set up the
|
|
||||||
system, down to minute details, whereas in a _declarative_ approach, the user
|
|
||||||
can simply specify what the system _should look like_, and abstractions take
|
|
||||||
care of the _how_. This is what NixOS does, and it gives you remote syncing,
|
|
||||||
versioning (via `git`), and rollbacks _for free_.
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="$lang$">
|
<html lang="$lang$">
|
||||||
<head>
|
<head>
|
||||||
<title>$title$ | gradient ascent</title>
|
<title>$title$ | conditional finality</title>
|
||||||
|
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
<a
|
<a
|
||||||
href="/"
|
href="/"
|
||||||
class="dark:hover:text-muted-dark hover:text-muted-light transition-all duration-500 text-nowrap tracking-wide"
|
class="dark:hover:text-muted-dark hover:text-muted-light transition-all duration-500 text-nowrap tracking-wide"
|
||||||
><em>Gradient Ascent.</em></a
|
><em>Conditional Finality.</em></a
|
||||||
>
|
>
|
||||||
</h1>
|
</h1>
|
||||||
<div
|
<div
|
||||||
|
@ -126,18 +126,18 @@
|
||||||
<p class="mt-8 mb-3 px-1 italic font-light">
|
<p class="mt-8 mb-3 px-1 italic font-light">
|
||||||
a web-log about computers, math, hacks, and all the rest.
|
a web-log about computers, math, hacks, and all the rest.
|
||||||
</p>
|
</p>
|
||||||
<a class="text-sm external-link" href="https://youwen.dev"
|
<a class="text-sm text-iris-light dark:text-iris-dark hover:text-love-light dark:hover:text-love-dark" href="https://youwen.dev"
|
||||||
><em>by </em>Youwen Wu</a
|
><em>by </em>Youwen Wu</a
|
||||||
>
|
>
|
||||||
<span class="ml-2 font-serif">|</span>
|
<span class="ml-2 font-serif">|</span>
|
||||||
<button
|
<button
|
||||||
id="theme-toggle"
|
id="theme-toggle"
|
||||||
class="ml-2 text-sm hover:bg-indigo-200 dark:hover:bg-violet-950 rounded-sm transition-colors p-1 duration-500"
|
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||||
></button>
|
></button>
|
||||||
<span class="ml-2 font-serif">|</span>
|
<span class="ml-2 font-serif">|</span>
|
||||||
<button
|
<button
|
||||||
id="font-toggle"
|
id="font-toggle"
|
||||||
class="ml-2 text-sm hover:bg-indigo-200 dark:hover:bg-violet-950 rounded-sm transition-colors p-1 duration-500"
|
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||||
></button>
|
></button>
|
||||||
</header>
|
</header>
|
||||||
$body$
|
$body$
|
||||||
|
@ -149,14 +149,14 @@
|
||||||
© 2024 Youwen Wu. Generated by
|
© 2024 Youwen Wu. Generated by
|
||||||
<a
|
<a
|
||||||
href="https://jaspervdj.be/hakyll/"
|
href="https://jaspervdj.be/hakyll/"
|
||||||
class="external-link"
|
class="external-link-muted"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>Hakyll.</a
|
>Hakyll.</a
|
||||||
>
|
>
|
||||||
View the source
|
View the source
|
||||||
<a
|
<a
|
||||||
href="https://github.com/couscousdude/blog"
|
href="https://github.com/couscousdude/blog"
|
||||||
class="external-link"
|
class="external-link-muted"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>on GitHub.</a
|
>on GitHub.</a
|
||||||
>
|
>
|
||||||
|
@ -164,7 +164,7 @@
|
||||||
<p class="text-sm leading-relaxed mt-2">
|
<p class="text-sm leading-relaxed mt-2">
|
||||||
Content freely available under
|
Content freely available under
|
||||||
<a
|
<a
|
||||||
class="external-link"
|
class="external-link-muted"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en"
|
href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en"
|
||||||
><span class="smallcaps">CC BY-NC-SA</span> 4.0</a
|
><span class="smallcaps">CC BY-NC-SA</span> 4.0</a
|
||||||
|
|
|
@ -28,13 +28,13 @@ import Text.Pandoc.Options (
|
||||||
-- PERSONALIZATION
|
-- PERSONALIZATION
|
||||||
|
|
||||||
mySiteName :: String
|
mySiteName :: String
|
||||||
mySiteName = "gradient ascent"
|
mySiteName = "conditional finality"
|
||||||
|
|
||||||
mySiteRoot :: String
|
mySiteRoot :: String
|
||||||
mySiteRoot = "https://blog.youwen.dev"
|
mySiteRoot = "https://blog.youwen.dev"
|
||||||
|
|
||||||
myFeedTitle :: String
|
myFeedTitle :: String
|
||||||
myFeedTitle = "gradient ascent"
|
myFeedTitle = "conditional finality"
|
||||||
|
|
||||||
myFeedDescription :: String
|
myFeedDescription :: String
|
||||||
myFeedDescription = "on computers, hacks, math, and life"
|
myFeedDescription = "on computers, hacks, math, and life"
|
||||||
|
|
|
@ -10,24 +10,42 @@ module.exports = {
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
primary: {
|
primary: {
|
||||||
dark: "#e7e5e4",
|
//dark: "#e7e5e4",
|
||||||
light: "#44403c",
|
light: "#44403c",
|
||||||
|
dark: "#e0def4",
|
||||||
|
//light: "#575279",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
dark: "#4c1d95",
|
//dark: "#4c1d95",
|
||||||
light: "#4338ca",
|
//light: "#4338ca",
|
||||||
|
dark: "#1f1d2e",
|
||||||
|
light: "#fffaf3",
|
||||||
},
|
},
|
||||||
accent: {
|
accent: {
|
||||||
dark: "#9ca3af",
|
//dark: "#9ca3af",
|
||||||
light: "#78716c",
|
//light: "#78716c",
|
||||||
|
dark: "#908caa",
|
||||||
|
light: "#797593",
|
||||||
},
|
},
|
||||||
muted: {
|
muted: {
|
||||||
dark: "#6b7280",
|
//dark: "#6b7280",
|
||||||
light: "#a8a29e",
|
//light: "#a8a29e",
|
||||||
|
dark: "#6e6a86",
|
||||||
|
light: "#9893a5",
|
||||||
},
|
},
|
||||||
background: {
|
background: {
|
||||||
light: "#d6d3d1",
|
//light: "#d6d3d1",
|
||||||
dark: "#101017",
|
//dark: "#101017",
|
||||||
|
dark: "#191724",
|
||||||
|
light: "#faf4ed",
|
||||||
|
},
|
||||||
|
iris: {
|
||||||
|
dark: "#c4a7e7",
|
||||||
|
light: "#907aa9",
|
||||||
|
},
|
||||||
|
love: {
|
||||||
|
dark: "#eb6f92",
|
||||||
|
light: "#b4637a",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue