├── ft_utils └── ft-discord-links │ ├── icons │ ├── icon-128.png │ └── icon-48.png │ ├── manifest.json │ ├── README.md │ └── content.js ├── LICENSE ├── .github └── workflows │ └── sync-to-gitlab.yml └── README.md /ft_utils/ft-discord-links/icons/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zelhajou/ft_cursus/HEAD/ft_utils/ft-discord-links/icons/icon-128.png -------------------------------------------------------------------------------- /ft_utils/ft-discord-links/icons/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zelhajou/ft_cursus/HEAD/ft_utils/ft-discord-links/icons/icon-48.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025 zelhajou 2 | 3 | All rights reserved. 4 | 5 | This README and portfolio documentation is made available for viewing and reference purposes only. 6 | No permission is granted to copy, reproduce, modify, or use any part of this content for personal 7 | portfolios, resumes, or other similar purposes. 8 | 9 | You may view and learn from this content, but you may not present it as your own work or use it 10 | as a template for your own portfolio. -------------------------------------------------------------------------------- /ft_utils/ft-discord-links/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "42 Discord Profile Links", 4 | "version": "1.0", 5 | "description": "Adds intra profile links to Discord usernames", 6 | "permissions": [], 7 | "content_scripts": [ 8 | { 9 | "matches": ["https://discord.com/*"], 10 | "js": ["content.js"] 11 | } 12 | ], 13 | "icons": { 14 | "48": "icons/icon-48.png", 15 | "128": "icons/icon-128.png" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ft_utils/ft-discord-links/README.md: -------------------------------------------------------------------------------- 1 | # 42 Discord Profile Links 2 | 3 | Adds quick access links to 42 intra profiles directly from Discord usernames. 4 | 5 | ## Installation 6 | 7 | 1. Download this folder as a zip from there [link](https://mega.nz/file/2MxXiaTI#uXjJkI2QyShHlOxndxFtTPflZ2eaJH04q1ydOa59X2I) and extract it 8 | 2. Open Chrome/Brave and go to `chrome://extensions/` 9 | 3. Enable "Developer mode" in the top right 10 | 4. Click "Load unpacked" 11 | 5. Select the folder containing the extension files 12 | 6. The extension is now installed! 13 | 14 | ## Features 15 | 16 |  17 | 18 | - Adds intra profile links next to usernames in Discord 19 | - Works in 1337 Discord server 20 | - Easy access to profiles with one click 21 | 22 | ## Usage 23 | 24 | Once installed, you'll see 🔗 links next to usernames in Discord. Click them to open the corresponding intra profile. 25 | -------------------------------------------------------------------------------- /ft_utils/ft-discord-links/content.js: -------------------------------------------------------------------------------- 1 | function addIntraLinks() { 2 | // For usernames in brackets 3 | document.querySelectorAll('.defaultColor_a595eb').forEach(element => { 4 | if (element.dataset.modified) return; 5 | element.dataset.modified = 'true'; 6 | 7 | const name = element.textContent; 8 | const logins = name.match(/\[(.*?)\]/g); 9 | 10 | if (logins && logins.length > 0) { 11 | // Get the last bracketed text 12 | const lastLogin = logins[logins.length - 1].match(/\[(.*?)\]/)[1]; 13 | addLink(element, lastLogin); 14 | } 15 | }); 16 | 17 | // For guild nicknames in mutual servers 18 | document.querySelectorAll('.guildNick_c5a773').forEach(element => { 19 | if (element.dataset.modified) return; 20 | element.dataset.modified = 'true'; 21 | 22 | const name = element.textContent; 23 | const serverName = element.closest('.listRowContent_d2d6cb')?.querySelector('.listName_d2d6cb')?.textContent; 24 | 25 | if (serverName === '1337') { 26 | // Get all bracketed texts and use the last one 27 | const logins = name.match(/\[(.*?)\]/g); 28 | if (logins && logins.length > 0) { 29 | // Extract the last login from brackets 30 | const lastLogin = logins[logins.length - 1].match(/\[(.*?)\]/)[1]; 31 | addLink(element, lastLogin); 32 | } else { 33 | // If no brackets, use the nickname itself as the login 34 | const cleanName = name.replace(/[^\w\s-]/g, '').trim(); 35 | addLink(element, cleanName); 36 | } 37 | } 38 | }); 39 | } 40 | 41 | function addLink(element, username) { 42 | const link = document.createElement('a'); 43 | link.href = `https://profile.intra.42.fr/users/${username}`; 44 | link.innerHTML = ' 🔗'; 45 | link.target = '_blank'; 46 | link.style.color = '#5865F2'; 47 | link.style.textDecoration = 'none'; 48 | link.onclick = e => { 49 | e.preventDefault(); 50 | e.stopPropagation(); 51 | window.open(link.href, '_blank'); 52 | }; 53 | element.appendChild(link); 54 | } 55 | 56 | new MutationObserver(() => addIntraLinks()) 57 | .observe(document.body, { 58 | childList: true, 59 | subtree: true 60 | }); 61 | 62 | addIntraLinks(); -------------------------------------------------------------------------------- /.github/workflows/sync-to-gitlab.yml: -------------------------------------------------------------------------------- 1 | name: Backup to GitLab 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | schedule: 9 | - cron: "0 2 * * *" 10 | 11 | jobs: 12 | backup: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Setup GitLab Backup 21 | env: 22 | GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }} 23 | GITLAB_URL: ${{ secrets.GITLAB_URL }} 24 | GITLAB_NAMESPACE: ${{ secrets.GITLAB_NAMESPACE }} 25 | run: | 26 | # Configure git 27 | git config --global user.name "github-actions[bot]" 28 | git config --global user.email "github-actions[bot]@users.noreply.github.com" 29 | 30 | # Extract repository name 31 | REPO_NAME=${GITHUB_REPOSITORY#*/} 32 | 33 | # Function to get project ID 34 | get_project_id() { 35 | curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 36 | "https://${GITLAB_URL}/api/v4/projects/${GITLAB_NAMESPACE}%2F${REPO_NAME}" | \ 37 | jq -r '.id' 38 | } 39 | 40 | # Function to configure project settings 41 | configure_project() { 42 | local project_id=$1 43 | echo "Configuring project settings..." 44 | 45 | # Configure project settings 46 | curl -s --request PUT \ 47 | --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 48 | --header "Content-Type: application/json" \ 49 | --data '{ 50 | "only_allow_merge_if_pipeline_succeeds": false, 51 | "allow_merge_on_skipped_pipeline": true, 52 | "restrict_user_defined_variables": false 53 | }' \ 54 | "https://${GITLAB_URL}/api/v4/projects/${project_id}" 55 | 56 | # Remove all existing branch protection 57 | curl -s --request DELETE \ 58 | --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 59 | "https://${GITLAB_URL}/api/v4/projects/${project_id}/protected_branches/main" 60 | 61 | # Add updated branch protection 62 | curl -s --request POST \ 63 | --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 64 | --header "Content-Type: application/json" \ 65 | --data '{ 66 | "name": "main", 67 | "push_access_level": 40, 68 | "merge_access_level": 40, 69 | "unprotect_access_level": 40, 70 | "allow_force_push": true 71 | }' \ 72 | "https://${GITLAB_URL}/api/v4/projects/${project_id}/protected_branches" 73 | } 74 | 75 | # Get or create project 76 | PROJECT_ID=$(get_project_id) 77 | 78 | if [ "$PROJECT_ID" = "null" ] || [ -z "$PROJECT_ID" ]; then 79 | echo "Creating new project..." 80 | curl -s --request POST \ 81 | --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ 82 | --header "Content-Type: application/json" \ 83 | --data "{ 84 | \"name\": \"${REPO_NAME}\", 85 | \"path\": \"${REPO_NAME}\", 86 | \"visibility\": \"private\", 87 | \"initialize_with_readme\": false 88 | }" \ 89 | "https://${GITLAB_URL}/api/v4/projects" 90 | 91 | sleep 5 # Wait for project creation 92 | PROJECT_ID=$(get_project_id) 93 | fi 94 | 95 | echo "Project ID: $PROJECT_ID" 96 | 97 | # Configure project settings 98 | configure_project "$PROJECT_ID" 99 | 100 | # Setup and push to GitLab 101 | echo "Setting up Git remote..." 102 | GITLAB_REPO_URL="https://oauth2:${GITLAB_TOKEN}@${GITLAB_URL}/${GITLAB_NAMESPACE}/${REPO_NAME}.git" 103 | git remote add gitlab "$GITLAB_REPO_URL" || git remote set-url gitlab "$GITLAB_REPO_URL" 104 | 105 | echo "Fetching from GitLab..." 106 | git fetch gitlab || true 107 | 108 | echo "Pushing to GitLab..." 109 | # Push all branches except HEAD ref 110 | for branch in $(git branch -r | grep 'origin/' | grep -v 'origin/HEAD'); do 111 | branch_name=${branch#origin/} 112 | git push -f gitlab "$branch:refs/heads/$branch_name" 113 | done 114 | 115 | # Push all tags 116 | git push -f gitlab refs/tags/*:refs/tags/* 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Hey! 👋 3 | 4 | This is where I keep all my coding projects from my time at [42](https://42.fr/en/homepage/). I'm studying at [1337](https://1337.ma/en/) (part of the [42](https://42.fr/en/homepage/) Network) and I'm learning everything from scratch - starting with C programming and working my way up to building entire web apps. 5 | 6 | What makes 42 different is there are no teachers and no lectures. Instead, you figure things out on your own, work on real projects, and learn alongside other students. Every project has to go through peer reviews (we call them "corrections") before you can move forward. It's intense, but it's a great way to learn how to code and solve problems. 7 | 8 | In this repo, you'll find my progress through the whole curriculum - from basic stuff like coding my own C library to more complex projects like building web servers and creating full-stack applications. Each project taught me something new about computer science and software development. 9 | 10 |
|
88 |
89 |
90 | #### Foundation Phase
91 |
94 | |
95 | |
| Project | 99 |Details | 100 |
|---|---|
|
104 |
105 |
106 | libft
107 |
110 | |
111 | Objective: Create a custom C library implementing standard functions and additional utilities | 112 |
Implementation:
115 |
|
122 | |
| Technical Stack: 125 | |
129 | |
Key Learnings:
132 |
|
139 | |
|
143 |
144 |
145 | ft_printf
146 |
149 |
150 | |
151 | Objective: Recreate the printf function with core format specifiers and various flags | 152 |
Implementation:
155 |
|
162 | |
| Technical Stack: 165 | |
169 | |
Key Learnings:
172 |
|
179 | |
|
183 |
184 |
185 | get_next_line
186 |
189 |
190 | |
191 | Objective: Develop a function that reads lines from file descriptors | 192 |
Implementation:
195 |
|
202 | |
| Technical Stack: 205 | |
209 | |
Key Learnings:
212 |
|
219 | |
|
229 |
230 |
231 | #### System Administration & Process Management
232 |
235 | |
236 | |
| Project | 240 |Details | 241 |
|---|---|
|
245 |
246 |
247 | Born2beroot
248 |
251 |
252 | |
253 | Objective: Set up and configure a secure Linux server with strict rules | 254 |
Implementation:
257 |
|
264 | |
| Technical Stack: 267 | |
271 | |
Key Learnings:
274 |
|
281 | |
|
285 |
286 |
287 | Minitalk
288 |
289 |
291 |
292 |
293 | |
294 | Objective: Create a client-server communication system using UNIX signals | 295 |
Implementation:
298 |
|
305 | |
| Technical Stack: 308 | |
312 | |
Key Learnings:
315 |
|
322 | |
|
326 |
327 |
328 | Philosophers
329 |
330 |
332 |
333 |
334 | |
335 | Objective: Solve the dining philosophers problem using threads and mutexes | 336 |
Implementation:
339 |
|
346 | |
| Technical Stack: 349 | |
353 | |
Key Learnings:
356 |
|
363 | |
|
367 |
368 |
369 | Minishell
370 |
373 |
374 | |
375 | Objective: Create a basic shell interpreter similar to bash | 376 |
Implementation:
379 |
|
386 | |
| Technical Stack: 389 | |
393 | |
Key Learnings:
396 |
|
403 | |
|
413 |
414 |
415 | #### Algorithm Implementation & Optimization
416 |
419 | |
420 | |
| Project | 424 |Details | 425 |
|---|---|
|
429 |
430 |
431 | Push_swap
432 |
434 |
435 | |
436 | Objective: Develop an efficient sorting algorithm using two stacks with limited operations | 437 |
Implementation:
440 |
|
447 | |
| Technical Stack: 450 | |
454 | |
Key Learnings:
457 |
|
464 | |
|
474 |
475 |
476 | #### Graphics Programming & Visualization
477 |
480 | |
481 | |
| Project | 485 |Details | 486 |
|---|---|
|
490 |
491 |
492 | Fract-ol
493 |
495 |
496 | |
497 | Objective: Create a graphical program to explore and render various fractals | 498 |
Implementation:
501 |
|
508 | |
| Technical Stack: 511 | |
515 | |
Key Learnings:
518 |
|
525 | |
|
529 |
530 |
531 | Cub3D
532 |
535 |
536 | |
537 | Objective: Develop a 3D game engine using raycasting techniques | 538 |
Implementation:
541 |
|
548 | |
| Technical Stack: 551 | |
555 | |
Key Learnings:
558 |
|
565 | |
|
574 |
575 |
576 | #### Network & Protocol Implementation
577 |
580 | |
581 | |
| Project | 585 |Details | 586 |
|---|---|
|
590 |
591 |
592 | NetPractice
593 |
594 |
596 |
597 | |
598 | Objective: Master network configuration and TCP/IP fundamentals | 599 |
Implementation:
602 |
|
609 | |
| Technical Stack: 612 | |
616 | |
Key Learnings:
619 |
|
626 | |
|
630 |
631 |
632 | Webserv
633 |
634 |
637 |
638 | |
639 | Objective: Build an HTTP/1.1 compliant web server from scratch | 640 |
Implementation:
643 |
|
650 | |
| Technical Stack: 653 | |
657 | |
Key Learnings:
660 |
|
667 | |
|
677 |
678 |
679 | #### Modern C++ Development
680 |
683 | |
684 | |
| Project | 687 |Details | 688 |
|---|---|
|
691 |
692 |
693 | CPP Modules
698 | (00-09) 694 | 695 | 697 | |
699 | Objective: Master fundamental and advanced C++ concepts, OOP principles, and Standard Template Library utilization | 700 |
Implementation:
703 |
|
714 | |
| Technical Stack: 717 | |
723 | |
Key Learnings:
726 |
|
737 | |
|
745 |
746 |
747 | #### Container Orchestration & Deployment
748 |
751 | |
752 | |
| Project | 756 |Details | 757 |
|---|---|
|
761 |
762 |
763 | Inception
764 |
765 |
767 |
768 | |
769 | Objective: Set up a complete containerized web infrastructure using Docker | 770 |
Implementation:
773 |
|
780 | |
| Technical Stack: 783 | |
788 | |
Key Learnings:
791 |
|
798 | |
|
808 |
809 |
810 | #### Web Development & Real-Time Applications
811 |
814 | |
815 | |
| Project | 819 |Details | 820 |
|---|---|
|
824 |
825 |
826 | ft_transcendence
827 |
828 |
832 |
833 | |
834 | Objective: Create a full-stack web application featuring real-time multiplayer game and social features | 835 |
Implementation:
838 |
|
846 | |
| Technical Stack: 849 | |
854 | |
Key Learnings:
857 |
|
864 | |
|
903 |
904 |
905 | #### 42 Community Tools & Educational Resources
906 |
909 | |
910 | |
| Project | 914 |Details | 915 |
|---|---|
|
919 |
920 |
921 | pmerge-me-visualizer
922 |
923 |
924 | |
925 | Objective: A web application that visualizes the Ford-Johnson (merge-insert) sorting algorithm | 926 |
Implementation:
929 |
|
936 | |
| Technical Stack: 939 | |
943 | |
Key Learnings:
946 |
|
953 | |
|
958 |
959 |
960 | 42Recall
961 |
962 |
963 | |
964 | Objective: A spaced repetition flashcard application designed specifically for 42 School students to enhance their learning journey | 965 |
Implementation:
968 |
|
975 | |
| Technical Stack: 978 | |
983 | |
Key Learnings:
986 |
|
993 | |
|
997 |
998 |
999 | 42term
1000 |
1001 |
1002 | |
1003 | Objective: Generate beautiful terminal-style widgets to showcase 42 school achievements on GitHub and other platforms | 1004 |
Implementation:
1007 |
|
1014 | |
| Technical Stack: 1017 | |
1021 | |
Key Learnings:
1024 |
|
1029 | |