feat(projects): load projects from content/
@@ -1,6 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Background from "./Background.vue";
|
import Background from "./Background.vue";
|
||||||
import Projects from "./Projects.vue";
|
import Projects from "./Projects.vue";
|
||||||
|
|
||||||
|
const store = useProjectsStore();
|
||||||
|
|
||||||
|
store.$reset();
|
||||||
|
await store.loadProjects();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// TODO: handle mouse wheel
|
|
||||||
|
|
||||||
import gsap from "gsap";
|
import gsap from "gsap";
|
||||||
import SELECTOR_IMAGE from "/assets/images/projects/bottom-screen/selector.webp";
|
import SELECTOR_IMAGE from "/assets/images/projects/bottom-screen/selector.webp";
|
||||||
import PROJECT_SQUARE_IMAGE from "/assets/images/projects/bottom-screen/project-square.webp";
|
import PROJECT_SQUARE_IMAGE from "/assets/images/projects/bottom-screen/project-square.webp";
|
||||||
import { useKeyDown } from "~/composables/useKeyDown";
|
|
||||||
|
|
||||||
const store = useProjectsStore();
|
const store = useProjectsStore();
|
||||||
|
|
||||||
@@ -68,7 +65,7 @@ useRender((ctx) => {
|
|||||||
|
|
||||||
ctx.font = "10px NDS10";
|
ctx.font = "10px NDS10";
|
||||||
|
|
||||||
const lines = store.projects[store.currentProject]!.description.split("\n");
|
const lines = store.projects[store.currentProject]!.description.split("\\n");
|
||||||
const textY = lines.length === 1 ? 35 : 28;
|
const textY = lines.length === 1 ? 35 : 28;
|
||||||
for (let i = 0; i < lines.length; i += 1) {
|
for (let i = 0; i < lines.length; i += 1) {
|
||||||
const { actualBoundingBoxRight: width } = ctx.measureText(lines[i]!);
|
const { actualBoundingBoxRight: width } = ctx.measureText(lines[i]!);
|
||||||
|
|||||||
@@ -1,67 +1,15 @@
|
|||||||
import PIHKAAL_ME_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/pihkaal.me.webp";
|
// import PIHKAAL_ME_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/pihkaal.me.webp";
|
||||||
import TLOCK_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/tlock.webp";
|
// import TLOCK_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/tlock.webp";
|
||||||
import SIMPLE_QR_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/simple-qr.webp";
|
// import SIMPLE_QR_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/simple-qr.webp";
|
||||||
import LILOU_CAT_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/lilou.cat.webp";
|
// import LILOU_CAT_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/lilou.cat.webp";
|
||||||
import LBF_BOT_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/lbf-bot.webp";
|
// import LBF_BOT_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/lbf-bot.webp";
|
||||||
import RAYLIB_SPEENDRUNS_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/raylib-speedruns.webp";
|
// import RAYLIB_SPEENDRUNS_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/raylib-speedruns.webp";
|
||||||
import SP3WEB_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/s3pweb.webp";
|
// import SP3WEB_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/s3pweb.webp";
|
||||||
import BIOBLEUD_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/biobleud.webp";
|
// import BIOBLEUD_THUMBNAIL from "/assets/images/projects/bottom-screen/thumbnails/biobleud.webp";
|
||||||
|
|
||||||
export const useProjectsStore = defineStore("projects", {
|
export const useProjectsStore = defineStore("projects", {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
// prettier-ignore
|
projects: [] as {
|
||||||
projects: [
|
|
||||||
{
|
|
||||||
description: "pihkaal.me - my personal website",
|
|
||||||
thumbnail: PIHKAAL_ME_THUMBNAIL,
|
|
||||||
url: "https://pihkaal.me",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "tlock - fully customizable and cross-\nplatform terminal based clock",
|
|
||||||
thumbnail: TLOCK_THUMBNAIL,
|
|
||||||
url: "https://github.com/pihkaal/tlock",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Simple QR - Simple QR code generator\nwith straightforward API",
|
|
||||||
thumbnail: SIMPLE_QR_THUMBNAIL,
|
|
||||||
url: "https://simple-qr.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "lilou.cat - My cat's website",
|
|
||||||
thumbnail: LILOU_CAT_THUMBNAIL,
|
|
||||||
url: "https://lilou.cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "LBF Bot - Custom Discord bot for\na gaming group",
|
|
||||||
thumbnail: LBF_BOT_THUMBNAIL,
|
|
||||||
url: "https://github.com/pihkaal/lbf-bot",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Raylib Speedruns - Collection of simple\nRaylib setups in multiple languages",
|
|
||||||
thumbnail: RAYLIB_SPEENDRUNS_THUMBNAIL,
|
|
||||||
url: "https://github.com/pihkaal/raylib-speedruns",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "S3P Map Editor - Web based map editor\nspecialized for trucks",
|
|
||||||
thumbnail: SP3WEB_THUMBNAIL,
|
|
||||||
url: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "S3P Eramba Visualizer - Eramba\nasset visualization",
|
|
||||||
thumbnail: SP3WEB_THUMBNAIL,
|
|
||||||
url: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "S3P Incident Engine - Automated\nalerts to Jira",
|
|
||||||
thumbnail: SP3WEB_THUMBNAIL,
|
|
||||||
url: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Biobleud - Automated Excel imports\nfor an ERP system",
|
|
||||||
thumbnail: BIOBLEUD_THUMBNAIL,
|
|
||||||
url: null,
|
|
||||||
},
|
|
||||||
] satisfies {
|
|
||||||
description: string;
|
description: string;
|
||||||
thumbnail: string;
|
thumbnail: string;
|
||||||
url: string | null;
|
url: string | null;
|
||||||
@@ -70,6 +18,14 @@ export const useProjectsStore = defineStore("projects", {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
async loadProjects() {
|
||||||
|
const { data: projects } = await useAsyncData("projects", () =>
|
||||||
|
queryCollection("projects").order("order", "ASC").all(),
|
||||||
|
);
|
||||||
|
if (!projects.value) throw "Cannot load projects";
|
||||||
|
this.projects = projects.value;
|
||||||
|
},
|
||||||
|
|
||||||
visitProject() {
|
visitProject() {
|
||||||
const url = this.projects[this.currentProject]!.url;
|
const url = this.projects[this.currentProject]!.url;
|
||||||
if (url) navigateTo(url, { external: true, open: { target: "_blank" } });
|
if (url) navigateTo(url, { external: true, open: { target: "_blank" } });
|
||||||
|
|||||||
17
content.config.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { defineContentConfig, defineCollection } from "@nuxt/content";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export default defineContentConfig({
|
||||||
|
collections: {
|
||||||
|
projects: defineCollection({
|
||||||
|
type: "page",
|
||||||
|
source: "projects/*.md",
|
||||||
|
schema: z.object({
|
||||||
|
description: z.string(),
|
||||||
|
url: z.url().nullable(),
|
||||||
|
thumbnail: z.string(),
|
||||||
|
order: z.number(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
6
content/projects/biobleud.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: Biobleud - Automated Excel imports\nfor an ERP system
|
||||||
|
url: null
|
||||||
|
thumbnail: /images/projects/biobleud.webp
|
||||||
|
order: 100
|
||||||
|
---
|
||||||
6
content/projects/lbf-bot.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: LBF Bot - Custom Discord bot for\na gaming group
|
||||||
|
url: https://github.com/pihkaal/lbf-bot
|
||||||
|
thumbnail: /images/projects/lbf-bot.webp
|
||||||
|
order: 50
|
||||||
|
---
|
||||||
6
content/projects/lilou-cat.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: lilou.cat - My cat's website
|
||||||
|
url: https://lilou.cat
|
||||||
|
thumbnail: /images/projects/lilou-cat.webp
|
||||||
|
order: 40
|
||||||
|
---
|
||||||
6
content/projects/pihkaal-me.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: pihkaal.me - my personal website
|
||||||
|
url: https://pihkaal.me
|
||||||
|
thumbnail: /images/projects/pihkaal-me.webp
|
||||||
|
order: 10
|
||||||
|
---
|
||||||
6
content/projects/raylib-speedruns.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: Raylib Speedruns - Collection of simple\nRaylib setups in multiple languages
|
||||||
|
url: https://github.com/pihkaal/raylib-speedruns
|
||||||
|
thumbnail: /images/projects/raylib-speedruns.webp
|
||||||
|
order: 60
|
||||||
|
---
|
||||||
6
content/projects/s3p-eramba-visualizer.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: S3P Eramba Visualizer - Eramba\nasset visualization
|
||||||
|
url: null
|
||||||
|
thumbnail: /images/projects/s3pweb.webp
|
||||||
|
order: 80
|
||||||
|
---
|
||||||
6
content/projects/s3p-incident-engine.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: S3P Incident Engine - Automated\nalerts to Jira
|
||||||
|
url: null
|
||||||
|
thumbnail: /images/projects/s3pweb.webp
|
||||||
|
order: 90
|
||||||
|
---
|
||||||
6
content/projects/s3p-map-editor.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: S3P Map Editor - Web based map editor\nspecialized for trucks
|
||||||
|
url: null
|
||||||
|
thumbnail: /images/projects/s3pweb.webp
|
||||||
|
order: 70
|
||||||
|
---
|
||||||
6
content/projects/simple-qr.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: Simple QR - Simple QR code generator\nwith straightforward API
|
||||||
|
url: https://simple-qr.com
|
||||||
|
thumbnail: /images/projects/simple-qr.webp
|
||||||
|
order: 30
|
||||||
|
---
|
||||||
6
content/projects/tlock.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
description: tlock - fully customizable and cross-\nplatform terminal based clock
|
||||||
|
url: https://github.com/pihkaal/tlock
|
||||||
|
thumbnail: /images/projects/tlock.webp
|
||||||
|
order: 20
|
||||||
|
---
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: "2025-07-15",
|
compatibilityDate: "2025-07-15",
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
modules: ["@nuxt/eslint", "@pinia/nuxt"],
|
modules: ["@nuxt/eslint", "@nuxt/content", "@pinia/nuxt"],
|
||||||
css: ["~/assets/app.css"],
|
css: ["~/assets/app.css"],
|
||||||
ssr: false,
|
ssr: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,9 @@
|
|||||||
"lint": "eslint --fix --cache ."
|
"lint": "eslint --fix --cache ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@nuxt/content": "^3.8.2",
|
||||||
"@pinia/nuxt": "0.11.3",
|
"@pinia/nuxt": "0.11.3",
|
||||||
|
"better-sqlite3": "^12.4.1",
|
||||||
"gsap": "^3.13.0",
|
"gsap": "^3.13.0",
|
||||||
"nuxt": "^4.2.1",
|
"nuxt": "^4.2.1",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
@@ -23,6 +25,7 @@
|
|||||||
"@nuxt/eslint": "^1.10.0",
|
"@nuxt/eslint": "^1.10.0",
|
||||||
"eslint": "^9.39.1",
|
"eslint": "^9.39.1",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3",
|
||||||
|
"zod": "^4.1.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2602
pnpm-lock.yaml
generated
@@ -1,4 +1,5 @@
|
|||||||
onlyBuiltDependencies:
|
onlyBuiltDependencies:
|
||||||
- "@parcel/watcher"
|
- "@parcel/watcher"
|
||||||
|
- better-sqlite3
|
||||||
- esbuild
|
- esbuild
|
||||||
- unrs-resolver
|
- unrs-resolver
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 42 B After Width: | Height: | Size: 42 B |
|
Before Width: | Height: | Size: 42 B After Width: | Height: | Size: 42 B |
|
Before Width: | Height: | Size: 42 B After Width: | Height: | Size: 42 B |
|
Before Width: | Height: | Size: 42 B After Width: | Height: | Size: 42 B |
|
Before Width: | Height: | Size: 42 B After Width: | Height: | Size: 42 B |
|
Before Width: | Height: | Size: 42 B After Width: | Height: | Size: 42 B |
|
Before Width: | Height: | Size: 94 B After Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 42 B After Width: | Height: | Size: 42 B |