This commit is contained in:
parent
4858c1a68a
commit
f62963f5c9
10 changed files with 119 additions and 299 deletions
53
@s
53
@s
|
|
@ -1,53 +0,0 @@
|
||||||
---
|
|
||||||
title: "Replacing garage guttering"
|
|
||||||
slug: /replacing-garage-guttering/
|
|
||||||
date: 2025-12-06
|
|
||||||
tags: ["projects", "DIY"]
|
|
||||||
---
|
|
||||||
|
|
||||||
I faced the following problems with the guttering on my garage:
|
|
||||||
|
|
||||||
- It had been bent out of shape by the wind
|
|
||||||
- The seals on the joins had worn away causing leaks
|
|
||||||
- There was sitting water that wasn't making it to the downpipe
|
|
||||||
- It was old and gross
|
|
||||||
|
|
||||||
Whenever it rained heavily, these problems would compound and lead to water
|
|
||||||
pouring over onto the garage brickwork.
|
|
||||||
|
|
||||||
The sitting water was caused by the lack of a sufficient drop from the union
|
|
||||||
join with my neighbour's gutter to the downpipe. A further impediment was that
|
|
||||||
the water had to turn a 90 degree angle, around the side of the garabe, before
|
|
||||||
reaching the downpipe. As a result, water was only making it to the downpipe
|
|
||||||
when there was very heavy rain and/or high winds. During normal drip-drainage of
|
|
||||||
the daily dew condensation on the roof, the water was just pooling in the
|
|
||||||
gutter.
|
|
||||||
|
|
||||||
I decided to redesign the passage to the downpipe. Instead of trying to make the
|
|
||||||
water turn a bend I thought it would be better to work _with_ gravity and have
|
|
||||||
the drop start at the end of the guttering, not around the corner. This way, the
|
|
||||||
water would have increased velocity at the beginning of its descent into the
|
|
||||||
downpipe.
|
|
||||||
|
|
||||||
By fashioning a "swans neck" sequence of joins, the downpipe now turns the
|
|
||||||
corner _during_ descent and is fed downwards along the wall to the water butt.
|
|
||||||
|
|
||||||
This has been working very well and the water no longer pools. I've noticed
|
|
||||||
however that condensation forms on the underside of the downpipe. This doesn't
|
|
||||||
look great and I worry about it wearing away the sealant I have applied at the
|
|
||||||
joins.
|
|
||||||
|
|
||||||
Overall, however I think it looks much neater as well as being more satisfying
|
|
||||||
from an engineering perspective. The white half-round gutters blend in nicely
|
|
||||||
with the neighbours' and look a lot cleaner.
|
|
||||||
|
|
||||||
I didn't keep track of costs for this project. I think in total it cost around
|
|
||||||
£80. This included the cost of the Floplast guttering and fixtures, the downpipe
|
|
||||||
and the protective mesh I applied to the top of the gutters to prevent blockages
|
|
||||||
from leaves and roof moss.
|
|
||||||
|
|
||||||
In order to drill the fixtures into the garage masonry I needed a more powerful
|
|
||||||
drill than my 18V battery-powered Erbauer. I bought this a few years ago before
|
|
||||||
I knew much about brands and power-tool quality. So I bought a wired Makita
|
|
||||||
hammer-drill for around £90. I think when I buy new power-tools in future I will
|
|
||||||
stick to Makita. The build quality and performance is excellent.
|
|
||||||
10
package-lock.json
generated
10
package-lock.json
generated
|
|
@ -80,7 +80,6 @@
|
||||||
"integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
|
"integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.0",
|
"@ampproject/remapping": "^2.2.0",
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
|
|
@ -2263,7 +2262,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.7.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.7.tgz",
|
||||||
"integrity": "sha512-wAHc/cgKzW7LZNFloThyHnV/AX9gTg3w5yAv0gvQHPZoCnepwqCMtzbuPbb2UvfvO32XZ46e8bPOYbfZhzVnnQ==",
|
"integrity": "sha512-wAHc/cgKzW7LZNFloThyHnV/AX9gTg3w5yAv0gvQHPZoCnepwqCMtzbuPbb2UvfvO32XZ46e8bPOYbfZhzVnnQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/query-core": "5.90.7"
|
"@tanstack/query-core": "5.90.7"
|
||||||
},
|
},
|
||||||
|
|
@ -2419,7 +2417,6 @@
|
||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
|
|
@ -2532,7 +2529,6 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caniuse-lite": "^1.0.30001716",
|
"caniuse-lite": "^1.0.30001716",
|
||||||
"electron-to-chromium": "^1.5.149",
|
"electron-to-chromium": "^1.5.149",
|
||||||
|
|
@ -2951,7 +2947,6 @@
|
||||||
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
|
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.8.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
|
|
@ -4386,7 +4381,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
||||||
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
|
|
@ -4396,7 +4390,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
||||||
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.26.0"
|
"scheduler": "^0.26.0"
|
||||||
},
|
},
|
||||||
|
|
@ -4814,7 +4807,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
|
|
@ -5004,7 +4996,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
|
||||||
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.4.4",
|
"fdir": "^6.4.4",
|
||||||
|
|
@ -5093,7 +5084,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ const renderer = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const highlighter = await createHighlighter({
|
const highlighter = await createHighlighter({
|
||||||
themes: ["gruvbox-dark-hard"],
|
themes: ["light-plus"],
|
||||||
|
|
||||||
langs: [
|
langs: [
|
||||||
"javascript",
|
"javascript",
|
||||||
|
|
@ -49,7 +49,7 @@ const posts = files.map((file) => {
|
||||||
(match, lang, code) => {
|
(match, lang, code) => {
|
||||||
return highlighter.codeToHtml(code.trim(), {
|
return highlighter.codeToHtml(code.trim(), {
|
||||||
lang: lang || "text",
|
lang: lang || "text",
|
||||||
theme: "gruvbox-dark-hard",
|
theme: "light-plus",
|
||||||
|
|
||||||
transformers: [transformerColorizedBrackets()],
|
transformers: [transformerColorizedBrackets()],
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,23 @@ import { convertDate } from "@/utils/convertDate"
|
||||||
|
|
||||||
const PostListing = ({ posts, title, showAllButton }) => {
|
const PostListing = ({ posts, title, showAllButton }) => {
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto py-4 px-1 md:p-4 grow">
|
<div className="">
|
||||||
<div className="space-my-8">
|
<div className="">
|
||||||
<section className="container">
|
<section className="">
|
||||||
<h2 className="text-2xl font-semibold mb-4 block h2-home scanlined px-2">
|
<h2 className="">
|
||||||
{`${title}`}
|
{`${title}`}
|
||||||
</h2>
|
</h2>
|
||||||
{posts.map((post) => (
|
{posts.map((post) => (
|
||||||
<ul>
|
<ul className="no-bullets">
|
||||||
<li className="mb-4">
|
<li className="">
|
||||||
<div className="flex justify-between flex-col relative hover:bg-[#504945]">
|
<div className="">
|
||||||
<span className="overflow-hidden whitespace-nowrap text-muted-foreground shrink-0 condensed">
|
<span style={{ marginRight: '1rem' }}>
|
||||||
{convertDate(post.date)}
|
{convertDate(post.date)}
|
||||||
</span>
|
</span>
|
||||||
<Link
|
<Link
|
||||||
to={`/posts/${post.slug}`}
|
to={`/posts/${post.slug}`}
|
||||||
key={post.slug}
|
key={post.slug}
|
||||||
className="overflow-hidden text-ellipsis whitespace-nowrap min-w-0"
|
className=""
|
||||||
>
|
>
|
||||||
{post.title}
|
{post.title}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -40,26 +40,26 @@ export default PostListing
|
||||||
/*
|
/*
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
to={`/posts/${post.slug}`}
|
to={`/posts/${post.slug}`}
|
||||||
key={post.slug}
|
key={post.slug}
|
||||||
className="block no-underline"
|
className="block no-underline"
|
||||||
>
|
>
|
||||||
<Card
|
<Card
|
||||||
key={post.slug}
|
key={post.slug}
|
||||||
className="flex flex-col h-full hover:bg-primary/5 py-4 rounded border-none "
|
className="flex flex-col h-full hover:bg-primary/5 py-4 rounded border-none "
|
||||||
>
|
>
|
||||||
<CardHeader className="">
|
<CardHeader className="">
|
||||||
<CardTitle className="leading-snug font-bold ">
|
<CardTitle className="leading-snug font-bold ">
|
||||||
{post.title}
|
{post.title}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="text-sm text-muted-foreground">
|
<CardDescription className="text-sm text-muted-foreground">
|
||||||
<div className="flex justify-between gap-2">
|
<div className="flex justify-between gap-2">
|
||||||
<span className="text-sm">{convertDate(post.date)}</span>
|
<span className="text-sm">{convertDate(post.date)}</span>
|
||||||
</div>
|
</div>
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
</Card>
|
</Card>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
||||||
102
src/index.css
102
src/index.css
|
|
@ -1,94 +1,42 @@
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap");
|
.header-links {
|
||||||
@import "./styles/_variables.css";
|
display: flex;
|
||||||
@import "tailwindcss";
|
list-style: none;
|
||||||
@import "tw-animate-css";
|
gap: .5rem;
|
||||||
|
margin: 0;
|
||||||
* {
|
padding: 0;
|
||||||
outline-color: color-mix(in srgb, var(--ring) 50%, transparent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
.plain-link {
|
||||||
font-family: var(--font-sansserif);
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
.no-bullets {
|
||||||
background-color: var(--background);
|
list-style: none;
|
||||||
color: var(--foreground);
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.condensed {
|
blockquote {
|
||||||
font-family: "Inter";
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
figcaption {
|
figcaption {
|
||||||
font-weight: 500;
|
text-align: center;
|
||||||
font-family: "Inter";
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
figure {
|
||||||
color: var(--color-orange-light);
|
text-align: center;
|
||||||
font-family: "Inter";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
figure img {
|
||||||
font-family: "Inter";
|
|
||||||
color: var(--color-green-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
.h2-home {
|
|
||||||
font-family: "Inter";
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-family: "Inter";
|
|
||||||
font-weight: 600 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.monospaced-font {
|
|
||||||
font-family: "iA Writer Mono";
|
|
||||||
}
|
|
||||||
|
|
||||||
.scanlined {
|
|
||||||
position: relative;
|
|
||||||
/* Add this */
|
|
||||||
}
|
|
||||||
|
|
||||||
.scanlined::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
max-width: 500px;
|
||||||
background-image: linear-gradient(rgba(0, 0, 0, 0.4) 1px, transparent 1px);
|
min-width: 300px;
|
||||||
background-size: 2px 2px;
|
height: auto;
|
||||||
background-repeat: repeat;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 9999;
|
|
||||||
/* Might want to lower this too */
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-family: var(--font-monospaced);
|
|
||||||
}
|
|
||||||
|
|
||||||
p code {
|
|
||||||
color: var(--foreground);
|
|
||||||
background: #504945;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 0.2rem 0.3rem;
|
|
||||||
border-radius: var(--radius);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.shiki {
|
.shiki {
|
||||||
padding: 1rem 1.2rem;
|
padding: 1rem;
|
||||||
border-radius: 0;
|
border: 1pt solid black;
|
||||||
overflow-x: auto;
|
}
|
||||||
margin: 1.5rem 0;
|
|
||||||
line-height: 1.3;
|
|
||||||
/* counter-reset: line; */
|
|
||||||
font-family: var(--font-monospaced) !important;
|
|
||||||
font-size: 14px !important;
|
|
||||||
}
|
|
||||||
|
|
@ -4,16 +4,16 @@ import portrait from "../images/portrait-compressed.jpg"
|
||||||
const AboutPage = () => {
|
const AboutPage = () => {
|
||||||
return (
|
return (
|
||||||
<MainTemplate>
|
<MainTemplate>
|
||||||
<div className="container mx-auto py-4 px-1 md:p-4">
|
<div className="">
|
||||||
<figure className="w-full flex flex-col items-center mb-6">
|
<figure className="">
|
||||||
<div className="scanlined inline-block">
|
<div className="">
|
||||||
<img
|
<img
|
||||||
alt="A portrait of the blog author"
|
alt="A portrait of the blog author"
|
||||||
src={portrait}
|
src={portrait}
|
||||||
className="w-80 flex"
|
style={{ width: '25%' }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<figcaption className="text-sm text-muted-foreground mt-3 text-center">
|
<figcaption className="">
|
||||||
Pictured with the WITCH computer at the{" "}
|
Pictured with the WITCH computer at the{" "}
|
||||||
<a
|
<a
|
||||||
href="https://www.tnmoc.org/"
|
href="https://www.tnmoc.org/"
|
||||||
|
|
@ -63,22 +63,22 @@ const AboutPage = () => {
|
||||||
|
|
||||||
<p className="leading-[1.6] [&:not(:first-child)]:mt-6">
|
<p className="leading-[1.6] [&:not(:first-child)]:mt-6">
|
||||||
Some things I like:
|
Some things I like:
|
||||||
<ul className="pt-2">
|
<ul className="no-bullets">
|
||||||
<li className="mb-1">🐶 Staffies and other bull-breeds</li>
|
<li className="">🐶 Staffies and other bull-breeds</li>
|
||||||
<li className="mb-1">🎼 Classical music (Haydn, Mozart, JSB)</li>
|
<li className="">🎼 Classical music (Haydn, Mozart, JSB)</li>
|
||||||
<li className="mb-1">🛸 Science fiction </li>
|
<li className="">🛸 Science fiction </li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className="leading-[1.6] [&:not(:first-child)]:mt-6">
|
<p className="">
|
||||||
Some things I'm interested in:
|
Some things I'm interested in:
|
||||||
<ul className="pt-2">
|
<ul className="no-bullets">
|
||||||
<li className="mb-1">🧑💻 Self-hosting and digital resiliance</li>
|
<li className="">🧑💻 Self-hosting and digital resiliance</li>
|
||||||
<li className="mb-1">🖳 The history of computing and networks</li>
|
<li className="">🖳 The history of computing and networks</li>
|
||||||
<li className="mb-1">☸️ Buddhism</li>
|
<li className="">☸️ Buddhism</li>
|
||||||
{/*
|
{/*
|
||||||
|
|
||||||
<li className="mb-1">📡 Civil communications infrastructure</li>
|
<li className="">📡 Civil communications infrastructure</li>
|
||||||
*/}
|
*/}
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -10,64 +10,21 @@ const HomePage = () => {
|
||||||
const { posts } = usePosts()
|
const { posts } = usePosts()
|
||||||
return (
|
return (
|
||||||
<MainTemplate>
|
<MainTemplate>
|
||||||
<div className="container mx-auto md:p-4 py-4 px-1 grow">
|
<p>A wizard who goes to bed early. This is my technical scrapbook
|
||||||
<div className="space-my-8">
|
and digital garden.
|
||||||
<section className="space-y-4">
|
</p>
|
||||||
<div className="gap-6 flex flex-col items-center sm:flex-row">
|
|
||||||
<div className="scanlined">
|
|
||||||
<img src={gruvboxComputer} className="md:w-80 w-50" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h1 className="text-4xl font-bold py-3 text-center sm:text-left md:text-left">
|
|
||||||
<div className="scanlined inline-block py-1 px-2">
|
|
||||||
systems obscure
|
|
||||||
</div>
|
|
||||||
</h1>
|
|
||||||
<p className="text-center sm:text-left md:text-left text-muted font-medium">
|
|
||||||
A wizard who goes to bed early. This is my technical scrapbook
|
|
||||||
and digital garden.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<PostListing title="recent posts" posts={posts.slice(0, 5)} />
|
|
||||||
|
<PostListing title="Recent posts" posts={posts.slice(0, 5)} />
|
||||||
|
|
||||||
<PostListing
|
<PostListing
|
||||||
title="highlights"
|
title="Highlights"
|
||||||
posts={posts.filter((post) => post.tags.includes("highlight"))}
|
posts={posts.filter((post) => post.tags.includes("highlight"))}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="container mx-auto md:p-4 py-4 px-1 grow">
|
|
||||||
<div className="space-my-8">
|
{/* <CodeStats />
|
||||||
<section className="container">
|
<EolasListing /> */}
|
||||||
<h2 className="text-2xl font-semibold mb-4 text-[#d3869b]! h2-home scanlined px-2">
|
|
||||||
{`projects`}
|
|
||||||
</h2>
|
|
||||||
<ul>
|
|
||||||
<li className="pb-2">
|
|
||||||
<a
|
|
||||||
className="underline underline-offset-4 text-[18px] text-primary hover:text-primary/80 font-medium"
|
|
||||||
href="https://eolas.systemsobscure.net"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
eolas
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p className="">
|
|
||||||
A public frontend for my local Zettelkasten created with
|
|
||||||
NodeJS, Python and React.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<CodeStats />
|
|
||||||
<EolasListing />
|
|
||||||
</MainTemplate>
|
</MainTemplate>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ const PostsPage = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MainTemplate>
|
<MainTemplate>
|
||||||
<PostListing title="all posts" posts={posts} />
|
<PostListing title="All posts" posts={posts} />
|
||||||
</MainTemplate>
|
</MainTemplate>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import MainTemplate from "./MainTemplate"
|
||||||
import { Link, useParams } from "react-router"
|
import { Link, useParams } from "react-router"
|
||||||
import { convertDate } from "@/utils/convertDate"
|
import { convertDate } from "@/utils/convertDate"
|
||||||
import { usePosts } from "@/hooks/usePosts"
|
import { usePosts } from "@/hooks/usePosts"
|
||||||
|
import { convertDateFriendly } from "../utils/convertDate"
|
||||||
|
|
||||||
const BlogTemplate = () => {
|
const BlogTemplate = () => {
|
||||||
const { slug } = useParams()
|
const { slug } = useParams()
|
||||||
|
|
@ -15,19 +16,19 @@ const BlogTemplate = () => {
|
||||||
{!post ? (
|
{!post ? (
|
||||||
<div>Loading...</div>
|
<div>Loading...</div>
|
||||||
) : (
|
) : (
|
||||||
<article className="prose prose-lg max-w-none">
|
<article className="">
|
||||||
<header className="mb-6 pb-4">
|
<header className="">
|
||||||
<h1 className="text-4xl font-bold mb-4 leading-tight inline-block scanlined px-2">
|
<h1 className="">
|
||||||
{post?.title}
|
{post?.title}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="flex flex-wrap align-center gap-4 text-[#928374] condensed font-medium">
|
<div className="">
|
||||||
<time datetime={convertDate(post?.date)} className="text-sm">
|
<time datetime={convertDate(post?.date)} className="text-sm">
|
||||||
{convertDate(post?.date)}
|
{convertDateFriendly(post?.date)}
|
||||||
</time>
|
</time>
|
||||||
<div className="flex flex-wrap gap-3 align-center">
|
<div className="flex flex-wrap gap-3 align-center">
|
||||||
{post?.tags?.map((tag, i) => (
|
{post?.tags?.map((tag, i) => (
|
||||||
<Link
|
<Link
|
||||||
className="text-primary text-sm underline underline-offset-3 hover:text-[#689d6a]"
|
style={{ marginRight: '0.5rem' }}
|
||||||
key={i}
|
key={i}
|
||||||
to={`/tags/${tag}`}
|
to={`/tags/${tag}`}
|
||||||
>
|
>
|
||||||
|
|
@ -40,30 +41,7 @@ const BlogTemplate = () => {
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="
|
className="
|
||||||
[&>h2]:text-2xl [&>h2]:font-bold [&>h2]:my-4 [&>h2]:text-[#ebdbb2]!
|
|
||||||
[&>h3]:text-xl [&>h3]:font-bold [&>h3]:my-4 [&>h3]:text-[#ebdbb2]!
|
|
||||||
[&>h4]:text-lg [&>h4]:font-bold [&>h4]:my-4 [&>h4]:text-[#ebdbb2]!
|
|
||||||
[&>p]:leading-7 [&>p:not(:first-child)]:mt-4
|
|
||||||
[&>p+:is(h1,h2,h3,h4,h5,h6)]:mt-6
|
|
||||||
[&>blockquote]:mt-4 [&>blockquote]:border-l-2 [&>blockquote]:pl-6 [&>blockquote]:text-muted-foreground
|
|
||||||
[&>ul]:my-4 [&>ul]:ml-6 [&>ul]:list-disc [&>ul>li]:mt-2
|
|
||||||
[&>pre]:mt-6 [&>pre]:mb-6
|
|
||||||
[&>p+pre]:mt-6
|
|
||||||
[&>pre+p]:mt-6
|
|
||||||
[&>ul+pre]:mt-6
|
|
||||||
[&>li]:leading-[1.6]
|
|
||||||
[&_li_code]:relative [&_li_code]:rounded [&_li_code]:bg-[#504945] [&_li_code]:px-[0.3rem] [&_li_code]:py-[0.2rem] [&_li_code]:font-mono [&_li_code]:text-sm [&_li_code]:font-normal
|
|
||||||
[&>code]:relative [&>code]:rounded [&>code]:bg-[#504945] [&>code]:px-[0.3rem] [&>code]:py-[0.2rem] [&>code]:font-mono [&>code]:text-sm [&>code]:font-normal
|
|
||||||
[&>figure]:w-full [&>figure]:max-w-2xl [&>figure]:flex [&>figure]:flex-col [&>figure]:items-center [&>figure]:justify-center [&>figure]:mb-6 [&>figure]:mx-auto [&>figure>img]:max-w-full [&>figure>img]:max-h-[700px] [&>figure>img]:w-auto [&>figure>img]:h-auto [&>figure>img]:object-contain
|
|
||||||
[&>figure>img]:max-w-2xl [&>figure>img]:max-h-[700px] [&>figure>img]:w-auto [&>figure>img]:h-auto [&>figure>img]:object-contain
|
|
||||||
[&>figure>figcaption]:text-sm [&>figure>figcaption]:text-[#bdae93] [&>figure>figcaption]:mt-3 [&>figure>figcaption]:text-center
|
|
||||||
[&>figure>figcaption>a]:text-primary [&>figure>figcaption>a:hover]:text-primary/80
|
|
||||||
[&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-[#689d6a] [&_a]:text-primary
|
|
||||||
[&>table]:w-full [&>table]:my-4
|
|
||||||
[&>table>thead>tr]:m-0 [&>table>thead>tr]:border-t [&>table>thead>tr]:p-0 [&>table>thead>tr:even]:bg-muted
|
|
||||||
[&>table>thead>tr>th]:border [&>table>thead>tr>th]:px-4 [&>table>thead>tr>th]:py-2 [&>table>thead>tr>th]:text-left [&>table>thead>tr>th]:font-bold [&>table>thead>tr>th[align=center]]:text-center [&>table>thead>tr>th[align=right]]:text-right
|
|
||||||
[&>table>tbody>tr]:m-0 [&>table>tbody>tr]:border-t [&>table>tbody>tr]:p-0 [&>table>tbody>tr:even]:bg-muted
|
|
||||||
[&>table>tbody>tr>td]:border [&>table>tbody>tr>td]:px-4 [&>table>tbody>tr>td]:py-2 [&>table>tbody>tr>td]:text-left [&>table>tbody>tr>td[align=center]]:text-center [&>table>tbody>tr>td[align=right]]:text-right
|
|
||||||
"
|
"
|
||||||
dangerouslySetInnerHTML={{ __html: post?.html }}
|
dangerouslySetInnerHTML={{ __html: post?.html }}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,32 @@
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
|
||||||
import gruvboxComputer from "../images/gruvbox-computer.svg"
|
|
||||||
import { Link } from "react-router"
|
import { Link } from "react-router"
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
return (
|
return (
|
||||||
<header className="md:py-6 pb-4">
|
<header>
|
||||||
<nav className="bg-sidebar container mx-auto justify-between flex gap-1">
|
<nav className="">
|
||||||
<Link to="/">
|
<h1>
|
||||||
<div className="scanlined">
|
<Link
|
||||||
<img src={gruvboxComputer} className="w-11" />
|
className="plain-link"
|
||||||
</div>
|
to="/">Systems Obscure</Link>
|
||||||
</Link>
|
</h1>
|
||||||
<ul class="flex space-x-4 px-4 py-2 text-sm">
|
<ul className="header-links">
|
||||||
<li class="flex flex-col items-center justify-center">
|
<li>
|
||||||
<Link
|
<Link to="/posts">Posts</Link>
|
||||||
class="text-primary underline underline-offset-3 hover:text-[#689d6a] condensed font-semibold text-lg"
|
|
||||||
to="/posts"
|
|
||||||
>
|
|
||||||
posts
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="flex flex-col items-center justify-center">
|
<li>
|
||||||
<Link
|
<Link to="/about">About</Link>
|
||||||
class="text-primary underline underline-offset-3 hover:text-[#689d6a] condensed font-semibold text-lg"
|
|
||||||
to="/about"
|
|
||||||
>
|
|
||||||
about
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
|
<li className="flex flex-col items-center justify-center">
|
||||||
|
<a
|
||||||
|
className=""
|
||||||
|
href="https://forgejo.systemsobscure.net/thomasabishop"
|
||||||
|
target="blank"
|
||||||
|
>
|
||||||
|
Forgejo
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -36,16 +35,16 @@ const Header = () => {
|
||||||
|
|
||||||
const Footer = () => {
|
const Footer = () => {
|
||||||
return (
|
return (
|
||||||
<footer className="bg-sidebar container mx-auto px-4 mt-10 mb-8">
|
<footer className="mx-auto">
|
||||||
<nav>
|
<nav>
|
||||||
<ul className="flex flex-row justify-start gap-4">
|
<ul className="">
|
||||||
<li className="flex flex-col items-center justify-center">
|
<li className="flex flex-col items-center justify-center">
|
||||||
<a
|
<a
|
||||||
className="text-primary underline underline-offset-3 hover:text-[#689d6a] font-semibold"
|
className=""
|
||||||
href="https://forgejo.systemsobscure.net/thomasabishop"
|
href="https://forgejo.systemsobscure.net/thomasabishop"
|
||||||
target="blank"
|
target="blank"
|
||||||
>
|
>
|
||||||
forgejo
|
Forgejo
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -56,13 +55,14 @@ const Footer = () => {
|
||||||
|
|
||||||
const MainTemplate = ({ children }) => {
|
const MainTemplate = ({ children }) => {
|
||||||
return (
|
return (
|
||||||
<div className="antialiased max-w-3xl mt-3 mx-auto bg-[#282828] no-scanlines wrapper">
|
<div className="">
|
||||||
<main className="flex-auto min-w-0 mt-0 flex flex-col px-2 md:px-0">
|
<main className="">
|
||||||
<Header />
|
<Header />
|
||||||
<div>{children}</div>
|
<div>{children}</div>
|
||||||
<Footer />
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
export default MainTemplate
|
export default MainTemplate
|
||||||
|
//antialiased max-w-3xl mt-3 mx-auto bg-[#282828] no-scanlines wrapper
|
||||||
|
//main: flex-auto min-w-0 mt-0 flex flex-col px-2 md:px-0
|
||||||
Loading…
Add table
Reference in a new issue