refactor(users/grfn): Rename gws.fyi -> web
Change-Id: Icdee0caa3a053958750d4b81853dbc3eee5b193a Reviewed-on: https://cl.tvl.fyi/c/depot/+/9973 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi> Autosubmit: grfn <grfn@gws.fyi>
This commit is contained in:
parent
f3dea2ffbc
commit
1027754b86
11 changed files with 7 additions and 9 deletions
1
users/grfn/web/.envrc
Normal file
1
users/grfn/web/.envrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
eval "$(lorri direnv)"
|
||||
3
users/grfn/web/.gitignore
vendored
Normal file
3
users/grfn/web/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
result
|
||||
letsencrypt
|
||||
index.html
|
||||
31
users/grfn/web/Makefile
Normal file
31
users/grfn/web/Makefile
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
.PHONY: deploy
|
||||
|
||||
deploy:
|
||||
@$(shell nix-build `git rev-parse --show-toplevel` -A 'users.grfn.web')
|
||||
|
||||
renew:
|
||||
@echo Renewing...
|
||||
@certbot certonly \
|
||||
--manual \
|
||||
--domain www.gws.fyi \
|
||||
--preferred-challenges dns \
|
||||
--server https://acme-v02.api.letsencrypt.org/directory \
|
||||
--agree-tos \
|
||||
--work-dir $(shell pwd)/letsencrypt/work \
|
||||
--logs-dir $(shell pwd)/letsencrypt/logs \
|
||||
--config-dir $(shell pwd)/letsencrypt/config
|
||||
@echo "Reimporting certificate"
|
||||
@aws acm import-certificate \
|
||||
--profile personal \
|
||||
--certificate file://letsencrypt/config/live/www.gws.fyi/cert.pem \
|
||||
--certificate-chain file://letsencrypt/config/live/www.gws.fyi/fullchain.pem \
|
||||
--private-key file://letsencrypt/config/live/www.gws.fyi/privkey.pem \
|
||||
--certificate-arn arn:aws:acm:us-east-1:797089351721:certificate/628e54f3-55f9-49c0-811a-eba516b68e30 \
|
||||
--region us-east-1
|
||||
|
||||
backup:
|
||||
@tarsnap -cf $(shell uname -n)-letsencrypt-$(shell date +%Y-%m-%d_%H-%M-%S) \
|
||||
letsencrypt/
|
||||
|
||||
open:
|
||||
$$BROWSER "https://www.gws.fyi"
|
||||
6
users/grfn/web/config.el
Normal file
6
users/grfn/web/config.el
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
(require 'org)
|
||||
|
||||
(setq org-html-postamble nil)
|
||||
|
||||
(defadvice org-export-grab-title-from-buffer
|
||||
(around org-export-grab-title-from-buffer-disable activate))
|
||||
37
users/grfn/web/default.nix
Normal file
37
users/grfn/web/default.nix
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
args@{ pkgs, depot, ... }:
|
||||
with pkgs;
|
||||
let
|
||||
site = import ./site.nix args;
|
||||
resume = import ../resume args;
|
||||
bucket = "s3://gws.fyi";
|
||||
distributionID = "E2ST43JNBH8C64";
|
||||
|
||||
css = runCommand "main.css"
|
||||
{
|
||||
buildInputs = [ pkgs.minify ];
|
||||
} ''
|
||||
minify --type css < ${./main.css} > $out
|
||||
'';
|
||||
|
||||
keys = runCommand "ssh-keys" { } ''
|
||||
touch $out
|
||||
echo "${depot.users.grfn.keys.main}" >> $out
|
||||
'';
|
||||
|
||||
website =
|
||||
runCommand "gws.fyi" { } ''
|
||||
mkdir -p $out
|
||||
cp ${css} $out/main.css
|
||||
cp ${site.index} $out/index.html
|
||||
cp -r ${site.recipes} $out/recipes
|
||||
cp ${resume} $out/resume.pdf
|
||||
cp ${keys} $out/keys
|
||||
'';
|
||||
|
||||
in
|
||||
(writeShellScript "deploy.sh" ''
|
||||
${awscli2}/bin/aws --profile personal s3 sync ${website}/ ${bucket}
|
||||
echo "Deployed to http://gws.fyi"
|
||||
'') // {
|
||||
inherit website site;
|
||||
}
|
||||
40
users/grfn/web/index.org
Normal file
40
users/grfn/web/index.org
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#+OPTIONS: title:nil toc:nil num:nil
|
||||
#+HTML_HEAD: <title>aspen smith</title>
|
||||
#+HTML_HEAD: <link rel="stylesheet" href="./main.css">
|
||||
|
||||
my name is aspen smith and i'm a software engineer and musician.
|
||||
|
||||
* code
|
||||
|
||||
- [[https://github.com/glittershark/][github]]
|
||||
- [[https://cs.tvl.fyi/depot/-/tree/users/grfn][my directory in the tvl monorepo]]
|
||||
|
||||
* work
|
||||
|
||||
i work on database internals at [[https://readyset.io/][readyset]], an incrementally maintained, partially
|
||||
stateful materialized view maintenance system for sql that's wire-compatible
|
||||
with postgresql and mysql, based on [[https://github.com/mit-pdos/noria][noria]]. readyset is currently looking for
|
||||
early users - if you're interested, check out the ~README~ or send me an email
|
||||
|
||||
* projects
|
||||
|
||||
- [[https://windtunnel.ci/][windtunnel]], a continuous benchmarking software-as-a-service currently accepting early alpha users (send me an email if you want to try it out!)
|
||||
- [[https://cs.tvl.fyi/depot/-/tree/users/grfn/achilles][achilles]], a compiler for (what I plan to become) a dependently typed, low-level functional programming language targeting LLVM
|
||||
- [[https://github.com/glittershark/org-clubhouse][org-clubhouse]], an emacs package for lightweight integration between [[https://orgmode.org/][org-mode]] and [[https://clubhouse.io/][the clubhouse project management tool]]
|
||||
- [[https://cs.tvl.fyi/depot/-/tree/users/grfn/xanthous][xanthous]], a terminal roguelike in haskell that I work on intermittently and exclusively for fun \\
|
||||
you can now try xanthous out over ssh by running ~ssh -p 2222 xanthous.gws.fyi~. if you do so I'd love if you send me an email about it
|
||||
|
||||
* music
|
||||
|
||||
- https://sacrosanct.bandcamp.com/, a post-rock project with a [[https://bandcamp.com/h34rken][friend of mine]]
|
||||
- [[https://soundcloud.com/missingggg][my current soundcloud]], releasing instrumental hip-hop under the name *missing*
|
||||
- you can also find a log of all the music I listen to [[https://www.last.fm/user/wildgriffin45][on last.fm]]
|
||||
|
||||
* contact
|
||||
|
||||
- [[mailto:web@gws.fyi][web@gws.fyi]]
|
||||
- [[https://twitter.com/glittershark1][twitter]]
|
||||
- [[https://bsky.app/profile/gws.fyi][bluesky]]
|
||||
- https://keybase.io/glittershark
|
||||
- grfn on IRC (hackint or libera.chat)
|
||||
- [[http://keys.gnupg.net/pks/lookup?op=get&search=0x44EF5B5E861C09A7][gpg key: 0F11A989879E8BBBFDC1E23644EF5B5E861C09A7]]
|
||||
139
users/grfn/web/main.css
Normal file
139
users/grfn/web/main.css
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
@import url(https://fonts.googleapis.com/css?family=Inconsolata|Inter&display=swap);
|
||||
|
||||
body {
|
||||
margin-top: 40px;
|
||||
max-width: 900px;
|
||||
line-height: 1.6;
|
||||
font-size: 16px;
|
||||
background: #f8f3ff;
|
||||
color: #3a1616;
|
||||
padding: 0 10px;
|
||||
font-family: Inter, sans-serif;
|
||||
}
|
||||
|
||||
@media (min-width: 1050px) {
|
||||
body {
|
||||
margin-left: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 2000px) {
|
||||
body {
|
||||
margin-left: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 10px 16px;
|
||||
margin: 2px 0;
|
||||
box-sizing: border-box;
|
||||
border: 2px solid #dabebe;
|
||||
border-radius: 6px;
|
||||
background: #f8f3ff;
|
||||
color: #3a1616;
|
||||
font-size: 16px;
|
||||
-webkit-transition: 0.5s;
|
||||
transition: 0.5s;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
border: 2px solid #3a1616;
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: #f8f3ff;
|
||||
border: none;
|
||||
color: #000;
|
||||
padding: 6px 14px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
margin: 4px 2px;
|
||||
transition-duration: 0.4s;
|
||||
cursor: pointer;
|
||||
border: 2px solid #3a1616;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: #3a1616;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.isa_error,
|
||||
.isa_info,
|
||||
.isa_success,
|
||||
.isa_warning {
|
||||
width: 90%;
|
||||
margin: 10px 0;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.isa_info {
|
||||
color: #00529b;
|
||||
background-color: #bde5f8;
|
||||
}
|
||||
|
||||
.isa_success {
|
||||
color: #4f8a10;
|
||||
background-color: #dff2bf;
|
||||
}
|
||||
|
||||
.isa_warning {
|
||||
color: #9f6000;
|
||||
background-color: #feefb3;
|
||||
}
|
||||
|
||||
.isa_error {
|
||||
color: #d8000c;
|
||||
background-color: #ffd2d2;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
line-height: 1.2;
|
||||
font-family: Inter, sans-serif;
|
||||
}
|
||||
|
||||
h1.title,
|
||||
h2.title,
|
||||
h3.title {
|
||||
text-align: left;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 750px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
color: #217ab7;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #e3d6ff;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #43458b;
|
||||
border-color: #43458b;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: Inconsolata, monospace;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: #fff;
|
||||
background: #ff4081;
|
||||
}
|
||||
67
users/grfn/web/orgExportHTML.nix
Normal file
67
users/grfn/web/orgExportHTML.nix
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{ pkgs, depot, ... }:
|
||||
|
||||
with pkgs;
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
emacs = pkgs.emacs28;
|
||||
|
||||
in
|
||||
|
||||
opts:
|
||||
|
||||
let
|
||||
src = if isAttrs opts then opts.src else opts;
|
||||
headline = if isAttrs opts then opts.headline else null;
|
||||
|
||||
bn = builtins.baseNameOf src;
|
||||
filename = elemAt (splitString "." bn) 0;
|
||||
|
||||
outName =
|
||||
if isNull headline
|
||||
then
|
||||
let
|
||||
bn = builtins.baseNameOf src;
|
||||
filename = elemAt (splitString "." bn) 0;
|
||||
in
|
||||
if depot.nix.utils.isDirectory src
|
||||
then filename
|
||||
else filename + ".html"
|
||||
else "${filename}-${replaceStrings [" "] ["-"] filename}.html";
|
||||
|
||||
escapeDoubleQuotes = replaceStrings [ "\"" ] [ "\\\"" ];
|
||||
|
||||
navToHeadline = optionalString (! isNull headline) ''
|
||||
(search-forward "${escapeDoubleQuotes headline}")
|
||||
(org-narrow-to-subtree)
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
runCommand outName { inherit src; } ''
|
||||
buildFile() {
|
||||
cp "$1" file.org
|
||||
${emacs}/bin/emacs --batch \
|
||||
--load ${./config.el} \
|
||||
--visit file.org \
|
||||
--eval "(progn
|
||||
${escapeDoubleQuotes navToHeadline}
|
||||
(org-html-export-to-html))" \
|
||||
--kill
|
||||
rm file.org
|
||||
substitute file.html "$2" \
|
||||
--replace '<title>‎</title>' ""
|
||||
rm file.html
|
||||
}
|
||||
|
||||
if [ -d $src ]; then
|
||||
for file in $src/*; do
|
||||
result=''${file/$src/$out}
|
||||
mkdir -p $(dirname $result)
|
||||
buildFile $file ''${result/.org/.html}
|
||||
done
|
||||
else
|
||||
buildFile $src $out
|
||||
fi
|
||||
''
|
||||
102
users/grfn/web/recipes/tomato-sauce.org
Normal file
102
users/grfn/web/recipes/tomato-sauce.org
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#+TITLE: Tomato Sauce
|
||||
#+OPTIONS: toc:nil num:nil
|
||||
#+HTML_HEAD: <link rel="stylesheet" href="../main.css">
|
||||
|
||||
This is a general, all-purpose framework for turning some form of tomatoes into
|
||||
some form of sauce. You can use fresh tomatoes or canned (the latter are really
|
||||
quite surprisingly good sometimes), and include or omit garlic, basil, or other
|
||||
add-ins. The only real non-negotiable ingredients are tomatoes (duh), onion, and
|
||||
some kind of fat (I prefer butter).
|
||||
|
||||
* Sauce
|
||||
|
||||
1. *Prep*. If starting with canned tomatoes, skip this step. if starting with
|
||||
whole tomatoes (which you should really only ever do if you grew them
|
||||
yourself or got them fresh at a farmers market, grocery store tomatoes are
|
||||
kinda sad), first, peel the tomatoes. The easiest way to do this is to score
|
||||
them with an X pattern cut as shallow as possible while still breaking the
|
||||
skin, trying to cover the whole surface area of the tomato, blanch them
|
||||
briefly in boiling water, then dunk into an ice bath. After this, the skins
|
||||
will slip right off. After peeling, cut out the stem, core, and any green or
|
||||
brown bits, and go to the next step
|
||||
|
||||
2. *Base layer*. Couple of variables here, though a perfectly good (in fact, my
|
||||
usual go-to) tomato sauce can also skip this entire step:
|
||||
- If you want meat with your sauce (pancetta/guanciale/bacon for an
|
||||
amatriciana, ground beef or pork for a bolognese) you'll start out by
|
||||
sautéing that in some sort of fat (probably olive oil), less fat for meat
|
||||
with a lot of fat already in it, to brown and render out fat from the meat
|
||||
- If you want onion in the final sauce, you'll chop them finely and sauté
|
||||
them with whatever fat you've got (either from the meat, or olive oil or
|
||||
butter if you're not making a meat sauce). Remember to always add a *bit*
|
||||
of salt when sautéing onion like this, not for flavor but to draw out the
|
||||
moisture. If you just want onion flavor but not bits of onion in the final
|
||||
sauce, it's added whole later (so ignore this bullet point).
|
||||
- If you feel like it (sometimes I do, usually I don't) you can also mince
|
||||
garlic here and sauté that in with everything else. Add a little after the
|
||||
onion, as garlic cooks faster than onion, unless you want something
|
||||
roastier (usually you don't for tomato sauce)
|
||||
- The traditional (so I'm told) thing to do with amatriciana, but also nice
|
||||
with all variations, is to add in a little crushed red pepper with the
|
||||
fat to flavor it slightly, but do this late so it doesn't burn
|
||||
- If you have tomato paste on hand and feel like using it, it's also nice to
|
||||
fry that in the oil for a little bit - usually I'd do that around the same
|
||||
time as the garlic
|
||||
|
||||
If you're making tomato *paste* from your sauce, skip all of this - paste is
|
||||
an ingredient, not a sauce on its own, so imo should be as neutral as
|
||||
possible (i.e. just tomato).
|
||||
|
||||
3. *Tomato layer*. Not a whole lot to do here, just add all of your tomatoes -
|
||||
either your peeled and de-cored tomatoes from step 1 if you're using whole
|
||||
tomatoes, or an entire can of whole, peeled san marzano tomatoes, including
|
||||
the juice in the can - to a pot over medium-high heat. If you need more fat
|
||||
or if you skipped step 2, this is where you'd add it - a classic and my
|
||||
personal favorite is like 2/3rds to 3/4ths of a stick of butter, but you can
|
||||
also go with olive oil. If you skipped the onion in step 2, add that here
|
||||
too - usually that'd just be a fist-sized amount of onion or so peeled but
|
||||
left with the stem on so you can fish it out from your final sauce later (and
|
||||
snack on it!). Also salt here, again not to taste but primarily to draw out
|
||||
moisture from the various ingredients.
|
||||
|
||||
4. You can cook that for a wide variety of times, especially depending on how
|
||||
hot you make your stove - there ends up being *lot* of liquid in there, so
|
||||
you can go (in my experience) a reasonable amount hotter than you expect
|
||||
without burning the sauce, though obviously your mileage may vary. The main
|
||||
thing you're looking for is the whole chunks of tomato to break down, and the
|
||||
whole sauce to get a texture that looks like it'll end up sticking to pasta
|
||||
nicely. In all versions of this, stir pretty regularly with a wooden spoon,
|
||||
and use the spoon to crush the big chunks of tomato occasionally.
|
||||
|
||||
5. *Final layer*. Usually I don't do anything here - but if you feel
|
||||
like it, usually right as you take stuff off the heat is where you'd add
|
||||
basil, if you're using it. You can also add sugar to balance out too much
|
||||
acidity from an especially acidic tomato here - I'm not going to tell anyone.
|
||||
Also salt, but make sure to account for the extra salt you're gonna get from
|
||||
the pasta water (see step 6)
|
||||
|
||||
6. *Pasta*. You know how to cook pasta, I'm not going to tell you that. But,
|
||||
like, salt your water until it tastes too salty, and remember to move the
|
||||
pasta itself *directly* into the sauce pot from the pasta pot before it's
|
||||
completely done cooking and without straining, bringing along some of the
|
||||
pasta water (and a little extra for good measure) then finishing the pasta in
|
||||
the sauce. You know, the thing you do for pasta. Remember the pasta water
|
||||
will have salt in it, so adjust for that when salting the sauce overall (I
|
||||
have made this mistake and ended up with too-salty pasta sauce).
|
||||
|
||||
* Paste
|
||||
|
||||
Start with the above recipe for tomato sauce, noting especially that (in my
|
||||
opinion) you should skip step 2 entirely. Keep cooking the sauce until it's
|
||||
*too* thick for pasta sauce (but don't burn it!), then spread it out across some
|
||||
sort of lined sheet pan (like a silpat, if you've got one) and bake in the oven
|
||||
at like 250-300 degrees for a *hell* of a long time - I've seen this take like
|
||||
10 hours, for an especially juicy batch of tomatoes, but obviously keep a close
|
||||
eye on it because it *definitely will burn* eventually. You're looking for the
|
||||
end result to be the texture of tomato paste, because that's what the recipe is
|
||||
for. Especially if you're using garden-grown or otherwise fresh tomatoes,
|
||||
you'll notice quite a few seeds in the final product - don't worry too much
|
||||
about those, they've never bothered me. Once everything's done and cooled down,
|
||||
store in a jar in a fridge, topped with olive oil to seal things off and prevent
|
||||
oxidation. Use in all your future endeavors, including the tomato sauce recipe
|
||||
above itself. Tomato sauce is a beautiful oroborous.
|
||||
9
users/grfn/web/shell.nix
Normal file
9
users/grfn/web/shell.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
with import <nixpkgs> { config.allowUnfree = true; };
|
||||
mkShell {
|
||||
buildInputs = [
|
||||
awscli
|
||||
gnumake
|
||||
letsencrypt
|
||||
tarsnap
|
||||
];
|
||||
}
|
||||
12
users/grfn/web/site.nix
Normal file
12
users/grfn/web/site.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
args@{ pkgs ? import <nixpkgs> { }, ... }:
|
||||
|
||||
let
|
||||
|
||||
orgExportHTML = import ./orgExportHTML.nix args;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
index = orgExportHTML ./index.org;
|
||||
recipes = orgExportHTML ./recipes;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue