+ {{ page.description }} +
+
+
- {{ error.message ?? 'Sorry, something went wrong.' }} -
-
-
+
+ {{ + work.title + }} + — {{ work.description }} +
+- {{ work.description }} -
-- I left school, my job, and moved to Austin in 2022 to write - code full time. That was definitely one of the best and - most life changing decisions I've ever made. I've learned - a lot since then and still have much more to learn. + {{ + project.title + }} + — {{ project.description }}
-- These days I build things because I find joy in making something - someone else really enjoys using. I get excited about reaching a - level of polish that users don't even notice. -
-- In a time where code is cheap I pride myself in taste and execution. - The best sticking point — in my limited opinion so far — is the - way using your product feels. So I want everything I make to - simply feel the best to use. -
-- If you want to build something cool or connect - hit me up - — we'll grab a coffee or beer if you're in Austin! I - still dont know enough people to form a band yet ;) -
-+ I left school, my job, and moved to Austin in 2022 to write code + full time. That was definitely one of the best and most life + changing decisions I've ever made. I've learned a lot since then + and still have much more to learn. +
++ These days I build things because I find joy in making something + someone else really enjoys using. I get excited about reaching a + level of polish that users don't even notice. +
++ In a time where code is cheap I pride myself in taste and + execution. The best sticking point — in my limited opinion so far + — is the way using your product feels. So I want + everything I make to simply feel the best to use. +
++ If you want to build something cool or connect + hit me up — we'll grab a coffee or + beer if you're in Austin! I still dont know enough people to form + a band yet ;) +
+ ++ {{ page.description }} +
+- {{ page.description }} -
-No thoughts...head empty
-No thoughts...head empty
+ + diff --git a/app/plugins/gsap.client.ts b/app/plugins/gsap.client.ts deleted file mode 100644 index 5cdb712..0000000 --- a/app/plugins/gsap.client.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { gsap } from 'gsap'; -import { ScrollTrigger } from 'gsap/ScrollTrigger'; - -export default defineNuxtPlugin(() => { - gsap.registerPlugin(ScrollTrigger); - - return { - provide: { - gsap, - ScrollTrigger, - }, - }; -}); diff --git a/app/utils/fonts.ts b/app/utils/fonts.ts new file mode 100644 index 0000000..49bb3fa --- /dev/null +++ b/app/utils/fonts.ts @@ -0,0 +1,22 @@ +export const BODY_FONTS = [ + { id: 'plantin', label: 'Plantin' }, + { id: 'alegreya', label: 'Alegreya' }, + { id: 'redaction', label: 'Redaction' }, + { id: 'redaction-35', label: 'Redaction 35' }, + { id: 'sohne', label: 'Sohne' }, + { id: 'space', label: 'Space Mono' }, + { id: 'georgia', label: 'Georgia' }, + { id: 'palatino', label: 'Palatino' }, + { id: 'iowan', label: 'Iowan' }, + { id: 'system', label: 'System Sans' }, + { id: 'courier', label: 'Courier' }, +] as const; + +export type BodyFontId = (typeof BODY_FONTS)[number]['id']; + +export const DEFAULT_BODY_FONT: BodyFontId = 'plantin'; +export const BODY_FONT_STORAGE_KEY = 'body-font'; + +export function isBodyFontId(value: string | null): value is BodyFontId { + return BODY_FONTS.some((font) => font.id === value); +} diff --git a/app/utils/themes.ts b/app/utils/themes.ts new file mode 100644 index 0000000..e0dacbc --- /dev/null +++ b/app/utils/themes.ts @@ -0,0 +1,22 @@ +export const BG_THEMES = [ + { id: 'dusk', label: 'Dusk' }, + { id: 'navy', label: 'Navy' }, + { id: 'midnight', label: 'Midnight' }, + { id: 'indigo', label: 'Indigo' }, + { id: 'storm', label: 'Storm' }, + { id: 'slate', label: 'Slate' }, + { id: 'ink', label: 'Ink' }, + { id: 'pine', label: 'Pine' }, + { id: 'wine', label: 'Wine' }, + { id: 'cocoa', label: 'Cocoa' }, + { id: 'paper', label: 'Paper' }, +] as const; + +export type BgThemeId = (typeof BG_THEMES)[number]['id']; + +export const DEFAULT_BG_THEME: BgThemeId = 'dusk'; +export const BG_THEME_STORAGE_KEY = 'bg-theme'; + +export function isBgThemeId(value: string | null): value is BgThemeId { + return BG_THEMES.some((theme) => theme.id === value); +} diff --git a/content/writing/notes-in-the-margin.md b/content/writing/notes-in-the-margin.md new file mode 100644 index 0000000..78f2653 --- /dev/null +++ b/content/writing/notes-in-the-margin.md @@ -0,0 +1,23 @@ +--- +title: Notes in the margin +date: 2026-08-22 +description: A quick look at the two asides this site knows how to make. +--- + +Most of what I write should just be the thing itself. Sometimes a thought doesn't belong in the sentence, though, it belongs next to it. :margin-note[(like this — a margin note sits beside the column on a wide screen, and drops under the paragraph on a small one)] That's what margin notes are for. Parentheticals you can actually skip. + +Notices are the opposite. They interrupt on purpose. + +::notice +**A note you shouldn't skip.** Use a notice when the aside *is* the point for a minute. It stays in the column, navy, hard to miss. +:: + +And if it needs to break the column entirely: + +::notice{bleed} +**Full-bleed.** Same idea, but it runs edge to edge. Save it for the one time in a piece you actually want to shout. +:: + +That's the whole vocabulary. Margin for a mutter. Band for a point. Everything else is just the writing. + +> A blockquote gets the little pointing hand in the left margin. Use it when you're quoting someone, or when you want a line to feel pointed at. diff --git a/nuxt.config.ts b/nuxt.config.ts index 1f3085a..4a7a79a 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -29,8 +29,9 @@ export default defineNuxtConfig({ }, }, + css: ['~/assets/css/main.css'], + app: { - pageTransition: { name: 'page', mode: 'out-in' }, head: { htmlAttrs: { lang: 'en' }, charset: 'utf-8', @@ -44,17 +45,21 @@ export default defineNuxtConfig({ }, ], link: [{ rel: 'icon', type: 'image/png', href: '/favicon.png' }], + script: [ + { + innerHTML: `(function(){try{var t=localStorage.getItem('bg-theme')||'dusk';var f=localStorage.getItem('body-font')||'plantin';document.documentElement.classList.add('theme-'+t,'font-'+f);}catch(e){document.documentElement.classList.add('theme-dusk','font-plantin');}})();`, + tagPosition: 'head', + }, + ], }, }, modules: ['@nuxt/content', '@nuxtjs/color-mode'], colorMode: { - preference: 'system', // default value of $colorMode.preference - fallback: 'light', // fallback value if not system preference found - globalName: '__NUXT_COLOR_MODE__', - componentName: 'ColorScheme', + preference: 'dark', + fallback: 'dark', classPrefix: '', - classSuffix: '-mode', // Results in .dark-mode or .light-mode + classSuffix: '-mode', storageKey: 'color-mode', }, });