feat: rewrite cv about text
All checks were successful
Docker / build-and-push-image (push) Successful in 2m13s

This commit is contained in:
Troy 2025-07-25 16:55:23 +01:00
parent a4fc110eb3
commit c7be9f3aba
Signed by: troy
GPG key ID: DFC06C02ED3B4711
18 changed files with 197 additions and 179 deletions

31
package-lock.json generated
View file

@ -13,7 +13,7 @@
"@astrojs/rss": "^4.0.12", "@astrojs/rss": "^4.0.12",
"@astrojs/sitemap": "3.4.1", "@astrojs/sitemap": "3.4.1",
"@tailwindcss/vite": "^4.1.11", "@tailwindcss/vite": "^4.1.11",
"astro": "^5.12.0", "astro": "^5.12.3",
"astro-icon": "^1.1.5", "astro-icon": "^1.1.5",
"rehype-external-links": "^3.0.0", "rehype-external-links": "^3.0.0",
"tailwindcss": "^4.1.11", "tailwindcss": "^4.1.11",
@ -22,8 +22,8 @@
"devDependencies": { "devDependencies": {
"@iconify-json/mdi": "^1.2.3", "@iconify-json/mdi": "^1.2.3",
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@types/node": "^24.0.15", "@types/node": "^24.1.0",
"npm-check-updates": "^18.0.1", "npm-check-updates": "^18.0.2",
"prettier": "^3.6.2", "prettier": "^3.6.2",
"prettier-plugin-astro": "^0.14.1", "prettier-plugin-astro": "^0.14.1",
"prettier-plugin-tailwindcss": "^0.6.14" "prettier-plugin-tailwindcss": "^0.6.14"
@ -2139,9 +2139,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "24.0.15", "version": "24.1.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.15.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz",
"integrity": "sha512-oaeTSbCef7U/z7rDeJA138xpG3NuKc64/rZ2qmUFkFJmnMsAPaluIifqyWd8hSSMxyP9oie3dLAqYPblag9KgA==", "integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~7.8.0" "undici-types": "~7.8.0"
@ -2455,9 +2455,9 @@
} }
}, },
"node_modules/astro": { "node_modules/astro": {
"version": "5.12.0", "version": "5.12.3",
"resolved": "https://registry.npmjs.org/astro/-/astro-5.12.0.tgz", "resolved": "https://registry.npmjs.org/astro/-/astro-5.12.3.tgz",
"integrity": "sha512-Oov5JsMFHuUmuO+Nx6plfv3nQNK1Xl/8CgLvR8lBhZTjYnraxhuPX5COVAzbom+YLgwaDfK7KBd8zOEopRf9mg==", "integrity": "sha512-fU1hNPMkccm+FuonGsY5DFkC2QyuLCju++8L2ubzBtYBDBf6bmfgmVM7A2dK+Hl+ZJCUNgepsClhBpczj+2LRw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@astrojs/compiler": "^2.12.2", "@astrojs/compiler": "^2.12.2",
@ -3888,14 +3888,15 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.2", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
@ -6243,9 +6244,9 @@
} }
}, },
"node_modules/npm-check-updates": { "node_modules/npm-check-updates": {
"version": "18.0.1", "version": "18.0.2",
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-18.0.1.tgz", "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-18.0.2.tgz",
"integrity": "sha512-MO7mLp/8nm6kZNLLyPgz4gHmr9tLoU+pWPLdXuGAx+oZydBHkHWN0ibTonsrfwC2WEQNIQxuZagYwB67JQpAuw==", "integrity": "sha512-9uVFZUCg5oDOcbzdsrJ4BEvq2gikd23tXuF5mqpl4mxVl051lzB00Xmd7ZVjVWY3XNUF3BQKWlN/qmyD8/bwrA==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {

View file

@ -17,7 +17,7 @@
"@astrojs/rss": "^4.0.12", "@astrojs/rss": "^4.0.12",
"@astrojs/sitemap": "3.4.1", "@astrojs/sitemap": "3.4.1",
"@tailwindcss/vite": "^4.1.11", "@tailwindcss/vite": "^4.1.11",
"astro": "^5.12.0", "astro": "^5.12.3",
"astro-icon": "^1.1.5", "astro-icon": "^1.1.5",
"rehype-external-links": "^3.0.0", "rehype-external-links": "^3.0.0",
"tailwindcss": "^4.1.11", "tailwindcss": "^4.1.11",
@ -26,8 +26,8 @@
"devDependencies": { "devDependencies": {
"@iconify-json/mdi": "^1.2.3", "@iconify-json/mdi": "^1.2.3",
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@types/node": "^24.0.15", "@types/node": "^24.1.0",
"npm-check-updates": "^18.0.1", "npm-check-updates": "^18.0.2",
"prettier": "^3.6.2", "prettier": "^3.6.2",
"prettier-plugin-astro": "^0.14.1", "prettier-plugin-astro": "^0.14.1",
"prettier-plugin-tailwindcss": "^0.6.14" "prettier-plugin-tailwindcss": "^0.6.14"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View file

@ -43,7 +43,7 @@ const { information } = Astro.props;
<div class="grow text-right"> <div class="grow text-right">
<p class="text-tertiary font-mono text-sm text-nowrap">{item.date}</p> <p class="text-tertiary font-mono text-sm text-nowrap">{item.date}</p>
{item.date_opt ? ( {item.date_opt ? (
<p class="text-secondary/70 text-xs">{item.date_opt}</p> <p class="text-secondary/70 text-sm">{item.date_opt}</p>
) : null} ) : null}
</div> </div>
</li> </li>

View file

@ -9,7 +9,7 @@ const { href, link } = Astro.props;
<a href={`${href}`}> <a href={`${href}`}>
<div <div
class="bg-button text-secondary hover:bg-button-active flex w-fit flex-row items-center gap-1 justify-self-center rounded-md px-3 py-1.5 text-center text-sm font-medium text-nowrap capitalize transition-colors duration-300" class="bg-button text-secondary hover:bg-button-active flex w-fit flex-row items-center gap-1 justify-self-center rounded-md px-3 py-1.5 text-center text-sm font-medium text-nowrap transition-colors duration-300"
> >
{link} {link}
</div> </div>

View file

@ -17,21 +17,14 @@ const { items } = Astro.props as Props;
<div class="grid grid-cols-1 gap-3 md:grid-cols-2"> <div class="grid grid-cols-1 gap-3 md:grid-cols-2">
{ {
items.map((item: Item) => ( items.map((item: Item) => (
<div class="flex-col overflow-hidden rounded-sm"> <div class="aspect-square flex-col overflow-hidden rounded-sm">
{item.src && ( {item.src && (
<a <Image
href={item.src.src} src={item.src}
target="_blank" alt={item.alt}
class="cursor-zoom-in" loading="lazy"
title="Open image in new tab" class="mt-0 mb-0 aspect-square h-full w-full object-cover"
> />
<Image
src={item.src}
alt={item.alt}
loading="lazy"
class="mt-0 mb-0 h-full max-h-[90svh] w-full object-cover"
/>
</a>
)} )}
</div> </div>
)) ))

View file

@ -9,7 +9,7 @@
class="text-secondary/70 animate-reveal text-lg font-medium opacity-0 [animation-delay:0.1s]" class="text-secondary/70 animate-reveal text-lg font-medium opacity-0 [animation-delay:0.1s]"
> >
Im a recent <a Im a recent <a
href="/about#education" href="/about"
class="text-secondary decoration-tertiary underline hover:no-underline" class="text-secondary decoration-tertiary underline hover:no-underline"
>Game Arts and Design</a >Game Arts and Design</a
> graduate with a chosen area of focus on the design, lighting, and rendering > graduate with a chosen area of focus on the design, lighting, and rendering

View file

@ -17,7 +17,7 @@ const { collection } = Astro.props;
src={collection.data.image.url} src={collection.data.image.url}
alt={collection.data.image.alt} alt={collection.data.image.alt}
loading="eager" loading="eager"
class="aspect-[2/1] object-cover transition-all duration-300 ease-in-out group-hover:brightness-50" class="aspect-square object-cover transition-all duration-300 ease-in-out group-hover:brightness-50"
fit="cover" fit="cover"
/> />
</div> </div>
@ -25,7 +25,16 @@ const { collection } = Astro.props;
class="relative opacity-0 transition-all delay-100 duration-300 ease-in-out group-hover:opacity-100" class="relative opacity-0 transition-all delay-100 duration-300 ease-in-out group-hover:opacity-100"
> >
<p class="absolute right-5 bottom-5 font-medium text-white"> <p class="absolute right-5 bottom-5 font-medium text-white">
{collection.data.title} {
collection.data.collection ? (
<span>
{collection.data.title}{" "}
<span class="font-light">(Collection)</span>
</span>
) : (
<span>{collection.data.title}</span>
)
}
</p> </p>
</div> </div>
{ {

View file

@ -3,7 +3,7 @@ import type { Metadata, Site } from "@types";
export const SITE: Site = { export const SITE: Site = {
TITLE: "Troy Lusty", TITLE: "Troy Lusty",
DESCRIPTION: DESCRIPTION:
"Hi, my name is Troy and Im a student 3D artist studying on a BA (Hons) Game Arts and Design course in the UK.", "Hi, my name is Troy and Im a recent Game Arts and Design graduate with a chosen area of focus on the design, lighting, and rendering of 3D environments.",
EMAIL: "hello@troylusty.com", EMAIL: "hello@troylusty.com",
KEYWORDS: [ KEYWORDS: [
"troy", "troy",
@ -74,7 +74,7 @@ export const SITE: Site = {
export const HOME: Metadata = { export const HOME: Metadata = {
TITLE: "Troy Lusty", TITLE: "Troy Lusty",
DESCRIPTION: DESCRIPTION:
"Hi, my name is Troy and I'm a student 3D artist currently studying in my second year of an FdA Games and Interactive Design course in the UK.", "Hi, my name is Troy and Im a recent Game Arts and Design graduate with a chosen area of focus on the design, lighting, and rendering of 3D environments.",
}; };
export const PROJECTS: Metadata = { export const PROJECTS: Metadata = {

View file

@ -56,6 +56,7 @@ const projects = defineCollection({
featured: z.boolean().optional(), featured: z.boolean().optional(),
collection: z.boolean().optional(), collection: z.boolean().optional(),
highlight: z.boolean().optional(), highlight: z.boolean().optional(),
rank: z.number().optional().default(0),
}) })
.merge(rssSchema), .merge(rssSchema),
}); });

View file

@ -7,6 +7,7 @@ image: { url: "alwd-img1.jpg", alt: "A Long Way Down Intro Showcase" }
tags: ["unreal engine", "blender", "inkscape"] tags: ["unreal engine", "blender", "inkscape"]
categories: ["education"] categories: ["education"]
extraAuthors: [{ name: "Sam Griffiths", url: "https://samgriffiths.dev" }] extraAuthors: [{ name: "Sam Griffiths", url: "https://samgriffiths.dev" }]
rank: 7
--- ---
import Gallery from "@components/Gallery.astro"; import Gallery from "@components/Gallery.astro";

View file

@ -1,6 +1,6 @@
--- ---
title: "Archive" title: "Archive"
description: "A collection of smaller, unfinished, or historic personal works." description: "A collection of smaller, historic, or incomplete personal works."
date: 2021-01-15 date: 2021-01-15
featured: true featured: true
image: { url: "2023-11-23.jpg", alt: "Ugolino and His Sons lighting" } image: { url: "2023-11-23.jpg", alt: "Ugolino and His Sons lighting" }
@ -8,6 +8,7 @@ tags:
[ [
"blender", "blender",
"unreal engine", "unreal engine",
"houdini",
"davinci resolve", "davinci resolve",
"photoshop", "photoshop",
"gimp", "gimp",
@ -15,11 +16,13 @@ tags:
] ]
categories: ["personal"] categories: ["personal"]
highlight: true highlight: true
rank: 10
collection: true
--- ---
import Gallery from "@components/Gallery.astro"; import Gallery from "@components/Gallery.astro";
Whilst not all of these pieces are large enough to have their own project page, I still think they showcase what I am interested in and it didn't feel right to exclude them entirely. This page receives updates periodically. Whilst not all of these pieces are large enough to have their own project page, I still think they showcase what I am interested in and it didn't feel right to exclude them entirely. This page receives updates periodically with work not necessarily being arranged in order of completion.
import video2023_04_08 from "./2023-04-08.webm"; import video2023_04_08 from "./2023-04-08.webm";
import video2023_02_08 from "./2023-02-08.webm"; import video2023_02_08 from "./2023-02-08.webm";

View file

@ -10,6 +10,7 @@ image:
featured: true featured: true
tags: ["blender", "davinci resolve"] tags: ["blender", "davinci resolve"]
categories: ["personal"] categories: ["personal"]
rank: 9
--- ---
import Gallery from "@components/Gallery.astro"; import Gallery from "@components/Gallery.astro";

View file

@ -16,6 +16,7 @@ tags:
"clip studio paint", "clip studio paint",
] ]
categories: ["education"] categories: ["education"]
rank: 8
--- ---
import image1 from "googleformexportframe_3.1.1.jpg"; import image1 from "googleformexportframe_3.1.1.jpg";

View file

@ -6,6 +6,7 @@ image: { url: "15.jpg", alt: "Tomb final" }
tags: ["blender", "affinity photo", "affinity designer", "gimp"] tags: ["blender", "affinity photo", "affinity designer", "gimp"]
categories: ["personal"] categories: ["personal"]
featured: true featured: true
rank: 6
--- ---
import Gallery from "@components/Gallery.astro"; import Gallery from "@components/Gallery.astro";

View file

@ -1,20 +1,15 @@
--- ---
import Layout from "@layouts/Layout.astro"; import Layout from "@layouts/Layout.astro";
import { SITE, ABOUT } from "@consts"; import { SITE, ABOUT } from "@consts";
import { Image } from "astro:assets";
import { Icon } from "astro-icon/components"; import { Icon } from "astro-icon/components";
import Link from "@components/Link.astro"; import Link from "@components/Link.astro";
import { createSlug } from "@lib/utils";
import AboutList from "@components/AboutList.astro"; import AboutList from "@components/AboutList.astro";
import me from "@assets/me.jpg";
import camoicon from "@assets/camouflage-store.png"; import camoicon from "@assets/camouflage-store.png";
import nisaicon from "@assets/nisa.png"; import nisaicon from "@assets/nisa.png";
import pphicon from "@assets/paigntonpicturehouse.png"; import pphicon from "@assets/paigntonpicturehouse.png";
import webbossicon from "@assets/webboss.png"; import webbossicon from "@assets/webboss.png";
import uopicon from "@assets/uop.png"; import uopicon from "@assets/uop.png";
import ucsdicon from "@assets/ucsd.png";
import sdcicon from "@assets/sdc.png"; import sdcicon from "@assets/sdc.png";
import keviccicon from "@assets/kevicc.png"; import keviccicon from "@assets/kevicc.png";
@ -23,8 +18,16 @@ const projects = [
id: 1, id: 1,
name: "MUST FIND BEANS", name: "MUST FIND BEANS",
description: description:
"A fast-paced first person shooter set following the realization that youre all out of beans. The problem is, youre nearing the end of cooking all the other items and you cant just not have them. Without beans, the day just wont be started off right.", "A fast-paced first person shooter set following the realization that youre all out of beans, and without beans the day just wont be started off right. This game is very early in development but there is a public playtest available on Steam.",
tags: ["Godot", "Blender", "GIMP", "Steamworks"], tags: [
"Godot",
"Blender",
"GIMP",
"Steamworks",
"Git version control",
"Performance optimisation",
"GDScript",
],
link: "/projects/must-find-beans", link: "/projects/must-find-beans",
print_link: "https://troylusty.com/projects/must-find-beans", print_link: "https://troylusty.com/projects/must-find-beans",
done: false, done: false,
@ -33,8 +36,18 @@ const projects = [
id: 2, id: 2,
name: "Sinkie Soldiers", name: "Sinkie Soldiers",
description: description:
"Sinkie Soldiers is a local co-op versus game in which you battle against your friends for control of the castle! Your goal is to break down the integrity of your enemy's armour and finish them off to claim the victory.", "Sinkie Soldiers is a local co-op versus game in which you battle against your friends for control of the castle! This started off as a game jam submission but is being polished up and published onto Steam.",
tags: ["Unreal Engine", "Blender", "GIMP", "FL Studio", "Inkscape"], tags: [
"Unreal Engine",
"Blender",
"GIMP",
"FL Studio",
"Inkscape",
"Asset creation",
"Team collaboration",
"Time management",
"Branding design",
],
link: "/projects/sinkie-soldiers", link: "/projects/sinkie-soldiers",
print_link: "https://troylusty.com/projects/sinkie-soldiers", print_link: "https://troylusty.com/projects/sinkie-soldiers",
done: true, done: true,
@ -43,13 +56,15 @@ const projects = [
id: 3, id: 3,
name: "troylusty.com", name: "troylusty.com",
description: description:
"My personal website made using Astro as a way to show off my portfolio of work and display blog posts.", "My personal website made using Astro as a way to show off my portfolio of work, display blog posts, and host my CV.",
tags: [ tags: [
"Astro", "Astro",
"Tailwind CSS", "Tailwind CSS",
"TypeScript", "TypeScript",
"Self-hosted Forgejo Actions", "Self-hosted Forgejo Actions",
"Docker", "Docker",
"CI/CD",
"Open source",
], ],
link: "https://code.threepop.com/troy/troylusty.com", link: "https://code.threepop.com/troy/troylusty.com",
print_link: "https://code.threepop.com/troy/troylusty.com", print_link: "https://code.threepop.com/troy/troylusty.com",
@ -59,8 +74,18 @@ const projects = [
id: 4, id: 4,
name: "Artwork", name: "Artwork",
description: description:
"A collection of digital artwork created with a variety of tools.", "A collection of digital artwork created with a variety of tools to showcase software proficiency and develop skills.",
tags: ["Blender", "Cinema 4D", "DaVinci Resolve"], tags: [
"Blender",
"Cinema 4D",
"Houdini",
"DaVinci Resolve",
"Image manipulation",
"Environment design",
"Lighting",
"Cycles",
"EEVEE",
],
link: "/projects", link: "/projects",
print_link: "https://troylusty.com/projects", print_link: "https://troylusty.com/projects",
done: true, done: true,
@ -70,7 +95,7 @@ const projects = [
name: "Packard", name: "Packard",
description: description:
"Packard is a simple terminal based RSS aggregator meant to allow you to take a quick glance at whats occurring in topics you care about.", "Packard is a simple terminal based RSS aggregator meant to allow you to take a quick glance at whats occurring in topics you care about.",
tags: ["Rust", "Tokio", "Clap", "NixOS Flake"], tags: ["Rust", "Tokio", "NixOS Flake", "Command-line interaction"],
link: "/projects/packard", link: "/projects/packard",
print_link: "https://troylusty.com/projects/packard", print_link: "https://troylusty.com/projects/packard",
done: true, done: true,
@ -89,23 +114,23 @@ const experience = [
}, },
{ {
id: 2, id: 2,
location: "Paignton Picture House Trust",
image: pphicon,
main: "Photogrammetrist (Volunteer)",
date: "2023",
},
{
id: 3,
location: "Nisa", location: "Nisa",
image: nisaicon, image: nisaicon,
main: "Promotional graphic design", main: "Promotional graphic design",
date: "2022", date: "2022",
}, },
{
id: 3,
location: "Paignton Picture House Trust",
image: pphicon,
main: "Photogrammetrist (Volunteering)",
date: "2023",
},
{ {
id: 4, id: 4,
location: "WebBoss", location: "WebBoss",
image: webbossicon, image: webbossicon,
main: "Website mock-up templates (Work experience)", main: "Website template design (Work experience)",
date: "2019", date: "2019",
}, },
]; ];
@ -117,16 +142,9 @@ const education = [
location: "University of Plymouth", location: "University of Plymouth",
image: uopicon, image: uopicon,
main: "BA (Hons) Game Arts and Design", main: "BA (Hons) Game Arts and Design",
date: "2024 - 2025", date: "2022 - 2025",
date_opt: "First Class Honours", date_opt: "First Class Honours",
}, },
{
id: 2,
location: "University Centre South Devon",
image: ucsdicon,
main: "FdA Games and Interactive Design",
date: "2022 - 2024",
},
{ {
id: 3, id: 3,
location: "South Devon College", location: "South Devon College",
@ -136,9 +154,9 @@ const education = [
}, },
{ {
id: 4, id: 4,
location: "King Edward VI Community College", location: "King Edward VI Community College (Kennicott)",
image: keviccicon, image: keviccicon,
main: "Art & Design BTEC, Computer Science A-level, 10 GCSEs, Creative iMedia Level 2", main: "Art & Design BTEC and Computer Science A-level",
date: "2014 - 2020", date: "2014 - 2020",
}, },
]; ];
@ -180,74 +198,73 @@ const sortedLinks = [...links].sort((a, b) => a.id - b.id);
--- ---
<Layout title={SITE.TITLE} description={ABOUT.DESCRIPTION}> <Layout title={SITE.TITLE} description={ABOUT.DESCRIPTION}>
<div class="animate-reveal flex items-center justify-between opacity-0"> <section
<div class="flex-1 space-y-1.5"> class="animate-reveal items-center justify-between space-y-1.5 opacity-0"
<h1 >
class="animate-reveal flex flex-col text-start text-3xl font-semibold opacity-0 sm:block" <h1
> class="animate-reveal flex flex-col text-start text-3xl font-semibold opacity-0 sm:block"
<span class="text-secondary text-nowrap">{SITE.AUTHOR}</span><span
class="text-tertiary sm:ml-2">Digital designer</span
>
</h1>
<p class="text-secondary/70 max-w-md text-pretty">
<Link
class="decoration-tertiary inline-flex items-center gap-x-1.5 align-baseline leading-none hover:underline hover:decoration-2 hover:underline-offset-2"
href="https://www.google.com/maps/place/Devon"
>
<Icon name="mdi:earth" class="h-5 w-auto" />
Devon, United Kingdom, GMT
</Link>
</p>
<div class="text-secondary/70 flex gap-x-2 text-sm print:hidden">
{
sortedLinks.map((link) => (
<Link
href={link.href}
aria-label={link.label}
class="text-tertiary hover:text-secondary items-center transition-colors duration-300"
>
<Icon name={link.icon} class="h-5 w-auto" />
</Link>
))
}
</div>
<p
class="text-secondary/70 hidden max-w-md items-center text-pretty print:inline-flex"
>
<Link
class="decoration-tertiary inline-flex items-center gap-x-1.5 align-baseline leading-none"
href={`mailto:${SITE.EMAIL}`}
>
<Icon name="mdi:email" class="h-5 w-auto" />
{SITE.EMAIL}
</Link>
</p>
</div><span
class="relative flex h-28 w-28 shrink-0 overflow-hidden rounded-sm"
> >
<Image <span class="text-secondary text-nowrap">{SITE.AUTHOR}</span><span
src={me} class="text-tertiary sm:ml-2">Digital designer</span
alt={SITE.AUTHOR} >
class="aspect-square h-full w-full" </h1>
loading="eager" <p class="text-secondary/70 max-w-md text-pretty">
/> <Link
</span> class="decoration-tertiary inline-flex items-center gap-x-1.5 align-baseline leading-none hover:underline hover:decoration-2 hover:underline-offset-2"
</div> href="https://www.google.com/maps/place/Devon"
>
<Icon name="mdi:earth" class="h-5 w-auto" />
Devon, United Kingdom, GMT
</Link>
</p>
<div class="text-secondary/70 flex gap-x-2 text-sm print:hidden">
{
sortedLinks.map((link) => (
<Link
href={link.href}
aria-label={link.label}
class="text-tertiary hover:text-secondary items-center transition-colors duration-300"
>
<Icon name={link.icon} class="h-5 w-auto" />
</Link>
))
}
</div>
<p
class="text-secondary/70 hidden max-w-md items-center text-pretty print:inline-flex"
>
<Link
class="decoration-tertiary inline-flex items-center gap-x-1.5 align-baseline leading-none"
href={`mailto:${SITE.EMAIL}`}
>
<Icon name="mdi:email" class="h-5 w-auto" />
{SITE.EMAIL}
</Link>
</p>
</section>
<section class="animate-reveal opacity-0 [animation-delay:0.1s]"> <section class="animate-reveal space-y-3 opacity-0 [animation-delay:0.1s]">
<p class="text-secondary/70 text-lg font-medium"> <p class="text-secondary/70 text-lg font-medium">
Im a recent <a As a recent <a
href="#education" href="#education"
class="text-secondary decoration-tertiary underline hover:no-underline" class="text-secondary decoration-tertiary underline hover:no-underline"
>Game Arts and Design</a >Game Arts and Design</a
> graduate with a chosen area of focus on the design, lighting, and rendering > graduate with a specialization in 3D environment design, I'm passionate about
of 3D environments. Using either real-time or offline rendering techniques crafting visually compelling atmospheres which utilize dynamic lighting in
in software packages such as Blender, Unreal Engine, and more recently: Godot. order to enhance storytelling and create a more memorable space. I have experience
In addition to this I also have interests in web development, graphic design, designing within Blender, Unreal Engine, and Godot possessing a thorough
and cyber security in addition to motorbike touring. An up-to-date portfolio understanding of both real-time and offline rendering techniques.
of my work can be found on my website at <a </p>
<p class="text-secondary/70 text-lg font-medium">
My skillset extends beyond traditional 3D art; Im proficient in
programming leveraging Godot's GDScript for example to develop robust game
logic and systems that complement my visual assets whilst still achieving
high performance on the end-user's hardware.
</p>
<p class="text-secondary/70 text-lg font-medium">
You can view my portfolio at <a
href="/projects" href="/projects"
class="text-secondary decoration-tertiary underline hover:no-underline" class="rounded-sm border border-sky-500 bg-sky-50/20 px-1 py-0.5 text-sky-800 transition-colors duration-300 ease-in-out hover:border-sky-700 hover:bg-sky-50/80 hover:text-sky-900 dark:bg-sky-950/20 dark:text-sky-200 dark:hover:border-sky-300 dark:hover:bg-sky-950/80 dark:hover:text-sky-100"
>troylusty.com/projects</a >troylusty.com/projects</a
>. >.
</p> </p>
@ -255,73 +272,58 @@ const sortedLinks = [...links].sort((a, b) => a.id - b.id);
<section <section
id="education" id="education"
class="animate-reveal opacity-0 [animation-delay:0.3s]" class="animate-reveal space-y-3 opacity-0 [animation-delay:0.3s]"
> >
<h2 class="text-2xl font-semibold">Education</h2> <h2 class="text-2xl font-semibold">Education</h2>
<ol class="mt-3 flex flex-col gap-3"> <ol class="flex flex-col gap-3">
<AboutList information={sortedEducation} /> <AboutList information={sortedEducation} />
</ol> </ol>
<h3 class="mt-3 text-xl font-semibold">Other education</h3>
<div class="mt-3 flex flex-col gap-3">
<ul class="text-secondary/70 list-inside list-disc text-lg font-medium">
<li>Full drivers licence (Category A & B)</li>
</ul>
</div>
</section> </section>
<section <section
id="experience" id="experience"
class="animate-reveal opacity-0 [animation-delay:0.4s]" class="animate-reveal space-y-3 opacity-0 [animation-delay:0.4s]"
> >
<h2 class="text-2xl font-semibold">Experience</h2> <h2 class="text-2xl font-semibold">Experience</h2>
<ol class="mt-3 flex flex-col gap-3"> <ol class="flex flex-col gap-3">
<AboutList information={sortedExperience} /> <AboutList information={sortedExperience} />
</ol> </ol>
</section> </section>
<section <section
id="projects" id="projects"
class="animate-reveal opacity-0 [animation-delay:0.5s]" class="animate-reveal space-y-3 opacity-0 [animation-delay:0.5s]"
> >
<h2 class="text-2xl font-semibold">Projects</h2> <h2 class="text-2xl font-semibold">Projects</h2>
<ol class="mt-3 grid grid-cols-1 gap-3 md:grid-cols-2 print:grid-cols-2"> <ol class="grid grid-cols-1 gap-3 md:grid-cols-2 print:grid-cols-2">
{ {
sortedProjects.map((project) => ( sortedProjects.map((project) => (
<li class="bg-tertiary/10 flex flex-col overflow-hidden rounded-sm p-3 transition-transform duration-300 hover:scale-102"> <li class="bg-tertiary/10 flex flex-col overflow-hidden rounded-sm p-3 transition-transform duration-300 hover:scale-102">
<div class="flex flex-col space-y-1.5"> <div class="flex flex-col space-y-1.5">
<div class="space-y-1"> <h3 class="text-secondary mt-0 font-medium tracking-tight">
<> <Link
<h3 class="text-secondary mt-0 font-medium tracking-tight"> href={project.link}
<Link class="decoration-tertiary inline-flex items-center gap-1 font-medium underline hover:no-underline"
href={project.link} >
class="decoration-tertiary inline-flex items-center gap-1 font-medium underline hover:no-underline" {project.done ? (
> <span class="mr-1 h-1.5 w-1.5 rounded-full bg-green-600 dark:bg-green-400" />
{project.done ? ( ) : (
<span class="mr-1 h-1.5 w-1.5 rounded-full bg-green-600 dark:bg-green-400" /> <span class="mr-1 h-1.5 w-1.5 rounded-full bg-amber-600 dark:bg-amber-400" />
) : ( )}
<span class="mr-1 h-1.5 w-1.5 rounded-full bg-amber-600 dark:bg-amber-400" /> {project.name}
)} </Link>
{project.name} </h3>
</Link> <p class="text-secondary/70 text-sm">{project.description}</p>
</h3> <p class="text-secondary/40 hidden text-xs print:block">
<p class="text-secondary/70 text-sm">{project.description}</p> Available at {project.print_link}.
<p class="text-secondary/40 hidden text-xs print:block"> </p>
Available at {project.print_link}.
</p>
</>
</div>
</div> </div>
<div class="mt-auto flex text-sm text-pretty"> <div class="flex flex-wrap gap-1 text-sm text-pretty">
<div class="mt-2 flex flex-wrap gap-1"> {project.tags.map((tag) => (
{project.tags.map((tag) => ( <p class="bg-button text-secondary flex w-fit flex-row items-center gap-1 justify-self-center rounded-sm px-2 py-1 text-center text-xs font-light text-nowrap">
<a {tag}
href={`/tags/${createSlug(tag)}`} </p>
class="bg-button text-secondary hover:bg-button-active decoration-tertiary flex w-fit flex-row items-center gap-1 justify-self-center rounded-sm px-2 py-1 text-center font-sans text-xs font-light text-nowrap capitalize no-underline transition-colors duration-300" ))}
>
{tag}
</a>
))}
</div>
</div> </div>
</li> </li>
)) ))

View file

@ -6,7 +6,12 @@ import ShowcaseProject from "@components/ShowcaseProject.astro";
const projects = (await getCollection("projects")) const projects = (await getCollection("projects"))
.filter((project) => !project.data.draft) .filter((project) => !project.data.draft)
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); .sort((a, b) => {
if (a.data.rank !== b.data.rank) {
return b.data.rank - a.data.rank;
}
return b.data.date.valueOf() - a.data.date.valueOf();
});
--- ---
<Layout title={SITE.TITLE} description={PROJECTS.DESCRIPTION}> <Layout title={SITE.TITLE} description={PROJECTS.DESCRIPTION}>

View file

@ -34,7 +34,7 @@
color-scheme: light dark; color-scheme: light dark;
--primary: light-dark(oklch(0.855 0.01 264), oklch(0.145 0.01 264)); --primary: light-dark(oklch(0.855 0.01 264), oklch(0.145 0.01 264));
--secondary: light-dark(oklch(0.145 0.01 264), oklch(0.855 0.01 264)); --secondary: light-dark(oklch(0.145 0.01 264), oklch(0.855 0.01 264));
--tertiary: light-dark(oklch(0.556 0.01 264), oklch(0.556 0.01 264)); --tertiary: light-dark(oklch(0.456 0.01 264), oklch(0.556 0.01 264));
--button: light-dark(oklch(0.731 0.01 264), oklch(0.269 0.01 264)); --button: light-dark(oklch(0.731 0.01 264), oklch(0.269 0.01 264));
--button-active: light-dark(oklch(0.629 0.01 264), oklch(0.371 0.01 264)); --button-active: light-dark(oklch(0.629 0.01 264), oklch(0.371 0.01 264));