10 KiB
Experience Timeline Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Replace the horizontal experience card carousel with a full-width vertical timeline that surfaces job descriptions and sub-phase breakdowns from static data.
Architecture: Extend the Job type with optional summary and sub_phases fields, update data.ts with CV content, then replace the card carousel with a new ExperienceTimeline server component. No client-side JS — all content is statically rendered.
Tech Stack: Next.js (App Router), TypeScript, TailwindCSS
File Map
| Action | File | Responsibility |
|---|---|---|
| Modify | lib/types.ts |
Add JobSubPhase, extend Job |
| Modify | lib/data.ts |
Add summary + sub_phases to WPP and GIAP entries |
| Create | components/experience-timeline.tsx |
Renders the full vertical timeline (server component) |
| Modify | components/experience.tsx |
Swap card loop for <ExperienceTimeline> |
| Delete | components/experience-card.tsx |
Replaced by timeline component |
Task 1: Extend types
Files:
-
Modify:
lib/types.ts -
Step 1: Add
JobSubPhaseand extendJob
Replace the entire contents of lib/types.ts with:
export interface Skill {
name: string;
}
export interface JobSubPhase {
label: string;
start_date: string;
end_date: string | null;
bullets: string[];
}
export interface Job {
id: number;
position: string;
company: string;
still_working: boolean;
start_date: string;
end_date: string | null;
technologies: string[];
summary?: string;
sub_phases?: JobSubPhase[];
}
export interface Project {
id: number;
name: string;
short_description: string;
description: string;
technologies: string[];
thumbnails: string[];
category: 'Web' | 'Mobile' | 'Desktop' | 'Api' | 'Game';
github_url?: string | null;
visit_url?: string | null;
download_url?: string | null;
commercial?: boolean;
}
- Step 2: Verify TypeScript is happy
npx tsc --noEmit
Expected: no errors (existing job entries have no sub_phases yet, so optional fields are fine).
- Step 3: Commit
git add lib/types.ts
git commit -m "feat: add JobSubPhase type and extend Job with summary and sub_phases"
Task 2: Update job data
Files:
-
Modify:
lib/data.ts -
Step 1: Update the WPP entry (id: 8)
Replace the WPP job object in the jobs array:
{
id: 8,
position: "Software Engineer",
company: "WPP Media | Choreograph | Wavemaker",
still_working: true,
start_date: "2023-09-13",
end_date: null,
summary:
"Advanced from frontend UI development to backend systems engineering, leading infrastructure-agnostic design initiatives.",
sub_phases: [
{
label: "Backend & Infrastructure",
start_date: "2025-03-01",
end_date: null,
bullets: [
"Engineered and optimized backend applications and internal tools using Python, FastAPI, and Django.",
"Streamlined CI/CD workflows and containerized applications with GitLab Pipelines, Docker, and Kubernetes across GCP and Azure environments.",
],
},
{
label: "Frontend Architecture",
start_date: "2023-09-13",
end_date: "2025-03-01",
bullets: [
"Architected scalable microfrontends utilizing Angular and Module Federation, seamlessly integrating standalone internal tools into a unified enterprise shell application.",
"Ensured seamless integration of UI components with Kubernetes-based deployments and Azure Pipelines.",
],
},
],
technologies: [
"Angular",
"Azure",
"Azure Pipelines",
"Django",
"Docker",
"FastAPI",
"GCP",
"Gitlab CI",
"Gitlab Pipelines",
"Kubernetes",
"PostgreSQL",
"Python",
"React",
"SCSS",
"TailwindCSS",
"Typescript",
],
},
- Step 2: Update the GIAP entry (id: 2)
Replace the GIAP job object:
{
id: 2,
position: "Full Stack Developer",
company: "GIAP",
still_working: false,
start_date: "2021-05-19",
end_date: "2023-02-03",
sub_phases: [
{
label: "Desktop / Backend",
start_date: "2021-05-19",
end_date: "2022-02-01",
bullets: [
"Architected and optimized complex PostGIS/PostgreSQL cross-database comparison queries utilizing Common Table Expressions (CTEs), drastically reducing execution time from over 5 minutes to under 15 seconds.",
"Developed a robust GIS data assertion module using Python and Qt to automatically validate spatial data against strict compliance standards.",
],
},
{
label: "Frontend",
start_date: "2022-02-01",
end_date: "2023-02-03",
bullets: [
"Engineered a comprehensive, public-facing web application for the City of Gdańsk (geogdansk.pl) leveraging React, TypeScript, Redux, and the ArcGIS JS API.",
],
},
],
technologies: [
"Python",
"React",
"Typescript",
"PostgreSQL",
"PostGIS",
"ArcGIS JS API",
"Redux",
"Qt",
"QGIS",
"Git",
],
},
- Step 3: Verify TypeScript is happy
npx tsc --noEmit
Expected: no errors.
- Step 4: Commit
git add lib/data.ts
git commit -m "feat: add sub_phases and summary to WPP and GIAP job entries"
Task 3: Create ExperienceTimeline component
Files:
-
Create:
components/experience-timeline.tsx -
Step 1: Create the component
import { Job } from "@/lib/types";
import Chip from "./chip";
import formatDate from "@/utils/format-date";
const ExperienceTimeline = ({ jobs }: { jobs: Job[] }) => (
<div className="relative w-full max-w-3xl mx-auto flex flex-col gap-0">
<div className="absolute left-[9px] top-3 bottom-3 w-px bg-gradient-to-b from-white/30 to-white/0" />
{jobs.map((job) => (
<div key={job.id} className="flex gap-6 pb-10 last:pb-0">
<div className="flex flex-col items-center shrink-0 w-5 pt-1.5 z-10">
<div className="w-3 h-3 rounded-full bg-white/40 border border-white/20 shadow-[0_0_8px_rgba(255,255,255,0.2)]" />
</div>
<div className="flex-1 bg-white/5 border border-white/10 rounded-2xl p-5 hover:border-white/20 transition-colors">
<div className="flex justify-between items-start flex-wrap gap-1 mb-1">
<h4 className="text-lg font-semibold text-white">{job.position}</h4>
<span className="text-xs text-white/40">
{formatDate(job.start_date)} –{" "}
{job.still_working ? "Present" : formatDate(job.end_date!)}
</span>
</div>
<p className="text-sm text-white/60 mb-4">{job.company}</p>
{job.summary && (
<p className="text-sm text-white/50 italic mb-4">{job.summary}</p>
)}
{job.sub_phases && job.sub_phases.length > 0 && (
<div className="flex flex-col gap-3 mb-4">
{job.sub_phases.map((phase) => (
<div
key={phase.label}
className="bg-white/[0.03] border border-white/[0.07] rounded-xl px-4 py-3"
>
<div className="flex justify-between items-center flex-wrap gap-1 mb-2">
<span className="text-[11px] font-semibold uppercase tracking-widest text-white/50">
{phase.label}
</span>
<span className="text-[10px] text-white/30">
{formatDate(phase.start_date)} –{" "}
{phase.end_date ? formatDate(phase.end_date) : "Present"}
</span>
</div>
<ul className="list-disc list-inside space-y-1">
{phase.bullets.map((b) => (
<li key={b} className="text-xs text-white/50 leading-relaxed">
{b}
</li>
))}
</ul>
</div>
))}
</div>
)}
<div className="border-t border-white/10 pt-4 mt-2">
<p className="text-[10px] uppercase tracking-widest text-white/30 mb-2">
Technologies
</p>
<div className="flex flex-wrap gap-2">
{job.technologies.map((tech) => (
<Chip key={tech} text={tech} />
))}
</div>
</div>
</div>
</div>
))}
</div>
);
export default ExperienceTimeline;
- Step 2: Verify TypeScript is happy
npx tsc --noEmit
Expected: no errors.
- Step 3: Commit
git add components/experience-timeline.tsx
git commit -m "feat: add ExperienceTimeline server component"
Task 4: Wire up timeline in Experience section and remove old card
Files:
-
Modify:
components/experience.tsx -
Delete:
components/experience-card.tsx -
Step 1: Replace
experience.tsx
import { Job } from "@/lib/types";
import ExperienceTimeline from "@/components/experience-timeline";
const Experience = ({ jobs }: { jobs: Job[] }) => (
<div
id="experience"
className="flex flex-col items-center gap-8 p-4 w-full"
>
<h3 className="mt-4 text-5xl font-bold tracking-tight text-white">
Experience
</h3>
<ExperienceTimeline jobs={jobs} />
</div>
);
export default Experience;
- Step 2: Delete the old card component
rm components/experience-card.tsx
- Step 3: Verify no remaining imports of ExperienceCard
grep -r "experience-card\|ExperienceCard" /mnt/drive/dev/gabrielkaszewski-next --include="*.tsx" --include="*.ts" | grep -v node_modules
Expected: no output.
- Step 4: Verify TypeScript is happy
npx tsc --noEmit
Expected: no errors.
- Step 5: Start dev server and visually verify the timeline renders correctly
npm run dev
Open http://localhost:3000 and scroll to the Experience section. Verify:
-
Vertical line and dots are visible
-
WPP shows summary + two sub-phase blocks with bullets
-
digimonkeys.com shows only dates + chips (no sub-phases)
-
GIAP shows two sub-phase blocks with bullets
-
Tech chips render under each entry
-
Step 6: Commit
git add components/experience.tsx
git commit -m "feat: replace experience card carousel with vertical timeline"