get routing working, add index for poetry, list first 6 poems on index, let each take you to their page with the poem's content

This commit is contained in:
Silas 2024-05-16 02:52:32 -04:00
parent 2cf484aa46
commit 3d22344e7f
Signed by: silentsilas
GPG Key ID: 4199EFB7DAA34349
44 changed files with 1134 additions and 178 deletions

1
.tool-versions Normal file
View File

@ -0,0 +1 @@
nodejs 20.13.1

58
package-lock.json generated
View File

@ -12,6 +12,7 @@
"@threlte/core": "^7.3.0", "@threlte/core": "^7.3.0",
"@threlte/extras": "^8.11.2", "@threlte/extras": "^8.11.2",
"@threlte/rapier": "^2.0.0", "@threlte/rapier": "^2.0.0",
"mdsvex": "^0.11.0",
"three": "^0.159.0", "three": "^0.159.0",
"three-inspect": "^0.4.5" "three-inspect": "^0.4.5"
}, },
@ -1986,6 +1987,11 @@
"meshoptimizer": "~0.18.1" "meshoptimizer": "~0.18.1"
} }
}, },
"node_modules/@types/unist": {
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz",
"integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA=="
},
"node_modules/@types/webxr": { "node_modules/@types/webxr": {
"version": "0.5.15", "version": "0.5.15",
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.15.tgz", "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.15.tgz",
@ -5028,6 +5034,20 @@
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
}, },
"node_modules/mdsvex": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/mdsvex/-/mdsvex-0.11.0.tgz",
"integrity": "sha512-gJF1s0N2nCmdxcKn8HDn0LKrN8poStqAicp6bBcsKFd/zkUBGLP5e7vnxu+g0pjBbDFOscUyI1mtHz+YK2TCDw==",
"dependencies": {
"@types/unist": "^2.0.3",
"prism-svelte": "^0.4.7",
"prismjs": "^1.17.1",
"vfile-message": "^2.0.4"
},
"peerDependencies": {
"svelte": ">=3 <5"
}
},
"node_modules/meow": { "node_modules/meow": {
"version": "6.1.1", "version": "6.1.1",
"resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz", "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz",
@ -5962,6 +5982,19 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1" "url": "https://github.com/chalk/ansi-styles?sponsor=1"
} }
}, },
"node_modules/prism-svelte": {
"version": "0.4.7",
"resolved": "https://registry.npmjs.org/prism-svelte/-/prism-svelte-0.4.7.tgz",
"integrity": "sha512-yABh19CYbM24V7aS7TuPYRNMqthxwbvx6FF/Rw920YbyBWO3tnyPIqRMgHuSVsLmuHkkBS1Akyof463FVdkeDQ=="
},
"node_modules/prismjs": {
"version": "1.29.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
"integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
"engines": {
"node": ">=6"
}
},
"node_modules/pseudomap": { "node_modules/pseudomap": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@ -7874,6 +7907,18 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"node_modules/unist-util-stringify-position": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
"integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
"dependencies": {
"@types/unist": "^2.0.2"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/universalify": { "node_modules/universalify": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
@ -7936,6 +7981,19 @@
"spdx-expression-parse": "^3.0.0" "spdx-expression-parse": "^3.0.0"
} }
}, },
"node_modules/vfile-message": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
"integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
"dependencies": {
"@types/unist": "^2.0.0",
"unist-util-stringify-position": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/vite": { "node_modules/vite": {
"version": "5.2.10", "version": "5.2.10",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz",

View File

@ -45,6 +45,7 @@
"@threlte/core": "^7.3.0", "@threlte/core": "^7.3.0",
"@threlte/extras": "^8.11.2", "@threlte/extras": "^8.11.2",
"@threlte/rapier": "^2.0.0", "@threlte/rapier": "^2.0.0",
"mdsvex": "^0.11.0",
"three": "^0.159.0", "three": "^0.159.0",
"three-inspect": "^0.4.5" "three-inspect": "^0.4.5"
} }

View File

