New website based on customized blog template

This commit is contained in:
Luke Wilson 2025-05-16 23:28:36 -05:00
parent e8f394285f
commit 05e28a507a
25 changed files with 5780 additions and 2 deletions

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/

4
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

View File

@ -1,3 +1,68 @@
# site # Astro Starter Kit: Blog
My personal website ```sh
npm create astro@latest -- --template blog
```
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/blog)
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/blog)
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/blog/devcontainer.json)
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
![blog](https://github.com/withastro/astro/assets/2244813/ff10799f-a816-4703-b967-c78997e8323d)
Features:
- ✅ Minimal styling (make it your own!)
- ✅ 100/100 Lighthouse performance
- ✅ SEO-friendly with canonical URLs and OpenGraph data
- ✅ Sitemap support
- ✅ RSS Feed support
- ✅ Markdown & MDX support
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
```text
├── public/
├── src/
│   ├── components/
│   ├── content/
│   ├── layouts/
│   └── pages/
├── astro.config.mjs
├── README.md
├── package.json
└── tsconfig.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
The `src/content/` directory contains "collections" of related Markdown and MDX documents. Use `getCollection()` to retrieve posts from `src/content/blog/`, and type-check your frontmatter using an optional schema. See [Astro's Content Collections docs](https://docs.astro.build/en/guides/content-collections/) to learn more.
Any static assets, like images, can be placed in the `public/` directory.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
## 👀 Want to learn more?
Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
## Credit
This theme is based off of the lovely [Bear Blog](https://github.com/HermanMartinus/bearblog/).

9
astro.config.mjs Normal file
View File

@ -0,0 +1,9 @@
// @ts-check
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
// https://astro.build/config
export default defineConfig({
site: 'https://luke.frop.prof',
integrations: [sitemap()],
});

4959
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

16
package.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/rss": "^4.0.11",
"@astrojs/sitemap": "^3.4.0",
"astro": "^5.7.13"
}
}

9
public/favicon.svg Normal file
View File

@ -0,0 +1,9 @@
<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>

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,55 @@
---
// Import the global.css file here so that it is included on
// all pages through the use of the <BaseHead /> component.
import '../styles/global.css';
import { SITE_TITLE } from '../consts';
interface Props {
title: string;
description: string;
image?: string;
}
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props;
---
<!-- Global Metadata -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="sitemap" href="/sitemap-index.xml" />
<link
rel="alternate"
type="application/rss+xml"
title={SITE_TITLE}
href={new URL('rss.xml', Astro.site)}
/>
<meta name="generator" content={Astro.generator} />
<!-- Font preloads -->
<link rel="preload" href="/fonts/atkinson-regular.woff" as="font" type="font/woff" crossorigin />
<link rel="preload" href="/fonts/atkinson-bold.woff" as="font" type="font/woff" crossorigin />
<!-- Canonical URL -->
<link rel="canonical" href={canonicalURL} />
<!-- Primary Meta Tags -->
<title>{title}</title>
<meta name="title" content={title} />
<meta name="description" content={description} />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={new URL(image, Astro.url)} />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={Astro.url} />
<meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} />
<meta property="twitter:image" content={new URL(image, Astro.url)} />

View File

@ -0,0 +1,39 @@
---
const today = new Date();
---
<footer>
&copy; {today.getFullYear()} Luke Wilson. All content CC0.
<div class="social-links">
<a href="https://github.com/lukewilson2002" target="_blank">
<span class="sr-only">Go to Luke's GitHub</span>
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" astro-icon="social/github"
><path
fill="currentColor"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path></svg
>
</a>
</div>
</footer>
<style>
footer {
padding: 2em 1em 6em 1em;
background: linear-gradient(var(--gray-gradient)) no-repeat;
color: rgb(var(--gray));
text-align: center;
}
.social-links {
display: flex;
justify-content: center;
gap: 1em;
margin-top: 1em;
}
.social-links a {
text-decoration: none;
color: rgb(var(--gray));
}
.social-links a:hover {
color: rgb(var(--gray-dark));
}
</style>

View File

@ -0,0 +1,17 @@
---
interface Props {
date: Date;
}
const { date } = Astro.props;
---
<time datetime={date.toISOString()}>
{
date.toLocaleDateString('en-us', {
year: 'numeric',
month: 'short',
day: 'numeric',
})
}
</time>

View File

@ -0,0 +1,69 @@
---
import HeaderLink from './HeaderLink.astro';
import { SITE_TITLE } from '../consts';
---
<header>
<nav>
<h2><a href="/">{SITE_TITLE}</a></h2>
<div class="internal-links">
<HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink>
</div>
<div class="social-links">
<a href="/rss.xml" target="_blank">
<span class="sr-only">RSS Feed</span>
<svg viewBox="0 0 20 20" aria-hidden="true" width="32" height="32"
><path
fill="currentColor"
d="M14.92 18H18C18 9.32 10.82 2.25 2 2.25v3.02c7.12 0 12.92 5.71 12.92 12.73zm-5.44 0h3.08C12.56 12.27 7.82 7.6 2 7.6v3.02c2 0 3.87.77 5.29 2.16C8.7 14.17 9.48 16.03 9.48 18zm-5.35-.02c1.17 0 2.13-.93 2.13-2.09 0-1.15-.96-2.09-2.13-2.09-1.18 0-2.13.94-2.13 2.09 0 1.16.95 2.09 2.13 2.09z"
></path></svg
>
</a>
</div>
</nav>
</header>
<style>
header {
margin: 0;
padding: 0 1em;
background: white;
}
h2 {
margin: 0;
font-size: 1em;
}
h2 a,
h2 a.active {
text-decoration: none;
}
nav {
display: flex;
align-items: center;
justify-content: space-between;
}
nav a {
padding: 0.25em 0.5em;
color: rgb(var(--black));
text-decoration: none;
}
nav .internal-links a.active {
color: var(--accent);
text-decoration: none;
}
.social-links,
.social-links a {
display: flex;
}
.social-links a {
padding: 0.25em;
}
.social-links a svg {
height: 25px;
}
@media (max-width: 720px) {
.social-links {
display: none;
}
}
</style>

View File

@ -0,0 +1,23 @@
---
import type { HTMLAttributes } from 'astro/types';
type Props = HTMLAttributes<'a'>;
const { href, class: className, ...props } = Astro.props;
const pathname = Astro.url.pathname.replace(import.meta.env.BASE_URL, '');
const subpath = pathname.match(/[^\/]+/g);
const isActive = href === pathname || href === '/' + (subpath?.[0] || '');
---
<a href={href} class:list={[className, { active: isActive }]} {...props}>
<slot />
</a>
<style>
a {
display: inline-block;
text-decoration: none;
}
a.active {
text-decoration: underline;
}
</style>

5
src/consts.ts Normal file
View File

@ -0,0 +1,5 @@
// Place any global data in this file.
// You can import this data from anywhere in your site by using the `import` keyword.
export const SITE_TITLE = "Luke's Blog";
export const SITE_DESCRIPTION = 'A blog about stuff';

18
src/content.config.ts Normal file
View File

@ -0,0 +1,18 @@
import { glob } from 'astro/loaders';
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
// Load Markdown and MDX files in the `src/content/blog/` directory.
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
// Type-check frontmatter using a schema
schema: z.object({
title: z.string(),
description: z.string(),
// Transform string to Date object
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
heroImage: z.string().optional(),
}),
});
export const collections = { blog };

View File

@ -0,0 +1,56 @@
---
title: "Everyone makes decisions in their own interests"
description: "Theory: everyone makes decisions in that moment based on their own belief of personal gain, whether it's truly for their benefit or not. People never choose to do things which they do not receive some sort of benefit from choosing to do."
pubDate: 'Mar 03 2025'
# heroImage: '/blog-placeholder-3.jpg'
---
Update May 16, 2025: Turns out that this is a centuries-old philosophical debate: https://en.wikipedia.org/wiki/Psychological_egoism
---
Theory: everyone makes decisions in that moment based on their own belief of personal gain, whether it's truly for their benefit or not. People never choose to do things which they do not receive some sort of benefit from choosing to do.
Essentially, every action seems to stem from a calculation—whether conscious or subconscious—that it serves some form of personal interest, even if that interest isn't always immediately obvious.
There are some general observable guidelines that form the basis of this theory:
1. People assess the "worth" of an action based on the benefits they expect to receive, whether those benefits are physical pleasure, emotional relief, social approval, or alignment with personal values. What counts as "benefit" can vary widely from person to person.
2. While long-term outcomes are considered, many decisions are heavily influenced by immediate rewards. For example, a drug user might choose to take drugs because the immediate euphoria or escape they provide is compelling—even if, in the long run, these actions cause harm to their relationships or themselves.
3. Our brains are wired to seek pleasure and avoid pain. Even when someone makes a decision that appears self-destructive, it's often because their internal reward circuitry has prioritized a short-term benefit over potential long-term costs.
4. "Self-interest" doesn't always mean purely selfish or hedonistic choices. Sometimes, actions like donating to charity or following a strict ethical code are done because they provide a sense of fulfillment, social belonging, or alignment with one's identity. In this broader view, even altruistic actions serve personal interests.
5. Decisions aren't just about weighing benefits and drawbacks in a straightforward way. Emotions, biases, social pressures, and even habits can alter how we perceive what's "worth it" at any given moment.
Every decision goes through a kind of personal cost-benefit analysis.
From the journal Frontiers in Ecology and Evolution:
> In these modeling approaches, the researcher deduces the predicted decision by maximizing a metric of evolutionary fitness. Already Alfred Lotka hinted that there are mechanisms within a body that enable the organism to make evolutionarily good decisions: “What guides a human being, for example in the selection of his activities, are his tastes, his desires, his pleasures and pains, actual or prospective” (Lotka, 1925, p. 352). He pointed at an evolved neurological basis—and an ability to predict—that controls decisions. ([Source](https://www.frontiersin.org/journals/ecology-and-evolution/articles/10.3389/fevo.2019.00164/full#:~:text=In%20these%20modelingthat%20controls%20decisions.))
The article also includes many examples of animals that exhibit this selfish subconscious decision making, including unicellular organisms which evaluate conditions inside the cell and the surroundings, pursue resources, close enemies out, divide, or enter resting stage. ([Highlight](https://www.frontiersin.org/journals/ecology-and-evolution/articles/10.3389/fevo.2019.00164/full#:~:text=Even%20unicellulars%20can%20evaluate%20the%20situation%20within%20the%20cell%20and%20in%20the%20surroundings%20and%20make%20decisions%20about%20pursuing%20resources%2C%20closing%20enemies%20out%2C%20dividing%2C%20or%20entering%20a%20resting%20stage%20(V%C3%A5ge%20et%20al.%2C%202014%3B%20Lyon%2C%202015%3B%20Bi%20and%20Sourjik%2C%202018)))
Is it irrational to believe that maybe our decision making has evolved over time to be exceptionally fast and accurate at calculating what would benefit us, “selfishly”? Selfish, as in doing something because it makes you feel better, or it makes you feel more socially acceptable, or you do it because you want to, or it provides dopamine and it's stimulating, or you only do it because it's the better of the worse choices.
So let me present some hypotheticals.
Hypothetical: Being forced to do something under coercion, you agree to do it, are you really acting in selfish interest?
Yes, because say the police have forced me to go to prison for the rest of my life or I can kill myself. Coercion, or alternative. How do I choose? Well, prison sucks but it's not the end of the world. There are many things to do, they have a library and computers, I can still enjoy life to some degree and maybe there's a chance for parole. Or, I kill myself and it's all over. Now I have to decide what's more ideal, well maybe I'll give prison a try for a while and see how it goes before I kill myself. Why did I choose that? Because I want to live, ideally, so it's a decision made in my personal interest to potentially remain alive and still enjoy the things life has to offer like warm food and comfort, and attempting suicide has a risk of remaining alive but a vegetable, which I don't want to be. Decision made in my own interest.
Hypothetical: Pregnant woman smoking a cigarette. Did she decide to smoke the cigarette out of her own interest, or is it only because she is addicted and unable to stop?
She decided to smoke the cigarette because of the stress relief, dopamine, and minor euphoria she has become dependent on to enjoy life. She looks forward to each cigarette because it's a comforting vice. She knows smoking while pregnant is a bad idea, but in this moment, she thinks it's okay to smoke one more cigarette and she plans to stop someday soon. So the decision was made out of her own interest in the euphoria rather than because she's forced to act out of addiction.
Hypothetical: Are mundane decisions and actions also chosen out of personal interest? What about deciding where to place your foot in each step, or choosing the next word to come out of your mouth, or when you decide to go to sleep?
All actions are made in your interest. You choose the best place for your foot because you don't want to break it, or get hurt, because that's an unpleasant experience. You choose your words based on what you know about English, and you want to be well understood and you want to talk like the person you're communicating with so they will like you more, and relate to you more, because that provides you with a feeling of social acceptance, bond, or companionship, which derives from evolutionary social survival pressures. You decide to go to sleep when the relief of sleep outweighs the experience of remaining awake, essentially your body makes remaining awake more and more unbearable to the degree of complete and total physiological suffering, to encourage you to decide by your own self interest to end the unpleasant experience and feel comfort again.
Hypothetical: Can someone make decisions they believe are NOT in their own interests, for example punching yourself suddenly for no reason (“to test my theory” sounds fun but this implies there's actually purpose so we won't include that).
You punch yourself very hard in the face for no reason at all. What compelled you to make this decision? If it was truly unexpected, then you didn't make the decision, so it wasn't anything you had some conscious or subconscious control over. Or if you truly did intend to hit yourself but for no reason at all, then you already knew the outcome in advance, hitting yourself, so it was an acceptable outcome and you made that decision. A decision cannot be unacceptable (the agent is uncompliant), and acted upon willingly, as that would be contradictory.
In a way, it's impossible to make a decision without doing a cost-benefit analysis at least subconsciously, and deciding that you accept the outcome. If it were possible to decide to do anything without some underlying logic, then the average animal would probably look a lot more retarded.
What would be the case for illogical decision making, from the perspective of the decision-maker, in evolution? In my mind, there can't be one. Evolution has determined since unicellular organisms that we act depending upon our needs and the environment, weighing risks and variables if the size of the brain or processor permits. All animals acting irrationally would not have survived very long, running directly into the mouth of a tiger, or throwing themselves from cliffsides.
Arguably, many animals do throw themselves from cliffsides, but they likely don't understand the consequences. They don't need to understand the consequences to make the decision. When the decision is made, the brain believes it is the next best choice, regardless of whatever logic got them there.

View File

@ -0,0 +1,84 @@
---
import type { CollectionEntry } from 'astro:content';
import BaseHead from '../components/BaseHead.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import FormattedDate from '../components/FormattedDate.astro';
type Props = CollectionEntry<'blog'>['data'];
const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
---
<html lang="en">
<head>
<BaseHead title={title} description={description} />
<style>
main {
width: calc(100% - 2em);
max-width: 100%;
margin: 0;
}
.hero-image {
width: 100%;
}
.hero-image img {
display: block;
margin: 0 auto;
border-radius: 12px;
}
.prose {
width: 720px;
max-width: calc(100% - 2em);
margin: auto;
padding: 1em;
color: rgb(var(--gray-dark));
}
.title {
margin-bottom: 1em;
padding: 1em 0;
text-align: center;
line-height: 1;
}
.title h1 {
margin: 0 0 0.5em 0;
}
.date {
margin-bottom: 0.5em;
color: rgb(var(--gray));
}
.last-updated-on {
font-style: italic;
}
</style>
</head>
<body>
<Header />
<main>
<article>
<div class="hero-image">
{heroImage && <img width={1020} height={510} src={heroImage} alt="" />}
</div>
<div class="prose">
<div class="title">
<div class="date">
<FormattedDate date={pubDate} />
{
updatedDate && (
<div class="last-updated-on">
Last updated on <FormattedDate date={updatedDate} />
</div>
)
}
</div>
<h1>{title}</h1>
<hr />
</div>
<slot />
</div>
</article>
</main>
<Footer />
</body>
</html>

View File

@ -0,0 +1,21 @@
---
import { type CollectionEntry, getCollection } from 'astro:content';
import BlogPost from '../../layouts/BlogPost.astro';
import { render } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({
params: { slug: post.id },
props: post,
}));
}
type Props = CollectionEntry<'blog'>;
const post = Astro.props;
const { Content } = await render(post);
---
<BlogPost {...post.data}>
<Content />
</BlogPost>

View File

@ -0,0 +1,79 @@
---
import BaseHead from '../../components/BaseHead.astro';
import Header from '../../components/Header.astro';
import Footer from '../../components/Footer.astro';
import { SITE_TITLE, SITE_DESCRIPTION } from '../../consts';
import { getCollection } from 'astro:content';
import FormattedDate from '../../components/FormattedDate.astro';
const posts = (await getCollection('blog')).sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
---
<!doctype html>
<html lang="en">
<head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
<style>
ul {
display: flex;
flex-wrap: wrap;
gap: 2rem;
list-style-type: none;
margin: 0;
padding: 0;
}
ul li * {
text-decoration: none;
}
ul li a {
display: block;
}
.title {
margin: 0;
color: rgb(var(--black));
line-height: 1;
}
.date {
margin: 0;
color: rgb(var(--gray));
}
ul li a:hover h4,
ul li a:hover .date {
color: rgb(var(--accent));
}
@media (max-width: 720px) {
ul {
gap: 0.5em;
}
ul li {
width: 100%;
text-align: center;
}
}
</style>
</head>
<body>
<Header />
<main>
<section>
<ul>
{
posts.map((post) => (
<li>
<a href={`/blog/${post.id}/`}>
<h4 class="title">{post.data.title}</h4>
<p class="date">
<FormattedDate date={post.data.pubDate} />
</p>
</a>
</li>
))
}
</ul>
</section>
</main>
<Footer />
</body>
</html>

36
src/pages/index.astro Normal file
View File

@ -0,0 +1,36 @@
---
import BaseHead from '../components/BaseHead.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
---
<!doctype html>
<html lang="en">
<head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
</head>
<body>
<Header />
<main>
<h1>The Homepage of Luke Wilson</h1>
<p>
Welcome to my website! I'm a software developer and I love to write about technology, philosophy, and
the intersection of the two. I hope you enjoy reading my posts.
</p>
<p>
Why do I believe evolution is so important when considering psychology, nature, and the very world as
we know it? Because evolution has shaped and molded these very things we take as fact. Evolution is our
God that crafted our dizzying belief that nothing else could ever be.
</p>
<p>
But one could never be more wrong.
</p>
<p>
Nothing on the Earth today was created without intention. It's all a product of evolution. Everything
serves some kind of purpose because of the evolutionary algorithm.
</p>
</main>
<Footer />
</body>
</html>

16
src/pages/rss.xml.js Normal file
View File

@ -0,0 +1,16 @@
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
export async function GET(context) {
const posts = await getCollection('blog');
return rss({
title: SITE_TITLE,
description: SITE_DESCRIPTION,
site: context.site,
items: posts.map((post) => ({
...post.data,
link: `/blog/${post.id}/`,
})),
});
}

155
src/styles/global.css Normal file
View File

@ -0,0 +1,155 @@
/*
The CSS in this style tag is based off of Bear Blog's default CSS.
https://github.com/HermanMartinus/bearblog/blob/297026a877bc2ab2b3bdfbd6b9f7961c350917dd/templates/styles/blog/default.css
License MIT: https://github.com/HermanMartinus/bearblog/blob/master/LICENSE.md
*/
:root {
--accent: #a70202;
--accent-dark: #a70202;
--black: 11, 0, 38;
--gray: 101, 101, 101;
--gray-light: 229, 233, 240;
--gray-dark: 34, 41, 57;
--gray-gradient: rgba(var(--gray-light), 50%), #fff;
}
@font-face {
font-family: 'Atkinson';
src: url('/fonts/atkinson-regular.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Atkinson';
src: url('/fonts/atkinson-bold.woff') format('woff');
font-weight: 700;
font-style: normal;
font-display: swap;
}
body {
font-family: 'Atkinson', sans-serif;
margin: 0;
padding: 0;
text-align: left;
background: linear-gradient(var(--gray-gradient)) no-repeat;
background-size: 100% 600px;
word-wrap: break-word;
overflow-wrap: break-word;
color: rgb(var(--gray-dark));
font-size: 20px;
line-height: 1.7;
}
main {
width: 720px;
max-width: calc(100% - 2em);
margin: auto;
padding: 3em 1em;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0 0 0.5rem 0;
color: rgb(var(--black));
line-height: 1.2;
font-weight: normal;
}
h1 {
font-size: 2em;
}
h2 {
font-size: 1.6em;
}
h3 {
font-size: 1.4em;
}
h4 {
font-size: 1.2em;
}
h5 {
font-size: 1.1em;
}
h6 {
font-size: 1em;
}
strong,
b {
font-weight: 700;
}
a {
color: var(--accent);
}
a:hover {
color: var(--accent);
}
p {
margin-bottom: 1em;
}
.prose p {
margin-bottom: 2em;
}
textarea {
width: 100%;
font-size: 16px;
}
input {
font-size: 16px;
}
table {
width: 100%;
}
img {
max-width: 100%;
height: auto;
border-radius: 8px;
}
code {
padding: 2px 5px;
background-color: rgb(var(--gray-light));
border-radius: 2px;
}
pre {
padding: 1.5em;
border-radius: 8px;
}
pre > code {
all: unset;
}
blockquote {
border-left: 4px solid var(--accent);
padding: 0 0 0 20px;
margin: 0px;
}
hr {
border: none;
border-top: 1px solid rgb(var(--gray-light));
}
@media (max-width: 720px) {
body {
font-size: 18px;
}
main {
padding: 1em;
}
}
.sr-only {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
/* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px 1px 1px 1px);
/* maybe deprecated but we need to support legacy browsers */
clip: rect(1px, 1px, 1px, 1px);
/* modern browsers, clip-path works inwards from each corner */
clip-path: inset(50%);
/* added line to stop words getting smushed together (as they go onto separate lines and some screen readers do not understand line feeds as a space */
white-space: nowrap;
}

8
tsconfig.json Normal file
View File

@ -0,0 +1,8 @@
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"],
"compilerOptions": {
"strictNullChecks": true
}
}