the horrors

This commit is contained in:
Laker Turner 2025-03-17 12:49:54 +00:00
parent 0d9be3d002
commit 4245370f61
No known key found for this signature in database
48 changed files with 2513 additions and 265 deletions

10
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,10 @@
{
"files.associations": {
"src/styles/global.css": "tailwindcss"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
}
}

View file

@ -1,5 +1,13 @@
// @ts-check
import { defineConfig } from 'astro/config';
import tailwindcss from '@tailwindcss/vite';
// https://astro.build/config
export default defineConfig({});
export default defineConfig({
site: "https://ivyneeds.rest",
prefetch: true,
vite: {
plugins: [tailwindcss()]
}
});

View file

@ -6,9 +6,14 @@
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
"astro": "astro",
"test": "ava"
},
"dependencies": {
"astro": "^5.4.3"
"@tailwindcss/vite": "^4.0.13",
"astro": "^5.4.3",
"ava": "^6.2.0",
"luxon": "^3.5.0",
"tailwindcss": "^4.0.13"
}
}

1454
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
</svg>

Before

Width:  |  Height:  |  Size: 749 B

BIN
public/images/ivy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" width="115" height="48"><path fill="#17191E" d="M7.77 36.35C6.4 35.11 6 32.51 6.57 30.62c.99 1.2 2.35 1.57 3.75 1.78 2.18.33 4.31.2 6.33-.78.23-.12.44-.27.7-.42.18.55.23 1.1.17 1.67a4.56 4.56 0 0 1-1.94 3.23c-.43.32-.9.61-1.34.91-1.38.94-1.76 2.03-1.24 3.62l.05.17a3.63 3.63 0 0 1-1.6-1.38 3.87 3.87 0 0 1-.63-2.1c0-.37 0-.74-.05-1.1-.13-.9-.55-1.3-1.33-1.32a1.56 1.56 0 0 0-1.63 1.26c0 .06-.03.12-.05.2Z"/><path fill="url(#a)" d="M7.77 36.35C6.4 35.11 6 32.51 6.57 30.62c.99 1.2 2.35 1.57 3.75 1.78 2.18.33 4.31.2 6.33-.78.23-.12.44-.27.7-.42.18.55.23 1.1.17 1.67a4.56 4.56 0 0 1-1.94 3.23c-.43.32-.9.61-1.34.91-1.38.94-1.76 2.03-1.24 3.62l.05.17a3.63 3.63 0 0 1-1.6-1.38 3.87 3.87 0 0 1-.63-2.1c0-.37 0-.74-.05-1.1-.13-.9-.55-1.3-1.33-1.32a1.56 1.56 0 0 0-1.63 1.26c0 .06-.03.12-.05.2Z"/><path fill="#17191E" d="M.02 30.31s4.02-1.95 8.05-1.95l3.04-9.4c.11-.45.44-.76.82-.76.37 0 .7.31.82.76l3.04 9.4c4.77 0 8.05 1.95 8.05 1.95L17 11.71c-.2-.56-.53-.91-.98-.91H7.83c-.44 0-.76.35-.97.9L.02 30.31Zm42.37-5.97c0 1.64-2.05 2.62-4.88 2.62-1.85 0-2.5-.45-2.5-1.41 0-1 .8-1.49 2.65-1.49 1.67 0 3.09.03 4.73.23v.05Zm.03-2.04a21.37 21.37 0 0 0-4.37-.36c-5.32 0-7.82 1.25-7.82 4.18 0 3.04 1.71 4.2 5.68 4.2 3.35 0 5.63-.84 6.46-2.92h.14c-.03.5-.05 1-.05 1.4 0 1.07.18 1.16 1.06 1.16h4.15a16.9 16.9 0 0 1-.36-4c0-1.67.06-2.93.06-4.62 0-3.45-2.07-5.64-8.56-5.64-2.8 0-5.9.48-8.26 1.19.22.93.54 2.83.7 4.06 2.04-.96 4.95-1.37 7.2-1.37 3.11 0 3.97.71 3.97 2.15v.57Zm11.37 3c-.56.07-1.33.07-2.12.07-.83 0-1.6-.03-2.12-.1l-.02.58c0 2.85 1.87 4.52 8.45 4.52 6.2 0 8.2-1.64 8.2-4.55 0-2.74-1.33-4.09-7.2-4.39-4.58-.2-4.99-.7-4.99-1.28 0-.66.59-1 3.65-1 3.18 0 4.03.43 4.03 1.35v.2a46.13 46.13 0 0 1 4.24.03l.02-.55c0-3.36-2.8-4.46-8.2-4.46-6.08 0-8.13 1.49-8.13 4.39 0 2.6 1.64 4.23 7.48 4.48 4.3.14 4.77.62 4.77 1.28 0 .7-.7 1.03-3.71 1.03-3.47 0-4.35-.48-4.35-1.47v-.13Zm19.82-12.05a17.5 17.5 0 0 1-6.24 3.48c.03.84.03 2.4.03 3.24l1.5.02c-.02 1.63-.04 3.6-.04 4.9 0 3.04 1.6 5.32 6.58 5.32 2.1 0 3.5-.23 5.23-.6a43.77 43.77 0 0 1-.46-4.13c-1.03.34-2.34.53-3.78.53-2 0-2.82-.55-2.82-2.13 0-1.37 0-2.65.03-3.84 2.57.02 5.13.07 6.64.11-.02-1.18.03-2.9.1-4.04-2.2.04-4.65.07-6.68.07l.07-2.93h-.16Zm13.46 6.04a767.33 767.33 0 0 1 .07-3.18H82.6c.07 1.96.07 3.98.07 6.92 0 2.95-.03 4.99-.07 6.93h5.18c-.09-1.37-.11-3.68-.11-5.65 0-3.1 1.26-4 4.12-4 1.33 0 2.28.16 3.1.46.03-1.16.26-3.43.4-4.43-.86-.25-1.81-.41-2.96-.41-2.46-.03-4.26.98-5.1 3.38l-.17-.02Zm22.55 3.65c0 2.5-1.8 3.66-4.64 3.66-2.81 0-4.61-1.1-4.61-3.66s1.82-3.52 4.61-3.52c2.82 0 4.64 1.03 4.64 3.52Zm4.71-.11c0-4.96-3.87-7.18-9.35-7.18-5.5 0-9.23 2.22-9.23 7.18 0 4.94 3.49 7.59 9.21 7.59 5.77 0 9.37-2.65 9.37-7.6Z"/><defs><linearGradient id="a" x1="6.33" x2="19.43" y1="40.8" y2="34.6" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient></defs></svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1024" fill="none"><path fill="url(#a)" fill-rule="evenodd" d="M-217.58 475.75c91.82-72.02 225.52-29.38 341.2-44.74C240 415.56 372.33 315.14 466.77 384.9c102.9 76.02 44.74 246.76 90.31 366.31 29.83 78.24 90.48 136.14 129.48 210.23 57.92 109.99 169.67 208.23 155.9 331.77-13.52 121.26-103.42 264.33-224.23 281.37-141.96 20.03-232.72-220.96-374.06-196.99-151.7 25.73-172.68 330.24-325.85 315.72-128.6-12.2-110.9-230.73-128.15-358.76-12.16-90.14 65.87-176.25 44.1-264.57-26.42-107.2-167.12-163.46-176.72-273.45-10.15-116.29 33.01-248.75 124.87-320.79Z" clip-rule="evenodd" style="opacity:.154"/><path fill="url(#b)" fill-rule="evenodd" d="M1103.43 115.43c146.42-19.45 275.33-155.84 413.5-103.59 188.09 71.13 409 212.64 407.06 413.88-1.94 201.25-259.28 278.6-414.96 405.96-130 106.35-240.24 294.39-405.6 265.3-163.7-28.8-161.93-274.12-284.34-386.66-134.95-124.06-436-101.46-445.82-284.6-9.68-180.38 247.41-246.3 413.54-316.9 101.01-42.93 207.83 21.06 316.62 6.61Z" clip-rule="evenodd" style="opacity:.154"/><defs><linearGradient id="b" x1="373" x2="1995.44" y1="1100" y2="118.03" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient><linearGradient id="a" x1="107.37" x2="1130.66" y1="1993.35" y2="1026.31" gradientUnits="userSpaceOnUse"><stop stop-color="#3245FF"/><stop offset="1" stop-color="#BC52EE"/></linearGradient></defs></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -1,210 +0,0 @@
---
import astroLogo from '../assets/astro.svg';
import background from '../assets/background.svg';
---
<div id="container">
<img id="background" src={background.src} alt="" fetchpriority="high" />
<main>
<section id="hero">
<a href="https://astro.build"
><img src={astroLogo.src} width="115" height="48" alt="Astro Homepage" /></a
>
<h1>
To get started, open the <code><pre>src/pages</pre></code> directory in your project.
</h1>
<section id="links">
<a class="button" href="https://docs.astro.build">Read our docs</a>
<a href="https://astro.build/chat"
>Join our Discord <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"
><path
fill="currentColor"
d="M107.7 8.07A105.15 105.15 0 0 0 81.47 0a72.06 72.06 0 0 0-3.36 6.83 97.68 97.68 0 0 0-29.11 0A72.37 72.37 0 0 0 45.64 0a105.89 105.89 0 0 0-26.25 8.09C2.79 32.65-1.71 56.6.54 80.21a105.73 105.73 0 0 0 32.17 16.15 77.7 77.7 0 0 0 6.89-11.11 68.42 68.42 0 0 1-10.85-5.18c.91-.66 1.8-1.34 2.66-2a75.57 75.57 0 0 0 64.32 0c.87.71 1.76 1.39 2.66 2a68.68 68.68 0 0 1-10.87 5.19 77 77 0 0 0 6.89 11.1 105.25 105.25 0 0 0 32.19-16.14c2.64-27.38-4.51-51.11-18.9-72.15ZM42.45 65.69C36.18 65.69 31 60 31 53s5-12.74 11.43-12.74S54 46 53.89 53s-5.05 12.69-11.44 12.69Zm42.24 0C78.41 65.69 73.25 60 73.25 53s5-12.74 11.44-12.74S96.23 46 96.12 53s-5.04 12.69-11.43 12.69Z"
></path></svg
>
</a>
</section>
</section>
</main>
<a href="https://astro.build/blog/astro-5/" id="news" class="box">
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg"
><path
d="M24.667 12c1.333 1.414 2 3.192 2 5.334 0 4.62-4.934 5.7-7.334 12C18.444 28.567 18 27.456 18 26c0-4.642 6.667-7.053 6.667-14Zm-5.334-5.333c1.6 1.65 2.4 3.43 2.4 5.333 0 6.602-8.06 7.59-6.4 17.334C13.111 27.787 12 25.564 12 22.666c0-4.434 7.333-8 7.333-16Zm-6-5.333C15.111 3.555 16 5.556 16 7.333c0 8.333-11.333 10.962-5.333 22-3.488-.774-6-4-6-8 0-8.667 8.666-10 8.666-20Z"
fill="#111827"></path></svg
>
<h2>What's New in Astro 5.0?</h2>
<p>
From content layers to server islands, click to learn more about the new features and
improvements in Astro 5.0
</p>
</a>
</div>
<style>
#background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
filter: blur(100px);
}
#container {
font-family: Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif;
height: 100%;
}
main {
height: 100%;
display: flex;
justify-content: center;
}
#hero {
display: flex;
align-items: start;
flex-direction: column;
justify-content: center;
padding: 16px;
}
h1 {
font-size: 22px;
margin-top: 0.25em;
}
#links {
display: flex;
gap: 16px;
}
#links a {
display: flex;
align-items: center;
padding: 10px 12px;
color: #111827;
text-decoration: none;
transition: color 0.2s;
}
#links a:hover {
color: rgb(78, 80, 86);
}
#links a svg {
height: 1em;
margin-left: 8px;
}
#links a.button {
color: white;
background: linear-gradient(83.21deg, #3245ff 0%, #bc52ee 100%);
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, 0.12),
inset 0 -2px 0 rgba(0, 0, 0, 0.24);
border-radius: 10px;
}
#links a.button:hover {
color: rgb(230, 230, 230);
box-shadow: none;
}
pre {
font-family:
ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono',
monospace;
font-weight: normal;
background: linear-gradient(14deg, #d83333 0%, #f041ff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin: 0;
}
h2 {
margin: 0 0 1em;
font-weight: normal;
color: #111827;
font-size: 20px;
}
p {
color: #4b5563;
font-size: 16px;
line-height: 24px;
letter-spacing: -0.006em;
margin: 0;
}
code {
display: inline-block;
background:
linear-gradient(66.77deg, #f3cddd 0%, #f5cee7 100%) padding-box,
linear-gradient(155deg, #d83333 0%, #f041ff 18%, #f5cee7 45%) border-box;
border-radius: 8px;
border: 1px solid transparent;
padding: 6px 8px;
}
.box {
padding: 16px;
background: rgba(255, 255, 255, 1);
border-radius: 16px;
border: 1px solid white;
}
#news {
position: absolute;
bottom: 16px;
right: 16px;
max-width: 300px;
text-decoration: none;
transition: background 0.2s;
backdrop-filter: blur(50px);
}
#news:hover {
background: rgba(255, 255, 255, 0.55);
}
@media screen and (max-height: 368px) {
#news {
display: none;
}
}
@media screen and (max-width: 768px) {
#container {
display: flex;
flex-direction: column;
}
#hero {
display: block;
padding-top: 10%;
}
#links {
flex-wrap: wrap;
}
#links a.button {
padding: 14px 18px;
}
#news {
right: 16px;
left: 16px;
bottom: 2.5rem;
max-width: 100%;
}
h1 {
line-height: 1.5;
}
}
</style>

View file

@ -0,0 +1,48 @@
---
import Date from "~/components/util/Date.astro";
import { getCollection } from "astro:content";
import { getPublishedAndSortedPosts } from "~/lib/blog";
interface Props {
collection: string;
limit?: number;
}
const { collection, limit } = Astro.props;
const items = getPublishedAndSortedPosts(await getCollection(collection));
const limitedItems = limit ? items.slice(0, limit) : items;
const getPostIcon = (item: { data: { icon?: string } }) => {
if (item.data.icon && item.data.icon !== "fa-solid fa-blog") {
return item.data.icon;
}
return "fa-solid fa-arrow-right";
};
---
<ul class="fa-ul space-y-4 my-2">
{
limitedItems.map((item) => (
<li>
<i class={`fa-li ${getPostIcon(item)}`} />
<a href={`/${collection}/${item.id}`}>
<h3 class="font-bold mb-0.5">{item.data.title}</h3>
</a>
<p class="text-sm text-light-tx-2 dark:text-dark-tx-2">
<i class="fa-solid fa-calendar-alt mr-1 text-light-pu dark:text-dark-pu" />
<Date date={item.data.date} />
<i class="fa-solid fa-tags mx-1 text-light-pu dark:text-dark-pu" />
{(item.data.tags ?? []).map((tag) => (
<a class="bg-light-pu dark:bg-dark-pu text-white px-1 py-0.5 rounded-md" href={`/${collection}/tags/${tag}`}>{tag}</a>
))}
</p>
<blockquote class="border-l-2 border-light-pu dark:border-dark-pu pl-4 mt-2 text-light-tx-2 dark:text-dark-tx-2">
{item.data.description}
</blockquote>
</li>
))
}
</ul>

View file

@ -0,0 +1,38 @@
---
import { getCollection } from "astro:content";
import { getPublishedAndSortedNotes } from "~/lib/blog";
import Date from "~/components/util/Date.astro";
import { render } from "astro:content";
interface Props {
limit?: number;
}
const { limit } = Astro.props;
const items = getPublishedAndSortedNotes(await getCollection("notes"));
const limitedItems = limit ? items.slice(0, limit) : items;
// Render all note contents
const renderedItems = await Promise.all(
limitedItems.map(async (item) => {
const { Content } = await render(item);
return { ...item, Content };
})
);
---
<ul class="fa-ul space-y-4 my-2">
{
renderedItems.map((item) => (
<li>
<i class={`fa-li ${item.data.icon}`} />
<a href={`/notes/${item.id}`}>
<Date date={item.data.date} />
</a>
<div>
<item.Content />
</div>
</li>
))
}
</ul>

View file

@ -0,0 +1,45 @@
---
import Date from "~/components/util/Date.astro";
import { getCollection } from "astro:content";
interface Props {
limit?: number;
}
const { limit } = Astro.props;
const items = await getCollection("projects");
const limitedItems = limit ? items.slice(0, limit) : items;
---
<ul class="fa-ul space-y-4 my-2">
{
limitedItems.map((item) => (
<li>
<i class={`fa-li ${item.data.icon}`} />
<a href={`/projects/${item.id}`}>
<h3 class="font-bold mb-0.5">{item.data.name}</h3>
</a>
<p class="text-sm text-light-tx-2 dark:text-dark-tx-2">
<i class="fa-solid fa-calendar-alt mr-1 text-light-pu dark:text-dark-pu" />
<Date date={item.data.date} />
<i class="fa-solid fa-tags mx-1 text-light-pu dark:text-dark-pu" />
{(item.data.tags ?? []).map((tag) => (
<a
class="bg-light-pu dark:bg-dark-pu text-white px-1 py-0.5 rounded-md"
href={`/${collection}/tags/${tag}`}
>
{tag}
</a>
))}
</p>
<blockquote class="border-l-2 border-light-pu dark:border-dark-pu pl-4 mt-2 text-light-tx-2 dark:text-dark-tx-2">
{item.data.description}
</blockquote>
</li>
))
}
</ul>

