Skip to content
pnmrvvtlPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

3D Portfolio — Vitalii Ponomarov

An interactive portfolio built as a desktop OS experience with 3D capabilities. No frameworks — just TypeScript, Three.js, and a custom virtual DOM engine.

Live: vitalii-ponomarov.com


Tech Stack

Layer Technology
Language TypeScript 5.2 (strict mode)
Build Vite 5
3D Graphics Three.js 0.160
Testing Vitest 1 + jsdom
Linting ESLint 8 + @typescript-eslint
Git Hooks Husky 9
Deployment AWS S3 + CloudFront
CI/CD GitHub Actions

No React, Vue, or any UI framework. The component system, virtual DOM, and state management are all custom-built.


Features

  • Desktop OS interface — draggable/resizable windows, taskbar, desktop shortcuts, right-click context menu
  • 7 animated backgrounds — particles, constellation nodes, glass bubbles, grid distortion, noise gradient, floating shapes, Three.js WebGL
  • Interactive 3D world — full Three.js scene accessible as a desktop window
  • Portfolio windows — Stack, Experience, Education, Contacts, CV, GitHub, Email
  • Client-side routing — history API with deep link support
  • localStorage persistence — desktop shortcut positions survive refresh
  • SEO optimized — JSON-LD structured data, Open Graph, Twitter Cards, sitemap, robots.txt
  • Analytics — Google Tag Manager + Hotjar

Project Structure

src/
├── lib/                    # Custom framework
│   ├── Component.ts        # Abstract base component (lifecycle: mount/update/unmount)
│   ├── Dom.ts              # VNode creation utilities
│   ├── Reconciler.ts       # Virtual DOM diffing & patching
│   ├── Store.ts            # Pub/sub state store
│   ├── FormValidator.ts    # Form validation helpers
│   ├── Types.ts            # Core type definitions (VNode, VNodeChild)
│   └── __tests__/
├── apps/
│   ├── os/                 # Main portfolio OS app
│   │   ├── components/
│   │   │   ├── Background/         # 7 animated background implementations
│   │   │   ├── ContextMenu/        # Right-click menu
│   │   │   ├── Desktop/            # Root desktop container
│   │   │   ├── DesktopIcon/        # Draggable shortcut icons
│   │   │   ├── Taskbar/            # Bottom bar with window buttons
│   │   │   ├── ThreeWorld/         # Three.js 3D scene (excluded from coverage)
│   │   │   └── WindowFrame/        # Movable/resizable window chrome
│   │   ├── data/                   # JSON content (projects, stack, education, etc.)
│   │   ├── types/                  # Domain type definitions
│   │   ├── styles/
│   │   ├── __tests__/
│   │   ├── AppRegistry.ts          # Maps app IDs to content renderers
│   │   ├── OsState.ts              # Global state initialization
│   │   ├── OsTypes.ts              # WindowConfig, ShortcutConfig, OsState
│   │   ├── Router.ts               # Client-side router
│   │   ├── WindowManager.ts        # Window open/close/minimize/maximize/focus
│   │   ├── MetadataManager.ts      # Page title & meta tag updates
│   │   └── RouteConfig.ts          # Route → app ID mapping
│   └── CounterApp.ts               # Minimal example app
├── components/
│   └── CookieConsent.ts
├── styles/
│   ├── theme.css                   # CSS custom properties / design tokens
│   └── responsive.css
└── main.ts                         # Entry point

Getting Started

Prerequisites

  • Node.js 20+
  • npm

Install

npm install

Development

npm run dev

Opens at http://localhost:5173 (or the LAN IP printed in the terminal due to --host).

Production build

npm run build
npm run preview   # preview the dist/ output locally

Scripts

Script What it does
npm run dev Start Vite dev server with --host
npm run build Production build → dist/
npm run preview Serve the production build locally
npm run test Run all unit tests
npm run test:coverage Run tests with V8 coverage report
npm run type-check tsc --noEmit type validation
npm run lint ESLint over src/
npm run check:all type-check + lint + test (full quality gate)

check:all is the gate. It runs automatically on every git commit (via Husky pre-commit hook) and is the required verification step after any code change.


Testing

Tests use Vitest with a jsdom environment.

npm run test              # run once
npm run test:coverage     # with coverage report

Coverage thresholds (enforced by vitest config):

Metric Threshold
Lines 80%
Functions 80%
Branches 80%
Statements 80%

Test locations:

  • src/lib/__tests__/ — Component, FormValidator, Reconciler
  • src/apps/os/__tests__/ — AppRegistry, MetadataManager, RouteConfig, Router, WindowManager
  • src/apps/os/components/WindowFrame/__tests__/ — WindowFrame

Excluded from coverage: ThreeWorld, CounterApp, test files, .d.ts files.


Architecture

Custom Framework (src/lib/)

Built from scratch — no React, no Vue.

  • Component — Abstract base class. Subclasses implement render(): VNode. The base handles mounting to DOM, reconciliation on state changes, and unmounting.
  • Dom — Factory helpers for creating VNode objects (similar to React.createElement).
  • Reconciler — Diffs old and new VNode trees and applies minimal DOM patches.
  • Store — Pub/sub store. Components subscribe to slices of state; mutations trigger re-renders.

State Management

OsState.ts initializes the global Store<OsState> instance. State shape:

interface OsState {
  windows: WindowConfig[];
  shortcuts: ShortcutConfig[];
  activeWindowId: string | null;
  currentBackground: string;
}

Desktop shortcut positions are persisted to localStorage and rehydrated on load. Conflicting icon positions are resolved automatically.

Routing

Router.ts wraps the History API. RouteConfig.ts maps URL paths to app IDs. When a window opens/closes the URL updates automatically; navigating directly to a URL re-opens the corresponding window.

Window Management

WindowManager.ts owns the full window lifecycle: open, close, minimize, maximize, restore, focus (z-index), drag (move), and resize. Each window is a WindowConfig object stored in OsState.


Deployment

Deployments trigger automatically on push to the production branch.

Pipeline (.github/workflows/production.yml):

  1. Checkout + Node 20 setup
  2. npm install && npm run build
  3. OIDC-based AWS role assumption
  4. Sync dist/ to S3 (--delete for clean deploy)
  5. CloudFront cache invalidation (/*)

Required GitHub secrets: AWS_ROLE_ARN, S3_BUCKET_NAME, CLOUDFRONT_DIST_ID


Git Hooks (Husky)

Hook Command
pre-commit npm run check:all
pre-push npm run build

Commits are blocked if type-check, lint, or any test fails.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages