feat: add K-Suite page with interactive application organism and new app images.
All checks were successful
Build and Deploy Gabriel Kaszewski Portfolio / build-and-deploy-local (push) Successful in 1m49s
All checks were successful
Build and Deploy Gabriel Kaszewski Portfolio / build-and-deploy-local (push) Successful in 1m49s
This commit is contained in:
433
app/k-suite/page.tsx
Normal file
433
app/k-suite/page.tsx
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { ExternalLink, Github } from "lucide-react";
|
||||||
|
|
||||||
|
interface KSuiteApp {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
shortDescription: string;
|
||||||
|
description: string;
|
||||||
|
url: string;
|
||||||
|
githubUrl?: string | null;
|
||||||
|
icon: string;
|
||||||
|
technologies: string[];
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const kSuiteApps: KSuiteApp[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "K-Notes",
|
||||||
|
shortDescription: "Google Keep replica",
|
||||||
|
description:
|
||||||
|
"A full-featured note-taking app designed for speed and simplicity.",
|
||||||
|
url: "https://knotes.gabrielkaszewski.dev/",
|
||||||
|
githubUrl: "https://github.com/GKaszewski/k-notes",
|
||||||
|
icon: "/images/k-notes.png",
|
||||||
|
technologies: ["Rust", "React", "TailwindCSS", "PWA"],
|
||||||
|
color: "from-amber-400 to-orange-500",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Thoughts",
|
||||||
|
shortDescription: "Microblogging platform",
|
||||||
|
description:
|
||||||
|
"Nostalgic social platform with Frutiger Aero style. 128-char posts, custom CSS profiles.",
|
||||||
|
url: "https://thoughts.gabrielkaszewski.dev/",
|
||||||
|
githubUrl: "https://git.gabrielkaszewski.dev/GKaszewski/thoughts",
|
||||||
|
icon: "/images/thoughts.avif",
|
||||||
|
technologies: ["Rust", "Next.js", "Axum"],
|
||||||
|
color: "from-cyan-400 to-blue-500",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "K-Tuner",
|
||||||
|
shortDescription: "Instrument tuner",
|
||||||
|
description:
|
||||||
|
"Tune guitar, ukulele, and piano with this Frutiger Aero styled PWA.",
|
||||||
|
url: "https://tuner.gabrielkaszewski.dev/",
|
||||||
|
githubUrl: "https://github.com/GKaszewski/aero-tuner",
|
||||||
|
icon: "/images/k-tuner.png",
|
||||||
|
technologies: ["React", "PWA"],
|
||||||
|
color: "from-emerald-400 to-teal-500",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "K-QR",
|
||||||
|
shortDescription: "QR code generator",
|
||||||
|
description:
|
||||||
|
"High-performance QR generator. Single Rust executable serving clean HTML.",
|
||||||
|
url: "https://qr.gabrielkaszewski.dev/",
|
||||||
|
githubUrl: "https://github.com/GKaszewski/k-qr",
|
||||||
|
icon: "/images/k-qr.png",
|
||||||
|
technologies: ["Rust", "HTML"],
|
||||||
|
color: "from-amber-400 to-orange-500"
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// Connection definitions for the organism
|
||||||
|
const connections = [
|
||||||
|
{ from: 0, to: 1 }, // K-Notes -> Thoughts
|
||||||
|
{ from: 1, to: 2 }, // Thoughts -> K-Tuner
|
||||||
|
{ from: 2, to: 3 }, // K-Tuner -> K-QR
|
||||||
|
{ from: 3, to: 0 }, // K-QR -> K-Notes
|
||||||
|
{ from: 0, to: 2 }, // K-Notes -> K-Tuner (cross)
|
||||||
|
{ from: 1, to: 3 }, // Thoughts -> K-QR (cross)
|
||||||
|
];
|
||||||
|
|
||||||
|
const KSuiteOrganism = () => {
|
||||||
|
// Calculate positions for apps in a circular pattern
|
||||||
|
const getPosition = (index: number, total: number, radius: number) => {
|
||||||
|
const angle = (index * 2 * Math.PI) / total - Math.PI / 2;
|
||||||
|
return {
|
||||||
|
x: 50 + radius * Math.cos(angle),
|
||||||
|
y: 50 + radius * Math.sin(angle),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const radius = 35;
|
||||||
|
const positions = kSuiteApps.map((_, i) =>
|
||||||
|
getPosition(i, kSuiteApps.length, radius)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative w-full max-w-4xl mx-auto aspect-square">
|
||||||
|
{/* SVG Connection Lines */}
|
||||||
|
<svg
|
||||||
|
className="absolute inset-0 w-full h-full pointer-events-none"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stopColor="rgba(59, 130, 246, 0.6)" />
|
||||||
|
<stop offset="50%" stopColor="rgba(147, 51, 234, 0.6)" />
|
||||||
|
<stop offset="100%" stopColor="rgba(59, 130, 246, 0.6)" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter id="glow">
|
||||||
|
<feGaussianBlur stdDeviation="0.5" result="coloredBlur" />
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode in="coloredBlur" />
|
||||||
|
<feMergeNode in="SourceGraphic" />
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
{/* Connection lines */}
|
||||||
|
{connections.map((conn, i) => {
|
||||||
|
const from = positions[conn.from];
|
||||||
|
const to = positions[conn.to];
|
||||||
|
return (
|
||||||
|
<line
|
||||||
|
key={i}
|
||||||
|
x1={from.x}
|
||||||
|
y1={from.y}
|
||||||
|
x2={to.x}
|
||||||
|
y2={to.y}
|
||||||
|
stroke="url(#lineGradient)"
|
||||||
|
strokeWidth="0.3"
|
||||||
|
filter="url(#glow)"
|
||||||
|
className="animate-pulse"
|
||||||
|
style={{ animationDelay: `${i * 0.2}s` }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{/* Lines from center to each app */}
|
||||||
|
{positions.map((pos, i) => (
|
||||||
|
<line
|
||||||
|
key={`center-${i}`}
|
||||||
|
x1={50}
|
||||||
|
y1={50}
|
||||||
|
x2={pos.x}
|
||||||
|
y2={pos.y}
|
||||||
|
stroke="url(#lineGradient)"
|
||||||
|
strokeWidth="0.2"
|
||||||
|
strokeDasharray="1 0.5"
|
||||||
|
filter="url(#glow)"
|
||||||
|
className="animate-pulse"
|
||||||
|
style={{ animationDelay: `${i * 0.3}s` }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{/* App Cards */}
|
||||||
|
{kSuiteApps.map((app, index) => {
|
||||||
|
const pos = positions[index];
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={app.id}
|
||||||
|
className="absolute transform -translate-x-1/2 -translate-y-1/2 w-32 md:w-40 lg:w-48"
|
||||||
|
style={{
|
||||||
|
left: `${pos.x}%`,
|
||||||
|
top: `${pos.y}%`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`group relative p-3 md:p-4 rounded-2xl bg-white/10 backdrop-blur-lg border border-white/20 shadow-xl hover:bg-white/20 hover:scale-105 transition-all duration-300 cursor-pointer`}
|
||||||
|
>
|
||||||
|
{/* Glow effect on hover */}
|
||||||
|
<div
|
||||||
|
className={`absolute inset-0 rounded-2xl bg-gradient-to-br ${app.color} opacity-0 group-hover:opacity-20 transition-opacity duration-300 blur-xl`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="relative z-10 flex flex-col items-center text-center">
|
||||||
|
<div className="relative w-12 h-12 md:w-16 md:h-16 mb-2">
|
||||||
|
<Image
|
||||||
|
src={app.icon}
|
||||||
|
alt={app.name}
|
||||||
|
fill
|
||||||
|
className="object-contain rounded-lg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-sm md:text-base font-bold text-white mb-1">
|
||||||
|
{app.name}
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-white/70 mb-2 hidden md:block">
|
||||||
|
{app.shortDescription}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Links */}
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<a
|
||||||
|
href={app.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="p-1.5 rounded-full bg-white/10 hover:bg-white/30 transition-colors"
|
||||||
|
title="Visit"
|
||||||
|
>
|
||||||
|
<ExternalLink size={14} className="text-white" />
|
||||||
|
</a>
|
||||||
|
{app.githubUrl && (
|
||||||
|
<a
|
||||||
|
href={app.githubUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="p-1.5 rounded-full bg-white/10 hover:bg-white/30 transition-colors"
|
||||||
|
title="GitHub"
|
||||||
|
>
|
||||||
|
<Github size={14} className="text-white" />
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const KSuiteAppCard = ({ app }: { app: KSuiteApp }) => {
|
||||||
|
return (
|
||||||
|
<div className="group relative p-6 rounded-3xl bg-white/10 backdrop-blur-lg border border-white/20 shadow-xl hover:bg-white/15 transition-all duration-300">
|
||||||
|
{/* Gradient glow */}
|
||||||
|
<div
|
||||||
|
className={`absolute inset-0 rounded-3xl bg-gradient-to-br ${app.color} opacity-0 group-hover:opacity-10 transition-opacity duration-300`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="relative z-10">
|
||||||
|
<div className="flex items-start gap-4 mb-4">
|
||||||
|
<div className="relative w-16 h-16 shrink-0">
|
||||||
|
<Image
|
||||||
|
src={app.icon}
|
||||||
|
alt={app.name}
|
||||||
|
fill
|
||||||
|
className="object-contain rounded-xl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-bold text-white">{app.name}</h3>
|
||||||
|
<p className="text-white/70">{app.shortDescription}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-white/80 mb-4">{app.description}</p>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap gap-2 mb-4">
|
||||||
|
{app.technologies.map((tech) => (
|
||||||
|
<span
|
||||||
|
key={tech}
|
||||||
|
className="px-2 py-1 text-xs rounded-full bg-white/10 text-white/80"
|
||||||
|
>
|
||||||
|
{tech}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<a
|
||||||
|
href={app.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className={`flex-1 flex items-center justify-center gap-2 px-4 py-2 rounded-xl bg-gradient-to-r ${app.color} text-white font-semibold hover:opacity-90 transition-opacity`}
|
||||||
|
>
|
||||||
|
<ExternalLink size={16} />
|
||||||
|
Visit
|
||||||
|
</a>
|
||||||
|
{app.githubUrl && (
|
||||||
|
<a
|
||||||
|
href={app.githubUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center justify-center px-4 py-2 rounded-xl border border-white/20 text-white hover:bg-white/10 transition-colors"
|
||||||
|
>
|
||||||
|
<Github size={16} />
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function KSuitePage() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen pt-20">
|
||||||
|
{/* Hero Section */}
|
||||||
|
<section className="relative py-16 md:py-24 overflow-hidden">
|
||||||
|
<div className="container mx-auto px-4 text-center">
|
||||||
|
<h1 className="text-5xl md:text-7xl font-bold text-white mb-4 text-shadow-lg">
|
||||||
|
K-Suite
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl md:text-2xl text-white/80 max-w-3xl mx-auto mb-2">
|
||||||
|
A cohesive ecosystem of open-source, self-hosted applications
|
||||||
|
designed to restore digital sovereignty to the user.
|
||||||
|
</p>
|
||||||
|
<p className="text-base text-white/60 max-w-2xl mx-auto mb-12">
|
||||||
|
A "Personal Universe" containing interconnected applications ranging
|
||||||
|
from media playback to knowledge management.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Organism Visualization */}
|
||||||
|
<KSuiteOrganism />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Origin Story Section */}
|
||||||
|
<section className="py-16">
|
||||||
|
<div className="container mx-auto px-4">
|
||||||
|
<div className="max-w-3xl mx-auto">
|
||||||
|
<div className="p-8 rounded-3xl bg-white/5 backdrop-blur-lg border border-white/10">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6 flex items-center gap-3">
|
||||||
|
Origin Story
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-4 text-white/80 leading-relaxed">
|
||||||
|
<p>
|
||||||
|
The concept of K-Suite was born in <span className="text-yellow-400 font-semibold">2017</span>.
|
||||||
|
As a middle school student, I envisioned a digital environment where every
|
||||||
|
tool I used was built by my own hands—a space customized exactly to my needs.
|
||||||
|
However, my vision at the time far outpaced my technical abilities.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
K-Suite is the realization of that long-standing dream. It bridges the gap
|
||||||
|
between the middle schooler who wanted to build, and the developer who now can.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Engineering Mission Section */}
|
||||||
|
<section className="py-16">
|
||||||
|
<div className="container mx-auto px-4">
|
||||||
|
<div className="max-w-3xl mx-auto">
|
||||||
|
<div className="p-8 rounded-3xl bg-gradient-to-br from-purple-500/10 to-blue-500/10 backdrop-blur-lg border border-white/10">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6 flex items-center gap-3">
|
||||||
|
Engineering Mission
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-4 text-white/80 leading-relaxed">
|
||||||
|
<p>
|
||||||
|
This project represents my <span className="text-yellow-400 font-semibold">Magnum Opus</span>.
|
||||||
|
It is the most ambitious software engineering undertaking I have attempted to date.
|
||||||
|
Beyond simply providing privacy and utility, K-Suite serves as a rigorous testing
|
||||||
|
ground for advanced <span className="text-cyan-400">System Design</span> and{" "}
|
||||||
|
<span className="text-cyan-400">Software Architecture</span>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Core Goals */}
|
||||||
|
<div className="mt-8 space-y-6">
|
||||||
|
<h3 className="text-xl font-semibold text-white">Core Goals</h3>
|
||||||
|
|
||||||
|
<div className="p-4 rounded-2xl bg-white/5 border border-white/10">
|
||||||
|
<h4 className="text-lg font-bold text-amber-400 mb-2">
|
||||||
|
Architectural Mastery
|
||||||
|
</h4>
|
||||||
|
<p className="text-white/70">
|
||||||
|
To design a distributed system where independent modules (like K-Notes)
|
||||||
|
function flawlessly on their own but become exponentially more powerful when connected.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 rounded-2xl bg-white/5 border border-white/10">
|
||||||
|
<h4 className="text-lg font-bold text-emerald-400 mb-2">
|
||||||
|
Digital Sovereignty
|
||||||
|
</h4>
|
||||||
|
<p className="text-white/70">
|
||||||
|
To create a viable, privacy-first alternative to commercial ecosystems
|
||||||
|
(Google/Apple), focused entirely on open-source principles and self-hosting.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 rounded-2xl bg-white/5 border border-white/10">
|
||||||
|
<h4 className="text-lg font-bold text-blue-400 mb-2">
|
||||||
|
Seamless Integration
|
||||||
|
</h4>
|
||||||
|
<p className="text-white/70">
|
||||||
|
To solve the complex challenge of inter-app communication. In K-Suite,
|
||||||
|
a photo stored in K-Photos isn't just a file; it's an asset that can be
|
||||||
|
referenced in other apps or attached to a task in the upcoming K-Mood.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Detailed Cards Section */}
|
||||||
|
<section className="py-16">
|
||||||
|
<div className="container mx-auto px-4">
|
||||||
|
<h2 className="text-3xl font-bold text-white text-center mb-4">
|
||||||
|
Explore the Suite
|
||||||
|
</h2>
|
||||||
|
<p className="text-white/60 text-center mb-12 max-w-xl mx-auto">
|
||||||
|
Each application is designed to work independently, but together they form
|
||||||
|
something greater.
|
||||||
|
</p>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl mx-auto">
|
||||||
|
{kSuiteApps.map((app) => (
|
||||||
|
<KSuiteAppCard key={app.id} app={app} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Coming Soon Section */}
|
||||||
|
<section className="py-16">
|
||||||
|
<div className="container mx-auto px-4 text-center">
|
||||||
|
<div className="max-w-2xl mx-auto p-8 rounded-3xl bg-white/5 backdrop-blur-lg border border-white/10">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-4">
|
||||||
|
More Apps Coming Soon
|
||||||
|
</h2>
|
||||||
|
<p className="text-white/70 mb-4">
|
||||||
|
K-Suite is still growing. The ecosystem will expand with more interconnected
|
||||||
|
applications including K-Photos, K-Mood, and more.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-white/50">
|
||||||
|
Built with Rust, React, and modern web technologies.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ const Navbar = () => {
|
|||||||
|
|
||||||
const navLinks = [
|
const navLinks = [
|
||||||
{ href: "/", label: "Home" },
|
{ href: "/", label: "Home" },
|
||||||
|
{ href: "/k-suite", label: "K-Suite" },
|
||||||
{ href: "/projects", label: "Projects" },
|
{ href: "/projects", label: "Projects" },
|
||||||
{
|
{
|
||||||
href: "https://blog.gabrielkaszewski.dev/",
|
href: "https://blog.gabrielkaszewski.dev/",
|
||||||
@@ -31,6 +32,7 @@ const Navbar = () => {
|
|||||||
{ href: "/about", label: "About" },
|
{ href: "/about", label: "About" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
const baseClasses =
|
const baseClasses =
|
||||||
"fixed z-20 flex w-full items-center justify-center p-4 transition-all duration-300";
|
"fixed z-20 flex w-full items-center justify-center p-4 transition-all duration-300";
|
||||||
const scrolledClasses = "bg-gray-900/80 backdrop-blur-md";
|
const scrolledClasses = "bg-gray-900/80 backdrop-blur-md";
|
||||||
@@ -38,16 +40,14 @@ const Navbar = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
className={`${baseClasses} ${
|
className={`${baseClasses} ${isScrolled ? scrolledClasses : transparentClasses
|
||||||
isScrolled ? scrolledClasses : transparentClasses
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="flex flex-1"></div>
|
<div className="flex flex-1"></div>
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
{navLinks.map((link) => {
|
{navLinks.map((link) => {
|
||||||
const isActive = pathname === link.href;
|
const isActive = pathname === link.href;
|
||||||
const linkClasses = `text-lg hover:text-yellow-400 transition-colors ${
|
const linkClasses = `text-lg hover:text-yellow-400 transition-colors ${isActive ? "text-yellow-400 font-semibold" : "text-white"
|
||||||
isActive ? "text-yellow-400 font-semibold" : "text-white"
|
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
if (link.external) {
|
if (link.external) {
|
||||||
|
|||||||
97
lib/data.ts
97
lib/data.ts
@@ -166,6 +166,71 @@ export const jobs: Job[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const projects: Project[] = [
|
export const projects: Project[] = [
|
||||||
|
{
|
||||||
|
"id": 16,
|
||||||
|
"name": "K-Notes",
|
||||||
|
"short_description": "A Google Keep replica focusing on simplicity.",
|
||||||
|
"description": "A full-featured Google Keep replica designed for speed and simplicity. It allows users to manage their notes efficiently and is a core part of the K-Suite.\n\n**Technical details:**\n- **Backend:** Rust\n- **Frontend:** React",
|
||||||
|
"category": "Web",
|
||||||
|
"github_url": "https://github.com/GKaszewski/k-notes",
|
||||||
|
"visit_url": "https://knotes.gabrielkaszewski.dev/",
|
||||||
|
"download_url": null,
|
||||||
|
"technologies": [
|
||||||
|
"Rust",
|
||||||
|
"React",
|
||||||
|
"TailwindCSS",
|
||||||
|
"PWA"
|
||||||
|
],
|
||||||
|
"thumbnails": ["/images/k-notes.png"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"name": "Thoughts",
|
||||||
|
"short_description": "Nostalgic microblogging platform with a Frutiger Aero aesthetic.",
|
||||||
|
"description": "Thoughts is a microblogging social website straight out of the 00s, featuring a distinctive Frutiger Aero style. Users can post short text-based thoughts (up to 128 characters), customize their entire profile page with their own CSS, and follow others in a purely chronological, algorithm-free environment. It's a return to the 'old times' of the web, focusing on genuine interaction and user expression.\n\n**Technical details:**\n- **Backend:** Rust\n- **Frontend:** Next.js",
|
||||||
|
"category": "Web",
|
||||||
|
"github_url": "https://git.gabrielkaszewski.dev/GKaszewski/thoughts",
|
||||||
|
"visit_url": "https://thoughts.gabrielkaszewski.dev/",
|
||||||
|
"download_url": null,
|
||||||
|
"technologies": [
|
||||||
|
"Rust",
|
||||||
|
"Next.js",
|
||||||
|
"TailwindCSS",
|
||||||
|
"Axum"
|
||||||
|
],
|
||||||
|
"thumbnails": ["/images/thoughts.avif"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 17,
|
||||||
|
"name": "K-Tuner",
|
||||||
|
"short_description": "Web app to tune guitar, ukulele and piano.",
|
||||||
|
"description": "A web application for tuning musical instruments including guitar, ukulele, and piano. It features a nostalgic Frutiger Aero style and is built as a Progressive Web App (PWA) for use on any device.\n\n**Technical details:**\n- **Frontend:** React PWA",
|
||||||
|
"category": "Web",
|
||||||
|
"github_url": "https://github.com/GKaszewski/aero-tuner",
|
||||||
|
"visit_url": "https://tuner.gabrielkaszewski.dev/",
|
||||||
|
"download_url": null,
|
||||||
|
"technologies": [
|
||||||
|
"React",
|
||||||
|
"PWA",
|
||||||
|
"TailwindCSS"
|
||||||
|
],
|
||||||
|
"thumbnails": ["/images/k-tuner.png"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"name": "K-QR",
|
||||||
|
"short_description": "Fast and simple QR code generator.",
|
||||||
|
"description": "A high-performance QR code generator built with Rust. It serves a clean HTML template and provides a fast, single-executable solution for generating QR codes. Part of the K-Suite.\n\n**Technical details:**\n- **Backend:** Rust\n- **Frontend:** HTML templates",
|
||||||
|
"category": "Web",
|
||||||
|
"github_url": "https://github.com/GKaszewski/k-qr",
|
||||||
|
"visit_url": "https://qr.gabrielkaszewski.dev/",
|
||||||
|
"download_url": null,
|
||||||
|
"technologies": [
|
||||||
|
"Rust",
|
||||||
|
"HTML"
|
||||||
|
],
|
||||||
|
"thumbnails": ["/images/k-qr.png"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"name": "Spanish Inquisition",
|
"name": "Spanish Inquisition",
|
||||||
@@ -227,24 +292,6 @@ export const projects: Project[] = [
|
|||||||
],
|
],
|
||||||
"thumbnails": []
|
"thumbnails": []
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"name": "Thoughts",
|
|
||||||
"short_description": "A nostalgic social platform prioritizing chronological feeds and user customization.",
|
|
||||||
"description": "Thoughts is a deliberate step away from algorithm-driven feeds. The vision is to create a digital \"third place\" that prioritizes genuine connection and user control, all wrapped in a nostalgic Frutiger Aero aesthetic.\n\nHere are the core principles I built this on:\n- **Chronological Above All:** Your feed is your feed, sorted by time. No algorithms, no \"you might also like.\"\n- **Radical Self-Expression:** Profiles are a canvas. I've brought back the ability for users to customize their pages with their own CSS, just like the good old days.\n- **Built for the Fediverse:** ActivityPub integration isn't in this MVP, but it's a top priority for the future to connect Thoughts with the wider decentralized web.\n\n**Technical details:**\n- **Backend:** Rust (Axum)\n- **Frontend:** Next.js\n- **Infrastructure:** Dockerized",
|
|
||||||
"category": "Web",
|
|
||||||
"github_url": "https://git.gabrielkaszewski.dev/GKaszewski/thoughts",
|
|
||||||
"visit_url": "https://thoughts.gabrielkaszewski.dev/",
|
|
||||||
"download_url": null,
|
|
||||||
"technologies": [
|
|
||||||
"Rust",
|
|
||||||
"Axum",
|
|
||||||
"Next.js",
|
|
||||||
"Docker",
|
|
||||||
"TailwindCSS"
|
|
||||||
],
|
|
||||||
"thumbnails": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": 7,
|
"id": 7,
|
||||||
"name": "Fleet Compass",
|
"name": "Fleet Compass",
|
||||||
@@ -367,19 +414,5 @@ export const projects: Project[] = [
|
|||||||
"Rust"
|
"Rust"
|
||||||
],
|
],
|
||||||
"thumbnails": []
|
"thumbnails": []
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 15,
|
|
||||||
"name": "QR Generator",
|
|
||||||
"short_description": "Fast and simple QR code generator.",
|
|
||||||
"description": "A utility tool for generating QR codes instantly.",
|
|
||||||
"category": "Api",
|
|
||||||
"github_url": "https://github.com/GKaszewski/qr-generator",
|
|
||||||
"visit_url": null,
|
|
||||||
"download_url": null,
|
|
||||||
"technologies": [
|
|
||||||
"Rust",
|
|
||||||
],
|
|
||||||
"thumbnails": []
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
BIN
public/images/k-notes.png
Normal file
BIN
public/images/k-notes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 512 KiB |
BIN
public/images/k-qr.png
Normal file
BIN
public/images/k-qr.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
public/images/k-tuner.png
Normal file
BIN
public/images/k-tuner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 276 KiB |
BIN
public/images/thoughts.avif
Normal file
BIN
public/images/thoughts.avif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Reference in New Issue
Block a user