View file

@ -0,0 +1,20 @@
---
interface Props {
title?: string;
description?: string;
icon?: string;
}
const { title, description, icon } = Astro.props;
---
<div
class="border-3 border-light-pu dark:border-dark-pu px-4 py-3 mt-5 w-fit"
>
<span class="mb-1">
{icon && <i class={`fa-lg mr-1 ${icon}`} />}
{title && <span class="text-lg font-bold">{title}</span>}
{description && <span class="text-sm text-gray-500">{description}</span>}
</span>
<slot />
</div>

View file

@ -0,0 +1,14 @@
---
---
<footer class="mt-12 text-sm text-light-tx-2 dark:text-dark-tx-2">
<p>© {new Date().getFullYear()} Ivy Turner</p>
<p>
<a class="underline" href="https://github.com/ivyturner">github</a> ~
<a class="underline" href="https://github.com/ivyturner/trellis">
ivyturner/trellis
</a>
</p>
<p>love yourself.</p>
</footer>

View file

@ -0,0 +1,40 @@
---
import siteConfig from "~/site.config";
import { descriptionConstructor, titleConstructor } from "~/lib/metadata";
const { title, description } = Astro.props;
---
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{titleConstructor(title)}</title>
<meta name="description" content={descriptionConstructor(description)} />
<meta name="author" content="Ivy Turner" />
{/* og */}
<meta property="og:title" content={titleConstructor(title)} />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://ivyneeds.rest" />
<meta property="og:image" content="https://ivyneeds.rest/image.jpg" />
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta name="theme-color" content="#5E409D" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
{/* font awesone */}
<link
href="https://cdn.laker.tech/web/fa/css/fontawesome.css"
rel="stylesheet"
/>
<link href="https://cdn.laker.tech/web/fa/css/brands.css" rel="stylesheet" />
<link href="https://cdn.laker.tech/web/fa/css/solid.css" rel="stylesheet" />
{/* analytics */}
{/* astro generator */}
<meta name="generator" content={Astro.generator} />
</head>

View file

@ -0,0 +1,34 @@
---
import Navigation from "./Navigation.astro";
import conf from "~/site.config";
let headertext = conf.siteName;
let headerurl = "/";
let headerarrow = false;
function isBlog() {
return Astro.url.pathname.startsWith("/blog");
}
if (isBlog()) {
headertext = "Everything And The Girl";
headerurl = "/blog";
headerarrow = true;
}
---
<header class="md:flex md:justify-between md:items-center mb-4">
<h1 class="text-2xl font-bold">
{
headerarrow && (
<span class="mr-2">
<a href="/">
<i class="fa-solid fa-arrow-left text-light-pu dark:text-dark-pu" />
</a>
</span>
)
}
<a href={headerurl}>{headertext}</a>
</h1>
<Navigation />
</header>

View file

@ -0,0 +1,51 @@
---
const headerLinks = [
{
label: "About",
href: "/about",
icon: "fa-solid fa-user", // font awesome css class
},
{
label: "Projects",
href: "/projects",
icon: "fa-solid fa-folder",
},
{
label: "Notes",
href: "/notes",
icon: "fa-solid fa-sticky-note",
},
{
label: "Blog",
href: "/blog",
icon: "fa-solid fa-blog",
},
{
label: "Contact",
href: "/contact",
icon: "fa-solid fa-envelope",
},
{
label: "More",
href: "/more",
icon: "fa-solid fa-ellipsis",
},
];
---
<nav class="flex flex-row gap-4">
{
headerLinks.map((link) => (
<span>
<i class={`${link.icon} mr-0.5 text-sm`} />
<a
href={link.href}
class="underline decoration-wavy underline-offset-4 decoration-1.5
decoration-light-pu dark:decoration-dark-pu"
>
{link.label}
</a>
</span>
))
}
</nav>

View file

@ -0,0 +1,3 @@
<div class="bg-light-ye dark:bg-dark-ye sm:block md:hidden text-black">
<p>This view port may be too small.</p> <p>Try ivyneeds.rest on a bigger screen.</p>
</div>

View file

@ -0,0 +1,24 @@
---
import Date from "../util/Date.astro";
const { title, description, icon, date } = Astro.props;
---
<div class="mb-4">
<h2 class="text-xl font-bold">
<i class={`${icon} text-xl mr-2 text-light-pu dark:text-dark-pu`}></i>
{title}
</h2>
<p class="mt-2 text-sm text-light-tx-2 dark:text-dark-tx-2">{description}</p>
{
() => {
if (date) {
return (
<p class="mt-2 text-sm text-light-tx-2 dark:text-dark-tx-2">
last updated: <Date date={date} />
</p>
);
}
}
}
</div>

View file

@ -0,0 +1,17 @@
---
export interface Props {
date: string | Date;
}
const { date } = Astro.props;
if (!date) {
return null;
}
const dateObj = typeof date === "string" ? new Date(date) : date;
const options = { year: "numeric", month: "long", day: "numeric" };
const formattedDate = dateObj.toLocaleDateString("en-GB", options);
const isoDate = dateObj.toISOString();
---
<time datetime={isoDate}>{formattedDate}</time>

View file

@ -0,0 +1,12 @@
---
const { href, icon = "fa-solid fa-arrow-right" } = Astro.props;
---
<ul class="fa-ul mb-2">
<li>
<a href={href} class="link">
<i class={`fa-li ${icon}`} />
<slot />
</a>
</li>
</ul>

53
src/content.config.ts Normal file
View file

