diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 2420e15..b169764 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -4,72 +4,16 @@ on:
push:
branches: [ "main" ]
-env:
- REGISTRY: ghcr.io
- IMAGE_NAME: ${{ github.repository }}
-
jobs:
- build-and-push:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: Log in to the Container registry
- uses: docker/login-action@v3
- with:
- registry: ${{ env.REGISTRY }}
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Extract metadata (tags, labels) for Docker
- id: meta
- uses: docker/metadata-action@v5
- with:
- images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- tags: |
- type=raw,value=latest
- type=sha
-
- - name: Build and push Docker image
- uses: docker/build-push-action@v5
- with:
- context: .
- push: true
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
-
deploy:
runs-on: ubuntu-latest
- needs: build-and-push
steps:
- - name: Deploy to Remote Server
+ - name: Deploy Application
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.REMOTE_HOST }}
username: ${{ secrets.REMOTE_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
+ passphrase: ${{ secrets.SSH_PASSPHRASE }}
script: |
- # Login to registry
- echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
-
- # Pull new image
- docker pull ghcr.io/${{ env.IMAGE_NAME }}:latest
-
- # Stop and remove existing container
- docker stop resume-frontend || true
- docker rm resume-frontend || true
-
- # Run new container
- docker run -d \
- --name resume-frontend \
- --restart unless-stopped \
- -p 80:80 \
- ghcr.io/${{ env.IMAGE_NAME }}:latest
-
- # Cleanup unused images
- docker image prune -f
+ powershell -ExecutionPolicy Bypass -Command "Write-Host '=== Starting deployment ==='; if (Test-Path 'C:\projects\digital-resume-FE') { Set-Location 'C:\projects\digital-resume-FE'; git pull origin main } else { New-Item -ItemType Directory -Path 'C:\projects' -Force; Set-Location 'C:\projects'; git clone https://gitea.sashabayda.ca/Bayda77/digital-resume-FE.git }; Write-Host '=== Stopping container ==='; docker stop resume-frontend; docker rm resume-frontend; Write-Host '=== Building image ==='; Set-Location 'C:\projects\digital-resume-FE'; docker build -t resume-frontend:latest .; Write-Host '=== Running container ==='; docker run -d --name resume-frontend --network nginx_web --restart unless-stopped -p 3001:80 resume-frontend:latest; Write-Host '=== Verifying ==='; docker ps -a --filter name=resume-frontend"
diff --git a/public/beszel.png b/public/beszel.png
new file mode 100644
index 0000000..02a43d7
Binary files /dev/null and b/public/beszel.png differ
diff --git a/public/fampic.jpg b/public/fampic.jpg
new file mode 100644
index 0000000..198e57c
Binary files /dev/null and b/public/fampic.jpg differ
diff --git a/public/gangpic.jpg b/public/gangpic.jpg
new file mode 100644
index 0000000..b785361
Binary files /dev/null and b/public/gangpic.jpg differ
diff --git a/public/janepic.jpg b/public/janepic.jpg
new file mode 100644
index 0000000..a6e4d9c
Binary files /dev/null and b/public/janepic.jpg differ
diff --git a/src/App.css b/src/App.css
index 9ab18dd..fa0b6da 100644
--- a/src/App.css
+++ b/src/App.css
@@ -55,7 +55,99 @@ p {
}
/* Home page specific styles */
+.home-container {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ min-height: 80vh;
+ /* Takes up most of the viewport */
+ text-align: center;
+ gap: 30px;
+ padding: 20px;
+}
+
+.hero-profile-container {
+ padding: 10px;
+ background: rgba(255, 255, 255, 0.05);
+ /* Subtle backing */
+ border-radius: 50%;
+ backdrop-filter: blur(10px);
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.hero-profile-img {
+ width: 200px;
+ height: 200px;
+ object-fit: cover;
+ border-radius: 50%;
+ /* Circle */
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
+ display: block;
+}
+
+.hero-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 15px;
+ color: white;
+ max-width: 700px;
+}
+
+.hero-name {
+ font-size: clamp(40px, 6vw, 80px);
+ font-family: 'Roboto', sans-serif;
+ font-weight: 700;
+ color: white;
+ margin: 0;
+ letter-spacing: -0.5px;
+ text-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
+}
+
+.hero-bio {
+ font-size: clamp(16px, 1.5vw, 20px);
+ /* font-family: 'Roboto', sans-serif; - inherent*/
+ font-weight: 300;
+ line-height: 1.6;
+ color: rgba(255, 255, 255, 0.9);
+ max-width: 600px;
+}
+
+.hero-socials {
+ display: flex;
+ gap: 20px;
+ margin-top: 20px;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.hero-social-link {
+ text-decoration: none;
+ color: rgba(255, 255, 255, 0.85);
+ font-size: 16px;
+ font-weight: 500;
+ padding: 10px 24px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ border-radius: 50px;
+ /* Pill shape */
+ background: rgba(255, 255, 255, 0.05);
+ transition: all 0.3s ease;
+ backdrop-filter: blur(5px);
+}
+
+.hero-social-link:hover {
+ background: rgba(255, 255, 255, 0.2);
+ color: white;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ border-color: rgba(255, 255, 255, 0.5);
+}
+
+/* Legacy Home styles (keep if referenced elsewhere, otherwise minimal) */
.hero-card {
+ /* Kept for backward compat if needed, but redesigned home won't use it */
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 10px;
background: rgba(255, 255, 255, 0.1);
@@ -318,6 +410,10 @@ p {
width: 100%;
padding: 20px;
}
+
+ .home-container {
+ padding-top: 50px;
+ }
}
@media (max-width: 768px) {
@@ -329,6 +425,11 @@ p {
.about-title {
margin-bottom: 20px;
}
+
+ .home-container {
+ min-height: 70vh;
+ gap: 20px;
+ }
}
/* Projects Page Styles */
@@ -357,26 +458,31 @@ p {
}
.project-card {
- background: rgba(255, 255, 255, 0.07);
- backdrop-filter: blur(12px);
- border: 1px solid rgba(255, 255, 255, 0.15);
- border-radius: 16px;
+ background: rgba(255, 255, 255, 0.08);
+ /* Slightly lighter base */
+ backdrop-filter: blur(16px);
+ /* Increased blur */
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ /* Softer border */
+ border-radius: 24px;
+ /* More rounded */
padding: 25px;
display: flex;
flex-direction: column;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
- /* Bouncy feel */
height: 100%;
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+ /* Softer shadow */
position: relative;
overflow: hidden;
}
.project-card:hover {
- background: rgba(255, 255, 255, 0.12);
+ background: rgba(255, 255, 255, 0.15);
transform: translateY(-8px) scale(1.02);
- box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
- border-color: rgba(255, 255, 255, 0.3);
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
+ /* Deeper but soft shadow */
+ border-color: rgba(255, 255, 255, 0.4);
}
.project-card::before {
diff --git a/src/App.tsx b/src/App.tsx
index a756f1c..03f99b4 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -7,6 +7,7 @@ import Home from './pages/Home';
import About from './pages/About';
import WorkExperience from './pages/WorkExperience';
import Projects from './pages/Projects';
+import Skills from './pages/Skills';
import Contact from './pages/Contact';
function ScrollToTop() {
@@ -39,6 +40,7 @@ function App() {
} />
} />
} />
+ } />
} />
diff --git a/src/components/BioSection.tsx b/src/components/BioSection.tsx
new file mode 100644
index 0000000..64c66b3
--- /dev/null
+++ b/src/components/BioSection.tsx
@@ -0,0 +1,100 @@
+import { motion, AnimatePresence } from "framer-motion";
+import { useState, useEffect } from "react";
+
+interface BioSectionProps {
+ imageSrc: string;
+ imageAlt: string;
+ text: string;
+ reversed?: boolean;
+}
+
+export default function BioSection({ imageSrc, imageAlt, text, reversed = false }: BioSectionProps) {
+ const images = imageSrc.split(',').map(src => src.trim()).filter(src => src.length > 0);
+ const [currentIndex, setCurrentIndex] = useState(0);
+ const [prevIndex, setPrevIndex] = useState(0);
+ const [direction, setDirection] = useState(1); // 1 for right, -1 for left (though we always slide right here)
+
+ useEffect(() => {
+ if (images.length <= 1) return;
+
+ const interval = setInterval(() => {
+ setPrevIndex(currentIndex);
+ setCurrentIndex((prev) => (prev + 1) % images.length);
+ }, 6000);
+
+ return () => clearInterval(interval);
+ }, [images.length, currentIndex]);
+
+ const slideVariants = {
+ enter: {
+ x: "-100%",
+ opacity: 1
+ },
+ center: {
+ x: 0,
+ opacity: 1
+ },
+ exit: {
+ x: "100%",
+ opacity: 1
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+ {text}
+
+
+
+ );
+}
diff --git a/src/components/ParticlesBackground.tsx b/src/components/ParticlesBackground.tsx
index 2e423d3..b5e2da6 100644
--- a/src/components/ParticlesBackground.tsx
+++ b/src/components/ParticlesBackground.tsx
@@ -35,31 +35,6 @@ const ParticlesBackground: React.FC = () => {
this.x += this.speedX;
this.y += this.speedY;
- // update speedX
- let speedXRng = Math.random();
- if (speedXRng > 0.75) {
- this.speedX += Math.random() * 0.1;
- } else if (speedXRng < 0.25) {
- this.speedX -= Math.random() * 0.1;
- }
- if (this.speedX > 1) {
- this.speedX = 1;
- } else if (this.speedX < -1) {
- this.speedX = -1;
- }
-
- // update speedY
- let speedYRng = Math.random();
- if (speedYRng > 0.75) {
- this.speedY += Math.random() * 0.1;
- } else if (speedYRng < 0.25) {
- this.speedY -= Math.random() * 0.1;
- }
- if (this.speedY > 1) {
- this.speedY = 1;
- } else if (this.speedY < -1) {
- this.speedY = -1;
- }
//size
let sizeRng = Math.random();
diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx
new file mode 100644
index 0000000..ca8f926
--- /dev/null
+++ b/src/components/ProjectCard.tsx
@@ -0,0 +1,62 @@
+import { motion, Variants } from "framer-motion";
+
+export interface Project {
+ id: number;
+ title: string;
+ description: string;
+ techStack: string[];
+ image: string;
+ links: {
+ demo?: string;
+ repo?: string;
+ };
+}
+
+interface ProjectCardProps {
+ project: Project;
+ variants: Variants;
+}
+
+export default function ProjectCard({ project, variants }: ProjectCardProps) {
+ return (
+
+
+
+
+
+
{project.title}
+
+
+
+ {project.techStack.map(tech => (
+ {tech}
+ ))}
+
+
+
+ {project.description}
+
+
+
+
+ );
+}
diff --git a/src/components/floatingHeader.tsx b/src/components/floatingHeader.tsx
index 60f5eed..131654a 100644
--- a/src/components/floatingHeader.tsx
+++ b/src/components/floatingHeader.tsx
@@ -6,32 +6,38 @@ export default function FloatingHeader() {
return (
-
Home
-
Work Experience
-
+ Skills
+
+
About Me
-
- Projects
+ Projects and Sidequests
-
Contact
diff --git a/src/pages/About.tsx b/src/pages/About.tsx
index 17726d1..dd2ddf5 100644
--- a/src/pages/About.tsx
+++ b/src/pages/About.tsx
@@ -1,8 +1,14 @@
import { motion } from "framer-motion";
import VisitedMap from "../components/VisitedMap";
+import BioSection from "../components/BioSection";
const ABOUT_TEXT = "Hi! I'm Sasha Bayda, a passionate developer focused on creating beautiful and functional web experiences. With a background in computer science and a keen eye for design, I strive to bridge the gap between technology and user-centric solutions. When I'm not coding, you can find me exploring the outdoors, experimenting with new recipes, or indulging in photography. Feel free to explore my projects and get in touch if you'd like to collaborate or learn more about my work!" + "\n\n" + "Thank you for visiting my digital resume site. I look forward to connecting with you!";
+const JANE_TEXT = "Outside of work, I enjoy spending time with my girlfriend, family and friends. Doing things such as cooking, watching shows or movies, gaming, snowboarding, or just relaxing with a glass of something warm.";
+
+const HOMELAB_TEXT = "I love hosting my own applications and learning new technologies. Right now I host my own gitea server to host my own git repositories and host my own 'runners', immich to host my own photo gallery, and a beszel to monitor all of my applications with a dashboards, graphs and webhook alerts."
+
+
const VISITED_CITIES = [
"Melfort",
"Star City",
@@ -41,31 +47,12 @@ export default function About() {
About Me
-
-
-
-
+
-
-
- {ABOUT_TEXT}
-
-
-
- My Hot Chocolate Journey
+ Places I've Visited
- Places across the world where I've enjoyed a hot chocolate ☕
+ Some of the More Interesting Places I've visited, I hope to one day fill this map with more cool spots!
+
+
+
+
+
+
diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx
index 8f22df2..f0a207f 100644
--- a/src/pages/Home.tsx
+++ b/src/pages/Home.tsx
@@ -1,26 +1,11 @@
+import { motion } from "framer-motion";
import TypingText from "../components/animatedTyping";
-import FullPageImage from "../components/fullPageImage";
-import { delay, motion } from "framer-motion";
-// Animation and typing timing configuration
-const ANIMATION_TIMINGS = {
- // Animation delays (in seconds)
- elementIn: 2.0, // When elements fade in
+const welcomeText = `Hello! My name is Sasha Bayda and welcome to my digital resume site!
- // Typing speeds (in milliseconds per character)
- welcomeTextSpeed: 45,
- nameSpeed: 120,
+Here you will find some of my projects, skills, contact information and any information I couldn't fit into my resume.
- // Typing delays (in milliseconds) - time before text starts typing
- welcomeTextDelay: 2000,
- nameDelay: 2000,
-
- // Test items animation (slides in from bottom)
- testItemsStartDelay: 3.5, // When to start the first test item animation (in seconds)
- testItemStaggerDelay: 0.2, // Delay between each test item (in seconds)
- testItemAnimationDuration: 0.5, // Duration of each item's slide-in animation
-};
-const welcomeText = "Hello! My name is Sasha Bayda and welcome to my digital resume site! Here you will find some of my projects, skills, contact information and any information I couldn't fit into my resume. Feel free to explore and learn more about me and if something isn't answered, don't hesitate to reach out via the contact page!";
+Feel free to explore and learn more about me and if something isn't answered, don't hesitate to reach out via the contact page!`;
const CONTACT_LINKS = [
{ label: "Email", url: "mailto:sasha.bayda@outlook.com" },
@@ -33,48 +18,55 @@ const CONTACT_LINKS = [
export default function Home() {
return (
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
+
+
+
+
-
+
+ {welcomeText}
+
+
+
{CONTACT_LINKS.map((link, index) => (
{link.label}
+ >
+ {link.label}
+
))}
diff --git a/src/pages/Projects.tsx b/src/pages/Projects.tsx
index 2dfbd47..cf1feac 100644
--- a/src/pages/Projects.tsx
+++ b/src/pages/Projects.tsx
@@ -1,19 +1,8 @@
import { motion, Variants } from "framer-motion";
import FullPageImage from "../components/fullPageImage";
+import ProjectCard, { Project } from "../components/ProjectCard";
-interface Project {
- id: number;
- title: string;
- description: string;
- techStack: string[];
- image: string; // Ensure these images exist in public/ or use placeholders
- links: {
- demo?: string;
- repo?: string;
- };
-}
-
-const PROJECTS: Project[] = [
+const FEATURED_PROJECTS: Project[] = [
{
id: 1,
title: "Digital Resume",
@@ -27,6 +16,29 @@ const PROJECTS: Project[] = [
},
];
+const SIDEQUESTS: Project[] = [
+ {
+ id: 101, // Different ID range for sidequests
+ title: "Experimental Shader",
+ description: "A WebGL shader experiment creating procedural textures and animations. Exploring noise functions and light interactions.",
+ techStack: ["WebGL", "GLSL", "React Three Fiber"],
+ image: "https://placehold.co/600x400/1a1a1a/cccccc?text=Shader+Experiment", // Placeholder image
+ links: {
+ repo: "https://github.com/Bayda77/sidequests", // Placeholder link
+ }
+ },
+ {
+ id: 102,
+ title: "CLI Tool",
+ description: "A command-line utility for automating daily workflows and file management tasks.",
+ techStack: ["Rust", "Clap"],
+ image: "https://placehold.co/600x400/2a2a2a/dddddd?text=CLI+Tool", // Placeholder
+ links: {
+ repo: "https://github.com/Bayda77/cli-tools"
+ }
+ }
+];
+
const containerVariants: Variants = {
hidden: { opacity: 0 },
visible: {
@@ -55,63 +67,50 @@ export default function Projects() {
-
- Featured Projects
-
-
+ {/* Featured Projects Section */}
- {PROJECTS.map((project) => (
-
-
-
-
-
-
{project.title}
-
+
+ Featured Projects
+
-
- {project.techStack.map(tech => (
- {tech}
- ))}
-
+
+ {FEATURED_PROJECTS.map((project) => (
+
+ ))}
+
+
-
- {project.description}
-
-
-
- ))}
+ {/* Sidequests Section */}
+
+
+ Sidequests
+
+
+
+ {SIDEQUESTS.map((project) => (
+
+ ))}
+
diff --git a/src/pages/Skills.tsx b/src/pages/Skills.tsx
new file mode 100644
index 0000000..db6d8aa
--- /dev/null
+++ b/src/pages/Skills.tsx
@@ -0,0 +1,170 @@
+import { motion, Variants } from "framer-motion";
+
+interface SkillCategory {
+ category: string;
+ skills: string[];
+}
+
+interface ProfessionalSkill {
+ skill: string;
+ description: string;
+}
+
+const TECHNICAL_SKILLS: SkillCategory[] = [
+ {
+ category: "Languages",
+ skills: ["JavaScript (ES6+)", "TypeScript", "Python", "Java", "C", "C++", "Lua", "HTML", "CSS", "SQL"]
+ },
+ {
+ category: "Frameworks/Libraries",
+ skills: ["React", "Express.js", "Django REST Framework", "AWS Lambda"]
+ },
+ {
+ category: "Databases",
+ skills: ["PostgreSQL (SQL Based)", "CouchDB (No-SQL Based)"]
+ },
+ {
+ category: "DevOps & Tools",
+ skills: ["Docker", "CircleCI", "Git (CLI)", "Postman", "AWS CDK", "Linux CLI"]
+ },
+ {
+ category: "AWS Technologies",
+ skills: ["S3", "Cloudfront", "Route 53", "API Gateway", "Lambda", "RDS", "VPC", "ECS", "SQS"]
+ },
+ {
+ category: "Concepts",
+ skills: ["RESTful APIs", "Agile/Scrum", "MVC Architecture", "Cloud Deployment", "Responsive Design"]
+ }
+];
+
+const PROFESSIONAL_SKILLS: ProfessionalSkill[] = [
+ {
+ skill: "Customer Service & Sales",
+ description: "Clear communication and coordination with customers and clients"
+ },
+ {
+ skill: "Technical Support",
+ description: "Diagnosing and resolving hardware/software issues across all major devices."
+ },
+ {
+ skill: "Web Development",
+ description: "WordPress plugin development, front-end design, and site optimization."
+ },
+ {
+ skill: "Scripting & Programming",
+ description: "JavaScript, Python, HTML/CSS, Git, and NPM package management."
+ },
+ {
+ skill: "Collaboration & Problem-Solving",
+ description: "Working effectively with diverse teams to meet deadlines and ensure quality results."
+ },
+ {
+ skill: "Adaptability",
+ description: "Quickly learning new tools, technologies, and processes in dynamic work environments."
+ }
+];
+
+const containerVariants: Variants = {
+ hidden: { opacity: 0 },
+ visible: {
+ opacity: 1,
+ transition: {
+ staggerChildren: 0.1,
+ delayChildren: 0.2
+ }
+ }
+};
+
+const itemVariants: Variants = {
+ hidden: { y: 20, opacity: 0 },
+ visible: {
+ y: 0,
+ opacity: 1,
+ transition: { type: "spring", stiffness: 100 }
+ }
+};
+
+export default function Skills() {
+ return (
+
+
+
+
+
+ Technical Skills
+
+
+ {TECHNICAL_SKILLS.map((category) => (
+
+ {category.category}
+
+ {category.skills.map((skill) => (
+
+ {skill}
+
+ ))}
+
+
+ ))}
+
+
+
+
+
+ Professional Skills
+
+
+ {PROFESSIONAL_SKILLS.map((skill) => (
+
+ {skill.skill}
+
+ {skill.description}
+
+
+ ))}
+
+
+
+
+ );
+}