From f3c8c6a27b35f11474e316537990bc84655552f3 Mon Sep 17 00:00:00 2001 From: 4life Date: Fri, 29 May 2026 11:52:53 +0500 Subject: [PATCH] Add Upwork link --- components/Portfolio/Portfolio.module.css | 64 +++++ components/Portfolio/index.tsx | 275 +++++++++++----------- components/Skills/Grid/SkillViewer.ts | 2 +- components/Skills/Grid/model.ts | 20 +- public/icons/upwork.svg | 1 + 5 files changed, 218 insertions(+), 144 deletions(-) create mode 100644 public/icons/upwork.svg diff --git a/components/Portfolio/Portfolio.module.css b/components/Portfolio/Portfolio.module.css index e5006fc..74789d2 100644 --- a/components/Portfolio/Portfolio.module.css +++ b/components/Portfolio/Portfolio.module.css @@ -81,6 +81,33 @@ opacity: 1; } +.emailText { + font-size: 12px; + font-weight: 300; + color: var(--color-text-muted); + text-decoration: none; + margin-left: 10px; +} + +.downloadBtn { + display: inline-flex; + align-items: center; + font-size: 12px; + font-weight: 700; + color: var(--color-primary); + text-decoration: none; + border: 1.5px solid var(--color-primary); + border-radius: 6px; + padding: 3px 10px; + opacity: 0.8; + transition: opacity 0.15s, background 0.15s; +} + +.downloadBtn:hover { + opacity: 1; + background: #f0faf4; +} + /* Intro */ .intro { padding: 8px 0 16px; @@ -236,6 +263,39 @@ gap: 8px; } +/* Improvement bullet rows */ +.text ul { + padding-left: 20px; + margin: 4px 0 14px; +} + +.improvementItem { + list-style: none; + margin-left: -20px; + margin-bottom: 8px; + padding: 8px 12px 8px 14px; + border-left: 3px solid var(--color-primary); + background: #f0faf4; + border-radius: 0 6px 6px 0; +} + +.improvementItem p { + margin: 0; +} + +.impactLabel { + display: inline-block; + font-size: 10px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--color-primary); + margin-left: 8px; + white-space: nowrap; + vertical-align: middle; + opacity: 0.7; +} + .iconLink img { vertical-align: middle; } @@ -258,6 +318,10 @@ } @media print { + .downloadBtn { + display: none; + } + .milestone { flex-direction: column; } diff --git a/components/Portfolio/index.tsx b/components/Portfolio/index.tsx index edab408..780f0c3 100644 --- a/components/Portfolio/index.tsx +++ b/components/Portfolio/index.tsx @@ -38,7 +38,7 @@ export default (): JSX.Element => { B2 - + Email { > LinkedIn - { > Github + + Upwork + + + + + ↓ Download CV +
-

Projects

+

My examples

{

Full-stack web developer with 10+ years of experience building web and mobile - applications. Comfortable across the entire stack - from database design and backend APIs + applications. Comfortable across the entire stack — from database design and backend APIs to frontend UIs.

@@ -177,7 +190,7 @@ export default (): JSX.Element => { NgRx for Angular. Graphics work using SVG (animations, data viz, custom UI) and Canvas (real-time rendering, image manipulation). Real-time UX via sockets and SSE. Styling & UI: CSS-in-JS, Tailwind, SCSS/CSS Modules, fluid typography, custom - animation with Framer Motion and CSS transitions. Built component libraries using + animation with Framer Motion and CSS transitions. Built component libraries using{' '} Storybook. Use Vite, Webpack. Experienced optimizing bundle size by code splitting, tree-shaking, lazy loading, and analyzing bundle output. Testing: Unit and integration tests with Mocha, Jest/Vitest. E2E with Cypress{' '} @@ -185,11 +198,11 @@ export default (): JSX.Element => {

Develop APIs, data models, and system architecture. Production experience with high-load - systems built on microservices - including an SNS/SQS + Lambda pipeline processing 30k + systems built on microservices — including an SNS/SQS + Lambda pipeline processing 30k health-check requests per minute. PostgreSQL as the primary relational database — schema design, query optimization, indexing strategies, migrations. ORM experience with{' '} TypeORM and Sequelize across multiple production codebases. DynamoDB{' '} - for high-perfomance, low-latency workloads. Builds APIs in REST (with OpenAPI/ + for high-performance, low-latency workloads. Builds APIs in REST (with OpenAPI/ Swagger schemas as the contract) and GraphQL (schema design, resolvers, subscriptions). Production experience with multiple auth approaches: OpenID,{' '} Auth0, AWS Amplify (Cognito-based auth), and next-auth with different @@ -210,10 +223,10 @@ export default (): JSX.Element => {

Mentors and leads developers formally and informally. Fluent with AI-assisted development - tools with a clear methodology for using them to ship faster without lost in quality or - security. Reviews teammates code to catch bugs and keep quality high. Writes clear docs, - branching policies or linting rules. Good at detecting issues early by terminal, curl, - logs, native db querries, etc. + tools with a clear methodology for using them to ship faster without losing quality or + security. Reviews teammates' code to catch bugs and keep quality high. Writes clear + docs, branching policies, and linting rules. Good at detecting issues early using the + terminal, curl, logs, and native database queries.

@@ -238,73 +251,76 @@ export default (): JSX.Element => {

- At Kupsilla, I worked on high-impact client projects including Strateos, a - pioneer in lab automation, and a Genetic Science research platform. + At Kupsilla I worked on two client projects: Strateos, a cloud lab automation + platform, and a Genetic Science research application.

- Conducted technical interviews for junior and middle-level candidates, - performed code reviews, and mentored developers to maintain code quality - and support team growth. + Conducted technical interviews for junior and mid-level candidates, performed{' '} + code reviews, and mentored developers to keep code quality high and + support team growth.

- Strateos Project – Contributed to the development of a cutting-edge{' '} - Cloud Lab Automation-as-a-Service platform that enables users to remotely run - real-world chemical reactions via automated robotics. + Strateos – A Cloud Lab Automation-as-a-Service platform where users + remotely run real chemical reactions via robotic systems.

    -
  • +
  • - Designed and developed user dashboards for managing lab automation processes using{' '} - React, TypeScript, SCSS, and Storybook. + Improved scalability and independent deployability of a large React codebase, + measured by separate release cycles per team, by re-architecting the frontend into{' '} + microfrontends using React, TypeScript, SCSS, and{' '} + Storybook.↑ Scalability

  • -
  • +
  • - Re-architected the large front-end codebase into microfrontends to improve - scalability and maintainability. + Increased development speed across teams, measured by reduced duplication of UI + work, by building shared UI libraries and publishing them to a private{' '} + NPM registry used by all microfrontend modules. + ↑ Dev Speed

  • -
  • +
  • - Created and maintained shared UI libraries distributed via a private NPM - registry for consistency across teams and faster development cycles. + Built a complex chemical reaction constructor — a heavy custom UI component that + lets users visually design lab reactions — and packaged it as a standalone NPM + module to keep the main app lightweight and maintainable. + ↑ Maintainability

- Genetic Science Project – Led front-end development for a web application that - allows users to{' '} - search and visualize scientific parameters related to human genes. + Genetic Science – A web application for searching and visualizing scientific + parameters related to human genes.

    -
  • +
  • - Built interactive, high-performance tables, plots, and graphs using{' '} - nivo.rocks, optimized for handling large genomic datasets. + Reduced initial page load time for data-heavy genomic pages by implementing{' '} + SSR and enabling gzip compression on API responses.{' '} + ↑ Performance

  • -
  • +
  • - Chose Server-Side Rendering (SSR) architecture to significantly improve - load times, especially for data-heavy pages. + Kept AWS infrastructure costs within the free tier, measured by zero hosting + spend, by deploying on AWS Amplify and managing build-minute usage within + free quota limits. ↓ Cost

  • -
  • +
  • - Implemented performance tuning strategies to ensure smooth user interactions, - including virtualization and efficient state management. + Built a complex interactive view combining a data plot and a collapsible rows + table in one synchronized layout using nivo.rocks, improving data + exploration for researchers. ↑ UX

  • -
  • -

    - Decided to deploy the application on AWS Amplify, integrating{' '} - Amazon Cognito with a Google OAuth provider for authentication. -

    -
  • -
  • +
  • - Set up CI/CD pipelines and established a branching policy to - streamline team collaboration and release management. + Enabled smooth collaboration across the team, measured by a consistent CI/CD flow + for all developers, by setting up AWS Amplify with Amazon Cognito{' '} + (Google OAuth), linting, testing, and a GitHub branching policy from + scratch. ↑ Team Flow

@@ -331,30 +347,28 @@ export default (): JSX.Element => {

- I worked at Strata, a full product life-cycle engineering company, on multiple - projects including the gmb.io website and Praxis, a fitness video - training platform targeted at North American users. -

-

- The technology stack included Next.js (with React, Redux-Saga,{' '} - Styled-Components, and Formik) for both the frontend and backend, and{' '} - NestJS on the server side, using TypeScript, PostgreSQL, and{' '} - TypeORM. User authentication was handled via Auth0. The system supported - video uploads through AWS Lambda and AWS Transcribe, integrated with the{' '} - MUX video streaming service. Applications were hosted on AWS EC2 with - automated deployment via GitHub Actions. -

-

- The gmb.io platform hosts a large library of training videos. I improved video - delivery by optimizing playback performance, including automatic selection of the best - video resolution and codecs based on the user's device and browser capabilities. - This significantly enhanced the streaming experience across a wide range of clients. -

-

- Additionally, I refactored and stabilized the existing codebase, resolved issues in - the CI/CD pipeline, and simplified the generation of closed captions using AWS - services. + At Strata I worked on gmb.io and Praxis — a fitness video training + platform for North American users. Stack: Next.js, NestJS,{' '} + PostgreSQL, TypeORM, Auth0, AWS Lambda, MUX.

+
    +
  • +

    + Improved video streaming quality across a wide range of devices, measured by + reduced buffering and format errors, by implementing automatic platform detection + that selects the optimal video codec and resolution for each client.{' '} + ↑ Video Quality +

    +
  • +
  • +

    + Reduced the maintenance cost of the video upload pipeline, measured by the number + of AWS services needed to operate it, by simplifying the microservice architecture + and removing redundant steps.{' '} + ↓ Ops Cost +

    +
  • +

Previous flow

@@ -380,7 +394,7 @@ export default (): JSX.Element => {

- Also i maintain admin panel on react-admin. + Also maintained an admin panel built with react-admin.

@@ -405,48 +419,44 @@ export default (): JSX.Element => {

- I worked at Nwave as a Full Stack Web Developer. Nwave develops IoT solutions, - specializing in the automation of parking bays using smart parking sensors that - collect and transmit data in real time. The company primarily serves clients in the - UK. -

-

- At Nwave, I developed and maintained SPlace - progressive web application (PWA) - using TypeScript for installing, checking, and calibrating parking sensors on a - map. This application were built with Ionic 3 and later migrated to{' '} - Ionic 4/5. Key features included a built-in QR code scanner, integration - with a third-party calibration tool, local storage for configuration, - performance optimization for displaying a large number of map markers, and location - search using the Google Maps API. Authentication was implemented using{' '} - AWS Amplify, and the app was published on{' '} - - Google Play - - . -

-

- I also developed and supported an admin dashboard web application for monitoring and - managing sensor statuses. The tech stack included React, Redux-Saga,{' '} - TypeScript, Material-UI, Moment.js, Lodash,{' '} - AWS Amplify, and the Google Maps API. It was a single-page application - (SPA) with unit and end-to-end tests, integrated with{' '} - Bitbucket CI/CD and Sentry for logging. The site was hosted on{' '} - AWS S3. + At Nwave, an IoT company building smart parking sensors for UK clients, I worked as a + Full Stack Web Developer on both frontend and backend systems managing{' '} + 20,000 IoT devices.

+

- Additionally, I participated in migrating the backend from a legacy system to AWS - microservices. I implemented a REST API microservice for device management - using AWS Lambda, written in Node.js with TypeScript. The - database was PostgreSQL accessed via pg-promise, with geospatial - operations handled by PostGIS. AWS API Gateway managed the REST routes, - and AWS Cognito was used for user authentication. Deployment was automated - using the AWS CDK. I also implemented comprehensive unit and{' '} - e2e tests using Mocha, Chai, and the AWS SDK, achieving - 99% code coverage. + Also developed and maintained an admin dashboard for monitoring sensor statuses, built + with React, Redux-Saga, TypeScript, Material-UI,{' '} + AWS Amplify, and the Google Maps API. The app had full unit and + end-to-end test coverage, integrated with Bitbucket CI/CD and Sentry.

Architecture diagram

@@ -477,15 +487,14 @@ export default (): JSX.Element => {

- I worked at Adguard, one of the most popular ad blockers, where I contributed to both - the main product and additional browser extensions. I developed several browser - extensions using JavaScript (ES6), including: + At AdGuard, one of the most popular ad blockers, I contributed to both the main + product and additional browser extensions, written in JavaScript (ES6):

- In addition, I worked on the front-end of the{' '} + Also worked on the front-end of the{' '} - Adguard + AdGuard {' '} website using Vue, Vuex, and PostCSS.

@@ -529,15 +538,13 @@ export default (): JSX.Element => {

- I worked as a Web Developer for several companies, where I was responsible for - creating and maintaining websites using PHP, WordPress,{' '} - JavaScript, and jQuery. During this time, I began working with modern - JavaScript frameworks, including AngularJS (Angular 1), and developed - single-page applications (SPAs). I also gained experience with real-time features - using WebSockets and implemented interactive SVG animations for various - projects. Additionally, I automated build and deployment processes using Grunt{' '} - and Gulp, which improved development efficiency and consistency across - environments. + Worked as a Web Developer for several companies, building and maintaining websites + using PHP, WordPress, JavaScript, and jQuery. Started + working with modern JavaScript frameworks, including AngularJS (Angular 1), and + built single-page applications. Gained experience with real-time features using{' '} + WebSockets and created interactive SVG animations for various projects. + Automated build and deployment processes using Grunt and Gulp, which + improved development consistency across environments.

@@ -551,7 +558,7 @@ export default (): JSX.Element => {

- I studied at Moscow State Mining University – Faculty of Information Systems. Degree: + Studied at Moscow State Mining University – Faculty of Information Systems. Degree: Specialist in Software Engineering.

diff --git a/components/Skills/Grid/SkillViewer.ts b/components/Skills/Grid/SkillViewer.ts index 70683a2..746452b 100644 --- a/components/Skills/Grid/SkillViewer.ts +++ b/components/Skills/Grid/SkillViewer.ts @@ -50,7 +50,7 @@ export default class SkillViewer { this.detailContainer.innerHTML = skill.copy; this.view.classList.add(skill.theme || themeDefault); this.detailDescriptionContainer.innerHTML = skill.story; - this.detailNameContainer.innerHTML = `${skill.url}`; + this.detailNameContainer.innerHTML = `${skill.url}`; this.detailContainer.style.color = skill.textColor || '#FFFFFF'; this.detailDescriptionContainer.style.color = skill.textColor || '#FFFFFF'; this.detailNameContainer.style.color = skill.textColor || '#FFFFFF'; diff --git a/components/Skills/Grid/model.ts b/components/Skills/Grid/model.ts index 1fe35da..582c6a8 100644 --- a/components/Skills/Grid/model.ts +++ b/components/Skills/Grid/model.ts @@ -17,6 +17,7 @@ export type SkillModel = { positionX?: number; positionY?: number; image?: HTMLImageElement; + isInternal?: boolean; }; const model: { content: SkillModel[]; layout: number[] } = { @@ -30,7 +31,7 @@ const model: { content: SkillModel[]; layout: number[] } = { color: '#f1ee00', textColor: '#000000', scale: 0.7, - url: 'tc39.es/', + url: 'http://tc39.es/', theme: 'white', }, { @@ -42,7 +43,7 @@ const model: { content: SkillModel[]; layout: number[] } = { color: '#b8d3ff', textColor: '#4e8ef7', scale: 0.7, - url: 'ionicframework.com/', + url: 'http://ionicframework.com/', theme: 'white', }, { @@ -54,8 +55,9 @@ const model: { content: SkillModel[]; layout: number[] } = { color: '#fff', textColor: '#000000', scale: 1, - url: '4life.work/portfolio', + url: '/portfolio', theme: 'white', + isInternal: true, }, { id: 'postgres', @@ -77,7 +79,7 @@ const model: { content: SkillModel[]; layout: number[] } = { color: '#b4b4b4', textColor: '#c4473a', scale: 0.7, - url: 'angularjs.org/', + url: 'http://angularjs.org/', }, { id: 'nodejs', @@ -88,7 +90,7 @@ const model: { content: SkillModel[]; layout: number[] } = { color: '#303030', textColor: '#ffffff', scale: 0.7, - url: 'nodejs.org/', + url: 'http://nodejs.org/', }, { id: 'github', @@ -99,7 +101,7 @@ const model: { content: SkillModel[]; layout: number[] } = { color: '#002f67', textColor: '#ffffff', scale: 0.7, - url: 'github.com/', + url: 'http://github.com/', }, { id: 'react', @@ -121,7 +123,7 @@ const model: { content: SkillModel[]; layout: number[] } = { color: '#adadadff', textColor: '#333', scale: 0.7, - url: 'nextjs.org/', + url: 'http://nextjs.org/', theme: 'white', }, { @@ -145,7 +147,7 @@ const model: { content: SkillModel[]; layout: number[] } = { color: '#493449ff', textColor: '#ffffff', scale: 0.7, - url: 'mochajs.org/', + url: 'http://mochajs.org/', theme: 'default', }, { @@ -156,7 +158,7 @@ const model: { content: SkillModel[]; layout: number[] } = { color: '#007acc', textColor: '#ffffff', scale: 0.7, - url: 'typescriptlang.org/', + url: 'http://typescriptlang.org/', }, { id: 'vue', diff --git a/public/icons/upwork.svg b/public/icons/upwork.svg new file mode 100644 index 0000000..ba342ef --- /dev/null +++ b/public/icons/upwork.svg @@ -0,0 +1 @@ +