Initial Commit

This commit is contained in:
Mrrp 2024-12-21 19:11:09 -08:00
commit a927fefeba
28 changed files with 5805 additions and 0 deletions

49
.github/workflows/deploy.yml vendored Normal file
View file

@ -0,0 +1,49 @@
name: Deploy
on:
push:
branches:
- main
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
- name: Install dependencies
uses: bahmutov/npm-install@v1
- name: Generate project as a static site
run: npm run generate
- name: Upload production-ready build files
uses: actions/upload-artifact@v4
with:
name: production-files
path: ./output/public
deploy:
name: Deploy
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: production-files
path: ./output/public
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./output/public

24
.gitignore vendored Normal file
View file

@ -0,0 +1,24 @@
# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache
dist
# Node dependencies
node_modules
# Logs
logs
*.log
# Misc
.DS_Store
.fleet
.idea
# Local env files
.env
.env.*
!.env.example

75
README.md Normal file
View file

@ -0,0 +1,75 @@
# Nuxt Minimal Starter
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
## Setup
Make sure to install dependencies:
```bash
# npm
npm install
# pnpm
pnpm install
# yarn
yarn install
# bun
bun install
```
## Development Server
Start the development server on `http://localhost:3000`:
```bash
# npm
npm run dev
# pnpm
pnpm dev
# yarn
yarn dev
# bun
bun run dev
```
## Production
Build the application for production:
```bash
# npm
npm run build
# pnpm
pnpm build
# yarn
yarn build
# bun
bun run build
```
Locally preview production build:
```bash
# npm
npm run preview
# pnpm
pnpm preview
# yarn
yarn preview
# bun
bun run preview
```
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.

17
app.vue Normal file
View file

@ -0,0 +1,17 @@
<script setup lang="ts">
import { main } from "@popperjs/core";
import MainPage from "./pages/index.vue"
import backgroundCalm from "./components/BackgroundCalm.vue";
import Navbar from "./components/Navbar.vue"
import './assets/style.css'
</script>
<template>
<div>
<Navbar/>
<NuxtLayout>
<NuxtPage/>
</NuxtLayout>
<background-calm />
</div>
</template>

33
assets/about_me.md Normal file
View file