@ -0,0 +1,53 @@
// 1. Import utilities from `astro:content`
import { defineCollection, z } from "astro:content";
// 2. Import loader(s)
import { glob } from "astro/loaders";
// 3. Define your collection(s)
const blog = defineCollection({
loader: glob({ pattern: "*.md", base: "src/content/blog" }),
schema: z.object({
title: z.string(),
description: z.string(),
date: z.date().default(new Date()),
tags: z.array(z.string()).optional(),
draft: z.boolean().default(false),
icon: z.string().optional().default("fa-solid fa-blog"),
image: z
.object({
src: z.string(),
alt: z.string(),
})
.optional(),
}),
});
const notes = defineCollection({
loader: glob({ pattern: "*.md", base: "src/content/notes" }),
schema: z.object({
title: z.string().optional(),
exturl: z.string().url().optional(),
date: z.date(),
tags: z.array(z.string()).optional(),
icon: z.string().optional().default("fa-solid fa-sticky-note"),
draft: z.boolean().default(false),
}),
});
const projects = defineCollection({
loader: glob({ pattern: "*.md", base: "src/content/projects" }),
schema: z.object({
name: z.string(),
description: z.string(),
date: z.date(),
url: z.string().url().optional(), // homepage
repo: z.string().url().optional(), // git{hub,.sr.ht} link
status: z.enum(["active", "finished", "backburner", "scrapped"]),
version: z.string(),
icon: z.string().optional().default("fa-solid fa-wrench"),
}),
});
// 4. Export a single `collections` object to register your collection(s)
export const collections = { blog, notes, projects };

8
src/content/blog/meow.md Normal file
View file

@ -0,0 +1,8 @@
---
title: meow
description: meow meow meow
date: 2025-03-17
icon: fa-solid fa-cat
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat

View file

@ -0,0 +1,8 @@
---
title: Welcome
description: Lorem ipsum dolor sit amet irure tempor adipisicing esse minim nisi, aute duis elit. Adipisicing consequat pariatur duis incididunt nisi pariatur proident dolor deserunt et.
tags:
- welcome
---
Something to do with the nature of truth and falsehood -- Chris Joel

View file

@ -0,0 +1,8 @@
---
title: meow
exturl: https://www.google.com
date: 2025-03-16
icon: fa-solid fa-cat
---
Non voluptate dolore cupidatat ex culpa ea. Amet in cupidatat amet dolore officia. Eiusmod cupidatat do cillum quis. Sint sit duis eiusmod duis irure sit consequat veniam ea laborum veniam. Nisi et commodo commodo ea non minim. Sint amet excepteur deserunt duis id elit elit id excepteur occaecat cupidatat. Est exercitation excepteur laboris cillum ad do est fugiat minim.

View file

@ -0,0 +1,9 @@
---
name: Scramble
description: Music tracking for the modern age
version: in development
status: active
date: 2025-03-17
---
aaa

15
src/layouts/Base.astro Normal file
View file

@ -0,0 +1,15 @@
---
import "~/styles/global.css";
import Head from "~/components/ui/Head.astro";
import { ClientRouter } from "astro:transitions";
import SizeWarning from "~/components/ui/SizeWarning.astro";
---
<html class="bg-light-bg text-light-tx dark:bg-dark-bg dark:text-dark-tx">
<Head />
<body class="pl-1 md:px-24 sm:pt-2 md:pt-6">
<ClientRouter />
<SizeWarning />
<slot />
</body>
</html>

View file

@ -1,22 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<title>Astro Basics</title>
</head>
<body>
<slot />
</body>
</html>
<style>
html,
body {
margin: 0;
width: 100%;
height: 100%;
}
</style>

45
src/layouts/Note.astro Normal file
View file

@ -0,0 +1,45 @@
---
import Base from "~/layouts/Base.astro";
import Header from "~/components/ui/Header.astro";
import Date from "~/components/util/Date.astro";
import { noteTitleConstructor } from "~/lib/metadata";
const { title, exturl, icon, date } = Astro.props;
---
<Base title={noteTitleConstructor(title, date)}>
<Header />
<ul class="fa-ul marker:text-accent">
<li>
<a href="/notes" class="link">
<i class="fa-li fa-solid fa-arrow-left marker:text-accent" />
Back to notes
</a>
</li>
</ul>
<h2 class="text-2xl font-bold mt-2">A note from <Date date={date} /></h2>
<div class="bg-light-bg-2 dark:bg-dark-bg-2 p-4 rounded-lg w-fit min-w-[500px] mt-4">
<ul class="fa-ul">
{
title && (
<li class="text-lg font-bold">
<i class={`fa-li ${icon}`} />
<h1 class="font-bold">{title}</h1>
</li>
)
}
{
exturl && (
<li>
<i class="fa-li fa-solid fa-link" />
<a href={exturl} class="link">
{exturl}
</a>
</li>
)
}
</ul>
<div class="pl-4 mt-2 prose dark:prose-invert">
<slot />
</div>
</div>
</Base>

18
src/layouts/Page.astro Normal file
View file

@ -0,0 +1,18 @@
---
import Layout from "~/layouts/Base.astro";
import Header from "~/components/ui/Header.astro";
import Strapline from "~/components/ui/Strapline.astro";
import Footer from "~/components/ui/Footer.astro";
const { title, description, icon, date } = Astro.props;
---
<Layout>
<div>
<Header />
<main>
<Strapline title={title} description={description} icon={icon} date={date} />
<slot />
</main>
<Footer />
</div>
</Layout>

41
src/lib/blog.ts Normal file
View file

@ -0,0 +1,41 @@
import siteConfig from "~/site.config";
import type { CollectionEntry } from "astro:content";
type PostWithDate = {
data: {
date: Date;
};
};
const sortByDateDescending = <T extends PostWithDate>(posts: T[]): T[] => {
return posts.sort((a, b) =>
isDateBefore(a.data.date, b.data.date) ? 1 : -1
);
};
const filterPublishedPosts = <T extends { data: { draft?: boolean } }>(
posts: T[]
): T[] => {
if (import.meta.env.PROD) {
return posts.filter((post) => !post.data.draft);
}
return siteConfig.devMode.showDraftPages
? posts
: posts.filter((post) => !post.data.draft);
};
export const getPublishedAndSortedPosts = (
allPosts: CollectionEntry<"blog">[]
): CollectionEntry<"blog">[] => {
return sortByDateDescending(filterPublishedPosts(allPosts));
};
export const getPublishedAndSortedNotes = (
allPosts: CollectionEntry<"notes">[]
): CollectionEntry<"notes">[] => {
return sortByDateDescending(allPosts);
};
// helper function to check if date1 is before date2
export const isDateBefore = (date1: Date, date2: Date): boolean =>
date1.getTime() < date2.getTime();