@ -0,0 +1,41 @@
<script lang="ts">
import { T, useTask, useThrelte } from '@threlte/core';
import { World } from '@threlte/rapier';
import { Inspector } from 'three-inspect';
import { dev } from '$app/environment';
import SpaceSkysphere from './SpaceSkysphere.svelte';
import { Group, type Object3DEventMap } from 'three';
import DollyCam from './DollyCam.svelte';
import Planet from '$lib/components/scenes/app/Planet.svelte';
const { invalidate } = useThrelte();
let spaceObjects: Group<Object3DEventMap>;
useTask(
'updateSpaceObjects',
(delta) => {
if (!spaceObjects) return;
spaceObjects.rotation.y += 0.3 * delta;
spaceObjects.position.y = Math.sin(spaceObjects.rotation.y);
invalidate();
},
{ autoInvalidate: false }
);
</script>
<World gravity={[0, 0, 0]}>
<DollyCam />
<T.Group bind:ref={spaceObjects}>
<SpaceSkysphere size={100} count={500} />
<Planet />
<slot />
</T.Group>
</World>
{#if false}
<Inspector />
{/if}

View File

@ -0,0 +1,26 @@
<!-- src/lib/CanvasLayout.svelte -->
<script lang="ts">
import { Canvas } from '@threlte/core';
</script>
<div class="canvas">
<Canvas>
<slot />
</Canvas>
</div>
<style>
:global(body) {
margin: 0;
}
.canvas {
width: 100%;
height: 100%;
background: rgb(0, 36, 6);
background: linear-gradient(180deg, rgba(0, 36, 6, 1) 0%, rgba(0, 0, 0, 1) 100%);
position: absolute;
justify-content: center;
align-items: center;
}
</style>

View File

@ -0,0 +1,44 @@
<script lang="ts">
import { T, useTask, useThrelte } from '@threlte/core';
import { onMount } from 'svelte';
import { PerspectiveCamera, Vector3 } from 'three';
const { invalidate } = useThrelte();
let camLookatPosition: Vector3 = new Vector3();
let camCurrentPosition: Vector3 = new Vector3();
let camDamping: number = 1;
let camera: PerspectiveCamera;
const handleMouseMove = (event: MouseEvent) => {
// normalize the mouse position to [-1, 1], and smoothly interpolate the camera's lookAt position
camLookatPosition.set(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1,
0
);
};
useTask(
'dollyCam',
(delta) => {
if (!camera) return;
camCurrentPosition.lerp(camLookatPosition, camDamping * delta);
camera.lookAt(camCurrentPosition);
if (camera && camCurrentPosition.distanceTo(camLookatPosition) > 0.1) {
invalidate();
}
},
{ autoInvalidate: false }
);
onMount(() => {
document.addEventListener('mousemove', handleMouseMove);
return () => {
document.removeEventListener('mousemove', handleMouseMove);
};
});
</script>
<T.PerspectiveCamera position.z={25} makeDefault fov={50} far={10000} bind:ref={camera} />

View File

@ -0,0 +1,51 @@
<script lang="ts">
import { HTML } from '@threlte/extras';
import { Attractor } from '@threlte/rapier';
export let position: [number, number, number] = [0, 0, 0];
export let range: number = 100;
export let clickHandler: (() => void) | undefined = undefined;
export let htmlContent: HTMLElement | string = 'Hello!';
export let href: string = '/';
let isHovering = false;
let isPointerDown = false;
const onClick = () => {
console.log('clicked!');
if (clickHandler) {
clickHandler();
}
};
</script>
<HTML position.x={position[0]} position.y={position[1]} position.z={position[2]}>
<a
{href}
on:pointerenter={() => (isHovering = true)}
on:pointerleave={() => {
isPointerDown = false;
isHovering = false;
}}
on:pointerdown={() => (isPointerDown = true)}
on:pointerup={() => (isPointerDown = false)}
on:pointercancel={() => {
isPointerDown = false;
isHovering = false;
}}
on:click={onClick}
class="bg-green-700 px-3 py-3 text-white opacity-50 hover:opacity-90 active:opacity-100"
style="transform: translate(-50%, 50%); display: block;"
>
{htmlContent}
</a>
</HTML>
<Attractor
position.x={position[0]}
position.y={position[1]}
position.z={position[2]}
{range}
strength={isHovering ? 1 : 0}
gravityType={'static'}
/>

View File

@ -0,0 +1,19 @@
<script lang="ts" context="module">
import { T } from '@threlte/core';
import { Attractor, Collider, RigidBody } from '@threlte/rapier';
import { MeshBasicMaterial, SphereGeometry } from 'three';
const geometry = new SphereGeometry(1, 8, 4);
const material = new MeshBasicMaterial({ color: '#339933', wireframe: true });
const position: [number, number, number] = [0, 0, 0];
const scale: number = 2;
const offset = position.map((el) => el + 1.5);
</script>
<Attractor {position} range={100} strength={0.3} gravityType={'linear'} />
<T.Group position.x={-offset[0]} position.y={-offset[1]} position.z={offset[2]}>
<RigidBody linearDamping={0.3}>
<Collider shape="ball" args={[scale]} mass={scale} />
<T.Mesh scale={[scale, scale, scale]} {geometry} {material} />
</RigidBody>
</T.Group>

View File

@ -5,7 +5,7 @@
import { Studio } from '@threlte/theatre'; import { Studio } from '@threlte/theatre';
</script> </script>
<Studio enabled={false} /> <Studio enabled={dev} />
<Canvas> <Canvas>
<Spinners /> <Spinners />

View File

@ -8,18 +8,18 @@
let sequence: SequenceController; let sequence: SequenceController;
let box: Mesh; let ball: Mesh;
let spotlight: SpotLight; let spotlight: SpotLight;
let lastBoxPosition = new Vector3(); let lastBallPosition = new Vector3();
let currentBoxPosition = new Vector3(); let currentBallPosition = new Vector3();
let config = spinnersJson as IProjectConfig; let config = spinnersJson as IProjectConfig;
const boxMoved: any = (props: { position: { x: number; y: number; z: number } }) => { const ballMoved: any = (props: { position: { x: number; y: number; z: number } }) => {
if (box && spotlight) { if (ball && spotlight) {
const { x, y, z } = props.position; const { x, y, z } = props.position;
currentBoxPosition.set(x, y, z); currentBallPosition.set(x, y, z);
spotlight.lookAt(currentBoxPosition); spotlight.lookAt(currentBallPosition);
lastBoxPosition.copy(currentBoxPosition); lastBallPosition.copy(currentBallPosition);
} }
}; };
</script> </script>
@ -33,10 +33,10 @@
<!-- create a T.SpotLight that looks at box--> <!-- create a T.SpotLight that looks at box-->
<T.SpotLight position={[0, 5, 3]} intensity={10} bind:ref={spotlight}></T.SpotLight> <T.SpotLight position={[0, 5, 3]} intensity={10} bind:ref={spotlight}></T.SpotLight>
<SheetObject key="Box" let:Transform let:Sync on:change={boxMoved}> <SheetObject key="Box" let:Transform let:Sync on:change={ballMoved}>
<Transform> <Transform>
<T.Mesh position.y={0.5} bind:ref={box}> <T.Mesh position.y={0.5} bind:ref={ball}>
<T.BoxGeometry args={[1, 1, 1]} /> <T.SphereGeometry args={[1, 8, 4]} />
<T.MeshStandardMaterial color="#b00d03"> <T.MeshStandardMaterial color="#b00d03">
<Sync color roughness metalness /> <Sync color roughness metalness />
</T.MeshStandardMaterial> </T.MeshStandardMaterial>

View File

@ -1,32 +0,0 @@
<script lang="ts">
import { Canvas, T } from '@threlte/core';
import { OrbitControls } from '@threlte/extras';
import OrbitingSpheres from '$lib/components/scenes/home/OrbitingSpheres.svelte';
import { World } from '@threlte/rapier';
import { Inspector } from 'three-inspect';
import { dev } from '$app/environment';
import SpaceSkysphere from './SpaceSkysphere.svelte';
</script>
<Canvas>
<World gravity={[0, 0, 0]}>
<T.PerspectiveCamera position.y={15} position.z={25} makeDefault fov={70} far={10000}>
<OrbitControls
enableZoom={false}
enablePan={false}
enableRotate={false}
enableDamping
target.y={0}
autoRotate
/>
</T.PerspectiveCamera>
<SpaceSkysphere size={100} count={500} />
<OrbitingSpheres position={[0, 0, 0]} range={10} />
</World>
{#if dev}
<Inspector />
{/if}
</Canvas>

View File

@ -1,86 +0,0 @@
<script lang="ts" context="module">
const geometry = new SphereGeometry(1, 8, 4);
const material = new MeshBasicMaterial({ color: '#339933' });
</script>
<script lang="ts">
import { T } from '@threlte/core';
import { HTML } from '@threlte/extras';
import { Attractor, Collider, RigidBody } from '@threlte/rapier';
import { MeshBasicMaterial, SphereGeometry, Vector3 } from 'three';
export let range: number = 10;
export let position: [number, number, number] = [0, 0, 0];
let isHovering = false;
let isPointerDown = false;
const bodyPositions = [
new Vector3(position[0] - range, position[0] - range, position[0] - range).toArray(),
new Vector3(position[1] + range / 2, position[1] + range, position[1] + range).toArray(),
new Vector3(position[2] + range, position[2] - range / 2, position[2] + range).toArray()
];
const getId = () => {
return Math.random().toString(16).slice(2);
};
const getRandomSize = (): number => {
return Math.random() / 4 + 0.25;
};
const generateBodies = (c: number) => {
return Array(c)
.fill('x')
.map((_, index) => {
return {
id: getId(),
position: bodyPositions[index],
size: getRandomSize()
};
});
};
const onClick = () => {
console.log('clicked');
};
$: bodies = generateBodies(2);
</script>
<HTML position.x={position[0]} position.y={position[1]} position.z={position[2]}>
<button
on:pointerenter={() => (isHovering = true)}
on:pointerleave={() => {
isPointerDown = false;
isHovering = false;
}}
on:pointerdown={() => (isPointerDown = true)}
on:pointerup={() => (isPointerDown = false)}
on:pointercancel={() => {
isPointerDown = false;
isHovering = false;
}}
on:click={onClick}
class="rounded-full bg-orange-500 px-3 text-white hover:opacity-90 active:opacity-70"
>
Hello!
</button>
</HTML>
<Attractor
position.x={position[0]}
position.y={position[1]}
position.z={position[2]}
range={200}
strength={isHovering ? 1 : 0.1}
gravityType={'linear'}
/>
{#each bodies as body (body.id)}
<T.Group position={body.position}>
<RigidBody>
<Collider shape="ball" args={[body.size]} mass={body.size} />
<Attractor range={50} strength={1} gravityType={'newtonian'} />
<T.Mesh scale={[body.size, body.size, body.size]} {geometry} {material} />
</RigidBody>
</T.Group>
{/each}

View File

@ -0,0 +1,63 @@
<script context="module">
import { tick } from 'svelte';
/**
* Usage: <div use:portal={'css selector'}> or <div use:portal={document.body}>
*
* @param {HTMLElement} el
* @param {HTMLElement|string} target DOM Element or CSS Selector
*/
export function portal(el, target = 'body') {
let targetEl;
/**
* @param {string | HTMLElement} newTarget
*/
async function update(newTarget) {
target = newTarget;
if (typeof target === 'string') {
targetEl = document.querySelector(target);
if (targetEl === null) {
await tick();
targetEl = document.querySelector(target);
}
if (targetEl === null) {
throw new Error(`No element found matching css selector: "${target}"`);
}
} else if (target instanceof HTMLElement) {
targetEl = target;
} else {
throw new TypeError(
`Unknown portal target type: ${
target === null ? 'null' : typeof target
}. Allowed types: string (CSS selector) or HTMLElement.`
);
}
targetEl.appendChild(el);
el.hidden = false;
}
function destroy() {
if (el.parentNode) {
el.parentNode.removeChild(el);
}
}
update(target);
return {
update,
destroy
};
}
</script>
<script>
/**
* DOM Element or CSS Selector
* @type { HTMLElement|string}
*/
export let target = 'body';
</script>
<div use:portal={target} hidden style="display: contents;">
<slot />
</div>

80
src/lib/utils/index.ts Normal file
View File

@ -0,0 +1,80 @@
export interface Metadata {
title: string;
date: string;
content: string;
categories?: string[];
section?: SectionKey;
}
export interface Section {
poetry: 'poetry';
thoughts: 'thoughts';
projects: 'projects';
}
type SectionKey = keyof Section;
export interface Post {
meta: Metadata;
path: string;
}
interface Data {
metadata: Metadata;
}
function isData(obj: unknown): obj is Data {
if (typeof obj !== 'object' || obj === null) {
return false;
}
const dataObj = obj as Data;
return (
'metadata' in dataObj &&
typeof dataObj.metadata.title === 'string' &&
typeof dataObj.metadata.date === 'string'
);
}
export const fetchMarkdownPosts = async (
section: SectionKey,
limit: number,
offset: number
): Promise<Post[]> => {
let posts: Record<string, () => Promise<unknown>>;
switch (section) {
case 'poetry':
posts = import.meta.glob('/src/posts/poetry/*.md');
break;
case 'projects':
posts = import.meta.glob('/src/routes/(app)/projects/posts/*.md');
break;
case 'thoughts':
posts = import.meta.glob('/src/routes/(app)/thoughts/posts/*.md');
break;
default:
throw new Error('Could not find this section');
}
const iterablePostFiles = Object.entries(posts);
const allPosts = await Promise.all(
iterablePostFiles.map(async ([path, resolver]) => {
const data = await resolver();
if (isData(data)) {
const { metadata } = data;
const postPath = path.slice(11, -3);
return {
meta: { ...metadata, section: section },
path: postPath
};
} else {
throw new Error('Could not properly parse this post');
}
})
);
const paginatedPosts = allPosts.slice(offset, offset + limit);
return paginatedPosts;
};

View File

@ -0,0 +1,35 @@
---
categories:
- Poetry
date: 2014-11-10 00:00:00 +0000
tags:
- Fall
title: Autumn Synesthesia
---
The trees branch out their reds and yellows.
Their last battle cry before the frost.
The further north, the more pronounced
As they recall the life they lost.
Shouting in color upon deaf ears,
Such beauty produced at a deadly cost.
The reds rage on
With blistering hate.
"Is there no escape
From our inevitable fate?"
The orange reminisce
On the seasons before.
"Winter is knocking,
But Spring is next door."
The yellows enjoy
The weather while it lasts.
"Best to live in the present
Than the future or past."
The browns mutter softly
The last lesson to learn.
"From dust I arose,
So to dust I return."

View File

@ -0,0 +1,31 @@
---
categories:
- Poetry
date: 2014-05-20 00:00:00 +0000
tags:
- Humor
- Muffins
- Love
- Relationships
title: Breakfast Blue Pt. 2
---
Oh, my good friend, I didn't mean to leave.
It wasn't your fault, so no longer grieve!
If I could, I would run back to your side.
But, alas, a lack of legs slows my stride.
It's been over a year since I've last seen
Your serious face and Chartwell's cuisine.
Often I think this is for the better
\'Til I shed tears as I read your letter.
Fake tears, that is, for I also lack eyes.
In fact, let me unveil my disguise:
I'm an object lacking animation,
Given life through personification.
What words can I say to help you move on
And accept the fact that I am now gone?
Know that I too will miss your sweet lovin'
For I'll always be your chocolate muffin.

View File

@ -0,0 +1,29 @@
---
categories:
- Poetry
date: 2013-01-10 00:00:00 +0000
tags:
- Humor
- Muffins
title: Breakfast Blues
---
Lost my reason to wake in the morning
Ever since you left me without warning.
We've always seemed to have gotten along
Now I'm wondering if I did you wrong.
Lost my reason to give you thanks and praise.
Each day that passes passes in a daze.
The life I live is a life of decay.
My happiness happens to never stay.
I would have treated you so much better,
Or perhaps branded a scarlet letter
Across my chest and openly confess
That I'm impressed by a snack I love best.
Oh chocolate muffin, why'd you have to leave?
I've learned not to wear my heart on my sleeve.
Instead my love will always be suppressed
As I keep it locked in a chocolate chest.

20
src/posts/poetry/djinn.md Normal file
View File

@ -0,0 +1,20 @@
---
categories:
- Poetry
date: 2019-03-06 12:00:00 +0000
tags:
- Christian
title: Djinn
year: 2019
---
"Jesus dropped by."
My roommate remarked.
"He told me to tell you
His phone fell apart."
I let out a chuckle
And a sigh of relief.
"He didn't holy ghost us
Despite such unbelief."

View File

@ -0,0 +1,25 @@
---
categories:
- Poetry
date: 2018-04-28 12:00:00 +0000
tags:
- Wisdom
- Lessons
title: I've Seen
year: 2018
---
I've seen tears fall
From the face of a giant,
A hint of desperation
In the pleas of a king,
An attempt to forgive
The guilt-tripping violent,
Their genuine surprise
That neither learned a thing.
The wishes of a mother
Remain whispers in the wind,
And the riches of the world
In the words of humbled men.

View File

@ -0,0 +1,43 @@
---
categories:
- Poetry
date: 2019-02-02 12:00:00 +0000
tags:
- Love
- Lovers
- Relationships
- Introspective
title: Infrared Homing
---
In a moment
Of relapse,
A desire
For love
Arose.
I gave my heartstrings
To a girl
To knit a warmer
Set of clothes.
I was hoping
For a sweater,
But instead,
Received her mask.
She thanked me kindly
For the coat
And I knew
I shouldn't ask.
Was it
Seasonal depression
That left me seeking
Out a sun?
A candle
Can't replace it,
But any fire
Is better than none.

View File

@ -0,0 +1,31 @@
---
categories:
- Poetry
date: 2020-10-01 20:00:00 +0000
tags:
- Neuroscience
- Wisdom
title: Judge Judy
---
With each passing moment,
A court case is held
For our mind to determine
Which actions to compel.
86 billion neurons
Take up the jury seats
And fire off responses
'Til a majority agrees.
"Your Honor, you don't exist,
But as an emergent behavior;
Yet still we reached a verdict
That should work in our favor."
The neurons are dismissed
Then return to jury duty
For another microcosm case
In their show of Judge Judy.

View File

@ -0,0 +1,27 @@
---
categories:
- Poetry
date: 2018-06-25 20:00:00 +0000
tags:
- Chess
- Lessons
title: King's Pin
year: 2018
---
You placed my king
In a surprising check
To ensure Im kept
On the tip of my toes.
Only a few
Of our pieces are left,
And each one of my moves
Are presupposed.
Unbeknownst,
Synonymous to beginner.
A satisfying poach
Awarded to the winner.

View File

@ -0,0 +1,36 @@
---
categories:
- Poetry
date: 2014-10-27 00:00:00 +0000
tags:
- Humor
title: Klepto Couches
---
My home houses countless couches.
Klepto-couches with pickpocket pouches
That swiftly swipe your cellular phone
Between the cushions of their comfy unknown.
Then your change jingles and jangles
Until they're untangled
From your Wrangler jeans pocket
As you wonder where your socks went.
But your socks and shoes
Were swept under your feet
Right under your nose.
So discreet are these deceitful seats
As they watch you search
For the keys they stole.
At last your quest
Leads you straight to the crook.
"I should have guessed
The klepto-couches had took!"
But still your lesson
Has yet to be learned.
These klepto-couches
Deserve to be burned.

View File

@ -0,0 +1,33 @@
---
categories:
- Poetry
date: 2012-02-25 00:00:00 +0000
tags:
- Grounds
- Covenant
title: Leafblower
---
You're the girl sitting on the park bench.
I'm the guy with a leaf blower.
I've gotta do my job,
So would you kindly please move over?
I'm walking right towards you,
So don't say you didn't notice me.
I'd like to get off work soon,
So I'll give you until the count of three.
One
Two
...
Alright, so you've called my bluff.
I'm not really going to do anything.
I just wanted to look real tough,
But this little bee ain't got no sting.
I'll just tell my boss that I missed a spot,
And I'll explain my sad situation.
Then we'll both laugh at the thought
Of me writing poetry about my frustration.

View File

@ -0,0 +1,52 @@
---
categories:
- Poetry
date: 2019-10-26 12:00:00 +0000
tags:
- Wisdom
title: Of Molecules And Men
---
May we lose
All language
That we may see
As it is
And not
As we think,
For cells
Arose
From division
To divide
And conquer
Molecules
And men.
From the
Prokaryote
To the
Proletariat
A conflict
Ensues.
You're so sure
That you're full
Of yourself
As your cells
Dismantle
All that's
Consumed.
We break to build
Each building block
Into a likeness
Worth worshipping to.
To be at peace
Is to decompose.
To cease to be
Is to become
Every friend
And alleged foe.

View File

@ -0,0 +1,35 @@
---
categories:
- Poetry
date: 2012-03-01 00:00:00 +0000
tags:
- Grounds
- Covenant
title: Monday Morning Shift
---
These plants look beautiful, but not at this location.
They must be eradicated according to administration.
I brought out my tools; Some gloves and a spade,
Then sat down, Indian style, to begin the raid.
The roots, like little fingers, held on to dear life
As I cut through their homes with an oddly-shaped knife.
To justify these cruel killings
I thought of what they've done:
Suffocated the superior plants
And blocked out the lovely sun.
But what makes one plant superior and the other inferior?
Just the fact that the other has a beautiful exterior?
They are simply trying their best to make a living.
We must see past our differences and be more forgiving.
But these thoughts lead down to a dangerous road;
Let's not personify each seed we've sowed.
The sun now rises and heats the ground.
The ice embedded within melts all around,
And now a nice wet spot on my pants is found
Which leaves me thinking of thoughts more profound:
"I really hope no one's looking at me right now."

View File

@ -0,0 +1,27 @@
---
categories:
- Poetry
date: 2016-05-10 00:00:00 +0000
tags:
- Work
- Worry
- Self-conscious
title: Morning Commute
---
A few minutes into my morning commute
I had forgotten we can all read minds.
So my thought faucet ran up my brain bill
Spewing a membraneous mess inside.
I didnt notice til I parked the car
And smelled the fumes from under the hood.
I frantically thought of cats and cookies
To clean up the mess, but it did no good.
So I ditched the car and snuck into work,
Though I knew my hopes and dreams would be seen
Swirled amidst my self-doubt and worries
Like creamer mixed in bitter cups of caffeine.

View File

@ -0,0 +1,36 @@
---
categories:
- Poetry
date: 2015-07-15 00:00:00 +0000
tags:
- Relationships
- Love
- Drinking
- Humor
title: Perfect Situation
---
When I'm hammered,
I'm left enamored
And content
With the Fate
Lady luck's prescribed.
Though we never
Will land together,
We're fledglings
With new wings
To take to the sky.
I ponder your passion
To pursue aspirations
And wonder what magic
You'll perform upon nations
And I speculate the odds
Given a perfect situation
In a parallel universe
If I'd rise to the occasion.

View File

@ -0,0 +1,27 @@
---
categories:
- Poetry
date: 2016-12-20 00:00:00 +0000
tags:
- Introspective
- Silence
title: Silent Silas
---
The windows to my soul
Tend to have their blinds up,
And I leave the door locked tight
By keeping my own mouth shut
So my apologies if it's frustrating
That I'm so cold and calculating.
It's my modus operandi;
You can't spell "Silent" without Si.
But if it's any consolation,
I am striving to get better
At voicing my own thoughts
Without resorting to writing letters.

View File

@ -0,0 +1,18 @@
---
categories:
- Poetry
date: 2014-07-20 00:00:00 +0000
tags:
- Love
- Relationships
- Realtalk
title: Thought Experiment
---
Love is a free fall
And I'm afraid of the ground.
If I jump and no one's there,
Will my body make a sound?

View File

@ -0,0 +1,32 @@
---
categories:
- Poetry
date: 2017-10-10 00:00:00 +0000
tags:
- Wisdom
- Speech
- Verbal Abuse
title: Unintentional Internalization
---
Our skin's as thick
As our words are sharp
To dampen the damage
We take to heart.
But sometimes they pierce
Right through our defenses,
Despite whether the offender
Had the best of intentions.
It's a wound that lingers
And leads to a scar
Once committed to memory
(Which shapes who you are).
For each one we've endured,
We've dealt so many more
For the most innocuous remark
Still can pierce like a sword.

View File

@ -0,0 +1,33 @@
---
categories:
- Poetry
date: 2013-05-10 00:00:00 +0000
tags:
- Realtalk
title: Who Am I?
---
Am I the clothes on my back
And the hair on my head?
Am I the people I'm with
And the words I've said?
Am I the field I study
And the school I attend?
Am I the programs I write
And the poems I've penned?
Am I the music I enjoy
And the guitar I play?
Am I the grade on my test
And my ten page essay?
Am I the habits I've formed
And the phrases I repeat?
Am I the fake smile given
To every person I meet?
Am I the religion I follow
And the politician I elect?
Am I every action I carry out
And every thought I reflect?

View File

@ -0,0 +1,7 @@
<script lang="ts">
import App from '$lib/components/scenes/app/App.svelte';
</script>
<App>
<slot />
</App>

View File

@ -0,0 +1,23 @@
<script lang="ts">
import MenuItem from '$lib/components/scenes/app/MenuItem.svelte';
</script>
<MenuItem position={[-2.5, 7.5, 0]} htmlContent="Poetry" href="/poetry" />
<MenuItem
position={[2.5, 2.5, -2.5]}
htmlContent="Projects"
clickHandler={() => console.log('clicked!')}
/>
<MenuItem
position={[-2.5, -2.5, -2.5]}
htmlContent="Thoughts"
clickHandler={() => console.log('clicked!')}
/>
<MenuItem
position={[2.5, -7.5, 2.5]}
htmlContent="About"
clickHandler={() => console.log('clicked!')}
/>

View File

@ -0,0 +1,39 @@
<script lang="ts">
import MenuItem from '$lib/components/scenes/app/MenuItem.svelte';
import type { PageData } from './$types';
export let data: PageData;
const xMin = -2.5,
xMax = 2.5;
const yMin = -7.5,
yMax = 7.5;
const zMin = -2.5,
zMax = 2.5;
// Calculate positions
const calculatePositions = (numPosts: number): Array<[number, number, number]> => {
const positions: Array<[number, number, number]> = [];
const numRows = Math.ceil(Math.sqrt(numPosts));
const numCols = Math.ceil(numPosts / numRows);
for (let i = 0; i < numPosts; i++) {
const row = Math.floor(i / numCols);
const col = i % numCols;
const x = xMin + (xMax - xMin) * (col / (numCols - 1));
const y = yMin + (yMax - yMin) * (row / (numRows - 1));
const z = zMin;
positions.push([x, y, z]);
}
return positions;
};
// Generate positions based on the number of posts
const positions = calculatePositions(data.posts.length);
</script>
{#each data.posts as post, i}
<MenuItem position={positions[i]} htmlContent={post.meta.title} href={post.path} />
{/each}

View File

@ -0,0 +1,8 @@
export const load = async ({ fetch }) => {
const response = await fetch(`/api/poetry?limit=5&offset=0`);
const posts = await response.json();
return {
posts
};
};

View File

@ -0,0 +1,19 @@
<script lang="ts">
import MenuItem from '$lib/components/scenes/app/MenuItem.svelte';
import type { PageData } from './$types';
import DomPortal from '$lib/utils/DomPortal.svelte';
export let data: PageData;
const { title, date: _date, Content, categories: _ } = data;
</script>
<MenuItem position={[-2.5, 10, 0]} htmlContent="Back" href="/poetry" />
<DomPortal target="#overlay">
<div class="py-4">
<h1 class="text-xl font-medium text-black pb-2">{title}</h1>
<div>
<Content />
</div>
</div>
</DomPortal>

View File

@ -0,0 +1,18 @@
import type { Metadata } from '$lib/utils/index.js';
export async function load({ params }) {
const post = await import(`../../../../posts/poetry/${params.slug}.md`);
const { title, date, categories } = post.metadata as Metadata;
const Content = post.default;
const parsedDate = new Date(date.slice(0, date.length - 6));
const validDate = `${
parsedDate.getMonth() + 1
}/${parsedDate.getDate()}/${parsedDate.getFullYear()}`;
return {
Content,
title,
date: validDate,
categories
};
}

View File

@ -1,5 +1,38 @@
<script> <script lang="ts">
import "../app.css"; import CanvasContainer from '$lib/components/scenes/app/CanvasContainer.svelte';
import '../app.css';
</script> </script>
<slot /> <CanvasContainer>
<slot />
</CanvasContainer>
<div class="overlay container" id="overlay"></div>
<style>
:global(body) {
margin: 0;
}
.canvas {
width: 100%;
height: 100%;
background: rgb(0, 36, 6);
background: linear-gradient(180deg, rgba(0, 36, 6, 1) 0%, rgba(0, 0, 0, 1) 100%);
position: absolute;
justify-content: center;
align-items: center;
}
.overlay {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(16, 56, 30, 0.9);
}
</style>

View File

@ -1,28 +0,0 @@
<script lang="ts">
import Home from '$lib/components/scenes/home/Home.svelte';
import type { PageData } from './$types';
export let data: PageData;
</script>
<div>
{#each data.models as model}
<span>{model.title}</span>
{/each}
<Home />
</div>
<style>
:global(body) {
margin: 0;
}
div {
width: 100vw;
height: 100vh;
background: rgb(0, 36, 6);
background: linear-gradient(180deg, rgba(0, 36, 6, 1) 0%, rgba(0, 0, 0, 1) 100%);
display: absolute;
justify-content: center;
align-items: center;
}
</style>

View File

@ -1,15 +0,0 @@
const models: Model[] = [
{ title: 'Model 1' },
{ title: 'Model 2' },
{ title: 'Model 3' }
];
export type Model = { title: string}
export function load(): { models: Model[] } {
return {
models: models.map((model) => ({
title: model.title
}))
};
}

View File

@ -0,0 +1,14 @@
import { fetchMarkdownPosts } from '$lib/utils';
import { json } from '@sveltejs/kit';
export const GET = async ({ url }) => {
const limit = Number(url.searchParams.get('limit')) || 6;
const offset = Number(url.searchParams.get('offset')) || 0;
const allPosts = await fetchMarkdownPosts('poetry', limit, offset);
const sortedPosts = allPosts.sort((a, b) => {
return new Date(b.meta.date).getTime() - new Date(a.meta.date).getTime();
});
return json(sortedPosts);
};

View File

@ -1,18 +1,20 @@
import adapter from '@sveltejs/adapter-auto'; import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import { mdsvex } from 'mdsvex';
/** @type {import('@sveltejs/kit').Config} */ /** @type {import('@sveltejs/kit').Config} */
const config = { const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors // Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors // for more information about preprocessors
preprocess: vitePreprocess(), preprocess: [vitePreprocess(), mdsvex({ extensions: ['.md'] })],
kit: { kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter. // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters. // See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter() adapter: adapter()
} },
extensions: ['.svelte', '.md']
}; };
export default config; export default config;