bringing intent into form
- primary intent: to communicate with like-minded people, to share information
- this process requires decision to make something concrete. the decisions can either be incidental or thoughtfull
- thoughtfull decisions yields a harmony between separate parts: it is the glue that binds them.
- consistent framework yields harmony between the visual and the content. between the technology and the intent.
- choices are made in content type, word choice, design elements, choice of technology, etc..
visual design choices: minimalism, readability/whitespace, anthrocentricity as opposed to techcentricity
- written word is the star of the show, with images and code for support
- black on white for readability, touch of human colors: beige, pink, ...
- consistent sans-serif font, 400 weight
- harmoniuous type scale
- consitent spacing based on 8px grid
tech choices
- sass for bottom up visual design: build up a set of design tokens
- avoid cascading styles for simplicity -> each react component will be styled immediately and concretely
- react components provide a functional visual unit
- top down visual design starting with pages
- markdown for simplicity, with markdoc for flexibility to include new visual elements when needed
why think too hard in the first place: efficiency comes from clarity of thought
- creating a mental framework yields consistent design
- scope: don't generalize for features that might never get used in the first place
- constraints help not to be overwhelemed by complexity
3 axis: content, audience, medium
- content: centered on text
- audience: wide audience -> accesible format
- medium: choices here are driven by contraints on the first two
design tokens: from visual harmony to tech constraints
react components: concrete styling
top-down vs bottom-up: nesting layouts vs design tokens and shared components
other technological constraints:
- don't want to use a platform: want flexibility
- leverage community: use well supported libraries. don't want to spend a time recreating the wheel or debugging libs
- don't want to fight a framework -> well supported robust building blocks
interesting aside: the process of creation is a process of self discovery: why do you make the stylistic choices that you do?
TODO: include space for quote: Whom the gods wish to destroy, they give unlimited resources -- Tyla Thwarp
I use k3d to run local experiments. I recently streamlined the configuration and figured I would share the setup code and figured I would share the basic workflow.
Why?
k3d is a lightweight kubernetes distribution based on docker. With docker, I can isolate all the packages needed for a particular application. The benefit is twofold:
- Reproducability
- Package management
I can create a docker container for a particular experiment. If I'm no longer interested, I can simply delete the docker image and I can remove all the clutter associated with the project. If I need to move the codebase to a seperate machine, I have all the steps needed to reproduce the working code in the docker container. Now lets move on to the code.
Install Dependencies
First, follow this guide to install k3d on your machine. Make sure you also install opentofu, which is an open source variant of terraform.
Create Docker Registry
Now we have to have a place to register custom docker images. The simplest setup for me is to use k3d to manage a local registry:
k3d registry create myregistry.localhost --port 45777
Where myregistry can be any name for the docker registry and 45777 is any free port on the host machine.
Create k3d Cluster
Now we can create k3d cluster and point it to the local docker registry. I also mount a volume that contains the code for all my projects. This makes it easy to hot-reload changes versus packaging the application code directly in the docker container. You can find a list of all the command line flags here
k3d cluster create
--registry-use k3d-myregistry.localhost:45777 # use the local registry that we have created in the previous steps
--volume /home/david/pkg:/pkg # mount any code that your application will need
--port "8000:80@loadbalancer" # expose loadbalancer on host port 8000
mycluster
We will also need the kubernetes configuration created by k3d so that we can access the kubernetes API with opentofu. It is enough to write this data to a file and read it back in opentofu:
k3d kubeconfig write maestro -o kubeconfig
OpenTofu Setup
Now we can create the standard main.tf file used in all opentofu projects:
# main.tf
# specify the kubernetes provider
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "2.11.0"
}
}
}
# use configuration created by k3d
# we should have already written the config to filesystem
provider "kubernetes" {
config_path = "${path.module}/kubeconfig"
}
Now we just initialize opentofu and apply the changes like we normally would:
tofu init
tofu apply
Fin
This is the basic setup to get opentofu talking to a k3d cluster. From here you can customize main.tf to include any specific changes that your cluster requires. I plan to do a future article where I go into depth streamlining any friction points. Happy hacking!