33
src/lib/fun.ts Normal file
View file

@ -0,0 +1,33 @@
// all the code for making fun stuff happen
const flavourText = [
"LOVE YOURSELF",
"Hack the planet!",
"all your base are belong to us!",
"must construct additional pylons",
"Everybody's dead, Dave.",
"Stay strange and be ace -- Yard Act",
"I'm a rocketman!",
"It's a fixer-upper!",
"💜",
"Sibelius crashed",
"All toasters toast toast",
"Trans rights are human rights!",
":wq",
];
export function getFlavourText() {
return flavourText[Math.floor(Math.random() * flavourText.length)];
}
export function isBirthday() {
const today = new Date();
const birthday = new Date(today.getFullYear(), 3, 13);
const check =
today.getMonth() === birthday.getMonth() &&
today.getDate() === birthday.getDate();
console.log(check);
return check;
}

17
src/lib/metadata.ts Normal file
View file

@ -0,0 +1,17 @@
import conf from "~/site.config";
// todo: add blog detection
export const titleConstructor = (title: string) => {
if (!title) return conf.siteName;
return `${title} | ${conf.siteName}`;
};
export const descriptionConstructor = (description: string) => {
if (!description) return conf.description;
return `${description}`;
};
export const noteTitleConstructor = (title: string, date: Date) => {
if (title) return title;
return `A note from ${date.toLocaleDateString()}`;
};

0
src/lib/util.ts Normal file
View file

14
src/pages/404.astro Normal file
View file

@ -0,0 +1,14 @@
---
import Layout from "~/layouts/Base.astro";
import Header from "~/components/ui/Header.astro";
import Footer from "~/components/ui/Footer.astro";
---
<Layout title="404" description="Page not found" icon="fa-solid fa-ghost">
<Header />
<main class="border-l-5 border-light-pu dark:border-dark-pu pl-4">
<h2 class="text-2xl font-bold">404</h2>
<p class="text-lg">Page not found</p>
</main>
<Footer />
</Layout>

7
src/pages/about.astro Normal file
View file

@ -0,0 +1,7 @@
---
import Page from "~/layouts/Page.astro";
---
<Page title="About" description="do you wanna know?" icon="fa-solid fa-user" date="2025-03-13">
<h1>i kiss girls</h1>
</Page>

24
src/pages/blog/[id].astro Normal file
View file

@ -0,0 +1,24 @@
---
import Page from "~/layouts/Page.astro";
import { getCollection, render } from "astro:content";
// 1. Generate a new path for every collection entry
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { id: post.id },
props: { post },
}));
}
// 2. For your template, you can get the entry directly from the prop
const { post } = Astro.props;
const { Content } = await render(post);
---
<Page
title={post.data.title}
description={post.data.description}
date={post.data.date}
icon={post.data.icon}
>
<Content />
</Page>

View file

@ -0,0 +1,12 @@
---
import Page from "~/layouts/Page.astro";
import BlogPostList from "~/components/lists/BlogPostList.astro";
---
<Page
title="Post index"
description="A list of all my blog posts."
icon="fa-solid fa-blog"
>
<BlogPostList collection="blog" />
</Page>

View file

@ -0,0 +1,35 @@
---
import Layout from "~/layouts/Page.astro";
---
<Layout
title="Contact"
description="how to get a hold of me if you ever need to"
icon="fa-solid fa-envelope"
>
<p>
I'm not really active on social media, but you can contact me via email.
</p>
<p>
<a href="mailto:hello@ivyneeds.rest">hello@ivyneeds.rest</a>
</p>
<h3 class="text-lg font-bold my-2">where i am / where i'm not</h3>
<ul class="fa-ul">
<li>
<i class="fa-li fa-brands fa-mastodon"></i>
Fediverse: <a href="https://social.lol/ivy">@ivy@social.lol</a>
</li>
<li>
<i class="fa-li fa-brands fa-github"></i>
GitHub: <a href="https://github.com/ivyturner">@ivyturner</a>
</li>
<li>
<i class="fa-li fa-brands fa-instagram"></i>
Instagram: <a href="https://www.instagram.com/ivyturner">@ivyturner</a>
</li>
<li>
<i class="fa-li fa-brands fa-twitter text-light-re dark:text-dark-re"></i>
Twitter: haha fuck right off, elon should get his arms broken
</li>
</ul>
</Layout>

View file

@ -0,0 +1,23 @@
---
import Layout from "~/layouts/Page.astro";
---
<Layout
title="Verify"
description="Everywhere you can find me, so you can check if it's me."
icon="fa-solid fa-envelope"
>
<ul>
<li>
Fediverse: <a href="https://social.lol/@ivy">@ivy@social.lol</a>,
<a href="https://social.lol/@la">@la@social.lol</a>
</li>
<li>
GitHub: <a href="https://github.com/ivyturner">@ivyturner</a>
(previously @lxjv)
</li>
<li>
Instagram: <a href="https://www.instagram.com/ivyturner">@ivyturner</a>
</li>
</ul>
</Layout>

View file