@ -0,0 +1,33 @@
# Helau! :3
## 🌙 Luna - She/Her
<a href="mailto: thelunacy@proton.me">`thelunacy@proton.me`</a>
###### This is a specific email for contact.
<br>
###### 🏳️‍⚧️ I am exploring identity, so this may change or I might go by different things elsewhere.
###### Regardless, try to respect this or else. I'm not here to debate my existence.
<div style="color: pink">
*Queer rights are human rights.*
</div>
---
<div style="justify-content: center; display: flex; align-items: center;">
![Visitors](https://api.visitorbadge.io/api/combined?path=https%3A%2F%2Fgithub.com%2Fmisslunatic%2FMissLunatic&label=VIsitors&countColor=%23e7c4ff&style=plastic)
</div>
I'm a student, apprentice, hobbyist, and generally a nerd who does some coding every once and a while.
I've mainly been messing with C, C++, C# and have been learning Rust. I'm presently learning more about web development, particularly regarding frameworks and libraries.
I'm a bit shy in terms of socializing, but I'm often open to chat about most things, so long as it's respectful.
Please reach out to me first, I probably won't do so myself.
Follow if you enjoy. I'm not *too* active, but I'll try to post some things every once and a while.

18
assets/blog_list.json Normal file
View file

@ -0,0 +1,18 @@
{
"posts": [
{
"metadata": {
"title": "Awesome", "description": "A curated list of awesome stuff I like", "date": "2024-11-26", "tags": ["awesome", "curated"]
},
"id": "awesome",
"url": "/blog/awesome.md"
},
{
"metadata": {
"title": "Badges!", "description": "A collection of 88x31 badges for various things", "date": "2024-12-21", "tags": ["badges", "retro", "web"]
},
"id": "badges",
"url": "/blog/badges.md"
}
]
}

152
assets/style.css Normal file
View file

@ -0,0 +1,152 @@
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&family=Lobster&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
html {
@apply min-h-screen bg-slate-950;
}
h1 {
font-family: 'Lobster', cursive, 'Courier New', Courier, monospace;
@apply text-3xl font-bold;
}
h2 {
@apply text-2xl font-bold;
}
h3 {
@apply text-xl font-bold;
}
h4 {
@apply text-lg font-bold;
}
h5 {
@apply text-base font-bold;
}
h6 {
@apply text-sm font-bold;
}
a {
@apply transition text-purple-400 hover:text-purple-500;
}
blockquote p {
@apply border-l-4 border-purple-400 pl-2;
container: block;
}
br {
content: '';
display: block;
margin-top: 1em;
}
ul {
@apply list-disc list-inside;
}
ol {
@apply list-decimal list-inside;
}
li {
@apply my-2;
}
p {
line-height: normal;
}
pre code {
white-space: pre-wrap;
display: block;
padding: 1em;
background-color: #272822;
@apply border-purple-400 border rounded-lg;
}
code {
font-family: 'JetBrains Mono', monospace;
@apply bg-purple-950 subpixel-antialiased;
}
/* Code if there is no pre tag before it */
:not(pre) > code {
@apply p-1 border-purple-800 border rounded-lg;
}
/* Code theme */
.hljs {
background: #272822;
color: #ddd;
}
.hljs-tag,
.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-strong,
.hljs-number,
.hljs-name {
color: #f92672;
}
.hljs-code {
color: #66d9ef;
}
.hljs-attribute,
.hljs-attr,
.hljs-symbol,
.hljs-regexp,
.hljs-link {
color: #bf79db;
}
.hljs-string,
.hljs-bullet,
.hljs-subst,
.hljs-title,
.hljs-section,
.hljs-emphasis,
.hljs-type,
.hljs-built_in,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-addition,
.hljs-variable,
.hljs-template-tag,
.hljs-template-variable {
color: #a6e22e;
}
.hljs-title.class_,
.hljs-class .hljs-title {
color: white;
}
.hljs-comment,
.hljs-quote,
.hljs-deletion,
.hljs-meta {
color: #75715e;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-doctag,
.hljs-title,
.hljs-section,
.hljs-type,
.hljs-selector-id {
font-weight: bold;
}

1
assets/vue.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

View file

@ -0,0 +1,77 @@
<script setup lang="ts">
import { Engine } from '@tsparticles/engine';
const onLoad = (container: Container) => {
}
</script>
<template>
<NuxtParticles
class="fixed w-full h-full"
id="tsparticles"
@load="onLoad"
:particlesInit="particlesInit"
:options="{
fullScreen: {
enable: true,
zIndex: -1
},
fpsLimit: 60,
interactivity: {
detect_on: 'window',
events: {
onHover: {
enable: true,
mode: 'repulse'
},
},
modes: {
repulse: {
distance: 100,
duration: 1.0
}
}
},
particles: {
zIndex: -10,
color: {
value: '#A020F0'
},
links: {
color: '#B020F0',
distance: 200,
enable: true,
opacity: 0.5,
width: 1.5
},
move: {
direction: 'none',
enable: true,
outModes: 'bounce',
random: false,
speed: 1.5,
straight: false
},
number: {
density: {
enable: true,
},
value: 40
},
opacity: {
value: 0.5
},
shape: {
type: 'circle'
},
size: {
value: { min: 2, max: 9 }
}
},
detectRetina: true
}"
>
</NuxtParticles>
<slot></slot>
</template>

15
components/Navbar.vue Normal file
View file

@ -0,0 +1,15 @@
<template>
<div class="flex justify-center">
<div class="flex-col transition-[margin] justify-center md:rounded-md max-md:w-screen lg:mt-3 w-fit-content pr-4 pl-4 bg-purple-500 bg-opacity-25 text-white">
<div class="flex justify-center">
<a href="/" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Home</a>
<a href="/blog/" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Blog</a>
<a href="/blog/?post=/blog/awesome.md" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Awesome</a>
<a href="/blog/?post=/blog/badges.md" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Badges</a>
</div>
<div class="flex justify-center">
<small class=" ml-3 mr-3">Hosted with <a href="https://github.com/misslunatic/misslunatic.github.io" class="text-blue-500">GitHub Pages</a></small>
</div>
</div>
</div>
</template>

80
components/PostCard.vue Normal file
View file

@ -0,0 +1,80 @@
<script setup>
import { ref, watch } from 'vue';
import fm from 'front-matter';
const props = defineProps({
url: String,
});
import { useSlots } from 'vue';
const slots = useSlots();
const url = ref(props.url)
url.value = props.url
const loading = ref(false)
const data = ref(null)
const error = ref(null)
const background = ref('');
const title = ref(null);
const description = ref(null);
const date = ref(null);
const tags = ref(null);
// watch the params of the route to fetch the data again
watch(url, async () => {
await fetchData()
}, {
immediate: true
});
async function fetchData() {
error.value = data.value = null
loading.value = true
try {
data.value = await (await fetch(url.value)).text()
const processed = fm(data.value)
background.value = processed.attributes.background
title.value = processed.attributes.title
description.value = processed.attributes.description
date.value = processed.attributes.date
tags.value = processed.attributes.tags
} catch (err) {
error.value = err.toString()
loading.value = false
} finally {
loading.value = false
}
}
</script>
<template>
<a :href="'/blog?post=' +url">
<div class="m-4 p-3 min-h-10 w-90 text-white rounded-2xl border-2 border-purple-300 transition hover:bg-purple-600 bg-purple-700 bg-opacity-50 hover:bg-opacity-70"
:style="{ backgroundImage: `url(${background})` }">
<div v-if="loading" class="text-center animate-pulse">
<h2>Loading...</h2>
</div>
<div v-else-if="error" class="text-center">
<h2>Error: {{ error }}</h2>
<button @click="fetchData">Retry</button>
</div>
<div v-else>
<div class="grid">
<div class="justify-center">
<h1>{{ title }}</h1>
</div>
<div class="flex justify-center">
<div v-for="tag in tags" :key="tag" class="m-1 text-center">
<span class="text-xs bg-purple-800 border-purple-400 border text-white p-1 rounded-md">{{ tag }}</span>
</div>
</div>
</div>
<p>{{ description }}</p>
</div>
</div>
</a>
</template>

4689
deno.lock generated Normal file

File diff suppressed because it is too large Load diff

24
nuxt.config.ts Normal file
View file

@ -0,0 +1,24 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: '2024-11-01',
devtools: { enabled: true },
postcss: {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
},
app: {
layoutTransition: {
name: 'layout',
mode: 'out-in'
}
},
modules: [
'nuxt-particles'
],
particles: {
mode: 'slim',
lazy: true
}
})

