update website
|
After Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 221 KiB |
|
Before Width: | Height: | Size: 214 KiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 2.7 MiB |
|
Before Width: | Height: | Size: 278 KiB |
|
Before Width: | Height: | Size: 4.8 MiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 72 KiB |
@@ -1,27 +1,63 @@
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
|
||||
export const metadata = {title: "About"};
|
||||
const timeline = [
|
||||
{year: "2018", title: "The first spark", text: "I discovered programming through Scratch, turning small ideas into simple, playable games.", skills: ["Scratch", "Game logic"]},
|
||||
{year: "2022", title: "Into the web", text: "I began building websites and learned the foundations of HTML, CSS, and accessible interface design.", skills: ["HTML", "CSS", "JavaScript"]},
|
||||
{year: "2022", title: "From screen to hardware", text: "A Raspberry Pi opened the door to Python scripting, Linux, and the fun of connecting software with real hardware.", skills: ["Python", "Linux", "Raspberry Pi"]},
|
||||
{year: "2024", title: "Full stack & beyond", text: "I expanded into databases, backend systems, Java, and larger projects—while continuing to sharpen my eye for frontend craft.", skills: ["SQL", "Python", "Java", "JavaScript"]},
|
||||
{
|
||||
year: "2018",
|
||||
title: "The first spark",
|
||||
text: "I discovered programming through Scratch, turning small ideas into simple, playable games.",
|
||||
skills: ["Scratch", "Game logic"]
|
||||
},
|
||||
{
|
||||
year: "2022",
|
||||
title: "Web & hardware",
|
||||
text: "I started building websites and exploring Python and Linux with a Raspberry Pi.",
|
||||
skills: ["HTML & CSS", "JavaScript", "Python", "Linux"]
|
||||
},
|
||||
{
|
||||
year: "2025", title: "Useful tools & web apps",
|
||||
text: "From Autoclicker and this portfolio to AI chat and Discord bots, I began building tools with interfaces, accounts, and backend systems.",
|
||||
skills: ["Python", "Next.js", "Express", "SQLite"],
|
||||
},
|
||||
{
|
||||
year: "2026", title: "From web to mobile",
|
||||
text: "The IDPA Webshop connected a React storefront to a REST API. Shoppy took that work to mobile with barcode scanning and personal shopping recommendations.",
|
||||
skills: ["React", "REST APIs", "React Native", "Expo"],
|
||||
},
|
||||
{
|
||||
year: "2026", title: "Games & gameplay systems",
|
||||
text: "I expanded my Minecraft work with Ascend and companion mods, while building Linux Distro Roguelite, a Unity card game inspired by Linux and programming.",
|
||||
skills: ["Java", "Forge", "Unity", "C#"],
|
||||
},
|
||||
];
|
||||
export default function About() {
|
||||
return (<>
|
||||
<header className="page-head"><div className="shell page-head-row">
|
||||
<header className="page-head">
|
||||
<div className="shell page-head-row">
|
||||
<div><p className="eyebrow">About me</p><h1 className="page-title">Always<br/>learning.</h1></div>
|
||||
<p className="page-intro">I’m a developer driven by curiosity, thoughtful details, and the satisfying moment when a complex problem finally clicks.</p>
|
||||
</div></header>
|
||||
<p className="page-intro">I’m a developer driven by curiosity and that satisfying moment when a complex
|
||||
problem finally clicks.</p>
|
||||
</div>
|
||||
</header>
|
||||
<div className="shell about-grid">
|
||||
<aside className="about-sticky">
|
||||
<div className="image-frame about-portrait portrait-frame">
|
||||
<Image src="/images/Fred3.png" alt="Frederik outdoors in a striped shirt" fill
|
||||
sizes="(max-width: 800px) 100vw, 40vw"/>
|
||||
</div>
|
||||
<p className="eyebrow">My path so far</p><h2>From playful experiments to complete products.</h2>
|
||||
<p>Every project has added a new tool, a sharper instinct, or a better question to ask.</p>
|
||||
<p>Every project has added a new tool or a better idea (occasionally both).</p>
|
||||
<Link href="/projects" className="button">View projects</Link>
|
||||
</aside>
|
||||
<div className="timeline">{timeline.map(item => (
|
||||
<article className="timeline-item" key={`${item.year}-${item.title}`}>
|
||||
<div className="timeline-year">{item.year}</div>
|
||||
<div><h3>{item.title}</h3><p>{item.text}</p><div className="skills">{item.skills.map(skill => <span className="skill" key={skill}>{skill}</span>)}</div></div>
|
||||
<div>
|
||||
<h3>{item.title}</h3><p>{item.text}</p>
|
||||
<div className="skills">{item.skills.map(skill => <span className="skill"
|
||||
key={skill}>{skill}</span>)}</div>
|
||||
</div>
|
||||
</article>
|
||||
))}</div>
|
||||
</div>
|
||||
|
||||
@@ -291,6 +291,11 @@ button {
|
||||
margin: 26px 0 34px;
|
||||
}
|
||||
|
||||
.featured h2 {
|
||||
font-size: clamp(3rem, 5vw, 4.5rem);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.image-frame {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
@@ -319,6 +324,20 @@ button {
|
||||
filter: saturate(1);
|
||||
}
|
||||
|
||||
.landscape-frame {
|
||||
aspect-ratio: 16/9;
|
||||
}
|
||||
|
||||
.landscape-frame img {
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.landscape-frame:hover img {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.page-head {
|
||||
padding: 110px 0 80px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
@@ -436,6 +455,20 @@ button {
|
||||
transition: transform .45s ease;
|
||||
}
|
||||
|
||||
.github-project-image {
|
||||
aspect-ratio: 2/1;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.github-project-image img {
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.project-card:hover .github-project-image img {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.project-card:hover .project-image img {
|
||||
transform: scale(1.035);
|
||||
}
|
||||
@@ -470,6 +503,120 @@ button {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.portrait-frame {
|
||||
background: radial-gradient(ellipse at 50% 100%, #e6b797, var(--paper-2) 75%);
|
||||
}
|
||||
|
||||
.portrait-frame img {
|
||||
object-fit: contain;
|
||||
object-position: center bottom;
|
||||
padding: 24px 24px 0;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.about-portrait {
|
||||
aspect-ratio: 4/3;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.text-link {
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid var(--accent);
|
||||
padding-bottom: 4px;
|
||||
color: var(--ink);
|
||||
font-size: .9rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.project-toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
.project-filters {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.project-filters button {
|
||||
min-height: 44px;
|
||||
padding: 10px 16px;
|
||||
border: 1px solid var(--line);
|
||||
background: transparent;
|
||||
color: var(--ink);
|
||||
cursor: pointer;
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
.project-filters button:hover { border-color: var(--ink); }
|
||||
|
||||
.project-filters button[aria-pressed="true"] {
|
||||
background: var(--ink);
|
||||
color: var(--paper);
|
||||
}
|
||||
|
||||
.project-count, .project-source {
|
||||
color: var(--muted);
|
||||
font: 500 .73rem var(--font-geist-mono), monospace;
|
||||
}
|
||||
|
||||
.project-collection .projects-grid { padding-top: 36px; }
|
||||
.project-card { min-width: 0; }
|
||||
|
||||
.project-cover {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
aspect-ratio: 16/9;
|
||||
padding: clamp(20px, 3vw, 36px);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--line);
|
||||
background-color: #e4e8dc;
|
||||
background-image: linear-gradient(var(--line) 1px, transparent 1px), linear-gradient(90deg, var(--line) 1px, transparent 1px);
|
||||
background-size: 40px 40px;
|
||||
}
|
||||
|
||||
.project-cover-web { background-color: #ead9c7; }
|
||||
.project-cover-game { background-color: #dce3ec; }
|
||||
.project-cover-tool { background-color: #e5dfe9; }
|
||||
|
||||
.project-cover-label {
|
||||
font: 600 .65rem var(--font-geist-mono), monospace;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .1em;
|
||||
}
|
||||
|
||||
.project-cover-mark {
|
||||
align-self: center;
|
||||
font: 600 clamp(2rem, 4.5vw, 4rem)/1.2 var(--font-geist-mono), monospace;
|
||||
letter-spacing: -.07em;
|
||||
white-space: nowrap;
|
||||
transition: transform .25s ease;
|
||||
}
|
||||
|
||||
.project-cover-tagline { font-size: .8rem; line-height: 1.4; }
|
||||
.project-card:hover .project-cover-mark { transform: translateY(-4px); }
|
||||
|
||||
.project-source {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-top: 22px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.project-card:focus-visible, .project-filters button:focus-visible, .text-link:focus-visible {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 6px;
|
||||
}
|
||||
|
||||
.contact-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1.1fr .9fr;
|
||||
|
||||
@@ -7,8 +7,8 @@ const geistSans = Geist({variable: "--font-geist-sans", subsets: ["latin"]});
|
||||
const geistMono = Geist_Mono({variable: "--font-geist-mono", subsets: ["latin"]});
|
||||
|
||||
export const metadata = {
|
||||
title: {default: "Fretux — Developer & digital maker", template: "%s — Fretux"},
|
||||
description: "Portfolio of Frederik Spirgi, a developer building thoughtful digital experiences.",
|
||||
title: {default: "Fretux | Developer & digital maker", template: "%s | Fretux"},
|
||||
description: "Portfolio of Frederik Spirgi, software developer",
|
||||
icons: {icon: "/favicon.ico"},
|
||||
};
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ export default function Home() {
|
||||
<div>
|
||||
<p className="eyebrow">A little about me</p>
|
||||
<h2>Curious by default.</h2>
|
||||
<p>I like learning how things work, then making them work better. My projects move between polished interfaces, practical backend systems, and playful experiments.</p>
|
||||
<p>I like learning how things work, then making them work better. My projects move between websites, games, and other experiments.</p>
|
||||
<Link className="button light" href="/about">My journey</Link>
|
||||
</div>
|
||||
<div className="image-frame">
|
||||
<Image src="/images/portfolio1.jpg" alt="A featured development project" fill sizes="(max-width: 800px) 100vw, 60vw"/>
|
||||
<div className="image-frame landscape-frame">
|
||||
<Image src="/images/portfolio2.jpg" alt="Frederik standing with outstretched arms beside the sea and rocky coastal cliffs" fill sizes="(max-width: 800px) calc(100vw - 30px), (max-width: 1228px) 60vw, 710px"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
"use client";
|
||||
|
||||
import {useState} from "react";
|
||||
import Image from "next/image";
|
||||
import {projects} from "./projects";
|
||||
|
||||
const categories = ["All", "Web & apps", "Minecraft", "Games", "Tools & bots"];
|
||||
|
||||
export default function ProjectGallery() {
|
||||
const [category, setCategory] = useState("All");
|
||||
const visibleProjects = projects.filter(project => category === "All" || project.category === category);
|
||||
|
||||
return <section className="shell project-collection" aria-label="Project collection">
|
||||
<div className="project-toolbar">
|
||||
<div className="project-filters" role="group" aria-label="Filter projects by category">
|
||||
{categories.map(item => <button type="button" key={item} aria-pressed={category === item}
|
||||
onClick={() => setCategory(item)}>{item}</button>)}
|
||||
</div>
|
||||
<p className="project-count" role="status">{visibleProjects.length} projects</p>
|
||||
</div>
|
||||
<div className="projects-grid">{visibleProjects.map(project => (
|
||||
<a className="project-card" href={`https://github.com/Fretuks/${project.repo}`}
|
||||
target="_blank" rel="noopener noreferrer" key={project.repo}>
|
||||
<div className="project-image github-project-image">
|
||||
<Image src={`/images/projects/${project.repo}.png`}
|
||||
alt={`${project.title} GitHub repository preview`}
|
||||
width={1200} height={600} sizes="(max-width: 800px) 100vw, 50vw"/>
|
||||
</div>
|
||||
<div className="project-meta"><h2>{project.title}</h2><span aria-hidden="true">↗</span></div>
|
||||
<p>{project.description}</p>
|
||||
<div className="skills">{project.stack.map(skill => <span className="skill" key={skill}>{skill}</span>)}</div>
|
||||
<div className="project-source"><span>View on GitHub</span>{project.attribution && <span>{project.attribution}</span>}</div>
|
||||
</a>
|
||||
))}</div>
|
||||
</section>;
|
||||
}
|
||||
@@ -1,23 +1,15 @@
|
||||
import Image from "next/image";
|
||||
import ProjectGallery from "./ProjectGallery";
|
||||
import {projects} from "./projects";
|
||||
export const metadata = {title: "Projects"};
|
||||
const projects = [
|
||||
{title: "Red Lake Stats", description: "An interactive JavaScript and Python tool for calculating damage statistics in the Roblox game The Red Lake.", image: "/images/portfolio-project1.png", link: "https://fretux.ch/trlstats"},
|
||||
{title: "SBB History", description: "An interactive journey through the creation of Switzerland’s railway company, featuring an explorable map.", image: "/images/portfolio-project2.png", link: "https://sbb-history.fretux.ch"},
|
||||
{title: "Fretux.ch", description: "My first portfolio—gamified to make exploring personal work feel more playful and memorable.", image: "/images/portfolio-project3.png", link: "https://fretux.ch"},
|
||||
{title: "KnockedBack", description: "A Minecraft mod that reimagines what happens when a player dies.", image: "/images/KnockedBack.png", link: "https://modrinth.com/mod/knockedback"},
|
||||
{title: "Stalinium", description: "A collaborative Minecraft mod adding the fictional Stalinium ore and a new layer of progression.", image: "/images/Stalinium.png", link: "https://modrinth.com/mod/stalinium-mod"},
|
||||
];
|
||||
export default function ProjectsPage() {
|
||||
return (<>
|
||||
<header className="page-head"><div className="shell page-head-row">
|
||||
<div><p className="eyebrow">Selected work</p><h1 className="page-title">Things I’ve<br/>made.</h1></div>
|
||||
<p className="page-intro">A mix of useful tools, interactive websites, and game modifications—each built to explore a new idea.</p>
|
||||
<div><p className="eyebrow">Open-source work</p><h1 className="page-title">Things I’ve<br/>made.</h1></div>
|
||||
<div className="page-intro">
|
||||
<p>From everyday tools to mods and games, a collection of {projects.length} projects to explore and build on.</p>
|
||||
<a className="text-link" href="https://github.com/Fretuks" target="_blank" rel="noopener noreferrer">Find me on GitHub <span aria-hidden="true">↗</span></a>
|
||||
</div>
|
||||
</div></header>
|
||||
<div className="shell projects-grid">{projects.map(project => (
|
||||
<a className="project-card" href={project.link} target="_blank" rel="noopener noreferrer" key={project.title}>
|
||||
<div className="project-image"><Image src={project.image} alt={`${project.title} project preview`} width={800} height={550}/></div>
|
||||
<div className="project-meta"><h2>{project.title}</h2><span aria-hidden="true">↗</span></div><p>{project.description}</p>
|
||||
</a>
|
||||
))}</div>
|
||||
<ProjectGallery/>
|
||||
</>);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
// Reviewed against public GitHub repositories on 2026-09-18.
|
||||
// Include implemented apps, tools, libraries, games, and substantial creative work.
|
||||
// Exclude Fretuks (profile), M324im_Code (course exercises), and the-ims-stack
|
||||
// (starter page). Developed forks are explicitly credited below.
|
||||
export const projects = [
|
||||
{
|
||||
repo: "linuxdistro-roguelite", title: "Linux Distro Roguelite", category: "Games",
|
||||
mark: "~/run", tagline: "Choose your distro. Build your deck.",
|
||||
description: "A Unity deck-building roguelite with Linux distributions, programming-language cards, turn-based combat, and persistent progression.",
|
||||
stack: ["Unity", "C#"],
|
||||
},
|
||||
{
|
||||
repo: "KrisHD_AI", title: "Elsewhere", category: "Web & apps",
|
||||
mark: "hello_", tagline: "A space for every conversation.",
|
||||
description: "An AI chat workspace with streaming conversations, custom personas, roleplay sessions, and a shared persona market. Built with Express and SQLite.",
|
||||
stack: ["JavaScript", "Express", "SQLite"],
|
||||
},
|
||||
{
|
||||
repo: "Shoppy", title: "Shoppy", category: "Web & apps",
|
||||
mark: "scan/+", tagline: "A little more clarity in every shop.",
|
||||
description: "A mobile shopping companion that scans barcodes and evaluates products against personal preferences. Includes shopping lists, allergy settings, and cached product data for offline use.",
|
||||
stack: ["React Native", "Expo", "Open Food Facts"],
|
||||
},
|
||||
{
|
||||
repo: "Ascend", title: "Ascend", category: "Minecraft",
|
||||
mark: "lvl ↑", tagline: "Make every level your own.",
|
||||
description: "A Minecraft RPG progression mod inspired by Deepwoken, with experience, ten upgradeable attributes, knowledge, and shrines for reshaping your build.",
|
||||
stack: ["Java", "Forge"],
|
||||
},
|
||||
{
|
||||
repo: "IDPA26_WebShop", title: "IDPA Webshop", category: "Web & apps",
|
||||
mark: "cart/+", tagline: "From the catalogue to checkout.",
|
||||
description: "A full-stack school project with product browsing, accounts, carts, orders, and an administration interface, backed by a REST API.",
|
||||
stack: ["React", "Express", "SQL"],
|
||||
},
|
||||
{
|
||||
repo: "linux_distro_roguelite_promotion", title: "Roguelite Launch Platform", category: "Web & apps",
|
||||
mark: "join_", tagline: "A community before the first run.",
|
||||
description: "A companion website and Quarkus backend for game pre-registration, platform preferences, email confirmation, community milestones, and rewards.",
|
||||
stack: ["Java", "Quarkus", "PostgreSQL"],
|
||||
},
|
||||
{
|
||||
repo: "SkillEngine", title: "Skill Engine", category: "Minecraft",
|
||||
mark: "[⋅]-[⋅]", tagline: "The foundation for a new skill tree.",
|
||||
description: "A reusable Forge framework for JSON-defined skill trees, with node requirements, skill points, tooltips, and server synchronization for other mods to build on.",
|
||||
stack: ["Java", "Forge", "JSON"],
|
||||
},
|
||||
{
|
||||
repo: "MindMotion", title: "Mind & Motion", category: "Minecraft",
|
||||
mark: "mind/", tagline: "Keep your sanity. Find your tempo.",
|
||||
description: "A configurable Minecraft mod introducing sanity, insanity, and combat tempo. Environmental effects and a defensive vent ability add new decisions to exploration and combat.",
|
||||
stack: ["Java", "Forge"],
|
||||
},
|
||||
{
|
||||
repo: "KnockedBack", title: "KnockedBack", category: "Minecraft",
|
||||
mark: "1 HP", tagline: "A second chance before the end.",
|
||||
description: "Replaces most lethal damage with a temporary knocked-out state, giving players a chance to recover, carry teammates to safety, or finish a fight.",
|
||||
stack: ["Java", "Forge"],
|
||||
},
|
||||
{
|
||||
repo: "Ailments", title: "Ascend: Ailments", category: "Minecraft",
|
||||
mark: "+effect", tagline: "Give combat a lasting effect.",
|
||||
description: "A Forge library of eight combat effects, including bleed, fear, and soul rot, with a public API, configurable interactions, and optional Ascend integration.",
|
||||
stack: ["Java", "Forge"],
|
||||
},
|
||||
{
|
||||
repo: "Gambling_API", title: "Virtual-Chip Poker", category: "Web & apps",
|
||||
mark: "♠ / ♣", tagline: "One table. A real-time connection.",
|
||||
description: "A multiplayer poker app with virtual chips, lobbies, live WebSocket play, and persistent accounts. Includes transaction recovery and an HTTP API.",
|
||||
stack: ["Express", "WebSockets", "SQLite"], attribution: "Fork-based project",
|
||||
},
|
||||
{
|
||||
repo: "TARS", title: "T.A.R.S.", category: "Tools & bots",
|
||||
mark: "/tars", tagline: "A helping hand for the server.",
|
||||
description: "A Python Discord bot combining moderation, reminders, server diagnostics, community commands, and a boost-points reward shop.",
|
||||
stack: ["Python", "Discord"],
|
||||
},
|
||||
{
|
||||
repo: "Discord_bot", title: "Discord Utility Bot", category: "Tools & bots",
|
||||
mark: "/help", tagline: "Small commands. Everyday utility.",
|
||||
description: "A Discord.js bot with moderation, virtual currency, quizzes, timestamps, weather, and Wikipedia lookups, plus per-server command permissions.",
|
||||
stack: ["JavaScript", "Discord.js", "MongoDB"], attribution: "Fork-based project",
|
||||
},
|
||||
{
|
||||
repo: "Autoclicker", title: "Autoclicker", category: "Tools & bots",
|
||||
mark: "click()", tagline: "Put repetitive clicks on repeat.",
|
||||
description: "A Python desktop utility with a Tkinter interface and configurable keyboard shortcuts to start and stop automated clicking.",
|
||||
stack: ["Python", "Tkinter", "pynput"],
|
||||
},
|
||||
{
|
||||
repo: "BruteForce", title: "BruteForce Lab", category: "Tools & bots",
|
||||
mark: "auth/?", tagline: "Explore how a login holds up.",
|
||||
description: "An educational local test application for exploring password attacks and defenses, pairing an Express login backend with controlled attack simulations.",
|
||||
stack: ["JavaScript", "Express", "Security education"],
|
||||
},
|
||||
{
|
||||
repo: "WebsitePortfolio2", title: "Fretux Portfolio", category: "Web & apps",
|
||||
mark: "<fred/>", tagline: "Code with character.",
|
||||
description: "The portfolio you are exploring: a responsive Next.js site bringing together my projects, background, and experiments in digital design.",
|
||||
stack: ["Next.js", "React", "CSS"],
|
||||
},
|
||||
];
|
||||