@ -1,11 +1,53 @@
---
import Welcome from '../components/Welcome.astro';
import Layout from '../layouts/Layout.astro';
// Welcome to Astro! Wondering what to do next? Check out the Astro documentation at https://docs.astro.build
// Don't want to use any of this? Delete everything in this file, the `assets`, `components`, and `layouts` directories, and start fresh.
import Layout from "~/layouts/Base.astro";
import Header from "~/components/ui/Header.astro";
import Footer from "~/components/ui/Footer.astro";
import Box from "~/components/ui/Box.astro";
import CollectionList from "~/components/lists/BlogPostList.astro";
import NoteList from "~/components/lists/NoteList.astro";
import StyledLink from "~/components/util/StyledLink.astro";
---
<Layout>
<Welcome />
<Header />
<main>
<h1
class="text-2xl font-bold underline decoration-wavy underline-offset-8 decoration-3
decoration-light-pu dark:decoration-dark-pu mb-6"
>
Hi! I'm Ivy, welcome to my website!
</h1>
<p>
I'm a musician, student, part-time software developer and <a
href="/blog"
class="link hover:decoration-solid">writer</a
>. <br />
I mostly work with <a
href="https://www.rust-lang.org/"
class="link hover:decoration-solid">Rust</a
>, <a
href="https://www.typescriptlang.org/"
class="link hover:decoration-solid">Typescript</a
>, and web frameworks like <a
href="https://astro.build/"
class="link hover:decoration-solid">Astro</a
>, and <a href="https://11ty.dev/" class="link hover:decoration-solid"
>Eleventy</a
>.
</p>
<div class="md:flex md:flex-column gap-2">
<Box title="latest blog posts" description="" icon="fa-solid fa-blog">
<CollectionList collection="blog" limit={5} />
<hr class="h-px my-8 bg-light-pu dark:bg-dark-pu" />
<StyledLink href="/blog">see more</StyledLink>
</Box>
<Box title="latest notes" description="" icon="fa-solid fa-sticky-note">
<NoteList limit={5} />
<hr class="h-px my-8 bg-light-pu dark:bg-dark-pu border-0" />
<StyledLink href="/notes">see more</StyledLink>
</Box>
</div>
</main>
</Layout>
<Footer />

View file

@ -0,0 +1,24 @@
---
import Note from "~/layouts/Note.astro";
import { getCollection, render } from "astro:content";
// 1. Generate a new path for every collection entry
export async function getStaticPaths() {
const posts = await getCollection("notes");
return posts.map((post) => ({
params: { id: post.id },
props: { post },
}));
}
// 2. For your template, you can get the entry directly from the prop
const { post } = Astro.props;
const { Content } = await render(post);
---
<Note
title={post.data.title}
exturl={post.data.exturl}
icon={post.data.icon}
date={post.data.date}
>
<Content />
</Note>

View file

@ -0,0 +1,8 @@
---
import Page from "~/layouts/Page.astro";
import NoteList from "~/components/lists/NoteList.astro";
---
<Page title="Notes" description="A collection of notes I've written." icon="fa-solid fa-note-sticky">
<NoteList />
</Page>

View file

@ -0,0 +1,24 @@
---
import Page from "~/layouts/Page.astro";
import { getCollection, render } from "astro:content";
// 1. Generate a new path for every collection entry
export async function getStaticPaths() {
const posts = await getCollection("projects");
return posts.map((post) => ({
params: { id: post.id },
props: { post },
}));
}
// 2. For your template, you can get the entry directly from the prop
const { post } = Astro.props;
const { Content } = await render(post);
---
<Page
title={post.data.name}
description={post.data.description}
date={post.data.date}
icon={post.data.icon}
>
<Content />
</Page>

View file

@ -0,0 +1,8 @@
---
import Page from "~/layouts/Page.astro";
import ProjectList from "~/components/lists/ProjectList.astro";
---
<Page title="Projects" description="stuff i'm working on" icon="fa-solid fa-wrench">
<ProjectList limit={1000} />
</Page>

8
src/site.config.ts Normal file
View file

@ -0,0 +1,8 @@
export default {
siteName: "Ivy Turner",
description: "Ivy Turner's personal website",
fediverse: "@ivy@social.lol",
devMode: {
showDraftPages: true,
},
};

202
src/styles/global.css Normal file
View file