31
package.json Normal file
View file

@ -0,0 +1,31 @@
{
"name": "nuxt-app",
"private": true,
"type": "module",
"scripts": {
"build": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json && nuxt build",
"dev": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json && nuxt dev",
"generate": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json && nuxt generate",
"preview": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json &&nuxt preview",
"postinstall": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json &&nuxt prepare"
},
"dependencies": {
"@popperjs/core": "^2.11.8",
"@tsparticles/slim": "^3.7.1",
"nuxt": "^3.14.1592",
"tsparticles": "^3.7.1",
"vue": "latest",
"vue-router": "latest",
"@tsparticles/engine": "^3.5.0",
"@tsparticles/vue3": "^3.0.1",
"front-matter": "^4.0.2",
"highlight.js": "^11.10.0",
"markdown-it": "^14.1.0"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"nuxt-particles": "^0.3.0",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.17"
}
}

202
pages/blog.vue Normal file
View file

@ -0,0 +1,202 @@
<script setup>
import { onMounted, watch, ref } from 'vue';
import fm from 'front-matter';
import markdownit from 'markdown-it'
import PostCard from '../components/PostCard.vue';
import hljs from 'highlight.js';
// Automatically maintained is a blog_list.json in assets/. This file contains a list of all blog posts and their metadata.
// This file is generated by a script in the root directory of the project.
import blog_list from '../assets/blog_list.json';
const md = markdownit({
breaks: true,
typographer: true,
html: true,
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return '<pre><code class="hljs">' +
hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
'</code></pre>';
} catch (__) { }
}
return '<pre><code class="hljs">' + md.utils.escapeHtml(str) + '</code></pre>';
}
})
md.renderer.rules.hr = function (tokens, idx, options, env, self) {
return '<div class="rounded-full h-0.5 bg-purple-500 my-3"></div>'
}
md.renderer.rules.softbreak = function (tokens, idx, options, env, self) {
return '<br>'
}
md.renderer.rules.hardbreak = function (tokens, idx, options, env, self) {
return '<br><br>'
}
const modules = import.meta.glob('/blog/');
for (const path in modules) {
const module = await modules[path]();
console.log(path, module.default); // module.default contains the image data
}
let route = useRoute();
console.log(route)
const url = ref(null)
url.value = route.query.post
console.log(url.value)
const loading = ref(false)
const data = ref([])
const text = ref([])
const error = ref([])
const list = ref([])
const tagList = ref([])
const tagFilter = ref([])
tagFilter.value = []
const background = ref('');
const title = ref(null);
const description = ref(null);
const date = ref(null);
const tags = ref(null);
// watch the params of the route to fetch the data again
fetchData(url.value)
async function fetchData(url) {
error.value = data.value = null
loading.value = true
console.log(url)
try {
data.value = await $fetch(url)
console.log(data.value)
const processed = fm(data.value)
text.value = md.render(processed.body)
console.log(text.value)
background.value = processed.attributes.background
title.value = processed.attributes.title
description.value = processed.attributes.description
date.value = processed.attributes.date
tags.value = processed.attributes.tags
} catch (err) {
error.value = err.toString()
console.error(err)
loading.value = false
} finally {
loading.value = false
}
}
/* If tags are specified, include only posts with those tags */
/* else, include all posts */
async function fetchList() {
/*Example formatting:
{
"posts": [
{
"metadata": {
"test": "mrrp"
},
"id": "test",
"url": "/blog/test"
},
{
"metadata": {
" title": "Awesome", "description": "A curated list of awesome stuff I like", "date": "2024-11-26", "tags": ["awesome", "curated"]
},
"id": "awesome",
"url": "/blog/awesome"
},
{
"metadata": {
"test": "mrrp",
"test2": "nya"
},
"id": "test2",
"url": "/blog/test2"
}
]
}
*/
// Extract the posts
list.value = blog_list.posts
// Extract the tags
tagList.value = blog_list.posts.flatMap(post => post.metadata.tags).filter((tag, index, self) => self.indexOf(tag) === index)
}
fetchList()
</script>
<template>
<div class="relative z-50 flex w-full justify-center text-white">
<div class="mt-8 flex-col text-center">
<div v-if="url == null">
<h1>Blog</h1>
<div class="flex justify-center m-5">
<div v-for="tag in tagList" :key="tag" class="m-1 text-center">
<button
@click="tagFilter.includes(tag) ? tagFilter.splice(tagFilter.indexOf(tag), 1) : tagFilter.push(tag)"
class="text-xs bg-purple-800 border-purple-400 border text-white p-1 rounded-md"
:class="tagFilter.includes(tag) ? 'border-2 border-purple-200 bg-purple-500' : 'border-1 border-purple-600 bg-purple-800 text-white'">{{
tag }}</button>
</div>
</div>
<div>
<TransitionGroup name="list">
<div v-for="post in tagFilter.length == 0 ? list : list.filter(post => tagFilter.some(tag => post.metadata.tags.includes(tag)))" :key="post.id">
<PostCard :url="post.url" :key="post.id" />
</div>
</TransitionGroup>
</div>
</div>
<div v-else>
<div class="flex flex-col">
<h1>{{ title }}</h1>
<div class="max-w-50 flex flex-row justify-center">
<div v-for="tag in tags" :key="tag" class="m-1 text-center">
<span class="text-xs bg-purple-800 border-purple-400 border text-white p-1 rounded-md">{{
tag }}</span>
</div>
</div>
<div
class="text-pretty min-w-96 text-left max-w-4xl mt-4 p-6 max-md:w-screen rounded-md container bg-opacity-90 bg-purple-950">
<div v-html="text"></div>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.list-move,
.list-enter-active,
.list-leave-active {
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translate(100px, 0);
}
.list-leave-active {
position: absolute;
}
</style>

47
pages/index.vue Normal file
View file

@ -0,0 +1,47 @@
<script setup>
import { ref } from 'vue';
import aboutMe from '../assets/about_me.md?raw'
import markdownit from 'markdown-it'
import PostCard from '../components/PostCard.vue';
const md = markdownit({
breaks: true,
typographer: true,
html: true,
})
md.renderer.rules.hr = function(tokens, idx, options, env, self) {
return '<div class="rounded-full h-0.5 bg-purple-500 my-3"></div>'
}
md.renderer.rules.softbreak = function(tokens, idx, options, env, self) {
return '<br>'
}
md.renderer.rules.hardbreak = function(tokens, idx, options, env, self) {
return '<br><br>'
}
md.renderer.rules.blockquote_open = function(tokens, idx, options, env, self) {
return '<blockquote class="border-l-4 border-purple-500 pl-4 my-4">'
}
const result = ref('')
result.value = md.render(aboutMe);
</script>
<template>
<div class="relative z-50 flex w-full justify-center text-white">
<div class="mt-8 flex-col text-center">
<div class="flex justify-center">
<div class="p-2 shadow-md rounded-full bg-pink-500">
<img class="z-20 transition-all w-40 h-40 md:w-56 md:h-56 rounded-full" src="https://avatars.githubusercontent.com/u/94077364?v=4" alt="User PFP" />
</div>
</div>
<div class="max-w-4xl mt-4 p-6 max-md:w-screen rounded-md container bg-opacity-70 bg-purple-950">
<div v-html=result></div>
</div>
</div>
</div>
</template>

