From 5e98765033b49a25ef9df5fda8d9bdf3b982abf5 Mon Sep 17 00:00:00 2001 From: Builder Date: Wed, 5 Aug 2026 14:59:19 -0400 Subject: [PATCH] Polish README and point Network tab at GitHub --- README.md | 46 +++++++++------------------------------------- index.html | 4 ++-- js/app.js | 2 +- js/data.js | 45 ++++++++++++++++++--------------------------- 4 files changed, 30 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 4c88dcc..49428d3 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,18 @@ # portfolio.spec.ts -> A personal portfolio + resume styled as a **Playwright test runner**. Built by an SDET, for SDETs. -> -> Gitea remote: `ilia/sdetProfile` (local folder is usually cloned as `portfolio`). +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) +[![Live](https://img.shields.io/badge/live-sdet.levkin.ca-0a0)](https://sdet.levkin.ca) -Click the green ▶ next to any test to "run" it — each passing test reveals a portfolio section. Filter by `@tag` chips like a real `--grep`. Includes a career-timeline trace viewer, a Source tab that renders the portfolio as actual-looking Playwright spec code, a **Network** tab that lists public [git.levkin.ca](https://git.levkin.ca/explore/repos) repos as Playwright-style `GET … 200` rows with expandable JSON (descriptions from the Gitea API or each repo's README), and a downloadable PDF resume. +Career portfolio styled as a **Playwright test runner** — sidebar explorer, editor tabs, trace viewer, Network tab, keyboard shortcuts. -**Live preview:** deploy locally (see below) or open `index.html` directly. - ---- +**Live:** [sdet.levkin.ca](https://sdet.levkin.ca) · **Public mirror:** [github.com/Gitilia/sdetProfile](https://github.com/Gitilia/sdetProfile) ## Why this exists -A traditional portfolio doesn't tell a hiring manager you live in test runners all day. This one does — every interaction is a love letter to the tooling SDETs use: - -- Sidebar **Test Explorer** (400px) with collapsible suites, green run arrows, and tree-view ellipsis for long describe labels -- **Editor tab strip** (28px, slim) above the report — switch between `portfolio.spec.ts`, `projects.spec.ts`, `skills.spec.ts`, `playground.spec.ts`; each rescopes the explorer, report, source view, and status counts (cookie-persisted) -- **Status pill** merged into the editor bar with live pass/fail/skip counts per active spec -- **Overflow menu** (⋯) on the right of the editor tabs with `--workers=` and `--headed` controls -- **Skipped test** (`should meet performance budget`) with amber ⊘ icon — a 100% green suite looks fake; mixed outcomes feel authentic -- Progress bars under each test that fill in real time -- **Auto-run** first test on page load so the hero arrives with body content rendered (runner animation still plays) -- **Summary stripe** above the results list: `Last run · 1.4s · 4 passed · 1 skipped` -- **Pending preview** — the first idle test's body is shown expanded with a faded look + "click ▶ to run" overlay -- **Tag bar** with 6 visible tags + "+N more" expand chip + a `× clear` button -- **Count bubbles** right-aligned with consistent width, tabular numerals, outlined — reads as "metric" not "tag" -- VS Code dark+ / Playwright trace viewer palette (Inter + JetBrains Mono) -- A `Trace` tab that draws your career as a Gantt-style waterfall -- A `Source` tab that renders the active spec as a real-looking `.spec.ts` file -- A `Console` tab that logs test run events live -- A `Network` tab modeled on Playwright's network panel — one row per public Gitea repo (`GET https://git.levkin.ca/api/v1/repos/…`), click to expand the faux JSON body -- `--headed` toggle that slows animations down for demo mode -- `--workers=` selector for parallel test execution (1, 2, or 4 workers) -- Cookie-persisted theme cycle: dark → light → high-contrast (WCAG AAA) -- Keyboard shortcuts (`?` to see all): `R` run all, `X` reset, `T` theme, `/` grep, `1–9` run Nth test -- Mobile drawer for the test explorer, fully responsive - ---- +Hiring managers who work with SDETs already live in test runners. This site uses +that UI metaphor instead of a generic landing page: sidebar explorer, editor tabs, +status pill, trace viewer, network panel, and keyboard shortcuts modeled on +Playwright and VS Code. ## Stack @@ -308,8 +284,4 @@ See [IDEAS.md](IDEAS.md) for the backlog. Quick wins on top, ambitious experimen ## License -MIT. Fork it, restyle it, replace the content with your own. If you ship a variation, a wave hello on LinkedIn would be appreciated but is not required. - ---- - -**Built by** [Ilia Dobkin](https://www.linkedin.com/in/ilia-dobkin-8263343/) · Senior SDET · Remote (ET) +MIT — see [LICENSE](LICENSE). Fork and replace the content as you like. diff --git a/index.html b/index.html index ccb5c30..1a875f2 100644 --- a/index.html +++ b/index.html @@ -186,11 +186,11 @@
- +
-
Network · git.levkin.ca
+
Network · github.com/Gitilia
200application/json
diff --git a/js/app.js b/js/app.js index 9d1d352..b2efe07 100644 --- a/js/app.js +++ b/js/app.js @@ -677,7 +677,7 @@ } const GF = window.PORTFOLIO; const repos = GF && Array.isArray(GF.giteaRepos) ? GF.giteaRepos : []; - const apiRoot = 'https://git.levkin.ca/api/v1/repos/'; + const apiRoot = 'https://api.github.com/repos/'; if (repos.length === 0) { wrap.innerHTML = `
No giteaRepos in js/data.js. Hard refresh the page (Cmd+Shift+R). If deploying, redeploy after adding the array.
`; return; diff --git a/js/data.js b/js/data.js index baf5cf6..3816e50 100644 --- a/js/data.js +++ b/js/data.js @@ -8,7 +8,8 @@ window.PORTFOLIO = { workAuth: "Canadian citizen", email: "idobkin@gmail.com", linkedin: "https://www.linkedin.com/in/ilia-dobkin-8263343/", - gitea: "https://git.levkin.ca", + gitea: "https://github.com/Gitilia", + github: "https://github.com/Gitilia", site: "https://sdet.levkin.ca", blurb: "Senior SDET with 20+ years in audit/financial software and regulated web, including real-money iGaming. Deep across Playwright, Swagger/OpenAPI contract testing, and performance baselines integrated into CI/CD. I treat automation as a personal discipline as much as a job: scripts, shortcuts, and agents that streamline my day so engineering effort goes where it matters. Strong instinct for stabilizing flaky suites, tightening quality gates, and removing manual regression effort wherever it lives.", @@ -185,7 +186,7 @@ window.PORTFOLIO = { tags: ["@api","@perf"], duration: 0, steps: [ - { kind: "ok", title: 'navigate to Gitea API endpoint', dur: 45 }, + { kind: "ok", title: 'navigate to GitHub API endpoint', dur: 45 }, { kind: "ok", title: 'send GET /api/v1/repos/ilia/portfolio', dur: 62 }, { kind: "ok", title: 'assert status 200', dur: 8 }, { kind: "fail", title: 'expect(latency).toBeLessThan(200)', dur: 347 }, @@ -377,30 +378,20 @@ window.PORTFOLIO = { ], /** - * Public repos on git.levkin.ca — descriptions from Gitea API when set, - * otherwise first paragraph of README (see scripts/fetch-gitea-repos.mjs). - * API lists all 19 repos on one page (explore UI may paginate). + * Public repos on github.com/Gitilia — mirrored from Gitea for recruiters. + * Keep this list to public GitHub only (no private forge links). */ giteaRepos: [ - { full_name: "ilia/ansible", name: "ansible", html_url: "https://git.levkin.ca/ilia/ansible", language: "Makefile", description: "Ansible automation for development machines, service hosts, and Proxmox-managed guests (LXC-first, with a path for KVM VMs)." }, - { full_name: "ilia/AtAnyRate", name: "AtAnyRate", html_url: "https://git.levkin.ca/ilia/AtAnyRate", language: "Python", description: "Local Python application that identifies upcoming Toronto events likely to increase Airbnb demand, sends Telegram alerts, and optionally adjusts nightly prices via Playwright automation." }, - { full_name: "ilia/atlas", name: "atlas", html_url: "https://git.levkin.ca/ilia/atlas", language: "Python", description: "Atlas is a local, privacy-focused home voice agent system — planning, architecture documentation, and kanban tickets for building the system." }, - { full_name: "ilia/crkl", name: "crkl", html_url: "https://git.levkin.ca/ilia/crkl", language: "Kotlin", description: "Privacy-first Android AI assistant — circle or touch any element on-screen; on-device AI transcribes, summarizes, explains, or drafts responses." }, - { full_name: "ilia/dotfiles", name: "dotfiles", html_url: "https://git.levkin.ca/ilia/dotfiles", language: "", description: "Dotfiles and shell configuration for dev machines." }, - { full_name: "ilia/hilitehero", name: "hilitehero", html_url: "https://git.levkin.ca/ilia/hilitehero", language: "Python", description: "Python tool for extracting highlighted text from PDFs with precise ordering and hyphenation handling." }, - { full_name: "ilia/invoice", name: "invoice", html_url: "https://git.levkin.ca/ilia/invoice", language: "JavaScript", description: "CLI for generating professional PDF invoices from JSON — interactive and non-interactive modes with preview-first workflow." }, - { full_name: "ilia/Jobber", name: "Jobber", html_url: "https://git.levkin.ca/ilia/Jobber", language: "TypeScript", description: "Self-hosted job search orchestration — discover roles, score fit, draft resumes and cover letters, export PDFs, track email; you submit applications yourself." }, - { full_name: "ilia/kanban", name: "kanban", html_url: "https://git.levkin.ca/ilia/kanban", language: "", description: "Kanban board project on self-hosted Gitea." }, - { full_name: "ilia/linkedout", name: "linkedout", html_url: "https://git.levkin.ca/ilia/linkedout", language: "JavaScript", description: "Job market intelligence platform with integrated AI-powered insights — modular architecture for extensibility." }, - { full_name: "ilia/llm_council", name: "llm_council", html_url: "https://git.levkin.ca/ilia/llm_council", language: "Python", description: "Local web UI like ChatGPT but sends each query to multiple LLMs — your \"LLM council\" votes with diverse models." }, - { full_name: "ilia/mirror_match", name: "mirror_match", html_url: "https://git.levkin.ca/ilia/mirror_match", language: "TypeScript", description: "Photo guessing game — upload photos, others guess who is in the picture for points. Next.js, PostgreSQL, NextAuth." }, - { full_name: "ilia/nanobot", name: "nanobot", html_url: "https://git.levkin.ca/ilia/nanobot", language: "Python", description: "Ultra-lightweight personal AI assistant (Python; published on PyPI as nanobot-ai)." }, - { full_name: "ilia/onboarding", name: "onboarding", html_url: "https://git.levkin.ca/ilia/onboarding", language: "Shell", description: "Developer environment setup — automates 60+ apps and tools plus Git and SSH configuration." }, - { full_name: "ilia/outreach", name: "outreach", html_url: "https://git.levkin.ca/ilia/outreach", language: "JavaScript", description: "Node.js email outreach for campaigns to law firms — templates, tracking, and tests." }, - { full_name: "ilia/POTE", name: "POTE", html_url: "https://git.levkin.ca/ilia/POTE", language: "Python", description: "Research-oriented tool for tracking and analyzing public stock trades by government officials." }, - { full_name: "ilia/profile", name: "profile", html_url: "https://git.levkin.ca/ilia/profile", language: "TypeScript", description: "Profile / personal site — TypeScript." }, - { full_name: "ilia/punimtag", name: "punimtag", html_url: "https://git.levkin.ca/ilia/punimtag", language: "TypeScript", description: "Modern photo management and facial recognition system." }, - { full_name: "ilia/resume", name: "resume", html_url: "https://git.levkin.ca/ilia/resume", language: "", description: "Résumé generator based on the best-resume-ever project." } + { full_name: "Gitilia/playkit", name: "playkit", html_url: "https://github.com/Gitilia/playkit", language: "TypeScript", description: "Shared Playwright + API test helpers — UI actions, API client, timings, metrics." }, + { full_name: "Gitilia/context-extractor", name: "context-extractor", html_url: "https://github.com/Gitilia/context-extractor", language: "JavaScript", description: "Browser extension + Playwright package that dumps AI-ready page markdown, console, and network noise." }, + { full_name: "Gitilia/PaperPod", name: "PaperPod", html_url: "https://github.com/Gitilia/PaperPod", language: "Python", description: "Offline overhead video → named PDFs for Paperless (CV + OCR)." }, + { full_name: "Gitilia/SwipeAnything", name: "SwipeAnything", html_url: "https://github.com/Gitilia/SwipeAnything", language: "TypeScript", description: "Local-first swipe-to-triage UI with pluggable adapters." }, + { full_name: "Gitilia/maCopy", name: "maCopy", html_url: "https://github.com/Gitilia/maCopy", language: "TypeScript", description: "Native macOS menu-bar clipboard manager (Tauri + React)." }, + { full_name: "Gitilia/slack-sieve", name: "slack-sieve", html_url: "https://github.com/Gitilia/slack-sieve", language: "Python", description: "Sieve a Slack workspace export before Mattermost import." }, + { full_name: "Gitilia/sdetProfile", name: "sdetProfile", html_url: "https://github.com/Gitilia/sdetProfile", language: "JavaScript", description: "Career portfolio styled as a Playwright test runner." }, + { full_name: "Gitilia/portfolio", name: "portfolio", html_url: "https://github.com/Gitilia/portfolio", language: "JavaScript", description: "Personal hub for iliadobkin.com — projects, demos, consulting lanes." }, + { full_name: "Gitilia/levkin.ca", name: "levkin.ca", html_url: "https://github.com/Gitilia/levkin.ca", language: "HTML", description: "Levkin Inc. public homepage — static stack site." }, + { full_name: "Gitilia/mirror_match", name: "mirror_match", html_url: "https://github.com/Gitilia/mirror_match", language: "TypeScript", description: "Photo guessing game — upload photos, others guess who is in the picture for points." }, ] }; @@ -482,7 +473,7 @@ function renderProjects(){ ${_tags(p.tags)}
`).join('') }
-

Public code on git.levkin.ca — open the tab for an API-style request list.

+

Public code on github.com/Gitilia — open the tab for an API-style request list.

`; } @@ -537,7 +528,7 @@ function renderContact(){ return `
in/idobkin
-
git.levkin.ca
+
${_esc(p.location)}${p.workAuth ? ` · ${_esc(p.workAuth)}` : ''}
`; @@ -552,7 +543,7 @@ function renderPerfBudget(){ function renderResponseTime(){ return `
-

The Gitea API endpoint GET /api/v1/repos/ilia/portfolio exceeded the 200 ms latency budget three times in a row.

+

The GitHub API endpoint GET /repos/Gitilia/portfolio exceeded the 200 ms latency budget three times in a row.

What happened