1
0
mirror of https://github.com/XFox111/my-website.git synced 2026-04-22 07:28:01 +03:00

init: First version

This commit is contained in:
2024-08-19 23:08:50 +00:00
commit 3ec7d9a722
134 changed files with 17088 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
@import "../theme.scss";
.section
{
@include centerTwo;
min-height: 75vh;
align-items: end;
.content
{
@include flex(column);
@include subtitle1($fontFamilyBaseAlt);
gap: $spacingXL;
h1
{
@include display($fontFamilyBaseAlt);
}
h2
{
@include title2($fontFamilyBaseAlt);
}
.ctaButtons
{
@include flex(row, wrap);
gap: $spacingS;
}
}
.highlight
{
color: $colorNeutralForegroundInverted;
background-color: $colorNeutralBackgroundInverted;
padding: $spacingXXS $spacingNone;
&::selection
{
color: $colorNeutralForegroundInverted;
background-color: $colorBrandForeground1;
}
}
.illustrations
{
justify-self: center;
position: relative;
margin-right: 48px;
margin-bottom: 12px;
.main
{
border-radius: $borderRadiusCircular;
max-width: 512px;
width: 100%;
height: auto;
}
.secondary
{
position: absolute;
bottom: -12px;
left: calc(60% + 48px);
width: 100%;
max-width: 40%;
height: auto;
}
}
}
+32
View File
@@ -0,0 +1,32 @@
import { homeDecor, profilePicture } from "@/_assets/illustrations";
import Button from "@/_components/Button";
import Image from "next/image";
import React from "react";
import cls from "./FrontSection.module.scss";
import links from "./links";
import Package from "@/../package.json";
const FrontSection: React.FC = () => (
<section className={ cls.section }>
<div className={ cls.content }>
<h1>Hello World!</h1>
<h2>{ Package.author.name } is here!</h2>
<p role="text">
I am a software engineer with extensive experience in<br aria-hidden />
<span className={ cls.highlight }>.NET and React development</span><br aria-hidden />
and you are on my website!
</p>
<div className={ cls.ctaButtons }>
<Button as="next" href={ links.resume }>Download resume</Button>
<Button appearance="secondary" as="next" href="#contacts">Contact me</Button>
</div>
</div>
<div className={ cls.illustrations }>
<Image className={ cls.main } src={ profilePicture.src } alt={ profilePicture.alt } priority />
<Image className={ cls.secondary } src={ homeDecor.src } alt={ homeDecor.alt } />
</div>
</section>
);
export default FrontSection;
+15
View File
@@ -0,0 +1,15 @@
import React from "react";
const ThirdPartyAttribution: React.FC = () => <>
<p>
Iconography, colorgraphy and typography of this website are based on
Microsoft's <a target="_blank" href="https://fluentui.dev/">Fluent Design System</a> licensed under
the <a target="_blank" href="https://github.com/microsoft/fluentui/blob/main/LICENSE">MIT License</a>.
</p>
<p>
Illustrations for GUT.Schedule and FoxTube projects use assets created
by <a target="_blank" href="https://www.freepik.com/author/rawpixel-com">rawpixel.com</a> on Freepik
</p>
</>;
export default ThirdPartyAttribution;
+40
View File
@@ -0,0 +1,40 @@
@import "../theme.scss";
.title
{
@include flex(row);
align-items: center;
background-size: 0% $strokeWidthThickest;
background-position: 33px 33px; // Some pixel-perfect stuff
color: $colorNeutralForeground1;
gap: $spacingS;
padding: $spacingNone;
padding-right: $spacingS;
> img
{
width: 36px;
height: 36px;
}
> p
{
@include title3($fontFamilyBaseAlt);
> sub
{
@include caption1($fontFamilyBaseAlt);
vertical-align: baseline;
}
}
&:hover,
&:focus-visible
{
background-size: 100% $strokeWidthThickest;
color: $colorNeutralForeground1;
}
}
+20
View File
@@ -0,0 +1,20 @@
import Link from "next/link";
import Image from "next/image";
import React from "react";
import logo from "@/icon.svg";
import cls from "./TitleLogo.module.scss";
const TitleLogo: React.FC = () => (
<Link className={ cls.title } href="/">
<Image src={ logo }
alt="A fox jumping down, and a diagonal stripe in the background, forming letters X and F"
aria-hidden
priority />
<p>
<span>xfox111</span>
<sub>.net</sub>
</p>
</Link>
);
export default TitleLogo;
+16
View File
@@ -0,0 +1,16 @@
export const bio: string[] =
[
"My name is Eugene Fox. I am a professional software developer primarily focused on .NET and React projects.",
"My journey as a programmer started in 2018 from a silly free-time hobby. Since then I've released a couple of personal projects, some of which have become quite popular.",
"Graduated from Bonch-Bruevich University of Telecommunications in 2023 where I've got my Bachelor degree in Computer science. It was fun. Took part in a number of hackathons (usually 1st place for us) as well as science conferences (including those, hosted by IEEE).",
"Also before graduation I've managed to work in several different companies in different IT fields (mostly software development, of course).",
"Out-of-box thinking and constant self-improvement is my life strategy. New tool released? - Yes, please! GitHub is hosting another conference? - Sign me up! There's a new challenging task to complete? - Oh, boy, here we go again! So much things to learn, so little time to spare...",
"Overall, enthusiastic, fast learning and energetic person. Love coding and creating something new. Like to draw and compose music. Proud member of the furry community."
];
export default bio;
+45
View File
@@ -0,0 +1,45 @@
import socials, { Socials } from "./socials";
import Package from "@/../package.json";
const contacts: ContactLinks =
{
email:
{
text: Package.author.email,
href: "mailto:" + Package.author.email
},
telephone:
{
text: "+7 996 929-19-69",
href: "tel:79969291969",
country: "Russia"
},
socials:
{
"LinkedIn": socials["LinkedIn"],
"Telegram":
{
username: "@xfox111",
href: "https://t.me/xfox111"
},
"Twitter": socials["Twitter"]
}
};
export default contacts;
export type ContactLinks =
{
email:
{
text: string;
href: string;
};
telephone?:
{
text: string;
href: string;
country: string;
};
socials: Socials;
};
+20
View File
@@ -0,0 +1,20 @@
const experience: WorkplaceEntry[] =
[
{ title: "IT/VR tutor", year: "2020", place: "Quantorium", tech: "Unity, STEM" },
{ title: "System administrator", year: "2021", place: "Quantorium", tech: "M365, Intune, Azure" },
{ title: "Software Engineer", place: "[nordcloud]", tech: "ASP.NET, EF Core" },
{ title: "CTO", year: "2022", place: "FoxDev Studio", tech: "Unity, Xamarin, .NET, React, Azure" },
{ title: "Software Engineer", year: "2023", place: "A-rial", tech: ".NET, React" },
{ title: "Lead Software Engineer", year: "2024 ", place: "Ubitel", tech: ".NET, React, IoT" },
{ title: "Here", place: "Your company" },
];
export default experience;
export type WorkplaceEntry =
{
year?: string;
place?: string;
title: string;
tech?: string;
};
+19
View File
@@ -0,0 +1,19 @@
import socials from "./socials";
const links: Links =
{
blog: "https://blog.xfox111.net",
linkedin: socials["LinkedIn"].href,
resume: "/resume",
github: socials["GitHub"].href
};
export default links;
type Links =
{
blog?: string;
linkedin?: string;
resume: string;
github: string;
}
+48
View File
@@ -0,0 +1,48 @@
import { Metadata } from "next";
import bio from "./bio";
import socials from "./socials";
import Package from "@/../package.json";
export const canonicalName: URL = new URL("https://xfox111.net");
const baseTitle: string = "Eugene Fox - Software developer";
const gender: string = "male";
const keywords: string[] = ["Eugene Fox", "software developer", ".net", "react", "frontend developer", "backend developer", ".net developer", "react developer", "fullstack developer", "software engineer", "Michael Gordeev", "Mikhail Gordeev"];
export const getTitle = (pageTitle: string, customBase?: string): string =>
pageTitle + " - " + (customBase ?? baseTitle);
export const metadata: Metadata =
{
title: baseTitle,
description: bio[0],
metadataBase: canonicalName,
openGraph:
{
title: baseTitle,
description: bio[0],
type: "profile",
firstName: Package.author.name.split(" ")[0],
lastName: Package.author.name.split(" ")[1],
gender,
username: socials["Twitter"].username,
siteName: canonicalName.hostname,
locale: "en_US"
},
twitter:
{
site: socials["Twitter"].username,
card: "summary_large_image"
},
alternates:
{
canonical: canonicalName.href
},
authors: [
{
name: Package.author.name,
url: socials["LinkedIn"].href
}
],
keywords
};
+181
View File
@@ -0,0 +1,181 @@
import ezlogImg from "@/_assets/illustrations/projects/EasyLogon.svg";
import foxTubeDark from "@/_assets/illustrations/projects/FoxTube/FoxTube-dark.webp";
import foxTubeLight from "@/_assets/illustrations/projects/FoxTube/FoxTube-light.webp";
import gutScheduleImg from "@/_assets/illustrations/projects/GUTSchedule.svg";
import motionDecoderDark from "@/_assets/illustrations/projects/MotionDecoder/MotionDecoder-dark.webp";
import motionDecoderLight from "@/_assets/illustrations/projects/MotionDecoder/MotionDecoder-light.webp";
import passwordGeneratorDark from "@/_assets/illustrations/projects/PasswordGenerator/PasswordGeneratorExtension-dark.webp";
import passwordGeneratorLight from "@/_assets/illustrations/projects/PasswordGenerator/PasswordGeneratorExtension-light.webp";
import simpleOtpImg from "@/_assets/illustrations/projects/SimpleOTP.svg";
import tabsAsideDark from "@/_assets/illustrations/projects/TabsAside/dark.webp";
import tabsAsideLight from "@/_assets/illustrations/projects/TabsAside/light.webp";
import * as ic from "@fluentui/react-icons";
import { StaticImageData } from "next/image";
const projects: Project[] =
[
{
title: "EasyLogon",
subtitle: "QR code authentication on any website",
description:
[
"During one of the classes at university I struggled to log into my account on a lab computer. I have long random passwords, so I had to type it in manually from my phone which took quite some time. I thought that there must be a better way to do this.",
"So I came up with this idea where you can easily send your credentials to any computer by simply scanning a QR code with a password manager app.",
"After testing it out I tried to make a startup out of it but sadly it didn't work. Still use it ocasiounally though."
],
image: ezlogImg,
link: "https://ezlog.app/about",
stack:
[
{ text: "C#/TypeScript", icon: ic.Code24Regular },
{ text: ".NET 6", icon: ic.Server24Regular },
{ text: "ReactJS", icon: ic.PhoneDesktop24Regular },
{ text: "Xamarin.Forms", icon: ic.Phone24Regular },
{ text: "SQL Server", icon: ic.Database24Regular },
{ text: "Azure DevOps", icon: ic.Branch24Regular },
{ text: "Azure Pipelines/AppCenter", icon: ic.FlashFlow24Regular },
{ text: "AppCenter", icon: ic.HeartPulse24Regular }
]
},
{
title: "Tabs aside",
subtitle: "Browser extension inspired by Edge's \"Tabs aside\" and Collections features",
description:
[
"Initially built on pure JS/CSS this extension was designed to recreate \"Tabs aside\" feature that Microsoft introduced in their EdgeHTML-based Microsoft Edge browser, but removed it in subsequent Chromium-based version.",
"Later it was rewritten in ReactJS and TypeScript and got new and unique features, yet still maintaining that original asthetics."
],
image: tabsAsideLight,
imageDark: tabsAsideDark,
link: "https://github.com/xfox111/TabsAsideExtension",
stack:
[
{ text: "ReactJS", icon: ic.Desktop24Regular },
{ text: "TypeScript/SASS", icon: ic.Code24Regular },
{ text: "Chrome/WebExt", icon: ic.FlashSettings24Regular },
{ text: "Fluent UI", icon: ic.Color24Regular },
{ text: "GitHub", icon: ic.Branch24Regular },
{ text: "GitHub Actions", icon: ic.FlashFlow24Regular },
]
},
{
title: "SimpleOTP",
subtitle: "Lightweight and simple .NET library for OTP implementation",
description:
[
"Initially created during EasyLogon development, this library was designed as a simple, yet flexible solution for one-time password authenticators and validators.",
"It provides extensive toolset for generation, validation and management of OTP configurations and can be used in any .NET application whether it is an authenticator app or a website that accepts OTP codes."
],
image: simpleOtpImg,
link: "https://github.com/xfox111/SimpleOTP",
stack:
[
{ text: ".NET/C#", icon: ic.Code24Regular },
{ text: "MSTest", icon: ic.Beaker24Regular },
{ text: "GitHub", icon: ic.Branch24Regular },
{ text: "GitHub Actions", icon: ic.FlashFlow24Regular },
]
},
{
title: "Password generator",
subtitle: "Simple browser extension for generating passwords",
description:
[
"Small pet project that I developed while my favorite password generator website was down.",
"Basically a playground, where I try out new technologies and approaches to web development."
],
image: passwordGeneratorLight,
imageDark: passwordGeneratorDark,
link: "https://github.com/xfox111/PasswordGeneratorExtension",
stack:
[
{ text: "React/Vite", icon: ic.Desktop24Regular },
{ text: "TypeScript", icon: ic.Code24Regular },
{ text: "Chrome/WebExt", icon: ic.FlashSettings24Regular },
{ text: "Fluent UI", icon: ic.Color24Regular },
{ text: "GitHub", icon: ic.Branch24Regular },
{ text: "GitHub Actions", icon: ic.FlashFlow24Regular },
]
},
{
title: "GUT.Schedule",
subtitle: "Mobile app that exports Bonch university schedule to e-calendar",
description:
[
"[2019]",
"I created this app during my time in Bonch-Bruevich University of Telecommunications as a BS student.",
"It was designed to help students to manage their timetable in a more convenient and effective way."
],
image: gutScheduleImg,
link: "https://github.com/xfox111/GUTSchedule",
stack:
[
{ text: ".NET/C#", icon: ic.Code24Regular },
{ text: "Xamarin.Android", icon: ic.Phone24Regular },
{ text: "GitHub", icon: ic.Branch24Regular },
{ text: "NUnit 3", icon: ic.Beaker24Regular },
{ text: "Azure Pipelines", icon: ic.FlashFlow24Regular },
]
},
{
title: "FoxTube",
subtitle: "UWP app that gives YouTube a fresh look on Windows",
description:
[
"[2019]",
"My first published app.",
"I like to watch videos while working on my projects, but at the time YouTube didn't have a proper picture-in-picture mode and overall had a lot of issues with the UX, so this was my way to fix this.",
"Unfortunately, Google doesn't like third-party YouTube clients."
],
image: foxTubeLight,
imageDark: foxTubeDark,
link: "https://www.youtube.com/watch?v=Mio9FbxmbhM",
stack:
[
{ text: ".NET/C#", icon: ic.Code24Regular },
{ text: "UWP", icon: ic.Desktop24Regular },
{ text: "Azure DevOps", icon: ic.Branch24Regular },
{ text: "AppCenter", icon: ic.HeartPulse24Regular },
{ text: "Azure Pipelines", icon: ic.FlashFlow24Regular },
]
},
{
title: "MotionDecoder",
subtitle: "CCTV footage analysis tool",
description:
[
"[2018]",
"My earliest attempt in software development.",
"Basically this program analyzes pre-recorded CCTV footage by comparing different frames and using some simple algorithms and provides user with a set of timecodes where a motion was detected.",
],
image: motionDecoderLight,
imageDark: motionDecoderDark,
link: "https://github.com/xfox111/MotionDecoder",
stack:
[
{ text: ".NET/C#", icon: ic.Code24Regular },
{ text: "WinForms", icon: ic.Desktop24Regular },
{ text: "Accord.NET", icon: ic.FlashSettings24Regular },
{ text: "GitHub", icon: ic.Branch24Regular },
]
}
];
export default projects;
export type Project =
{
title: string;
subtitle: string;
description: string[];
image: string | StaticImageData;
imageDark?: string | StaticImageData;
stack: TechStackItem[];
link: string;
};
type TechStackItem =
{
icon: ic.FluentIcon;
text: string;
};
+40
View File
@@ -0,0 +1,40 @@
import { ImageExport } from "@/_assets/assets";
import { dotnetResume, fullstackResume, reactResume } from "@/_assets/illustrations";
const resumeList: Resume[] =
[
{
key: "dotnet",
label: ".NET developer",
pageIndex: 1,
fileName: "Resume - Eugene Fox - .NET developer",
image: dotnetResume
},
{
key: "react",
label: "React developer",
pageIndex: 0,
fileName: "Resume - Eugene Fox - React developer",
image: reactResume
},
{
key: "fullstack",
label: "Fullstack developer",
pageIndex: 2,
fileName: "Resume - Eugene Fox - Fullstack developer",
image: fullstackResume,
default: true
},
];
export default resumeList;
export type Resume =
{
key: string;
pageIndex: number;
label: string;
image: ImageExport;
fileName: string;
default?: true;
};
+60
View File
@@ -0,0 +1,60 @@
import { ImageExport } from "@/_assets/assets";
import imgs from "@/_assets/illustrations/skills";
import * as ic from "@fluentui/react-icons";
const skills: Skill[] =
[
{
title: "NodeJS",
description: "React, Vite, Next.js, SASS, TypeScript",
icon: ic.WindowDevToolsRegular,
image: imgs.nodejs
},
{
title: ".NET",
description: "ASP.NET, Razor, WinUI/UWP, WPF, WinForms | Xamarin.Forms, MAUI",
icon: ic.PhoneDesktopRegular,
image: imgs.dotnet
},
{
title: "Architecture & systems",
description: "Docker, Nginx, Linux | Modules, microservices",
icon: ic.DesktopFlowRegular,
image: imgs.architecture
},
{
title: "Databases",
description: "Entity Framework, MongoDB",
icon: ic.DatabaseMultipleRegular,
image: imgs.databases
},
{
title: "Design",
description: "Figma, Photoshop, Illustrator",
icon: ic.DesignIdeasRegular,
// Note, this picture has a special behavior in @/_page_sections/SkillsSection.tsx:24
image: imgs.design
},
{
title: "DevOps",
description: "GitHub, Azure DevOps, AppCenter, Atlassian",
icon: ic.FlashFlowRegular,
image: imgs.devops
},
{
title: "Administration",
description: "Ansible, M365, Azure, InTune",
icon: ic.ConnectedRegular,
image: imgs.admin
}
];
export default skills;
export type Skill =
{
title: string;
description: string;
icon: ic.FluentIcon;
image: ImageExport;
};
+30
View File
@@ -0,0 +1,30 @@
import Package from "@/../package.json";
const socials: Socials =
{
"GitHub":
{
href: Package.author.url,
username: "@xfox111"
},
"LinkedIn":
{
href: "https://www.linkedin.com/in/xfox/",
username: "@xfox"
},
"Twitter":
{
href: "https://twitter.com/xfox111",
username: "@xfox111"
},
};
export default socials;
export type Socials = Record<string, SocialLink>;
export type SocialLink =
{
href: string;
username: string;
};