BIN
public/badges/nonbinary.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

BIN
public/badges/transfem.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 909 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/badges/transmasc.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,019 B

117
public/blog/awesome.md Normal file
View file

@ -0,0 +1,117 @@
---
title: Awesome
description: A curated list of awesome stuff I like
date: 2024-11-26
tags: ['awesome', 'curated']
---
# Awesome Stuff (WIP)
## Software
### Operating Systems
Honestly can't recommend Windows at all nowadays. It's just... Both spyware and bloatware. It's been enshittified to the point where it's just not worth using in comparison to Linux for most, if not all purposes nowadays, and the only thing it has going for it is existing software, which is a rapidly fading, if not fade***d***, advantage.
Windows Recall was especially egregious - The fact that a program that records all your screens, saves it to an unencrypted SQLite database, then feeds it to an AI network was *even on the table* is just... ***YIKES.***
- [Arch Linux](https://archlinux.org/)
> btw I use Arch
did I mention I use Arch
I use Arch btw just in case you didn't know
arch btw
/j
- [NixOS](https://nixos.org/)
> NixOS is a operating system that uses the Nix package manager. It's a great choice for people who want a declarative system configuration, and it's a great choice for people who want to be able to roll back to a previous system configuration if something goes wrong. It's also a great choice for people who want to be able to install packages without having to worry about dependency hell.
Because of the way NixOS works, I can use it pretty damn easily across my many systems, and it makes it easy to debloat if I need to.
## Software Development
### Languages
- [Rust](https://www.rust-lang.org/)
> I came to Rust from C/C++, and I've been loving it ever since. It's a great language that's easy to learn and has a lot of features that make it a great choice for systems programming. It's also a great choice for web development, and it's a decent choice for game development. It's a great choice for pretty much anything, really.
### Game Development
- [Godot Engine](https://godotengine.org)
> Nowadays, I'm mostly using Godot for game development. It's a great engine that's easy to use and has a lot of features. Plus, it's open-source, which is always a plus. The executable is in the magnitude of *MEGABYTES* and you can download it and just get going.
Unity is, at this point, inferior to Godot in my opinion for general purpose games. It's bloated as hell, slow, and has a lot of unnecessary core features that are often half-baked or deprecated - There is often 99 ways to do things, but none are good. It's not open source, and isn't nearly as capable of recompiling to cut down on unneeded features as a result. It's also not as user-friendly as Godot, and the documentation is often lacking or outdated. I've had a lot of issues with Unity, and I'm not a fan of it.
And on the other end, if you need high-fidelity games... Unreal Engine 5 is a no-brainer over Unity nowadays for the same purpose.
And for 2D games... Godot absolutely ***MOPS THE FLOOR WITH UNITY.*** It hardly even compares at this point.
- [Unreal Engine 5](https://www.unrealengine.com/)
> I don't use it much, but it's a great engine for high-fidelity games. It's a ***LOT*** more complex than Godot, but it's also more powerful. Plus, it's free to use until you make a certain amount of money, and they let you remain on the same licensing terms from when you start using it.
- [Material Maker](https://www.materialmaker.org/)
> Material Maker is a toolkit made in Godot that allows you to create procedural PBR materials, similar to how you would with Blender shaders.
It's a great tool for creating materials, and it's open-source, so you can modify it to your heart's content.
## Games
I will be using the Entertainment Software Rating Board's rating system for games, under my judgement if a rating does not already exist.
These may not actually be rated by the ESRB, but I will be using their rating system for simplicity.
See their [Ratings Guide](https://www.esrb.org/ratings-guide/) for more information about their rating system.
- [Celeste](https://www.celestegame.com/)
***Rated E10 for Everyone 10+ by the ESRB***
> What can I say? It's a great game. The story is touching, the gameplay is challenging, and the music is amazing.
Plus, the modding scene is very intense if you're into that.
Also... Heat from fire, fire from heat, if ya know. 🏳️‍⚧️
- [Wolfenstein: The New Order](https://store.steampowered.com/app/201810/Wolfenstein_The_New_Order/) and its sequel, [Wolfenstein: The New Colossus](https://store.steampowered.com/app/612880/Wolfenstein_II_The_New_Colossus/)
***Rated M for Mature 17+ by the ESRB***
> Before Id made DOOM in 1993, they made Wolfenstein, a game about beating up Nazis. Need I say more?
They made a new series of games, starting with The New Order, that are a great mix of story and gameplay. The story is great, the gameplay is great, and the music is great. Criminal that there isn't a third one, though.
- [OneShot](https://store.steampowered.com/app/420530/OneShot/)
***Rated E for Everyone by the ESRB***
> You only get one shot.
- [Papers, Please](https://store.steampowered.com/app/239030/Papers_Please/)
***Rated M for Mature 17+ by the ESRB***
> ***Glory to Arstotzka.***
- [Sonic Adventure 2](https://store.steampowered.com/app/213610/Sonic_Adventure_2/)
***Rated E10 for Everyone 10+ by the ESRB***
> I grew up with SA2. Sure, it has plenty of things that did NOT age well - Such as the audio mixing, the music is *twice as loud* as it should be during scenes, I can barely hear characters, or the quality of the ports being pretty abysmal - But it is still quite a fun game. The story is, perhaps, among the best, in the series, and Doctor Ivo "Eggman" Robotnik's characterization is ***OUTRIGHT the best in the series***. The music (Crush 40, anyone?) is also top-notch.
If you play this on PC, such as the Steam version, there exists a mod loader, and plenty of mods to improve the myriad issues with the port.
Mad Space is a bit maddening (Well, it's in the name I suppose) though, and the removal of the open-world that SA1 had isn't that great.
## Media
I will be using the Motion Picture Association's rating system for movies or media in general should it not have its own rating system, under my judgement if a rating does not already exist.
These may not actually be rated by the MPA, but I will be using their rating system for simplicity.
See the Motion Picture Association's [Film Ratings](https://www.motionpictures.org/film-ratings/) for more information about their rating system.
I will be using the TV Parental Guidelines's rating system for shows or series, under my judgement if a rating does not already exist.
These may not actually be rated by official organizations, but I will be using their rating system for simplicity.
### Shows
- [One Piece](https://www.crunchyroll.com/series/GRMG8ZQZR/one-piece)
***Rating varies depending on parts of the show, and movies and whatnot.***
***I rate the show as a range from TV-PG V to TV-MA LV.***
> Oda had better finish the story. I swear to Satan.
#### Fanmade
- [Dragon Ball Z Abridged](https://www.youtube.com/watch?v=2nYozPLpJRE&list=PL6EC7B047181AD013) (and related "movies" and videos) by TeamFourStar
***I rate this show and its movies as TV-MA DLSV (the whole shebang, in other words)***
> It's... The iconic parody of all time. It's a great show, and it's a shame that they aren't doing Buu Saga.
Even though the series is more comedy focused, it still manages to tell the story of Dragon Ball Z in an *excellent* way.
The creators are also based as hell.
...Watch it. Just watch it.

36
public/blog/badges.md Normal file
View file

@ -0,0 +1,36 @@
---
title: Badges!
description: A collection of 88x31 badges for various things
date: 2024-12-21
tags: ['badges', 'retro', 'web']
---
## A collection of 88x31 badges for various things
You can right-click any of these and either save or copy-link to use these badges on your site or profile.
### Myself
For adding to your site or profile.
Pending... Need to draw some up.
### LGBTQIA+
Very gay badges, incoming :3
(More to come, I'm still drawing them)
#### Identity
- Umbrellas
> [![Transgender](/badges/transgender.gif)](https://en.wikipedia.org/wiki/Transgender)
> [![Nonbinary](/badges/nonbinary.gif)](https://en.wikipedia.org/wiki/Non-binary)
- Specific Identities
> [![Transfem](/badges/transfem.gif)](https://en.wikipedia.org/wiki/Trans_woman)
> [![Transmasc](/badges/transmasc.gif)](https://en.wikipedia.org/wiki/Trans_man)
### Miscellaneous

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

1
public/robots.txt Normal file
View file

@ -0,0 +1 @@

3
server/tsconfig.json Normal file
View file

@ -0,0 +1,3 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}

30
tailwind.config.js Normal file
View file

@ -0,0 +1,30 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./components/**/*.{js,vue,ts}",
"./layouts/**/*.vue",
"./pages/**/*.vue",
"./plugins/**/*.{js,ts}",
"./app.vue",
"./error.vue",
],
theme: {
extend: {
keyframes: {
appear: {
"0%": {
opacity: "0",
},
"100%": {
opacity: "1",
},
},
animation: {
appear: "appear 0.5s ease-in-out",
}
}
},
},
plugins: [],
}

4
tsconfig.json Normal file
View file

@ -0,0 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}

80
utils/track_posts.sh Normal file
View file

@ -0,0 +1,80 @@
#!/bin/sh
# This is meant to track the contents of /public/blog/*.md
# to maintain an up-to-date list of blog posts.
#
# It outputs JSON to stdout:
# Given a file /public/blog/2019-01-01-foo-bar.md of contents:
#
# ---
# title: Foo Bar
# date: 2019-01-01
# arbitrary_key: arbitrary_value
# ---
# # Foo Bar
#
# it will output:
# {
# posts: [
# {
# id: "2019-01-01-foo-bar",
# title: "Foo Bar",
# date: "2019-01-01",
# arbitrary_key: "arbitrary_value",
# url: "/blog/2019-01-01-foo-bar"
# }
# ]
# }
# It should also read the YAML Front Matter of each post
# and place all the keys in the JSON output.
# The script should be run from the root of the project.
# SCRIPT ENTRY
echo "{"
echo " \"posts\": ["
# Front-Matter Extraction (procedure)
# Given data, extract the YAML Front Matter header
# and output it as JSON.
extract_front_matter() {
local data="$1"
local front_matter=$(echo "$data" | sed -n '/^---/,/^---/p')
echo "$front_matter" | sed '1d;$d' | sed 's/^/ "/' | sed 's/: /": "/' | sed 's/$/"/' | tr '\n' ',' | sed 's/,$//' | sed 's/"tags": "\[\(.*\)\]"/"tags": \[\1\]/g' | sed "s/'/\"/g"
}
# Find files via Regex
# Find all files in /public/blog/*.md
# Process and extract the front matter of each file.
# Output the JSON representation of the front matter.
extract_files() {
local files=$(find public/blog -type f -name "*.md")
for file in $files; do
# Enter, create {} for each file
echo " {"
echo " \"metadata\": {"
local data=$(cat $file)
local front_matter=$(extract_front_matter "$data")
echo "$front_matter"
echo " },"
# Add the id and url
local id=$(echo "$file" | sed 's/public\/blog\///' | sed 's/\.md//')
echo " \"id\": \"$id\","
echo " \"url\": \"/blog/$id.md\""
# Exit, close {} for each file
echo " },"
done
}
# Process all files
extract_files | sed '$s/,$//'
# SCRIPT EXIT
echo " ]"
echo "}"