chore(tazjin): Move //web/blog & //web/homepage to my userdir
Change-Id: I96a2620ffb1d9e98a1d8ce7d97f2c4f58c2dbfd3 Reviewed-on: https://cl.tvl.fyi/c/depot/+/603 Reviewed-by: tazjin <mail@tazj.in>
72
users/tazjin/homepage/default.nix
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Assembles the website index and configures an nginx instance to
|
||||
# serve it.
|
||||
#
|
||||
# The website is made up of a simple header&footer and content
|
||||
# elements for things such as blog posts and projects.
|
||||
#
|
||||
# Content for the blog is in //web/blog instead of here.
|
||||
{ depot, lib, ... }:
|
||||
|
||||
with depot;
|
||||
with nix.yants;
|
||||
|
||||
let
|
||||
inherit (builtins) readFile replaceStrings sort;
|
||||
inherit (third_party) writeFile runCommandNoCC;
|
||||
|
||||
# The different types of entries on the homepage.
|
||||
entryClass = enum "entryClass" [ "blog" "project" "misc" ];
|
||||
|
||||
# The definition of a single entry.
|
||||
entry = struct "entry" {
|
||||
class = entryClass;
|
||||
title = string;
|
||||
url = string;
|
||||
date = int; # epoch
|
||||
description = option string;
|
||||
};
|
||||
|
||||
escape = replaceStrings [ "<" ">" "&" "'" ] [ "<" ">" "&" "'" ];
|
||||
|
||||
postToEntry = defun [ web.blog.post entry ] (post: {
|
||||
class = "blog";
|
||||
title = post.title;
|
||||
url = "/blog/${post.key}";
|
||||
date = post.date;
|
||||
});
|
||||
|
||||
formatDate = defun [ int string ] (date: readFile (runCommandNoCC "date" {} ''
|
||||
date --date='@${toString date}' '+%Y-%m-%d' > $out
|
||||
''));
|
||||
|
||||
formatEntryDate = defun [ entry string ] (entry: entryClass.match entry.class {
|
||||
blog = "Blog post from ${formatDate entry.date}";
|
||||
project = "Project from ${formatDate entry.date}";
|
||||
misc = "Posted on ${formatDate entry.date}";
|
||||
});
|
||||
|
||||
entryToDiv = defun [ entry string ] (entry: ''
|
||||
<a href="${entry.url}" class="entry ${entry.class}">
|
||||
<div>
|
||||
<p class="entry-title">${escape entry.title}</p>
|
||||
${
|
||||
lib.optionalString ((entry ? description) && (entry.description != null))
|
||||
"<p class=\"entry-description\">${escape entry.description}</p>"
|
||||
}
|
||||
<p class="entry-date">${formatEntryDate entry}</p>
|
||||
</div>
|
||||
</a>
|
||||
'');
|
||||
|
||||
index = entries: third_party.writeText "index.html" (lib.concatStrings (
|
||||
[ (builtins.readFile ./header.html) ]
|
||||
++ (map entryToDiv (sort (a: b: a.date > b.date) entries))
|
||||
++ [ (builtins.readFile ./footer.html) ]
|
||||
));
|
||||
|
||||
homepage = index ((map postToEntry web.blog.posts) ++ (import ./entries.nix));
|
||||
in runCommandNoCC "website" {} ''
|
||||
mkdir $out
|
||||
cp ${homepage} $out/index.html
|
||||
cp -r ${./static} $out/static
|
||||
''
|
||||
64
users/tazjin/homepage/entries.nix
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
[
|
||||
{
|
||||
class = "misc";
|
||||
title = "The Virus Lounge";
|
||||
url = "https://tvl.fyi";
|
||||
date = 1587435629;
|
||||
description = "A daily social video call in these trying pandemic times. Join us!";
|
||||
}
|
||||
{
|
||||
class = "project";
|
||||
title = "depot";
|
||||
url = "https://code.tvl.fyi/about";
|
||||
date = 1576800000;
|
||||
description = "Merging all of my projects into a single, Nix-based monorepo";
|
||||
}
|
||||
{
|
||||
class = "project";
|
||||
title = "Nixery";
|
||||
url = "https://github.com/google/nixery";
|
||||
date = 1565132400;
|
||||
description = "A Nix-backed container registry that builds container images on demand";
|
||||
}
|
||||
{
|
||||
class = "project";
|
||||
title = "kontemplate";
|
||||
url = "https://code.tvl.fyi/about/ops/kontemplate";
|
||||
date = 1486550940;
|
||||
description = "Simple file templating tool built for Kubernetes resources";
|
||||
}
|
||||
{
|
||||
class = "misc";
|
||||
title = "dottime";
|
||||
url = "https://dotti.me/";
|
||||
date = 1560898800;
|
||||
description = "A universal convention for conveying time (by edef <3)";
|
||||
}
|
||||
{
|
||||
class = "project";
|
||||
title = "journaldriver";
|
||||
url = "https://code.tvl.fyi/about/ops/journaldriver";
|
||||
date = 1527375600;
|
||||
description = "Small daemon to forward logs from journald to Stackdriver Logging";
|
||||
}
|
||||
{
|
||||
class = "misc";
|
||||
title = "Principia Discordia";
|
||||
url = "https://principiadiscordia.com/book/1.php";
|
||||
date = 1495494000;
|
||||
description = ''
|
||||
The Principia is a short book I read as a child, and didn't
|
||||
understand until much later. It shaped much of my world view.
|
||||
'';
|
||||
}
|
||||
{
|
||||
class = "misc";
|
||||
title = "This Week in Virology";
|
||||
url = "http://www.microbe.tv/twiv/";
|
||||
date = 1585517557;
|
||||
description = ''
|
||||
Podcast with high-quality information about virology,
|
||||
epidemiology and so on. Highly relevant to COVID19.
|
||||
'';
|
||||
}
|
||||
]
|
||||
2
users/tazjin/homepage/footer.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
</div>
|
||||
</body>
|
||||
35
users/tazjin/homepage/header.html
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="tazjin's blog">
|
||||
<link rel="stylesheet" type="text/css" href="static/tazjin.css" media="all">
|
||||
<link rel="icon" type="image/webp" href="/static/favicon.webp">
|
||||
<title>tazjin's interblag</title>
|
||||
</head>
|
||||
<body class="dark">
|
||||
<header>
|
||||
<h1>
|
||||
<a class="interblag-title" href="/">tazjin's interblag</a>
|
||||
</h1>
|
||||
<hr>
|
||||
</header>
|
||||
<div class="introduction">
|
||||
<p>Hello, illuminated visitor.</p>
|
||||
<p>
|
||||
I'm tazjin. Usually you can find
|
||||
me <a class="dark-link" href="https://git.tazj.in/about">programming computers</a>
|
||||
using tools such as <a class="dark-link" href="https://nixos.org/nix">Nix</a>
|
||||
and <a class="dark-link" href="https://www.gnu.org/software/emacs/">Emacs</a>,
|
||||
cuddling <a class="dark-link" href="https://twitter.com/edefic">people I love</a>
|
||||
or posting nonsense <a class="dark-link" href="https://twitter.com/tazjin">on the
|
||||
internet</a>.
|
||||
</p>
|
||||
<p>
|
||||
Below is a collection of
|
||||
my <span class="project">projects</span>, <span class="blog">blog
|
||||
posts</span> and some <span class="misc">random things</span> by
|
||||
me or others. If you'd like to get in touch about anything, send
|
||||
me a mail at mail@[this domain] or ping me on IRC or Twitter.
|
||||
</p>
|
||||
</div>
|
||||
<div class="entry-container">
|
||||
BIN
users/tazjin/homepage/static/favicon.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
users/tazjin/homepage/static/img/nixery/dominator.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
users/tazjin/homepage/static/img/nixery/example_extra.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
users/tazjin/homepage/static/img/nixery/example_plain.webp
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
users/tazjin/homepage/static/img/nixery/ideal_layout.webp
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
users/tazjin/homepage/static/img/watchblob_1.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
users/tazjin/homepage/static/img/watchblob_2.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
users/tazjin/homepage/static/img/watchblob_3.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
users/tazjin/homepage/static/img/watchblob_4.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
users/tazjin/homepage/static/img/watchblob_5.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
users/tazjin/homepage/static/img/watchblob_6.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
users/tazjin/homepage/static/jetbrains-mono-bold-italic.woff2
Normal file
BIN
users/tazjin/homepage/static/jetbrains-mono-bold.woff2
Normal file
BIN
users/tazjin/homepage/static/jetbrains-mono-italic.woff2
Normal file
BIN
users/tazjin/homepage/static/jetbrains-mono.woff2
Normal file
183
users/tazjin/homepage/static/tazjin.css
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/* Jetbrains Mono font from https://www.jetbrains.com/lp/mono/
|
||||
licensed under Apache 2.0. Thanks, Jetbrains! */
|
||||
@font-face {
|
||||
font-family: jetbrains-mono;
|
||||
src: url(jetbrains-mono.woff2);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: jetbrains-mono;
|
||||
font-weight: bold;
|
||||
src: url(jetbrains-mono-bold.woff2);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: jetbrains-mono;
|
||||
font-style: italic;
|
||||
src: url(jetbrains-mono-italic.woff2);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: jetbrains-mono;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
src: url(jetbrains-mono-bold-italic.woff2);
|
||||
}
|
||||
|
||||
/* Generic-purpose styling */
|
||||
|
||||
body {
|
||||
max-width: 800px;
|
||||
margin: 40px auto;
|
||||
line-height: 1.6;
|
||||
font-size: 18px;
|
||||
padding: 0 10px;
|
||||
font-family: jetbrains-mono, monospace;
|
||||
}
|
||||
|
||||
p, a :not(.uncoloured-link) {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
line-height: 1.2
|
||||
}
|
||||
|
||||
/* Homepage styling */
|
||||
|
||||
.dark {
|
||||
background-color: #181818;
|
||||
color: #e4e4ef;
|
||||
}
|
||||
|
||||
.dark-link, .interblag-title {
|
||||
color: #96a6c8;
|
||||
}
|
||||
|
||||
.entry-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.interblag-title {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.entry {
|
||||
width: 42%;
|
||||
margin: 5px;
|
||||
padding-left: 7px;
|
||||
padding-right: 5px;
|
||||
border: 2px solid;
|
||||
border-radius: 5px;
|
||||
flex-grow: 1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.misc {
|
||||
color: #73c936;
|
||||
border-color: #73c936;
|
||||
}
|
||||
|
||||
.blog {
|
||||
color: #268bd2;
|
||||
border-color: #268bd2;
|
||||
}
|
||||
|
||||
.project {
|
||||
color: #ff4f58;
|
||||
border-color: #ff4f58;
|
||||
}
|
||||
|
||||
.entry-title {
|
||||
color: inherit !important;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.entry-date {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Blog styling */
|
||||
|
||||
.light {
|
||||
color: #383838;
|
||||
}
|
||||
|
||||
.blog-title {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.date {
|
||||
text-align: right;
|
||||
font-style: italic;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.lod {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.uncoloured-link {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
pre {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.cheddar-callout {
|
||||
display: block;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.cheddar-question {
|
||||
color: #3367d6;
|
||||
background-color: #e8f0fe;
|
||||
}
|
||||
|
||||
.cheddar-todo {
|
||||
color: #616161;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.cheddar-tip {
|
||||
color: #00796b;
|
||||
background-color: #e0f2f1;
|
||||
}
|
||||
|
||||
.cheddar-warning {
|
||||
color: #a52714;
|
||||
background-color: #fbe9e7;
|
||||
}
|
||||
|
||||
kbd {
|
||||
background-color: #eee;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #b4b4b4;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, .2), 0 2px 0 0 rgba(255, 255, 255, .7) inset;
|
||||
color: #333;
|
||||
display: inline-block;
|
||||
font-size: .85em;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
padding: 2px 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||