Added more project details
Some checks are pending
ci/woodpecker/release/woodpecker Pipeline is running
|
|
@ -226,7 +226,7 @@ export default function Home() {
|
|||
<div className="flex items-center gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<p>Pipeline Status</p>
|
||||
<Image
|
||||
<img
|
||||
src="https://ci.georgew.dev/api/badges/11/status.svg"
|
||||
alt="Build Status"
|
||||
className="h-3 grayscale opacity-50 hover:opacity-100 hover:grayscale-0 transition-all"
|
||||
|
|
|
|||
110
components/Mermaid copy 2.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
"use client";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import mermaid from "mermaid";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { Maximize2, Minimize2 } from "lucide-react";
|
||||
|
||||
export default function Mermaid({ chart }: { chart: string }) {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const [isRendered, setIsRendered] = useState(false);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
theme: "dark",
|
||||
securityLevel: "loose",
|
||||
fontFamily: "monospace",
|
||||
});
|
||||
|
||||
// Render the chart once. Use a timeout to ensure DOM is stable.
|
||||
const renderChart = async () => {
|
||||
try {
|
||||
await mermaid.contentLoaded();
|
||||
setIsRendered(true);
|
||||
} catch (err) {
|
||||
console.error("Mermaid render failed:", err);
|
||||
}
|
||||
};
|
||||
|
||||
renderChart();
|
||||
}, [chart]); // Only re-run if the chart string itself changes
|
||||
|
||||
return (
|
||||
<div className="relative max-w-4xl mx-auto group">
|
||||
<motion.div
|
||||
layout
|
||||
initial={false}
|
||||
animate={{
|
||||
height: isExpanded ? "auto" : "400px",
|
||||
}}
|
||||
transition={{ duration: 0.6, ease: [0.23, 1, 0.32, 1] }}
|
||||
className={`relative bg-neutral-900/20 rounded-3xl border border-neutral-800/50 overflow-hidden transition-colors duration-500 ${
|
||||
!isExpanded
|
||||
? "hover:border-neutral-700 cursor-pointer"
|
||||
: "cursor-default"
|
||||
}`}
|
||||
onClick={() => !isExpanded && setIsExpanded(true)}
|
||||
>
|
||||
{/* Legend */}
|
||||
<div className="absolute top-6 right-8 flex flex-col gap-2 z-20 bg-black/40 backdrop-blur-md p-3 rounded-xl border border-white/5 pointer-events-none">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2 h-2 rounded-full bg-blue-500" />
|
||||
<span className="text-[9px] font-mono text-neutral-400 uppercase tracking-wider">
|
||||
Traffic Flow
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2 h-2 rounded-full bg-green-500" />
|
||||
<span className="text-[9px] font-mono text-neutral-400 uppercase tracking-wider">
|
||||
Service Node
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Chart Area */}
|
||||
<div
|
||||
className={`p-4 md:p-12 transition-opacity duration-500 ${isRendered ? "opacity-100" : "opacity-0"}`}
|
||||
>
|
||||
<div className="mermaid flex justify-center">{chart}</div>
|
||||
</div>
|
||||
|
||||
{/* Fade Overlay */}
|
||||
<AnimatePresence>
|
||||
{!isExpanded && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="absolute inset-x-0 bottom-0 h-40 bg-gradient-to-t from-[#0a0a0a] via-[#0a0a0a]/90 to-transparent pointer-events-none"
|
||||
/>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
|
||||
{/* Toggle Button */}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setIsExpanded(!isExpanded);
|
||||
}}
|
||||
className={`absolute -bottom-5 left-1/2 -translate-x-1/2 z-30 flex items-center gap-2 px-5 py-2.5 rounded-full text-[10px] font-mono uppercase tracking-[0.2em] transition-all border shadow-xl
|
||||
${
|
||||
isExpanded
|
||||
? "bg-neutral-800 border-neutral-700 text-white"
|
||||
: "bg-neutral-900 border-neutral-800 text-neutral-500 group-hover:bg-neutral-800 group-hover:border-neutral-600 group-hover:text-white"
|
||||
}`}
|
||||
>
|
||||
{isExpanded ? (
|
||||
<>
|
||||
<Minimize2 size={12} /> Collapse Logic
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Maximize2 size={12} /> Expand Architecture
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
98
components/Mermaid copy.tsx
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
"use client";
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
import mermaid from "mermaid";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { Maximize2, Minimize2 } from "lucide-react";
|
||||
|
||||
export default function Mermaid({ chart }: { chart: string }) {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const [needsExpansion, setNeedsExpansion] = useState(false);
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
mermaid.initialize({
|
||||
startOnLoad: true,
|
||||
theme: "dark",
|
||||
securityLevel: "loose",
|
||||
fontFamily: "monospace",
|
||||
});
|
||||
mermaid.contentLoaded();
|
||||
|
||||
if (contentRef.current) {
|
||||
const height = contentRef.current.scrollHeight;
|
||||
setNeedsExpansion(height > 400);
|
||||
}
|
||||
}, [chart]);
|
||||
|
||||
return (
|
||||
<div className="relative max-w-4xl mx-auto group">
|
||||
<motion.div
|
||||
initial={false}
|
||||
onClick={() => needsExpansion && setIsExpanded(!isExpanded)}
|
||||
animate={{ height: isExpanded || !needsExpansion ? "auto" : "400px" }}
|
||||
className={`relative bg-neutral-900/20 rounded-3xl border border-neutral-800/50 p-4 md:p-12 overflow-hidden transition-colors duration-500
|
||||
${needsExpansion && !isExpanded ? "cursor-pointer hover:border-neutral-700" : "cursor-default"}`}
|
||||
>
|
||||
{/* Legend */}
|
||||
<div className="absolute top-6 right-8 flex flex-col gap-2 z-20 bg-black/40 backdrop-blur-md p-3 rounded-xl border border-white/5">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2 h-2 rounded-full bg-blue-500" />
|
||||
<span className="text-[9px] font-mono text-neutral-400 uppercase tracking-wider">
|
||||
Traffic Flow
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2 h-2 rounded-full bg-green-500" />
|
||||
<span className="text-[9px] font-mono text-neutral-400 uppercase tracking-wider">
|
||||
Service Node
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ref={contentRef} className="mermaid flex justify-center">
|
||||
{chart}
|
||||
</div>
|
||||
|
||||
{/* The "Fade to Darkness" Overlay (when expansion is needed) */}
|
||||
<AnimatePresence>
|
||||
{needsExpansion && !isExpanded && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="absolute inset-x-0 bottom-0 h-40 bg-gradient-to-t from-[#0a0a0a] via-[#0a0a0a]/80 to-transparent pointer-events-none"
|
||||
/>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
|
||||
{/* Expand/Collapse Button (when expansion is needed) */}
|
||||
{needsExpansion && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setIsExpanded(!isExpanded);
|
||||
}}
|
||||
className={`absolute -bottom-5 left-1/2 -translate-x-1/2 z-30 flex items-center gap-2 px-5 py-2.5 rounded-full text-[10px] font-mono uppercase tracking-[0.2em] transition-all border shadow-xl
|
||||
${
|
||||
isExpanded
|
||||
? "bg-neutral-800 border-neutral-700 text-white"
|
||||
: "bg-neutral-900 border-neutral-800 text-neutral-500 group-hover:bg-neutral-800 group-hover:border-neutral-600 group-hover:text-white"
|
||||
}`}
|
||||
>
|
||||
{isExpanded ? (
|
||||
<>
|
||||
{" "}
|
||||
<Minimize2 size={12} /> Collapse Logic{" "}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{" "}
|
||||
<Maximize2 size={12} /> Expand Architecture{" "}
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -114,12 +114,12 @@ export default function MonitorRegistry({ isHovered }: { isHovered: boolean }) {
|
|||
{m.name}
|
||||
</span>
|
||||
<div className="flex gap-1 shrink-0 scale-90 origin-right">
|
||||
<Image
|
||||
<img
|
||||
src={`https://status.georgew.dev/api/badge/${m.id}/status`}
|
||||
className="h-5"
|
||||
alt="up"
|
||||
/>
|
||||
<Image
|
||||
<img
|
||||
src={`https://status.georgew.dev/api/badge/${m.id}/avg-response/24`}
|
||||
className="h-5 opacity-60"
|
||||
alt="ms"
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default function ProjectShowcase({ images }: { images: string[] }) {
|
|||
: "border-neutral-800 opacity-40 hover:opacity-100"
|
||||
}`}
|
||||
>
|
||||
<Image
|
||||
<img
|
||||
src={img}
|
||||
className="h-full w-full object-cover"
|
||||
alt={`Thumb ${i}`}
|
||||
|
|
|
|||
201
data/projects.ts
|
|
@ -1,16 +1,21 @@
|
|||
import { Project } from "@/types/project";
|
||||
|
||||
export const PROJECT_REGISTRY: Project[] = [
|
||||
{
|
||||
{
|
||||
slug: "ratoong",
|
||||
category: "web",
|
||||
title: "Ratoong",
|
||||
subtitle: "High-Performance Ski & Travel Engine",
|
||||
role: "Full-Stack Engineer",
|
||||
duration: "2020 — 2022", // Adjusted based on your "long time ago" comment
|
||||
duration: "2020 — 2022",
|
||||
stack: ["Angular", "Firebase", "GCP Cloud Functions", "TypeScript"],
|
||||
metrics: ["< 200ms Search Latency", "10,000+ Active Data Points", "Fully Responsive Design"],
|
||||
description: "A comprehensive ski resort planning and rating platform featuring real-time weather integration and complex multi-parameter search filters.",
|
||||
metrics: [
|
||||
"< 200ms Search Latency",
|
||||
"10,000+ Active Data Points",
|
||||
"Fully Responsive Design",
|
||||
],
|
||||
description:
|
||||
"A comprehensive ski resort planning and rating platform featuring real-time weather integration and complex multi-parameter search filters.",
|
||||
engineeringStory: `
|
||||
Building Ratoong was an exercise in managing **High-Density Data** within a reactive frontend ecosystem. The core challenge was transforming thousands of resort data points—ranging from piste lengths to real-time weather—into a lightning-fast, searchable interface.
|
||||
|
||||
|
|
@ -31,7 +36,7 @@ A key architectural pillar was the implementation of a robust **Security Rules**
|
|||
"/projects/ratoong/ratoong-2.jpg",
|
||||
"/projects/ratoong/ratoong-3.jpg",
|
||||
"/projects/ratoong/ratoong-4.jpg",
|
||||
"/projects/ratoong/ratoong-5.jpg"
|
||||
"/projects/ratoong/ratoong-5.jpg",
|
||||
],
|
||||
liveUrl: "https://ratoong.com",
|
||||
isPrivate: false,
|
||||
|
|
@ -78,34 +83,166 @@ graph LR
|
|||
slug: "datasaur",
|
||||
category: "web",
|
||||
title: "Datasaur",
|
||||
subtitle: "Personal R&D Pipeline",
|
||||
role: "Architect & Creator",
|
||||
duration: "2025 — Present",
|
||||
stack: ["Python", "FastAPI", "Next.js", "Redis"],
|
||||
metrics: ["Sub-50ms Latency", "Automated ETL", "Self-Hosted"],
|
||||
description: "A data science pipeline tool built to explore high-speed processing and real-time visualization of large datasets.",
|
||||
images: ["/datasaur-1.jpg"],
|
||||
subtitle: "Automated Statistical Analysis Engine",
|
||||
role: "Lead Architect & Creator",
|
||||
duration: "2019 — 2021", // Reflecting "one of my first things"
|
||||
stack: ["Python", "Flask", "MongoDB", "Pandas", "SciPy"],
|
||||
metrics: [
|
||||
"Automated Stat-Testing",
|
||||
"Multi-Format ETL",
|
||||
"Self-Hosted Architecture",
|
||||
],
|
||||
description:
|
||||
"A comprehensive survey data platform that automates complex statistical workflows, from raw data aggregation to advanced hypothesis testing and visualization.",
|
||||
storyLabel: "ALGORITHMIC // STATISTICAL PROCESSING",
|
||||
images: [
|
||||
"/projects/datasaur/datasaur-1.jpg",
|
||||
"/projects/datasaur/datasaur-2.jpg",
|
||||
"/projects/datasaur/datasaur-3.jpg",
|
||||
"/projects/datasaur/datasaur-4.jpg",
|
||||
"/projects/datasaur/datasaur-5.jpg",
|
||||
"/projects/datasaur/datasaur-6.jpg",
|
||||
],
|
||||
repoUrl: "https://git.georgew.dev/georgew/datasaur",
|
||||
liveUrl: "https://ratoong.com",
|
||||
engineeringStory: "In this high-stakes medical environment, I implemented a custom audit logging system that ensured every state change was immutable...",
|
||||
storyLabel: "DATA EFFICIENCY",
|
||||
isPrivate: true,
|
||||
liveUrl: "https://datasaur.georgew.dev", // Adjusted based on your self-hosting mention
|
||||
isPrivate: false,
|
||||
engineeringStory: `
|
||||
Datasaur was born out of a necessity to bridge the gap between raw survey data and academic-grade statistical insights. The challenge wasn't just displaying data, but architecting a system capable of performing complex mathematical computations on-the-fly.
|
||||
|
||||
#### Statistical Automation Pipeline
|
||||
The core of the application is a robust processing engine built on **Pandas** and **SciPy**. I implemented automated workflows for non-parametric tests like **Kruskal-Wallis** and **Mann-Whitney U**, ensuring that the platform could intelligently suggest and execute the correct statistical test based on the data distribution.
|
||||
|
||||
#### Data Visualization & Export
|
||||
To translate these numbers into insights, I built a visualization layer supporting everything from standard histograms to complex **Box and Whisker** plots. Using **XlsxWriter**, I developed a custom export engine that allowed users to pull processed data directly into professional-grade spreadsheets with pre-formatted statistical summaries.
|
||||
|
||||
#### Infrastructure & Monolithic Integrity
|
||||
The project follows a classic monolithic architecture, which proved highly efficient for keeping memory-intensive dataframes close to the processing logic. Today, the platform is self-hosted using a **Caddy** reverse proxy and **MongoDB Atlas**, demonstrating the longevity and stability of a well-architected Flask ecosystem.
|
||||
`,
|
||||
mermaidChart: `
|
||||
graph LR
|
||||
subgraph Client_Layer [User Interface]
|
||||
A[Vanilla JS / Browser]:::traffic
|
||||
end
|
||||
|
||||
subgraph Server_Layer [Application Logic]
|
||||
B[Caddy Reverse Proxy]:::node
|
||||
C[Flask / Python Monolith]:::node
|
||||
end
|
||||
|
||||
subgraph Processing_Engine [Data Science Core]
|
||||
D[Pandas ETL]:::node
|
||||
E[SciPy / Pingouin Stats]:::node
|
||||
F[XlsxWriter Export]:::node
|
||||
end
|
||||
|
||||
subgraph Storage [Data Persistence]
|
||||
G[MongoDB Atlas]:::node
|
||||
end
|
||||
|
||||
A <-->|HTTPS| B
|
||||
B <-->|WSGI| C
|
||||
C <-->|Query/Write| G
|
||||
C ==>|Dataframes| D
|
||||
D --> E
|
||||
D --> F
|
||||
|
||||
%% Styles %%
|
||||
classDef traffic fill:#2563eb,stroke:#3b82f6,color:#fff
|
||||
classDef node fill:#16a34a,stroke:#22c55e,color:#fff
|
||||
`,
|
||||
},
|
||||
{
|
||||
slug: "ayla",
|
||||
category: "web",
|
||||
category: "infrastructure",
|
||||
title: "Ayla",
|
||||
subtitle: "Regulatory-Compliant Data Platform",
|
||||
role: "Lead Full-Stack Engineer",
|
||||
subtitle: "Regulatory-Compliant Medical Platform",
|
||||
role: "Tech Lead & Scrum Master",
|
||||
duration: "2022 — 2024",
|
||||
stack: ["Node.js", "PostgreSQL", "React", "Docker"],
|
||||
metrics: ["99.9% Uptime", "Zero-Data-Loss Integrity", "ISO 27001 Ready"],
|
||||
description: "Architected a high-integrity platform designed to meet rigid regulatory requirements.",
|
||||
engineeringStory: "In this high-stakes medical environment, I implemented a custom audit logging system that ensured every state change was immutable...",
|
||||
images: ["/ratoong-hero.jpg", "/ratoong-dashboard.jpg"],
|
||||
liveUrl: "https://ratoong.com",
|
||||
stack: [
|
||||
"Kubernetes",
|
||||
"Ruby on Rails",
|
||||
"Flutter",
|
||||
"Terraform",
|
||||
"GCP",
|
||||
"OTC",
|
||||
],
|
||||
metrics: [
|
||||
"Multi-Region Data Residency",
|
||||
"ISO 27001 Compliant",
|
||||
"Single-Click IaC Deployment",
|
||||
],
|
||||
description:
|
||||
"A high-availability medical device platform supporting dementia treatment, featuring multi-cloud infrastructure, automated pipelines, cross-platform web and mobile deployments and strict regulatory requirements.",
|
||||
storyLabel: "GOVERNANCE // CLOUD ORCHESTRATION",
|
||||
images: [
|
||||
"/projects/ayla/ayla-1.jpg",
|
||||
"/projects/ayla/ayla-2.jpg",
|
||||
"/projects/ayla/ayla-3.jpg",
|
||||
"/projects/ayla/ayla-4.jpg",
|
||||
"/projects/ayla/ayla-5.jpg",
|
||||
],
|
||||
isPrivate: true,
|
||||
storyLabel: "DATA EFFICIENCY",
|
||||
engineeringStory: `
|
||||
As Tech Lead for Ayla, I was responsible for architecting a platform that met the rigorous safety and security standards of a certified medical device. This required a "Security-by-Design" approach, balancing high availability (SLA) with rigid data residency requirements across the UK and EU.
|
||||
|
||||
#### Multi-Cloud Infrastructure & IaC
|
||||
To satisfy GDPR and local health data regulations, I architected a dual-cloud strategy: **Open Telekom Cloud (OTC)** for European users and **GCP** for the UK. Using **Terraform**, I codified the entire infrastructure, enabling us to spin up identical, audit-ready Kubernetes clusters or Cloud Run environments in minutes. This automation was critical for maintaining the "Release-Pre-Release" protocols required for medical certification.
|
||||
|
||||
#### Full-Stack Delivery & Automation
|
||||
The platform featured a **Flutter** frontend for Web, iOS, and Android, all managed through automated **CICD** pipelines. I implemented a layered automation strategy, combining **GitHub Actions** for web deployments and server-side logic with **Fastlane** for mobile app store distribution. The backend was a high-performance **Ruby on Rails** API, architected as a stateless "mini-service" to ensure horizontal scalability within Kubernetes. I also integrated **Squidex CMS** to empower non-technical colleagues to manage content without compromising the system's core integrity.
|
||||
|
||||
#### Leadership & Compliance
|
||||
Beyond the code, I served as Scrum Master and Product Owner, leading sprint planning, retro and demos. I worked closely with regulatory partners and personally oversaw the creation of **DPIAs**, **Cyber Essentials** certification, and the path to **ISO 27001** compliance. In the absence of a dedicated IT department, I managed the MDM systems and sysadmin duties, ensuring that every layer of the organization met the strict regulatory bar.
|
||||
`,
|
||||
mermaidChart: `
|
||||
graph TB
|
||||
%% Direction and Layout
|
||||
direction TB
|
||||
|
||||
subgraph Shared_Ops [DevOps & CMS]
|
||||
I[GitHub Actions CICD]:::traffic
|
||||
J[Terraform IaC]:::traffic
|
||||
K[Squidex CMS]:::node
|
||||
end
|
||||
|
||||
subgraph Frontend_Layer [Omni-Channel]
|
||||
A[Flutter Web / Mobile]:::traffic
|
||||
B[Bunny CDN / Edge Storage]:::node
|
||||
end
|
||||
|
||||
subgraph UK_Region [GCP]
|
||||
G[Cloud Run Containers]:::node
|
||||
H[Cloud SQL]:::node
|
||||
end
|
||||
|
||||
subgraph EU_Region [Open Telekom Cloud]
|
||||
D[NGINX Ingress]:::node
|
||||
C[K8s Cluster]:::node
|
||||
F[Object Storage]:::node
|
||||
E[PostgreSQL RDS]:::node
|
||||
end
|
||||
|
||||
%% Connections
|
||||
A <--> B
|
||||
I -->|Fastlane| A
|
||||
J -->|Provision| G
|
||||
J -->|Provision| C
|
||||
|
||||
B <-->|UK Traffic| G
|
||||
B <-->|EU Traffic| D
|
||||
|
||||
D --> C
|
||||
G <--> H
|
||||
C <--> E
|
||||
C --- F
|
||||
|
||||
G <--> K
|
||||
C <--> K
|
||||
|
||||
%% Styles
|
||||
classDef traffic fill:#2563eb,stroke:#3b82f6,color:#fff
|
||||
classDef node fill:#16a34a,stroke:#22c55e,color:#fff
|
||||
`,
|
||||
},
|
||||
{
|
||||
slug: "flutter-1",
|
||||
|
|
@ -116,11 +253,13 @@ graph LR
|
|||
duration: "2025 — Present",
|
||||
stack: ["Python", "FastAPI", "Next.js", "Redis"],
|
||||
metrics: ["Sub-50ms Latency", "Automated ETL", "Self-Hosted"],
|
||||
description: "A data science pipeline tool built to explore high-speed processing and real-time visualization of large datasets.",
|
||||
description:
|
||||
"A data science pipeline tool built to explore high-speed processing and real-time visualization of large datasets.",
|
||||
images: ["/datasaur-1.jpg"],
|
||||
repoUrl: "https://git.georgew.dev/georgew/datasaur",
|
||||
liveUrl: "https://ratoong.com",
|
||||
engineeringStory: "In this high-stakes medical environment, I implemented a custom audit logging system that ensured every state change was immutable...",
|
||||
engineeringStory:
|
||||
"In this high-stakes medical environment, I implemented a custom audit logging system that ensured every state change was immutable...",
|
||||
storyLabel: "DATA EFFICIENCY",
|
||||
isPrivate: true,
|
||||
},
|
||||
|
|
@ -133,11 +272,13 @@ graph LR
|
|||
duration: "2025 — Present",
|
||||
stack: ["Python", "FastAPI", "Next.js", "Redis"],
|
||||
metrics: ["Sub-50ms Latency", "Automated ETL", "Self-Hosted"],
|
||||
description: "A data science pipeline tool built to explore high-speed processing and real-time visualization of large datasets.",
|
||||
description:
|
||||
"A data science pipeline tool built to explore high-speed processing and real-time visualization of large datasets.",
|
||||
images: ["/datasaur-1.jpg"],
|
||||
repoUrl: "https://git.georgew.dev/georgew/datasaur",
|
||||
liveUrl: "https://ratoong.com",
|
||||
engineeringStory: "In this high-stakes medical environment, I implemented a custom audit logging system that ensured every state change was immutable...",
|
||||
engineeringStory:
|
||||
"In this high-stakes medical environment, I implemented a custom audit logging system that ensured every state change was immutable...",
|
||||
storyLabel: "DATA EFFICIENCY",
|
||||
isPrivate: true,
|
||||
},
|
||||
|
|
|
|||
BIN
public/projects/ayla/ayla-1.jpg
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
public/projects/ayla/ayla-2.jpg
Normal file
|
After Width: | Height: | Size: 245 KiB |
BIN
public/projects/ayla/ayla-3.jpg
Normal file
|
After Width: | Height: | Size: 179 KiB |
BIN
public/projects/ayla/ayla-4.jpg
Normal file
|
After Width: | Height: | Size: 330 KiB |
BIN
public/projects/ayla/ayla-5.jpg
Normal file
|
After Width: | Height: | Size: 221 KiB |
BIN
public/projects/datasaur/datasaur-1.jpg
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
public/projects/datasaur/datasaur-2.jpg
Normal file
|
After Width: | Height: | Size: 354 KiB |
BIN
public/projects/datasaur/datasaur-3.jpg
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
public/projects/datasaur/datasaur-4.jpg
Normal file
|
After Width: | Height: | Size: 350 KiB |
BIN
public/projects/datasaur/datasaur-5.jpg
Normal file
|
After Width: | Height: | Size: 212 KiB |
BIN
public/projects/datasaur/datasaur-6.jpg
Normal file
|
After Width: | Height: | Size: 290 KiB |