Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,39 @@ on:
pull_request:
types: [opened, reopened, synchronize, closed]

concurrency: preview-${{ github.ref }}
concurrency:
group: preview-${{ github.ref }}
cancel-in-progress: true

jobs:
deploy-preview:
runs-on: ubuntu-latest

permissions:
contents: write
pull-requests: write

steps:
- name: Checkout Code
uses: actions/checkout@v4

# Set up Ruby and cache gems for faster builds
- name: Set up Ruby
if: github.event.action != 'closed'
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2' # Match your local Ruby version
ruby-version: '3.2'
bundler-cache: true

# Compile Jekyll with a custom baseurl pointing to the preview folder
- name: Build Jekyll Site
if: github.event.action != 'closed'
run: |
bundle install
bundle exec jekyll build --baseurl "/${{ github.event.repository.name }}/pr-preview/pr-${{ github.event.number }}"
bundle exec jekyll build \
--baseurl "/${{ github.event.repository.name }}/pr-preview/pr-${{ github.event.number }}"

# Deploy the compiled static folder to GitHub Pages
- name: Deploy PR Preview to GitHub Pages
uses: rossjrw/pr-preview-action@v1
with:
source-dir: ./_site # Default output folder for Jekyll
preview-branch: gh-pages # The branch your live GitHub Pages site serves from
umbrella-dir: pr-preview # Parent folder for previews on the gh-pages branch
source-dir: ./_site
preview-branch: main
umbrella-dir: pr-preview
action: auto
4 changes: 2 additions & 2 deletions Abdullah_Khaled_CV_Extended.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ cv:
- Implemented driver-input buffering for teleop handoff to automated placement; built match logging/debug tooling and simulation workflows to validate behavior during an 8-week build season with limited robot access; taught mechanism simulation to supporting students
- Mentored rookie FTC teams 26357 and 28931 (2024–2025); supported ~30 students (6 programmers) from prototyping through competition, including ~25 hrs/week at peak ITKAN FTC build season
- "Applied FRC sensor-fusion experience to a custom FTC pose estimator (wheel odometry, IMU, vision) with Kalman filtering for localization and automated turret targeting; improved targeting/scoring accuracy by ~35%; [FTC codebase](https://github.com/itkan-of-icf/ftc-26357-2526-v2)"
- Delivered three 1-hour ICF FLL workshops (7 students/session) for refugee students using the self-developed OARobotics curriculum ([OARobotics](https://www.aakhaled.com/personal/oarobotics/)); students built FLL-class robots and completed block-code autonomous maze navigation by session end
- Delivered three 1-hour ICF FLL workshops (7 students/session) for refugee students using the self-developed OARobotics curriculum ([OARobotics](https://www.aakhaled.com/oarobotics/)); students built FLL-class robots and completed block-code autonomous maze navigation by session end
- company: ITKAN Robotics - FIRST Robotics Competition (FRC 9128)
position: Chief Technical Advisor
date:
Expand Down Expand Up @@ -164,7 +164,7 @@ cv:
- Lead pre-session briefings for peer instructors; assign age-banded groups and smaller ratios for newer volunteers; supervise instructional delivery while maintaining a direct tutoring load; train peers on Gideon-based methods informed by parallel Gideon student, TA, and instructor roles
- Recruit high-school volunteers from five schools via robotics networks and onboard them into the program; provide periodic updates to the volunteer coordinator
- Run multilingual sessions with peer interpretation when available, mid-session breaks, and age-separated groupings to stabilize pacing and engagement
- Deliver monthly robotics enrichment for Project Taleem using the OARobotics curriculum (www.aakhaled.com/personal/oarobotics)
- Deliver monthly robotics enrichment for Project Taleem using the OARobotics curriculum (www.aakhaled.com/oarobotics)
- Measured average ~15-point IXL SmartScore increase over four months (Nov–Feb; n=10 students)
- company: Mu Alpha Theta Math Honor Society, Wakeland High School
position: Vice President
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ GEM
faraday-net_http (3.4.1)
net-http (>= 0.5.0)
ffi (1.17.2-x64-mingw-ucrt)
ffi (1.17.2-x86_64-linux-gnu)
forwardable-extended (2.6.0)
gemoji (4.1.0)
github-pages (232)
Expand Down Expand Up @@ -244,6 +245,8 @@ GEM
uri
nokogiri (1.18.10-x64-mingw-ucrt)
racc (~> 1.4)
nokogiri (1.18.10-x86_64-linux-gnu)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
Expand Down Expand Up @@ -283,6 +286,7 @@ GEM

PLATFORMS
x64-mingw-ucrt
x86_64-linux

DEPENDENCIES
github-pages
Expand Down
4 changes: 2 additions & 2 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ title : "Abdullah Khaled"
title_separator : "|"
subtitle : "Engineering Portfolio"
name : "Abdullah Khaled"
description : "Engineering portfolio of Abdullah Khaled (akhaled247)robotics, FRC/FTC competition work, and software projects. Contact me@aakhaled.com."
description : "Engineering portfolio of Abdullah Khaled (akhaled247): robotics, FRC/FTC competition work, and software projects. Contact me@aakhaled.com."
url : "https://www.aakhaled.com"
baseurl : "" # empty string for root domain deployment
repository : akhaled247/akhaled247.github.io
Expand Down Expand Up @@ -125,7 +125,7 @@ analytics:
author:
name : "Abdullah Khaled"
avatar : # path of avatar image, e.g. "/assets/images/bio-photo.jpg"
bio : "Abdullah Khaled (akhaled247)engineering portfolio at www.aakhaled.com. Robotics, vision, and on-device ML. Contact me@aakhaled.com or connect on GitHub and LinkedIn."
bio : "Abdullah Khaled (akhaled247): engineering portfolio at www.aakhaled.com. Robotics, vision, and on-device ML. Contact me@aakhaled.com or connect on GitHub and LinkedIn."
location : "Frisco, Texas"
email : me@aakhaled.com
links:
Expand Down
8 changes: 0 additions & 8 deletions _data/navigation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,5 @@ main:
url: /
- title: "Projects"
url: /projects/
- title: "FIRST®"
url: /first/
- title: "Personal"
url: /personal/
- title: "PLTW"
url: /pltw-engineering/
- title: "Resume"
url: /resume/
- title: "About"
url: /about/
219 changes: 219 additions & 0 deletions _includes/carousel.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
{% assign letterstring = "a,b,c,d,e,f,g,h,i,j,k,l,m,n" %}
{% assign letters = letterstring | split: ',' %}
{% assign number = include.number | minus: 1 %}
<div class="carousel__holder" style="width: {{ include.width }}{{ include.unit }}; padding-bottom: {{ include.height }}{{ include.unit }}; {% if include.float %}float: {{ include.float }}; margin-{% if include.float == 'left' %}right{% else %}left{% endif %}: 1.5rem;{% endif %}">
<div id="carousel{{ number }}" class="carousel">
{% for item in page.carousels[number].images %}
<input class="carousel__activator" type="radio" name="carousel{{ number }}" id="{{ number }}{{ letters[forloop.index0] }}" {% if forloop.first %}checked="checked"{% endif %} />
{% endfor %}
{% for item in page.carousels[number].images %}
{% if forloop.index == forloop.length %}
{% assign nextindex = 0 %}
{% else %}
{% assign nextindex = forloop.index0 | plus: 1 %}
{% endif %}
{% assign nextletter = letters[nextindex] %}
{% if forloop.index0 == 0 %}
{% assign previndex = forloop.length | minus: 1 %}
{% else %}
{% assign previndex = forloop.index0 | minus: 1 %}
{% endif %}
{% assign prevletter = letters[previndex] %}
<div class="carousel__controls">
<label class="carousel__control carousel__control--backward" for="{{ number }}{{ prevletter }}"></label>
<label class="carousel__control carousel__control--forward" for="{{ number }}{{ nextletter }}"></label>
</div>
{% endfor %}
<div class="carousel__track">
<ul>
{% for item in page.carousels[number].images %}
<li class="carousel__slide" style="background-image: url('{{ item.image }}');"></li>
{% endfor %}
</ul>
</div>
<div class="carousel__indicators">
{% for item in page.carousels[number].images %}
<label class="carousel__indicator" for="{{ number }}{{ letters[forloop.index0] }}"></label>
{% endfor %}
</div>
</div>
</div>

<style>
.carousel__holder { position: relative; margin: 1rem 0 1rem; }
.carousel {
height: 100%;
width: 100%;
overflow: hidden;
text-align: center;
position: absolute;
padding: 0;
}
.carousel__controls,
.carousel__activator {
display: none;
}
{% for item in page.carousels[number].images %}
.carousel__activator:nth-of-type({{ forloop.index }}):checked ~ .carousel__track {
-webkit-transform: translateX(-{{ forloop.index0 }}00%);
transform: translateX(-{{ forloop.index0 }}00%);
}
.carousel__activator:nth-of-type({{ forloop.index }}):checked ~ .carousel__slide:nth-of-type({{ forloop.index }}) {
transition: opacity 0.5s, -webkit-transform 0.5s;
transition: opacity 0.5s, transform 0.5s;
transition: opacity 0.5s, transform 0.5s, -webkit-transform 0.5s;
top: 0;
left: 0;
right: 0;
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
.carousel__activator:nth-of-type({{ forloop.index }}):checked ~ .carousel__controls:nth-of-type({{ forloop.index }}) {
display: block;
opacity: 1;
}
.carousel__activator:nth-of-type({{ forloop.index }}):checked ~ .carousel__indicators .carousel__indicator:nth-of-type({{ forloop.index }}) {
opacity: 1;
}
{% endfor %}

.carousel__control {
height: 30px;
width: 30px;
margin-top: -15px;
top: 50%;
position: absolute;
display: block;
cursor: pointer;
border-width: 5px 5px 0 0;
border-style: solid;
border-color: #fafafa;
opacity: 0.35;
opacity: 1;
outline: 0;
z-index: 3;
}
.carousel__control:hover {
opacity: 1;
}
.carousel__control--backward {
left: 20px;
-webkit-transform: rotate(-135deg);
transform: rotate(-135deg);
}
.carousel__control--forward {
right: 20px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.carousel__indicators {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
}
.carousel__indicator {
height: 15px;
width: 15px;
border-radius: 100%;
display: inline-block;
z-index: 2;
cursor: pointer;
opacity: 0.35;
margin: 0 2.5px 0 2.5px;
}
.carousel__indicator:hover {
opacity: 0.75;
}
.carousel__track {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 0;
margin: 0;
transition: -webkit-transform 0.5s ease 0s;
transition: transform 0.5s ease 0s;
transition: transform 0.5s ease 0s, -webkit-transform 0.5s ease 0s;
}
.carousel__track .carousel__slide {
display: block;
top: 0;
left: 0;
right: 0;
opacity: 1;
}
{% for item in page.carousels[number].images %}
.carousel__track .carousel__slide:nth-of-type({{ forloop.index }}) {
-webkit-transform: translateX({{ forloop.index0 }}00%);
transform: translateX({{ forloop.index0 }}00%);
}
{% endfor %}

.carousel--scale .carousel__slide {
-webkit-transform: scale(0);
transform: scale(0);
}
.carousel__slide {
height: 100%;
position: absolute;
opacity: 0;
overflow: hidden;
}
.carousel__slide .overlay {height: 100%;}
.carousel--thumb .carousel__indicator {
height: 30px;
width: 30px;
}
.carousel__indicator {
background-color: #fafafa;
}
{% for item in page.carousels[number].images %}
.carousel__slide:nth-of-type({{ forloop.index }}),
.carousel--thumb .carousel__indicators .carousel__indicator:nth-of-type({{ forloop.index }}) {
background-size: cover;
background-position: center;
}
{% endfor %}
</style>

<script>
function isVisible(el) {
while (el) {
if (el === document) {
return true;
}

var $style = window.getComputedStyle(el, null);

if (!el) {
return false;
} else if (!$style) {
return false;
} else if ($style.display === 'none') {
return false;
} else if ($style.visibility === 'hidden') {
return false;
} else if (+$style.opacity === 0) {
return false;
} else if (($style.display === 'block' || $style.display === 'inline-block') &&
$style.height === '0px' && $style.overflow === 'hidden') {
return false;
} else {
return $style.position === 'fixed' || isVisible(el.parentNode);
}
}
}
{% if include.duration %}
setInterval(function(){
var j=0;
var elements = document.querySelectorAll('#carousel{{ number}} .carousel__control--forward');
for(i=(elements.length - 1);i>-1;i--) {
if(isVisible(elements[i])) j=i;
}
elements[j].click();
},{{ include.duration }}000);
{% endif %}
</script>
16 changes: 16 additions & 0 deletions _includes/masthead.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
{% capture logo_path %}{{ site.logo }}{% endcapture %}

<!-- <script>
/* When the user scrolls down, hide the navbar. When the user scrolls up, show the navbar */
var lastScrollTop = 0;
var masthead = document.querySelector(".masthead");
if (masthead) {
window.addEventListener("scroll", function () {
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if (scrollTop > lastScrollTop && scrollTop > 25) {
masthead.classList.add("is-hidden");
} else {
masthead.classList.remove("is-hidden");
}
lastScrollTop = scrollTop <= 0 ? 0 : scrollTop;
}, { passive: true });
}
</script> -->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
Expand Down
Loading
Loading