Work Experience
Display work experiences with role details, company logos, and durations.
Virallens
I build complete digital products end to end, where AI meets polished software people use every day.
- Citera: Built the pipeline that extracts factual claims from any text, link, or file and verifies each one against trusted sources with word-for-word evidence.
- L-K Drop Analysis: Built the front-end over the analysis engine, with hover-to-source citations and a live AI chat that streams its reasoning.
- Perssonify Website 3: Shipped a responsive, animated site for four brands from one codebase with a shared design system.
- TypeScript
- React 19
- Next.js 16
- Tailwind CSS
- shadcn/ui
- Framer Motion
- Node.js
- Vercel AI SDK
- Turborepo
Education
- C++
- Python
- Control Systems
- Embedded Systems
Features
- Supports multiple positions per company.
- Markdown in position descriptions: paragraphs, lists, bold,
code, and links. - Company logos, employment type, period, and a calculated duration.
- Positions with a description expand and collapse; positions without one stay static.
- No markdown, date, or icon libraries required.
Installation

pnpm dlx shadcn@latest add @cortexcn/work-experienceThe CLI also installs the shadcn/ui Collapsible and Separator components.
Usage
import { WorkExperience } from "@/components/work-experience";
import type { ExperienceItemType } from "@/components/work-experience";const experiences: ExperienceItemType[] = [
{
id: "acme",
companyName: "Acme",
companyWebsite: "https://acme.com",
isCurrentEmployer: true,
positions: [
{
id: "engineer",
title: "Software Engineer",
employmentPeriod: { start: "03.2024" },
employmentType: "Full-time",
description:
"- Shipped the new billing flow.\n- Led the design system.",
skills: ["React", "TypeScript"],
},
],
},
];
<WorkExperience experiences={experiences} />;Dates use MM.YYYY or YYYY. Leave end out for a current role; the period then ends with an infinity sign and the duration counts up to today. icon accepts any element, so you can use whichever icon set your project already has.
API reference
WorkExperience
| Prop | Type | Default | Description |
|---|---|---|---|
experiences | ExperienceItemType[] | required | Companies to list, in order |
className | string | - | Extra classes for the root div |
ExperienceItemType
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for the experience item |
companyName | string | Name of the company |
companyLogo | string? | URL or path to the company's logo image |
companyWebsite | string? | URL to the company's website |
positions | ExperiencePositionItemType[] | Positions held at the company |
isCurrentEmployer | boolean? | Shows a live indicator next to the company |
ExperiencePositionItemType
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for the position |
title | string | The job title or position name |
employmentPeriod | { start: string; end?: string } | MM.YYYY or YYYY. Omit end for current roles |
employmentType | string? | For example "Full-time", "Part-time", or "Contract" |
description | string? | Markdown description; the position collapses when it is set |
icon | ReactElement? | Icon for the position. Defaults to a briefcase |
skills | string[]? | Skills shown as tags under the position |
isExpanded | boolean? | Whether the description starts expanded |