@ -0,0 +1,202 @@
@import "tailwindcss";
@theme {
/* Disable default colors to prevent their use; feel free to re-enable as needed. */
--color-amber-*: initial;
--color-lime-*: initial;
--color-emerald-*: initial;
--color-teal-*: initial;
--color-sky-*: initial;
--color-indigo-*: initial;
--color-violet-*: initial;
--color-fuchsia-*: initial;
--color-pink-*: initial;
--color-rose-*: initial;
--color-slate-*: initial;
--color-zinc-*: initial;
--color-neutral-*: initial;
--color-stone-*: initial;
/* Specify new default colors. */
--color-black: #100F0F;
--color-paper: #FFFCF0;
--color-base-50: #F2F0E5;
--color-base-100: #E6E4D9;
--color-base-150: #DAD8CE;
--color-base-200: #CECDC3;
--color-base-300: #B7B5AC;
--color-base-400: #9F9D96;
--color-base-500: #878580;
--color-base-600: #6F6E69;
--color-base-700: #575653;
--color-base-800: #403E3C;
--color-base-850: #343331;
--color-base-900: #282726;
--color-base-950: #1C1B1A;
--color-red-50: #FFE1D5;
--color-red-100: #FFCABB;
--color-red-150: #FDB2A2;
--color-red-200: #F89A8A;
--color-red-300: #E8705F;
--color-red-400: #D14D41;
--color-red-500: #C03E35;
--color-red-600: #AF3029;
--color-red-700: #942822;
--color-red-800: #6C201C;
--color-red-850: #551B18;
--color-red-900: #3E1715;
--color-red-950: #261312;
--color-orange-50: #FFE7CE;
--color-orange-100: #FED3AF;
--color-orange-150: #FCC192;
--color-orange-200: #F9AE77;
--color-orange-300: #EC8B49;
--color-orange-400: #DA702C;
--color-orange-500: #CB6120;
--color-orange-600: #BC5215;
--color-orange-700: #9D4310;
--color-orange-800: #71320D;
--color-orange-850: #59290D;
--color-orange-900: #40200D;
--color-orange-950: #27180E;
--color-yellow-50: #FAEEC6;
--color-yellow-100: #F6E2A0;
--color-yellow-150: #F1D67E;
--color-yellow-200: #ECCB60;
--color-yellow-300: #DFB431;
--color-yellow-400: #D0A215;
--color-yellow-500: #BE9207;
--color-yellow-600: #AD8301;
--color-yellow-700: #8E6B01;
--color-yellow-800: #664D01;
--color-yellow-850: #503D02;
--color-yellow-900: #3A2D04;
--color-yellow-950: #241E08;
--color-green-50: #EDEECF;
--color-green-100: #DDE2B2;
--color-green-150: #CDD597;
--color-green-200: #BEC97E;
--color-green-300: #A0AF54;
--color-green-400: #879A39;
--color-green-500: #768D21;
--color-green-600: #66800B;
--color-green-700: #536907;
--color-green-800: #3D4C07;
--color-green-850: #313D07;
--color-green-900: #252D09;
--color-green-950: #1A1E0C;
--color-cyan-50: #DDF1E4;
--color-cyan-100: #BFE8D9;
--color-cyan-150: #A2DECE;
--color-cyan-200: #87D3C3;
--color-cyan-300: #5ABDAC;
--color-cyan-400: #3AA99F;
--color-cyan-500: #2F968D;
--color-cyan-600: #24837B;
--color-cyan-700: #1C6C66;
--color-cyan-800: #164F4A;
--color-cyan-850: #143F3C;
--color-cyan-900: #122F2C;
--color-cyan-950: #101F1D;
--color-blue-50: #E1ECEB;
--color-blue-100: #C6DDE8;
--color-blue-150: #ABCFE2;
--color-blue-200: #92BFDB;
--color-blue-300: #66A0C8;
--color-blue-400: #4385BE;
--color-blue-500: #3171B2;
--color-blue-600: #205EA6;
--color-blue-700: #1A4F8C;
--color-blue-800: #163B66;
--color-blue-850: #133051;
--color-blue-900: #12253B;
--color-blue-950: #101A24;
--color-purple-50: #F0EAEC;
--color-purple-100: #E2D9E9;
--color-purple-150: #D3CAE6;
--color-purple-200: #C4B9E0;
--color-purple-300: #A699D0;
--color-purple-400: #8B7EC8;
--color-purple-500: #735EB5;
--color-purple-600: #5E409D;
--color-purple-700: #4F3685;
--color-purple-800: #3C2A62;
--color-purple-850: #31234E;
--color-purple-900: #261C39;
--color-purple-950: #1A1623;
--color-magenta-50: #FEE4E5;
--color-magenta-100: #FCCFDA;
--color-magenta-150: #F9B9CF;
--color-magenta-200: #F4A4C2;
--color-magenta-300: #E47DA8;
--color-magenta-400: #CE5D97;
--color-magenta-500: #B74583;
--color-magenta-600: #A02F6F;
--color-magenta-700: #87285E;
--color-magenta-800: #641F46;
--color-magenta-850: #4F1B39;
--color-magenta-900: #39172B;
--color-magenta-950: #24131D;
}
/* Define some semantic aliases. */
@theme inline {
--color-light-bg: var(--color-paper);
--color-light-bg-2: var(--color-base-50);
--color-light-tx: var(--color-black);
--color-light-tx-2: var(--color-base-600);
--color-light-tx-3: var(--color-base-300);
--color-light-ui: var(--color-base-100);
--color-light-ui-2: var(--color-base-150);
--color-light-ui-3: var(--color-base-200);
--color-dark-bg: var(--color-black);
--color-dark-bg-2: var(--color-base-950);
--color-dark-tx: var(--color-base-200);
--color-dark-tx-2: var(--color-base-500);
--color-dark-tx-3: var(--color-base-700);
--color-dark-ui: var(--color-base-900);
--color-dark-ui-2: var(--color-base-850);
--color-dark-ui-3: var(--color-base-800);
--color-light-re: var(--color-red-600);
--color-light-or: var(--color-orange-600);
--color-light-ye: var(--color-yellow-600);
--color-light-gr: var(--color-green-600);
--color-light-cy: var(--color-cyan-600);
--color-light-bl: var(--color-blue-600);
--color-light-pu: var(--color-purple-600);
--color-light-ma: var(--color-magenta-600);
--color-dark-re: var(--color-red-400);
--color-dark-or: var(--color-orange-400);
--color-dark-ye: var(--color-yellow-400);
--color-dark-gr: var(--color-green-400);
--color-dark-cy: var(--color-cyan-400);
--color-dark-bl: var(--color-blue-400);
--color-dark-pu: var(--color-purple-400);
--color-dark-ma: var(--color-magenta-400);
--color-light-re-2: var(--color-red-400);
--color-light-or-2: var(--color-orange-400);
--color-light-ye-2: var(--color-yellow-400);
--color-light-gr-2: var(--color-green-400);
--color-light-cy-2: var(--color-cyan-400);
--color-light-bl-2: var(--color-blue-400);
--color-light-pu-2: var(--color-purple-400);
--color-light-ma-2: var(--color-magenta-400);
--color-dark-re-2: var(--color-red-600);
--color-dark-or-2: var(--color-orange-600);
--color-dark-ye-2: var(--color-yellow-600);
--color-dark-gr-2: var(--color-green-600);
--color-dark-cy-2: var(--color-cyan-600);
--color-dark-bl-2: var(--color-blue-600);
--color-dark-pu-2: var(--color-purple-600);
--color-dark-ma-2: var(--color-magenta-600);
--color-accent: light-dark(var(--color-light-pu), var(--color-dark-pu));
}
.link {
@apply underline decoration-dotted underline-offset-2 decoration-2 decoration-light-pu dark:decoration-dark-pu
}
hr {
@apply border-0 h-0.5 my-4 bg-light-pu dark:bg-dark-pu;
}

View file

@ -1,5 +1,11 @@
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
"exclude": ["dist", "node_modules"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./src/*"]
}
}
}