diff --git a/.eleventy.js b/.eleventy.js index a05ccd7..38e51f1 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,152 +1,44 @@ -module.exports = function(eleventyConfig) { +const fs = require("fs"); +const path = require("path"); + +const CSS_BUNDLE_FILES = [ + "css/base.css", + "css/header-and-profile.css", + "css/buttons-and-dropdowns.css", + "css/projects.css", + "css/footer.css", + "css/utilities.css" +]; + +function bundleCss() { + const bundled = CSS_BUNDLE_FILES + .map((file) => fs.readFileSync(path.join(__dirname, file), "utf8")) + .join("\n"); + fs.writeFileSync(path.join(__dirname, "stylesheet.css"), bundled); +} + +module.exports = function (eleventyConfig) { eleventyConfig.addPassthroughCopy("Images"); eleventyConfig.addPassthroughCopy("Scripts"); eleventyConfig.addPassthroughCopy("stylesheet.css"); eleventyConfig.addPassthroughCopy("Resume.pdf"); + eleventyConfig.addPassthroughCopy("robots.txt"); + eleventyConfig.addPassthroughCopy("llms.txt"); + eleventyConfig.addWatchTarget("css"); + eleventyConfig.on("eleventy.before", bundleCss); - eleventyConfig.addShortcode("ProjectCard", function(link, img, title, logo1, logo2, logo3, description) { - let logos = ''; - if (logo3) { - logos = ` - - - - `; - } else if (logo2) { - logos = ` - - - `; - } else if (logo1) { - logos = ` - - `; - } - - return `
- - - -
-

- ${title} - ${logos} -

-

${description}

- Learn More -
-
`; - }); - - eleventyConfig.addShortcode("NavigationButtons", function() { - return `
- - - -
`; - }); - - eleventyConfig.addShortcode("Footer", function() { - const year = new Date().getFullYear(); - return ``; - }); - - eleventyConfig.addShortcode("Sidebar", function() { - return ``; - }); - - eleventyConfig.addShortcode("Contact", function() { - return `
-
-

Contact Me

-
-
-

-

dylanka3@gmail.com

-
-
-

-

Sydney, Australia

-
-
-

-

(+61) 468 432 861

-
-
-
-
`; - }); + eleventyConfig.addFilter("encodeUri", (value) => encodeURI(value)); return { - dir: { - input: ".", - output: "_site" - } + dir: { + input: ".", + output: "_site", + includes: "_includes", + data: "_data" + }, + templateFormats: ["html", "njk", "md"], + markdownTemplateEngine: "njk", + htmlTemplateEngine: "njk", + dataTemplateEngine: "njk" }; - }; \ No newline at end of file +}; \ No newline at end of file diff --git a/.eleventyignore b/.eleventyignore new file mode 100644 index 0000000..1c518fe --- /dev/null +++ b/.eleventyignore @@ -0,0 +1,2 @@ +README.md +resume/ diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cf0f718..49deaf5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,12 +11,12 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: Install dependencies run: npm ci @@ -25,7 +25,7 @@ jobs: run: npx @11ty/eleventy - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./_site diff --git a/3DAnim.html b/3DAnim.html deleted file mode 100644 index 6a7a40c..0000000 --- a/3DAnim.html +++ /dev/null @@ -1,58 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Unity 3D Animation

- {% NavigationButtons %} -
-
- -
-
-

About the project

-

- "Why are we here?" is a 3D animation satire on first-person shooters, heavily inspired by Halo and Red vs. Blue. - It was developed over a few weeks in Unity using the HDRP rendering pipeline for a group project, where we used existing 3D models. - Throughout the process, I gained hands-on experience with the complete 3D animation production pipeline, - from storyboarding and pre-production planning to animation, lighting, rendering, and VFX. - This project helped me develop a stronger understanding of motion analysis, character animation, and scene composition, - while also giving me the opportunity to collaborate on production management and post-production tasks to deliver a polished final piece. -

-
- -
- -
-
-
- - - - diff --git a/Blender.html b/Blender.html deleted file mode 100644 index 37506d8..0000000 --- a/Blender.html +++ /dev/null @@ -1,84 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

3D Modelling Project

- {% NavigationButtons %} -
-
- -
-
-

About the project

-

- This personal project involved creating a detailed 3D model of a house using Blender to develop my modelling, UV unwrapping, texturing, lighting and rendering skills. - I focused on achieving realistic textures and materials by using my own photographs and free textures sourced online. -

-

What I learned

-

- In the course of this project, I learned how to UV unwrap models, which allowed me to apply textures accurately and realistically across different surfaces. - Working on lighting setups and camera positioning taught me how to enhance the final render, bringing out the model's textures and structure. - This project helped me understand the end-to-end process of creating a 3D environment, from modelling and texturing to lighting and rendering. -

-
- -
- - -
-
- - -
- - -
- - - -
-
-
- - - - diff --git a/CarRentalSystem.html b/CarRentalSystem.html deleted file mode 100644 index 963a8f2..0000000 --- a/CarRentalSystem.html +++ /dev/null @@ -1,81 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Car Rental System

- {% NavigationButtons %} -
-
- -
-
-

About the project

-

- I developed an interactive online car rental system as a solo project, using HTML, CSS, JavaScript, PHP, AJAX, and JSON. - The platform allows users to browse and search cars by type or brand, check availability, and make or cancel rental reservations. - I implemented dynamic features such as asynchronous data loading via AJAX, session-based reservation persistence, and real-time availability updates using JSON and MySQL. - User input validation and exception handling were built in to ensure a seamless user experience. - For data management, I designed a structured JSON file to store car details and integrated a MySQL database to handle rental orders. - The site was deployed on AWS Elastic Beanstalk, showcasing my ability to build and deploy full-stack web applications with rich interactivity and robust backend integration. -

- -
- -
- -
- -
- -
-
- - -
- - -
- - - -
-
-
- - - - - diff --git a/Caved-In.html b/Caved-In.html deleted file mode 100644 index cbd9db4..0000000 --- a/Caved-In.html +++ /dev/null @@ -1,99 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Caved In

- {% NavigationButtons %} -
-
- -
-
-

About the project

-

- Caved In is a cooperative first-person survival extraction game, developed over three months in Unreal Engine as part of a university group project. - Set within a cave system, 4-8 players must collect plant samples and transport them back to the exit to open the elevator door and escape. - However, while exploring the mine, players risk infection—forcing them to hide their condition from others. - Infected players can secretly sabotage the team by laying traps to spread the infection further. - We had the chance to collaborate with a sound design student, which helped us achieve our vision of an immersive survival horror experience. -

-

What I contributed

-

- I developed the player inventory and character selection systems, along with their user interfaces. - I also implemented nearly all the player items in the game, including both their functionality and animations. - Additionally, I created the user interface for the lobby's host/join screen. -

-

Difficulties in development

-

- The ambitious scope of implementing networked multiplayer presented significant challenges for us. - This complexity extended the development time of each feature, as we had to address numerous edge cases in client-server interactions. - As a result, our final submission wasn't as polished as we had hoped. -

- -
- -
-
- -
- -
-
- - -
- - -
- - - -
-
-
- - - - diff --git a/ClashOfCommands.html b/ClashOfCommands.html deleted file mode 100644 index 2e5a7a3..0000000 --- a/ClashOfCommands.html +++ /dev/null @@ -1,82 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Clash of Commands

- {% NavigationButtons %} -
-
- -
-
-

About the Project

-

- Clash of Commands is a web-based educational game designed to help IT students at UTS master - UNIX terminal commands through gamification. The Web Systems 31268 course is known for its difficulty, and this game makes - learning more interactive and engaging. Inspired by Kahoot!, it includes points, leaderboards, and increasing difficulty levels to - boost motivation. The game simulates a UNIX terminal, offering realistic command-line challenges that align with course content. Originally - planned as a multiplayer experience, it was adapted into a single-player format with a high-score system. Future updates could introduce - advanced topics like scripting, text processing, and command chaining. Designed for both classroom and independent learning, this tool - enhances engagement, progress tracking, and knowledge retention. -

-

What I Learned

-

- Developing Clash of Commands gave me hands-on experience in serious game design and gamification for education. - I learned how to create targeted game mechanics to support students struggling with UNIX commands, ensuring the game was - both fun and effective. The project strengthened my understanding of iterative design, as playtesting and feedback - drove improvements. I also gained insight into ethical and user-centered design, focusing on accessibility and engagement. - This experience has sharpened my ability to build purpose-driven interactive experiences that solve real-world learning challenges. -

- -
- -
- -
- - -
- - -
- - - -
-
-
- - - - diff --git a/Contact.html b/Contact.html deleted file mode 100644 index cd2a767..0000000 --- a/Contact.html +++ /dev/null @@ -1,73 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Dylan Archer

-

Software Developer (Games, Web, Mobile)

- {% NavigationButtons %} -
-
- -
-

Contact Me

-

Feel free to reach out if you'd like to connect or collaborate, and check out my games on Itch.io or explore more of my work on GitHub.

-
- -
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-

dylanka3@gmail.com

-
-
-

(+61) 468 432 861

-
- - - -
-
- -
- - \ No newline at end of file diff --git a/DualWield.html b/DualWield.html deleted file mode 100644 index be2834b..0000000 --- a/DualWield.html +++ /dev/null @@ -1,96 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Dual Wield

- {% NavigationButtons %} -
-
- -
-
-

About the project

-

- Dual Wield is a first-person shooter developed over three months using the Unity Game Engine as part of a university group project. - Players can wield two firearms simultaneously, allowing for up to 10 unique weapon combinations to tackle the enemies they encounter. - Our project was honoured with a nomination for the UTS Tech Festival 2024 Student Games Showcase. -

-

What I contributed

-

- Throughout the project's development, I contributed to various gameplay features and systems. - Additionally, I worked on 3D modelling for several of the weapons and some elements of the levels. -

-

What I learned

-

- As a collaborative project, Dual Wield provided me the opportunity to apply the project management principles I studied in my university course. - Regular reflection on our development process allowed us to adapt and improve our work continuously. - I gained valuable experience in integrating design, programming, and artistic skills from different team members to create a cohesive final product. - We also received feedback from playtests, which guided our development and strengthened our project. -

- - - -
- -
-
- -
- -
-
- - -
- - -
- - - -
-
-
- - - - - diff --git a/GroceryStore.html b/GroceryStore.html deleted file mode 100644 index 5d88e04..0000000 --- a/GroceryStore.html +++ /dev/null @@ -1,73 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Online Grocery Store

- {% NavigationButtons %} -
-
- -
-
-

About the project

-

- I developed a fully functional Online Grocery Store as a solo project, utilising a stack that included HTML, CSS, JavaScript, PHP, and SQL. - The website features a user-friendly interface that allows customers to browse products, add items to their cart, and complete purchases seamlessly. - I implemented dynamic functionalities such as product filtering and search options using JavaScript, while PHP and SQL were used for backend processes, including database management for inventory and orders. - As part of the assessment I deployed the website on AWS, allowing users to access it from anywhere. - This project not only enhanced my technical skills but also provided valuable experience in full-stack development and cloud deployment. -

- -
- -
- -
- - -
- - -
- - - -
-
-
- - - - diff --git a/Images/Favicon/apple-touch-icon.png b/Images/Favicon/apple-touch-icon.png new file mode 100644 index 0000000..fe01030 Binary files /dev/null and b/Images/Favicon/apple-touch-icon.png differ diff --git a/Images/Favicon/favicon-16x16.png b/Images/Favicon/favicon-16x16.png new file mode 100644 index 0000000..7215e41 Binary files /dev/null and b/Images/Favicon/favicon-16x16.png differ diff --git a/Images/Favicon/favicon-192x192.png b/Images/Favicon/favicon-192x192.png new file mode 100644 index 0000000..5b94c63 Binary files /dev/null and b/Images/Favicon/favicon-192x192.png differ diff --git a/Images/Favicon/favicon-32x32.png b/Images/Favicon/favicon-32x32.png new file mode 100644 index 0000000..e86e169 Binary files /dev/null and b/Images/Favicon/favicon-32x32.png differ diff --git a/Images/Favicon/favicon-512x512.png b/Images/Favicon/favicon-512x512.png new file mode 100644 index 0000000..a0f2fd2 Binary files /dev/null and b/Images/Favicon/favicon-512x512.png differ diff --git a/Images/Favicon/favicon.ico b/Images/Favicon/favicon.ico new file mode 100644 index 0000000..8276003 Binary files /dev/null and b/Images/Favicon/favicon.ico differ diff --git a/Images/Logos/AWS.png b/Images/Logos/AWS.png deleted file mode 100644 index c589f56..0000000 Binary files a/Images/Logos/AWS.png and /dev/null differ diff --git a/Images/Logos/AWS.webp b/Images/Logos/AWS.webp new file mode 100644 index 0000000..5235440 Binary files /dev/null and b/Images/Logos/AWS.webp differ diff --git a/Images/Logos/Blender-Logo.png b/Images/Logos/Blender-Logo.png deleted file mode 100644 index db8f257..0000000 Binary files a/Images/Logos/Blender-Logo.png and /dev/null differ diff --git a/Images/Logos/Blender-Logo.webp b/Images/Logos/Blender-Logo.webp new file mode 100644 index 0000000..c291b3b Binary files /dev/null and b/Images/Logos/Blender-Logo.webp differ diff --git a/Images/Logos/C++.png b/Images/Logos/C++.png deleted file mode 100644 index ece29d4..0000000 Binary files a/Images/Logos/C++.png and /dev/null differ diff --git a/Images/Logos/C++.webp b/Images/Logos/C++.webp new file mode 100644 index 0000000..909f8ea Binary files /dev/null and b/Images/Logos/C++.webp differ diff --git a/Images/Logos/CSS.png b/Images/Logos/CSS.png deleted file mode 100644 index bcc01d6..0000000 Binary files a/Images/Logos/CSS.png and /dev/null differ diff --git a/Images/Logos/CSS.webp b/Images/Logos/CSS.webp new file mode 100644 index 0000000..3fb0de3 Binary files /dev/null and b/Images/Logos/CSS.webp differ diff --git a/Images/Logos/CSharp.png b/Images/Logos/CSharp.png deleted file mode 100644 index dcec78b..0000000 Binary files a/Images/Logos/CSharp.png and /dev/null differ diff --git a/Images/Logos/CSharp.webp b/Images/Logos/CSharp.webp new file mode 100644 index 0000000..fea182d Binary files /dev/null and b/Images/Logos/CSharp.webp differ diff --git a/Images/Logos/GitHubLogo.png b/Images/Logos/GitHubLogo.png deleted file mode 100644 index 9490ffc..0000000 Binary files a/Images/Logos/GitHubLogo.png and /dev/null differ diff --git a/Images/Logos/GitHubLogo.webp b/Images/Logos/GitHubLogo.webp new file mode 100644 index 0000000..8a3149a Binary files /dev/null and b/Images/Logos/GitHubLogo.webp differ diff --git a/Images/Logos/HTML.png b/Images/Logos/HTML.png deleted file mode 100644 index 7620eee..0000000 Binary files a/Images/Logos/HTML.png and /dev/null differ diff --git a/Images/Logos/HTML.webp b/Images/Logos/HTML.webp new file mode 100644 index 0000000..9d3cfab Binary files /dev/null and b/Images/Logos/HTML.webp differ diff --git a/Images/Logos/IconMail.png b/Images/Logos/IconMail.png deleted file mode 100644 index 7f61d3c..0000000 Binary files a/Images/Logos/IconMail.png and /dev/null differ diff --git a/Images/Logos/IconMail.webp b/Images/Logos/IconMail.webp new file mode 100644 index 0000000..46fdb15 Binary files /dev/null and b/Images/Logos/IconMail.webp differ diff --git a/Images/Logos/IconPhone.png b/Images/Logos/IconPhone.png deleted file mode 100644 index 6b9ab45..0000000 Binary files a/Images/Logos/IconPhone.png and /dev/null differ diff --git a/Images/Logos/IconPhone.webp b/Images/Logos/IconPhone.webp new file mode 100644 index 0000000..faaae28 Binary files /dev/null and b/Images/Logos/IconPhone.webp differ diff --git a/Images/Logos/UE5-Logo.png b/Images/Logos/UE5-Logo.png deleted file mode 100644 index 5ae221b..0000000 Binary files a/Images/Logos/UE5-Logo.png and /dev/null differ diff --git a/Images/Logos/UE5-Logo.webp b/Images/Logos/UE5-Logo.webp new file mode 100644 index 0000000..c9ad830 Binary files /dev/null and b/Images/Logos/UE5-Logo.webp differ diff --git a/Images/Logos/Unity-Logo.png b/Images/Logos/Unity-Logo.png deleted file mode 100644 index afe943d..0000000 Binary files a/Images/Logos/Unity-Logo.png and /dev/null differ diff --git a/Images/Logos/Unity-Logo.webp b/Images/Logos/Unity-Logo.webp new file mode 100644 index 0000000..db8eb37 Binary files /dev/null and b/Images/Logos/Unity-Logo.webp differ diff --git a/Images/Logos/iOS-Logo.png b/Images/Logos/iOS-Logo.png deleted file mode 100644 index bcfe8b2..0000000 Binary files a/Images/Logos/iOS-Logo.png and /dev/null differ diff --git a/Images/Logos/iOS-Logo.webp b/Images/Logos/iOS-Logo.webp new file mode 100644 index 0000000..b0c3bbd Binary files /dev/null and b/Images/Logos/iOS-Logo.webp differ diff --git a/Images/Placeholder.png b/Images/Placeholder.png deleted file mode 100644 index d56c631..0000000 Binary files a/Images/Placeholder.png and /dev/null differ diff --git a/Images/ProfilePicture.jpeg b/Images/ProfilePicture.jpeg deleted file mode 100644 index d8c35a4..0000000 Binary files a/Images/ProfilePicture.jpeg and /dev/null differ diff --git a/Images/ProfilePicture.webp b/Images/ProfilePicture.webp new file mode 100644 index 0000000..d29b329 Binary files /dev/null and b/Images/ProfilePicture.webp differ diff --git a/Images/Project Screenshots/Blender/Blender Shot (1).png b/Images/Project Screenshots/Blender/Blender Shot (1).png deleted file mode 100644 index 698f2d9..0000000 Binary files a/Images/Project Screenshots/Blender/Blender Shot (1).png and /dev/null differ diff --git a/Images/Project Screenshots/Blender/Blender Shot (1).webp b/Images/Project Screenshots/Blender/Blender Shot (1).webp new file mode 100644 index 0000000..c1fa425 Binary files /dev/null and b/Images/Project Screenshots/Blender/Blender Shot (1).webp differ diff --git a/Images/Project Screenshots/Blender/Blender Shot (2).png b/Images/Project Screenshots/Blender/Blender Shot (2).png deleted file mode 100644 index 29903a2..0000000 Binary files a/Images/Project Screenshots/Blender/Blender Shot (2).png and /dev/null differ diff --git a/Images/Project Screenshots/Blender/Blender Shot (2).webp b/Images/Project Screenshots/Blender/Blender Shot (2).webp new file mode 100644 index 0000000..8ab5224 Binary files /dev/null and b/Images/Project Screenshots/Blender/Blender Shot (2).webp differ diff --git a/Images/Project Screenshots/Blender/Blender Shot (3).png b/Images/Project Screenshots/Blender/Blender Shot (3).png deleted file mode 100644 index 4f056f9..0000000 Binary files a/Images/Project Screenshots/Blender/Blender Shot (3).png and /dev/null differ diff --git a/Images/Project Screenshots/Blender/Blender Shot (3).webp b/Images/Project Screenshots/Blender/Blender Shot (3).webp new file mode 100644 index 0000000..47398f1 Binary files /dev/null and b/Images/Project Screenshots/Blender/Blender Shot (3).webp differ diff --git a/Images/Project Screenshots/Blender/Blender Shot (4).png b/Images/Project Screenshots/Blender/Blender Shot (4).png deleted file mode 100644 index e4d4ef0..0000000 Binary files a/Images/Project Screenshots/Blender/Blender Shot (4).png and /dev/null differ diff --git a/Images/Project Screenshots/Blender/Blender Shot (4).webp b/Images/Project Screenshots/Blender/Blender Shot (4).webp new file mode 100644 index 0000000..71db6b9 Binary files /dev/null and b/Images/Project Screenshots/Blender/Blender Shot (4).webp differ diff --git a/Images/Project Screenshots/Car Rental System/Filters.png b/Images/Project Screenshots/Car Rental System/Filters.png deleted file mode 100644 index 6be336a..0000000 Binary files a/Images/Project Screenshots/Car Rental System/Filters.png and /dev/null differ diff --git a/Images/Project Screenshots/Car Rental System/Filters.webp b/Images/Project Screenshots/Car Rental System/Filters.webp new file mode 100644 index 0000000..52353bc Binary files /dev/null and b/Images/Project Screenshots/Car Rental System/Filters.webp differ diff --git a/Images/Project Screenshots/Car Rental System/HomePage.png b/Images/Project Screenshots/Car Rental System/HomePage.png deleted file mode 100644 index d1906b0..0000000 Binary files a/Images/Project Screenshots/Car Rental System/HomePage.png and /dev/null differ diff --git a/Images/Project Screenshots/Car Rental System/HomePage.webp b/Images/Project Screenshots/Car Rental System/HomePage.webp new file mode 100644 index 0000000..7b62d16 Binary files /dev/null and b/Images/Project Screenshots/Car Rental System/HomePage.webp differ diff --git a/Images/Project Screenshots/Car Rental System/PlaceOrder.png b/Images/Project Screenshots/Car Rental System/PlaceOrder.png deleted file mode 100644 index ed21ed8..0000000 Binary files a/Images/Project Screenshots/Car Rental System/PlaceOrder.png and /dev/null differ diff --git a/Images/Project Screenshots/Car Rental System/PlaceOrder.webp b/Images/Project Screenshots/Car Rental System/PlaceOrder.webp new file mode 100644 index 0000000..f28d26d Binary files /dev/null and b/Images/Project Screenshots/Car Rental System/PlaceOrder.webp differ diff --git a/Images/Project Screenshots/Car Rental System/SearchResults.png b/Images/Project Screenshots/Car Rental System/SearchResults.png deleted file mode 100644 index 445bbe5..0000000 Binary files a/Images/Project Screenshots/Car Rental System/SearchResults.png and /dev/null differ diff --git a/Images/Project Screenshots/Car Rental System/SearchResults.webp b/Images/Project Screenshots/Car Rental System/SearchResults.webp new file mode 100644 index 0000000..3786f5d Binary files /dev/null and b/Images/Project Screenshots/Car Rental System/SearchResults.webp differ diff --git a/Images/Project Screenshots/Caved In/Caved In Bridge.png b/Images/Project Screenshots/Caved In/Caved In Bridge.png deleted file mode 100644 index bd6285c..0000000 Binary files a/Images/Project Screenshots/Caved In/Caved In Bridge.png and /dev/null differ diff --git a/Images/Project Screenshots/Caved In/Caved In Bridge.webp b/Images/Project Screenshots/Caved In/Caved In Bridge.webp new file mode 100644 index 0000000..02a3ea6 Binary files /dev/null and b/Images/Project Screenshots/Caved In/Caved In Bridge.webp differ diff --git a/Images/Project Screenshots/Caved In/Caved In Compass.png b/Images/Project Screenshots/Caved In/Caved In Compass.png deleted file mode 100644 index d54d8d8..0000000 Binary files a/Images/Project Screenshots/Caved In/Caved In Compass.png and /dev/null differ diff --git a/Images/Project Screenshots/Caved In/Caved In Compass.webp b/Images/Project Screenshots/Caved In/Caved In Compass.webp new file mode 100644 index 0000000..921418a Binary files /dev/null and b/Images/Project Screenshots/Caved In/Caved In Compass.webp differ diff --git a/Images/Project Screenshots/Caved In/Caved In Elevator.png b/Images/Project Screenshots/Caved In/Caved In Elevator.png deleted file mode 100644 index 6a43991..0000000 Binary files a/Images/Project Screenshots/Caved In/Caved In Elevator.png and /dev/null differ diff --git a/Images/Project Screenshots/Caved In/Caved In Elevator.webp b/Images/Project Screenshots/Caved In/Caved In Elevator.webp new file mode 100644 index 0000000..63261b1 Binary files /dev/null and b/Images/Project Screenshots/Caved In/Caved In Elevator.webp differ diff --git a/Images/Project Screenshots/Caved In/Caved In Heat Vision.png b/Images/Project Screenshots/Caved In/Caved In Heat Vision.png deleted file mode 100644 index 4ac0acc..0000000 Binary files a/Images/Project Screenshots/Caved In/Caved In Heat Vision.png and /dev/null differ diff --git a/Images/Project Screenshots/Caved In/Caved In Heat Vision.webp b/Images/Project Screenshots/Caved In/Caved In Heat Vision.webp new file mode 100644 index 0000000..c95b045 Binary files /dev/null and b/Images/Project Screenshots/Caved In/Caved In Heat Vision.webp differ diff --git a/Images/Project Screenshots/Caved In/Caved In Infected Tunnel.png b/Images/Project Screenshots/Caved In/Caved In Infected Tunnel.png deleted file mode 100644 index af36db4..0000000 Binary files a/Images/Project Screenshots/Caved In/Caved In Infected Tunnel.png and /dev/null differ diff --git a/Images/Project Screenshots/Caved In/Caved In Infected Tunnel.webp b/Images/Project Screenshots/Caved In/Caved In Infected Tunnel.webp new file mode 100644 index 0000000..80a09cf Binary files /dev/null and b/Images/Project Screenshots/Caved In/Caved In Infected Tunnel.webp differ diff --git a/Images/Project Screenshots/Caved In/Caved In Lobby.png b/Images/Project Screenshots/Caved In/Caved In Lobby.png deleted file mode 100644 index b447679..0000000 Binary files a/Images/Project Screenshots/Caved In/Caved In Lobby.png and /dev/null differ diff --git a/Images/Project Screenshots/Caved In/Caved In Lobby.webp b/Images/Project Screenshots/Caved In/Caved In Lobby.webp new file mode 100644 index 0000000..e89483b Binary files /dev/null and b/Images/Project Screenshots/Caved In/Caved In Lobby.webp differ diff --git a/Images/Project Screenshots/Caved In/Caved In Menu.png b/Images/Project Screenshots/Caved In/Caved In Menu.png deleted file mode 100644 index 76a9fc9..0000000 Binary files a/Images/Project Screenshots/Caved In/Caved In Menu.png and /dev/null differ diff --git a/Images/Project Screenshots/Caved In/Caved In Menu.webp b/Images/Project Screenshots/Caved In/Caved In Menu.webp new file mode 100644 index 0000000..629b38f Binary files /dev/null and b/Images/Project Screenshots/Caved In/Caved In Menu.webp differ diff --git a/Images/Project Screenshots/Caved In/Caved In Mining.png b/Images/Project Screenshots/Caved In/Caved In Mining.png deleted file mode 100644 index f90a3be..0000000 Binary files a/Images/Project Screenshots/Caved In/Caved In Mining.png and /dev/null differ diff --git a/Images/Project Screenshots/Caved In/Caved In Mining.webp b/Images/Project Screenshots/Caved In/Caved In Mining.webp new file mode 100644 index 0000000..8f46bcc Binary files /dev/null and b/Images/Project Screenshots/Caved In/Caved In Mining.webp differ diff --git a/Images/Project Screenshots/Caved In/Caved In Tunnel.png b/Images/Project Screenshots/Caved In/Caved In Tunnel.png deleted file mode 100644 index 582da51..0000000 Binary files a/Images/Project Screenshots/Caved In/Caved In Tunnel.png and /dev/null differ diff --git a/Images/Project Screenshots/Caved In/Caved In Tunnel.webp b/Images/Project Screenshots/Caved In/Caved In Tunnel.webp new file mode 100644 index 0000000..b365808 Binary files /dev/null and b/Images/Project Screenshots/Caved In/Caved In Tunnel.webp differ diff --git a/Images/Project Screenshots/Clash of Commands/ClashOfCommands1.png b/Images/Project Screenshots/Clash of Commands/ClashOfCommands1.png deleted file mode 100644 index 25357b2..0000000 Binary files a/Images/Project Screenshots/Clash of Commands/ClashOfCommands1.png and /dev/null differ diff --git a/Images/Project Screenshots/Clash of Commands/ClashOfCommands1.webp b/Images/Project Screenshots/Clash of Commands/ClashOfCommands1.webp new file mode 100644 index 0000000..177ec72 Binary files /dev/null and b/Images/Project Screenshots/Clash of Commands/ClashOfCommands1.webp differ diff --git a/Images/Project Screenshots/Clash of Commands/ClashOfCommands2.png b/Images/Project Screenshots/Clash of Commands/ClashOfCommands2.png deleted file mode 100644 index b2d058a..0000000 Binary files a/Images/Project Screenshots/Clash of Commands/ClashOfCommands2.png and /dev/null differ diff --git a/Images/Project Screenshots/Clash of Commands/ClashOfCommands2.webp b/Images/Project Screenshots/Clash of Commands/ClashOfCommands2.webp new file mode 100644 index 0000000..78d3c5e Binary files /dev/null and b/Images/Project Screenshots/Clash of Commands/ClashOfCommands2.webp differ diff --git a/Images/Project Screenshots/Clash of Commands/ClashOfCommands3.png b/Images/Project Screenshots/Clash of Commands/ClashOfCommands3.png deleted file mode 100644 index 139834e..0000000 Binary files a/Images/Project Screenshots/Clash of Commands/ClashOfCommands3.png and /dev/null differ diff --git a/Images/Project Screenshots/Clash of Commands/ClashOfCommands3.webp b/Images/Project Screenshots/Clash of Commands/ClashOfCommands3.webp new file mode 100644 index 0000000..e879383 Binary files /dev/null and b/Images/Project Screenshots/Clash of Commands/ClashOfCommands3.webp differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield Flame Rocket.png b/Images/Project Screenshots/Dual Wield/Dual Wield Flame Rocket.png deleted file mode 100644 index 9ca1671..0000000 Binary files a/Images/Project Screenshots/Dual Wield/Dual Wield Flame Rocket.png and /dev/null differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield Flame Rocket.webp b/Images/Project Screenshots/Dual Wield/Dual Wield Flame Rocket.webp new file mode 100644 index 0000000..0ed01ee Binary files /dev/null and b/Images/Project Screenshots/Dual Wield/Dual Wield Flame Rocket.webp differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield Flame.png b/Images/Project Screenshots/Dual Wield/Dual Wield Flame.png deleted file mode 100644 index 38274b7..0000000 Binary files a/Images/Project Screenshots/Dual Wield/Dual Wield Flame.png and /dev/null differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield Flame.webp b/Images/Project Screenshots/Dual Wield/Dual Wield Flame.webp new file mode 100644 index 0000000..a609e13 Binary files /dev/null and b/Images/Project Screenshots/Dual Wield/Dual Wield Flame.webp differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield Laser Rocket.png b/Images/Project Screenshots/Dual Wield/Dual Wield Laser Rocket.png deleted file mode 100644 index b948a09..0000000 Binary files a/Images/Project Screenshots/Dual Wield/Dual Wield Laser Rocket.png and /dev/null differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield Laser Rocket.webp b/Images/Project Screenshots/Dual Wield/Dual Wield Laser Rocket.webp new file mode 100644 index 0000000..99b28e4 Binary files /dev/null and b/Images/Project Screenshots/Dual Wield/Dual Wield Laser Rocket.webp differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield Title Screen.png b/Images/Project Screenshots/Dual Wield/Dual Wield Title Screen.png deleted file mode 100644 index d88cae8..0000000 Binary files a/Images/Project Screenshots/Dual Wield/Dual Wield Title Screen.png and /dev/null differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield Title Screen.webp b/Images/Project Screenshots/Dual Wield/Dual Wield Title Screen.webp new file mode 100644 index 0000000..ac60bf8 Binary files /dev/null and b/Images/Project Screenshots/Dual Wield/Dual Wield Title Screen.webp differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield UTS.png b/Images/Project Screenshots/Dual Wield/Dual Wield UTS.png deleted file mode 100644 index fcf9e22..0000000 Binary files a/Images/Project Screenshots/Dual Wield/Dual Wield UTS.png and /dev/null differ diff --git a/Images/Project Screenshots/Dual Wield/Dual Wield UTS.webp b/Images/Project Screenshots/Dual Wield/Dual Wield UTS.webp new file mode 100644 index 0000000..064882f Binary files /dev/null and b/Images/Project Screenshots/Dual Wield/Dual Wield UTS.webp differ diff --git a/Images/Project Screenshots/Grocery Store/Grocery Store (1).png b/Images/Project Screenshots/Grocery Store/Grocery Store (1).png deleted file mode 100644 index 48b953d..0000000 Binary files a/Images/Project Screenshots/Grocery Store/Grocery Store (1).png and /dev/null differ diff --git a/Images/Project Screenshots/Grocery Store/Grocery Store (1).webp b/Images/Project Screenshots/Grocery Store/Grocery Store (1).webp new file mode 100644 index 0000000..d45b9ec Binary files /dev/null and b/Images/Project Screenshots/Grocery Store/Grocery Store (1).webp differ diff --git a/Images/Project Screenshots/Grocery Store/Grocery Store (2).png b/Images/Project Screenshots/Grocery Store/Grocery Store (2).png deleted file mode 100644 index 2d1006c..0000000 Binary files a/Images/Project Screenshots/Grocery Store/Grocery Store (2).png and /dev/null differ diff --git a/Images/Project Screenshots/Grocery Store/Grocery Store (2).webp b/Images/Project Screenshots/Grocery Store/Grocery Store (2).webp new file mode 100644 index 0000000..368c475 Binary files /dev/null and b/Images/Project Screenshots/Grocery Store/Grocery Store (2).webp differ diff --git a/Images/Project Screenshots/Grocery Store/Grocery Store (3).png b/Images/Project Screenshots/Grocery Store/Grocery Store (3).png deleted file mode 100644 index b709aa5..0000000 Binary files a/Images/Project Screenshots/Grocery Store/Grocery Store (3).png and /dev/null differ diff --git a/Images/Project Screenshots/Grocery Store/Grocery Store (3).webp b/Images/Project Screenshots/Grocery Store/Grocery Store (3).webp new file mode 100644 index 0000000..2465eee Binary files /dev/null and b/Images/Project Screenshots/Grocery Store/Grocery Store (3).webp differ diff --git a/Images/Project Screenshots/Grocery Store/Grocery Store (4).png b/Images/Project Screenshots/Grocery Store/Grocery Store (4).png deleted file mode 100644 index b361cf5..0000000 Binary files a/Images/Project Screenshots/Grocery Store/Grocery Store (4).png and /dev/null differ diff --git a/Images/Project Screenshots/Grocery Store/Grocery Store (4).webp b/Images/Project Screenshots/Grocery Store/Grocery Store (4).webp new file mode 100644 index 0000000..2f91b9a Binary files /dev/null and b/Images/Project Screenshots/Grocery Store/Grocery Store (4).webp differ diff --git a/Images/Project Screenshots/OnTaskPro/Personae.jpg b/Images/Project Screenshots/OnTaskPro/Personae.jpg deleted file mode 100644 index 5b167c3..0000000 Binary files a/Images/Project Screenshots/OnTaskPro/Personae.jpg and /dev/null differ diff --git a/Images/Project Screenshots/OnTaskPro/Personae.webp b/Images/Project Screenshots/OnTaskPro/Personae.webp new file mode 100644 index 0000000..67a4906 Binary files /dev/null and b/Images/Project Screenshots/OnTaskPro/Personae.webp differ diff --git a/Images/Project Screenshots/OnTaskPro/Prototype.jpg b/Images/Project Screenshots/OnTaskPro/Prototype.jpg deleted file mode 100644 index 3c0efde..0000000 Binary files a/Images/Project Screenshots/OnTaskPro/Prototype.jpg and /dev/null differ diff --git a/Images/Project Screenshots/OnTaskPro/Prototype.webp b/Images/Project Screenshots/OnTaskPro/Prototype.webp new file mode 100644 index 0000000..ec6c4fb Binary files /dev/null and b/Images/Project Screenshots/OnTaskPro/Prototype.webp differ diff --git a/Images/Project Screenshots/OnTaskPro/QuestionMindmap.jpg b/Images/Project Screenshots/OnTaskPro/QuestionMindmap.jpg deleted file mode 100644 index 84417b6..0000000 Binary files a/Images/Project Screenshots/OnTaskPro/QuestionMindmap.jpg and /dev/null differ diff --git a/Images/Project Screenshots/OnTaskPro/QuestionMindmap.webp b/Images/Project Screenshots/OnTaskPro/QuestionMindmap.webp new file mode 100644 index 0000000..9318697 Binary files /dev/null and b/Images/Project Screenshots/OnTaskPro/QuestionMindmap.webp differ diff --git a/Images/Project Screenshots/OnTaskPro/SolutionMindmap.jpg b/Images/Project Screenshots/OnTaskPro/SolutionMindmap.jpg deleted file mode 100644 index 4d4fbff..0000000 Binary files a/Images/Project Screenshots/OnTaskPro/SolutionMindmap.jpg and /dev/null differ diff --git a/Images/Project Screenshots/OnTaskPro/SolutionMindmap.webp b/Images/Project Screenshots/OnTaskPro/SolutionMindmap.webp new file mode 100644 index 0000000..b9d1299 Binary files /dev/null and b/Images/Project Screenshots/OnTaskPro/SolutionMindmap.webp differ diff --git a/Images/Project Screenshots/OnTaskPro/TaskTracker.png b/Images/Project Screenshots/OnTaskPro/TaskTracker.png deleted file mode 100644 index 9c1febf..0000000 Binary files a/Images/Project Screenshots/OnTaskPro/TaskTracker.png and /dev/null differ diff --git a/Images/Project Screenshots/OnTaskPro/TaskTracker.webp b/Images/Project Screenshots/OnTaskPro/TaskTracker.webp new file mode 100644 index 0000000..7043b0a Binary files /dev/null and b/Images/Project Screenshots/OnTaskPro/TaskTracker.webp differ diff --git a/Images/Project Screenshots/PacStudent/PacStudent1.png b/Images/Project Screenshots/PacStudent/PacStudent1.png deleted file mode 100644 index 4feffba..0000000 Binary files a/Images/Project Screenshots/PacStudent/PacStudent1.png and /dev/null differ diff --git a/Images/Project Screenshots/PacStudent/PacStudent1.webp b/Images/Project Screenshots/PacStudent/PacStudent1.webp new file mode 100644 index 0000000..2cd2560 Binary files /dev/null and b/Images/Project Screenshots/PacStudent/PacStudent1.webp differ diff --git a/Images/Project Screenshots/PacStudent/PacStudent2.png b/Images/Project Screenshots/PacStudent/PacStudent2.png deleted file mode 100644 index d5a0387..0000000 Binary files a/Images/Project Screenshots/PacStudent/PacStudent2.png and /dev/null differ diff --git a/Images/Project Screenshots/PacStudent/PacStudent2.webp b/Images/Project Screenshots/PacStudent/PacStudent2.webp new file mode 100644 index 0000000..8a1be7f Binary files /dev/null and b/Images/Project Screenshots/PacStudent/PacStudent2.webp differ diff --git a/Images/Project Screenshots/Quiz App/Quiz App.png b/Images/Project Screenshots/Quiz App/Quiz App.png deleted file mode 100644 index 4d028e3..0000000 Binary files a/Images/Project Screenshots/Quiz App/Quiz App.png and /dev/null differ diff --git a/Images/Project Screenshots/Quiz App/Quiz App.webp b/Images/Project Screenshots/Quiz App/Quiz App.webp new file mode 100644 index 0000000..0c1c70a Binary files /dev/null and b/Images/Project Screenshots/Quiz App/Quiz App.webp differ diff --git a/Images/Project Screenshots/Snaked/Snaked-Together-1.webp b/Images/Project Screenshots/Snaked/Snaked-Together-1.webp new file mode 100644 index 0000000..e19c32e Binary files /dev/null and b/Images/Project Screenshots/Snaked/Snaked-Together-1.webp differ diff --git a/Images/Project Screenshots/Snaked/Snaked-Together-16x9.webp b/Images/Project Screenshots/Snaked/Snaked-Together-16x9.webp new file mode 100644 index 0000000..c402f95 Binary files /dev/null and b/Images/Project Screenshots/Snaked/Snaked-Together-16x9.webp differ diff --git a/Images/Project Screenshots/Snaked/Snaked-Together-2.webp b/Images/Project Screenshots/Snaked/Snaked-Together-2.webp new file mode 100644 index 0000000..8f167e9 Binary files /dev/null and b/Images/Project Screenshots/Snaked/Snaked-Together-2.webp differ diff --git a/Images/Project Screenshots/Wormy/Wormy (1).png b/Images/Project Screenshots/Wormy/Wormy (1).png deleted file mode 100644 index 3595af2..0000000 Binary files a/Images/Project Screenshots/Wormy/Wormy (1).png and /dev/null differ diff --git a/Images/Project Screenshots/Wormy/Wormy (1).webp b/Images/Project Screenshots/Wormy/Wormy (1).webp new file mode 100644 index 0000000..2ba4a0d Binary files /dev/null and b/Images/Project Screenshots/Wormy/Wormy (1).webp differ diff --git a/Images/Project Screenshots/Wormy/Wormy (2).png b/Images/Project Screenshots/Wormy/Wormy (2).png deleted file mode 100644 index 37410c5..0000000 Binary files a/Images/Project Screenshots/Wormy/Wormy (2).png and /dev/null differ diff --git a/Images/Project Screenshots/Wormy/Wormy (2).webp b/Images/Project Screenshots/Wormy/Wormy (2).webp new file mode 100644 index 0000000..d47de90 Binary files /dev/null and b/Images/Project Screenshots/Wormy/Wormy (2).webp differ diff --git a/Images/Project Screenshots/Wormy/Wormy (3).png b/Images/Project Screenshots/Wormy/Wormy (3).png deleted file mode 100644 index ac8be1f..0000000 Binary files a/Images/Project Screenshots/Wormy/Wormy (3).png and /dev/null differ diff --git a/Images/Project Screenshots/Wormy/Wormy (3).webp b/Images/Project Screenshots/Wormy/Wormy (3).webp new file mode 100644 index 0000000..cbac322 Binary files /dev/null and b/Images/Project Screenshots/Wormy/Wormy (3).webp differ diff --git a/OnTaskPro.html b/OnTaskPro.html deleted file mode 100644 index 44da6a3..0000000 --- a/OnTaskPro.html +++ /dev/null @@ -1,84 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Task Tracker App

- {% NavigationButtons %} -
-
- -
-
-

About the project

-

- OnTaskPro is an iOS app I developed as part of an individual assessment, where I was tasked with brainstorming, designing, and building an app to address a real-world problem for a specific target audience. - I chose to focus on individuals struggling with productivity and motivation. - The goal of OnTaskPro is to help users stay on track by reducing distractions and boosting their drive to complete tasks. - The app allows users to log their tasks, receive intelligent suggestions on what to work on, and stay focused through a simplified, goal-oriented interface. -

-

Technical Details

-

- OnTaskPro was built using Swift and SwiftUI, and follows the Model-View-ViewModel (MVVM) architecture to ensure a clean and maintainable codebase. -

-

Brainstorm & Design

-

- Attached are images showcasing my initial brainstorming and design process, which helped shape the app's features and user experience before development began. -

- -
- -
- - -
- - -
- - -
- - - -
-
-
- - - - diff --git a/PacStudent.html b/PacStudent.html deleted file mode 100644 index f02405d..0000000 --- a/PacStudent.html +++ /dev/null @@ -1,71 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

PacStudent

- {% NavigationButtons %} -
-
- -
-
-

About the project

-

- PacStudent is a recreation of the classic 1980 game Pac-Man, developed as part of an introductory game development subject. - This project served as a case study while I learned to navigate and utilise the Unity Game Engine for the first time. - Through this process, I gained hands-on experience with Unity's interface, applied vector and matrix mathematics for object transformations, and developed core programming skills using the engine's API. - The project challenged me to solve intermediate development problems, identify my own knowledge gaps, and design minor gameplay variations, helping me build both technical and creative skills in game development. -

- -
- -
- -
-
- - -
- - -
- - - -
-
-
- - - - \ No newline at end of file diff --git a/Quiz-App.html b/Quiz-App.html deleted file mode 100644 index df0c862..0000000 --- a/Quiz-App.html +++ /dev/null @@ -1,74 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Quiz App

-
- - - -
-
-
- -
-
-

About the project

-

- Quiz App is an iOS application developed over a few weeks as part of a group project using the SwiftUI framework. - The app fetches quizzes on various topics via an API, providing users with a range of quiz options. -

-

What I contributed

-

- I integrated the API to retrieve new questions and answers each time a user begins a quiz. - This involved using JSON parsing to display the data effectively within the app. - Additionally, I developed the UI that allows users to select the quiz difficulty, number of questions, and category. -

-

What I learned

-

- This was one of my early projects while I was learning iOS development for the first time. - As a result, the UI design wasn't fully refined, and some interface issues emerged, particularly with dynamic content, which occasionally caused the layout to appear inconsistent. - Despite these challenges, the project helped me build a solid foundation in SwiftUI and working with APIs. -

- -
- -
- -
-
-
- - - - diff --git a/README.md b/README.md new file mode 100644 index 0000000..aa0f49c --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# Dylan Archer Portfolio + +This is the source code for my personal portfolio website, built with [Eleventy](https://www.11ty.dev/). + +## Project Structure + +The project has been refactored to use Nunjucks templating for better maintainability. + +- **`_data/`**: Contains global data files. + - `projects.json`: Stores all project data (title, description, links, images). **Add new projects here.** + - `site.js`: Global site data (e.g., current year). +- **`_includes/`**: Contains Nunjucks templates. + - `layout.njk`: The main base layout for all pages. + - `components/`: Reusable components (Navigation, Footer, ProjectCard, etc.). +- **`html/`**: Contains the individual page templates. + - `index.html`: The home page, which loops through `projects.json` to display projects. + - `[ProjectName].html`: Individual project pages. +- **`css/`**: CSS files, organized by component/section. +- **`.eleventy.js`**: Eleventy configuration file. + +## How to Add a New Project + +1. Open `_data/projects.json`. +2. Add a new entry to the appropriate category array (e.g., "games", "web"). + ```json + { + "title": "My New Project", + "link": "MyProject.html", + "img": "Images/...", + "logos": ["Images/Logos/Tool.png"], + "description": "Description here..." + } + ``` +3. Create a new HTML file in `html/` (e.g., `MyProject.html`). +4. Add the front matter: + ```html + --- + layout: layout.njk + title: My New Project + permalink: "{{ page.fileSlug }}.html" + --- + ``` +5. Add your page content. + +## Local Development + +1. **Install dependencies:** + ```powershell + npm ci + ``` + +2. **Run the development server:** + ```powershell + npx @11ty/eleventy --serve + ``` + The site will be available at `http://localhost:8080`. + +## Deployment + +The site is automatically deployed to GitHub Pages via GitHub Actions when changes are pushed to the `main` branch. +See `.github/workflows/deploy.yml` for details. diff --git a/Resume.pdf b/Resume.pdf index 90ab010..77104b9 100644 Binary files a/Resume.pdf and b/Resume.pdf differ diff --git a/Wormy.html b/Wormy.html deleted file mode 100644 index 0575a10..0000000 --- a/Wormy.html +++ /dev/null @@ -1,94 +0,0 @@ ---- -permalink: "{{ page.fileSlug }}.html" ---- - - - - - Dylan Archer Portfolio - - - - - - - - -
- -
-
-

Wormy

- {% NavigationButtons %} -
-
- -
-
-

About the project

-

- Wormy is a 2D puzzle game developed in Unity as part of a group assessment task. - It was our first opportunity to design a game based entirely on our own ideas. - The goal was to create a small digital game that met specific design constraints and thematic requirements. - In Wormy, you play as a worm navigating a maze of underground tunnels to fertilize and grow a seed. -

-

What I contributed

-

- While the game was designed collaboratively, each team member was responsible for creating their own level, with each level introducing a unique gameplay mechanic. - I designed the first level following the tutorial, which introduced the portal mechanic. -

-

What I learned

-

- This project taught me how challenging it can be to maintain a cohesive game experience when multiple people contribute different design styles. - Each of our levels felt very distinct, which sometimes disrupted the flow of the game. I also learned the value of “finding the fun” during development. - Based on early playtester feedback, we significantly changed the player movement system from a traditional 2D platformer to something that better suited our game's concept. -

- - -
- -
-
- -
- -
-
- - -
- - -
- - - -
-
-
- - - - - diff --git a/_data/projects.json b/_data/projects.json new file mode 100644 index 0000000..b0ce2a8 --- /dev/null +++ b/_data/projects.json @@ -0,0 +1,153 @@ +{ + "games": [ + { + "link": "DualWield.html", + "img": "Images/Project Screenshots/Dual Wield/Dual Wield Title Screen.webp", + "title": "Dual Wield", + "logos": [ + "Images/Logos/Unity-Logo.webp", + "Images/Logos/CSharp.webp" + ], + "description": "Dual Wield is a first-person shooter developed over three months using the Unity Game Engine as part of a university group project. Players wield two firearms simultaneously, allowing up to 10 unique weapon combinations to tackle the enemies they encounter.", + "summary": "A Unity FPS built around dual-weapon combat and 10 weapon combinations.", + "tags": ["Unity", "C#", "Group", "3 months"] + }, + { + "link": "Caved-In.html", + "img": "Images/Project Screenshots/Caved In/Caved In Menu.webp", + "title": "Caved In", + "logos": [ + "Images/Logos/UE5-Logo.webp", + "Images/Logos/C++.webp" + ], + "description": "Caved In is a cooperative first-person survival extraction game, developed over three months in Unreal Engine as part of a university group project. Players must work together to collect samples and escape the cave, all while avoiding infection.", + "summary": "A cooperative Unreal extraction game about sampling, survival, and escape.", + "tags": ["Unreal", "C++", "Group", "3 months"] + }, + { + "link": "PacStudent.html", + "img": "Images/Project Screenshots/PacStudent/PacStudent1.webp", + "title": "PacStudent", + "logos": [ + "Images/Logos/Unity-Logo.webp", + "Images/Logos/CSharp.webp" + ], + "description": "PacStudent is a recreation of the classic 1980 game Pac-Man, developed as part of an introductory game development subject. This project served as a case study while I learned to navigate and utilise the Unity Game Engine for the first time.", + "summary": "A Unity recreation of Pac-Man created while learning core game systems.", + "tags": ["Unity", "C#", "Solo", "Game systems"] + }, + { + "link": "Wormy.html", + "img": "Images/Project Screenshots/Wormy/Wormy (1).webp", + "title": "Wormy", + "logos": [ + "Images/Logos/Unity-Logo.webp", + "Images/Logos/CSharp.webp" + ], + "description": "Wormy is a 2D puzzle game developed in Unity as part of a group assessment task. It was our first opportunity to design a game based entirely on our own ideas. In Wormy, you play as a worm navigating a maze of underground tunnels to fertilize and grow a seed.", + "summary": "A 2D Unity puzzle game about navigating tunnels to grow a seed.", + "tags": ["Unity", "C#", "Group", "2D puzzle"] + }, + { + "link": "Snaked-Together.html", + "img": "Images/Project Screenshots/Snaked/Snaked-Together-16x9.webp", + "title": "Snaked Together", + "logos": [ + "Images/Logos/Unity-Logo.webp", + "Images/Logos/CSharp.webp" + ], + "description": "You and a friend control a two-headed snake, bound together on a desperate climb from the depths of hell to the gates of heaven. The Catch? Only one head can move at a time, try moving together, and you'll tumble straight back down.", + "summary": "A cooperative climbing game where two players share one snake body.", + "tags": ["Unity", "C#", "Group", "Co-op"] + } + ], + "web": [ + { + "link": "GroceryStore.html", + "img": "Images/Project Screenshots/Grocery Store/Grocery Store (1).webp", + "title": "Online Grocery Store", + "logos": [ + "Images/Logos/HTML.webp", + "Images/Logos/CSS.webp" + ], + "description": "I developed a fully functional Online Grocery Store as a solo project, utilising HTML, CSS, JavaScript, PHP, and SQL. The website features a user-friendly interface that allows customers to browse products, add items to their cart, and complete purchases seamlessly.", + "summary": "A full-stack grocery storefront with browsing, cart, and checkout flows.", + "tags": ["HTML/CSS", "PHP", "SQL", "Solo"] + }, + { + "link": "CarRentalSystem.html", + "img": "Images/Project Screenshots/Car Rental System/HomePage.webp", + "title": "Online Car Rental", + "logos": [ + "Images/Logos/HTML.webp", + "Images/Logos/CSS.webp" + ], + "description": "I developed an interactive online car rental system as a solo project, using HTML, CSS, JavaScript, PHP, AJAX, and JSON. The platform allows users to browse and search cars by type or brand, check availability, and make or cancel rental reservations.", + "summary": "A car rental platform with filtering, availability checks, and bookings.", + "tags": ["HTML/CSS", "PHP", "AJAX", "Solo"] + } + ], + "mobile": [ + { + "link": "Quiz-App.html", + "img": "Images/Project Screenshots/Quiz App/Quiz App.webp", + "title": "Quiz App", + "logos": [ + "Images/Logos/swift.svg", + "Images/Logos/iOS-Logo.webp" + ], + "description": "Quiz App is an iOS application developed over a few weeks as part of a group project using the SwiftUI framework. The app fetches quizzes on various topics via an API, providing users with a range of quiz options.", + "summary": "A SwiftUI quiz app that fetches topic-based quizzes from an API.", + "tags": ["SwiftUI", "iOS", "Group", "API"] + }, + { + "link": "OnTaskPro.html", + "img": "Images/Project Screenshots/OnTaskPro/TaskTracker.webp", + "title": "Task Tracker App", + "logos": [ + "Images/Logos/swift.svg", + "Images/Logos/iOS-Logo.webp" + ], + "description": "OnTaskPro is an iOS app I developed as part of an individual assessment, where I was tasked with brainstorming, designing, and building an app to address a real-world problem for a specific target audience.", + "summary": "An iOS productivity app designed around a real user problem.", + "tags": ["SwiftUI", "iOS", "Solo", "UX design"] + } + ], + "modelling": [ + { + "link": "Blender.html", + "img": "Images/Project Screenshots/Blender/Blender Shot (1).webp", + "title": "3D Modelling Project", + "logos": [ + "Images/Logos/Blender-Logo.webp" + ], + "description": "This personal project involved creating a detailed 3D model of a house using Blender to develop my modelling, UV unwrapping, texturing, lighting and rendering skills. I focused on achieving realism by using my own photographs and free textures sourced online.", + "summary": "A Blender environment study focused on modelling, UVs, materials, and lighting.", + "tags": ["Blender", "Solo", "3D art", "Rendering"] + }, + { + "link": "3DAnim.html", + "img": "Images/Project Screenshots/Why are we here.webp", + "title": "Unity 3D Animation", + "logos": [ + "Images/Logos/Unity-Logo.webp" + ], + "description": "\"Why are we here?\" is a 3D animation satire on first-person shooters, heavily inspired by Halo and Red vs. Blue. It was developed over a few weeks in Unity using the HDRP rendering pipeline for a group project, where we used existing 3D models.", + "summary": "A Unity HDRP animation project inspired by FPS machinima comedy.", + "tags": ["Unity", "HDRP", "Group", "Animation"] + } + ], + "other": [ + { + "link": "ClashOfCommands.html", + "img": "Images/Project Screenshots/Clash of Commands/ClashOfCommands1.webp", + "title": "Clash of Commands", + "logos": [ + "Images/Logos/Unity-Logo.webp" + ], + "description": "Clash of Commands is an educational game that helps IT students learn UNIX terminal commands through gamification. I gained hands-on experience in serious game design, user-centered development, and iterative improvements based on feedback.", + "summary": "A serious game that teaches UNIX commands through repeatable challenges.", + "tags": ["Unity", "Education", "UX testing", "Serious game"] + } + ] +} diff --git a/_data/site.js b/_data/site.js new file mode 100644 index 0000000..3889a63 --- /dev/null +++ b/_data/site.js @@ -0,0 +1,6 @@ +module.exports = { + year: new Date().getFullYear(), + url: "https://dylan-archer-dev.com", + name: "Dylan Archer", + defaultImage: "Images/ProfilePicture.webp" +}; diff --git a/_includes/components/footer.njk b/_includes/components/footer.njk new file mode 100644 index 0000000..b5c0618 --- /dev/null +++ b/_includes/components/footer.njk @@ -0,0 +1,18 @@ + diff --git a/_includes/components/navigation.njk b/_includes/components/navigation.njk new file mode 100644 index 0000000..c65d613 --- /dev/null +++ b/_includes/components/navigation.njk @@ -0,0 +1,44 @@ +
+ + +
diff --git a/_includes/components/project-card.njk b/_includes/components/project-card.njk new file mode 100644 index 0000000..17de0a8 --- /dev/null +++ b/_includes/components/project-card.njk @@ -0,0 +1,30 @@ +{% macro projectCard(project) %} +
+ + {{ project.title }} project screenshot + +
+
+

+ {{ project.title }} +

+ {% if project.logos %} +
+ {% for logo in project.logos %} + + {% endfor %} +
+ {% endif %} +
+

{{ project.summary | default(project.description) }}

+ {% if project.tags %} +
+ {% for tag in project.tags %} + {{ tag }} + {% endfor %} +
+ {% endif %} + View Project +
+
+{% endmacro %} diff --git a/_includes/components/sidebar.njk b/_includes/components/sidebar.njk new file mode 100644 index 0000000..4853176 --- /dev/null +++ b/_includes/components/sidebar.njk @@ -0,0 +1,43 @@ + diff --git a/_includes/layout.njk b/_includes/layout.njk new file mode 100644 index 0000000..9b91031 --- /dev/null +++ b/_includes/layout.njk @@ -0,0 +1,183 @@ + + + + {% set pageTitle = seo_title | default(title) | default(site.name + " — Software Developer") %} + {% set pageDescription = seo_description | default("Portfolio of Dylan Archer, a software developer specialising in games, web and mobile development.") %} + {% set pageImage = image | default(site.defaultImage) %} + {% set canonicalUrl = site.url + page.url %} + {{ pageTitle }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% block head %}{% endblock %} + + + + +
+ {{ content | safe }} +
+ {% include "components/footer.njk" %} + + + {% block scripts %}{% endblock %} + + diff --git a/css/base.css b/css/base.css new file mode 100644 index 0000000..1e17afe --- /dev/null +++ b/css/base.css @@ -0,0 +1,476 @@ +/* HTML5 Elements & Base styles */ +:root { + color-scheme: dark; + --color-bg: #0f141b; + --color-surface: #161d27; + --color-surface-elevated: #1d2633; + --color-border: rgba(148, 163, 184, 0.22); + --color-text: #edf2f7; + --color-muted: #a8b3c2; + --color-accent: #38bdf8; + --color-accent-strong: #0ea5e9; + --color-button-text: #07111c; + --color-nav-bg: rgba(15, 20, 27, 0.9); + --color-hero-start: rgba(29, 38, 51, 0.94); + --color-hero-end: rgba(22, 29, 39, 0.84); + --color-award-bg: rgba(22, 29, 39, 0.72); + --color-card-bg: rgba(22, 29, 39, 0.92); + --color-chip-text: #c7eaff; + --color-chip-bg: rgba(56, 189, 248, 0.1); + --color-chip-border: rgba(56, 189, 248, 0.28); + --icon-filter: invert(1); + --shadow-soft: 0 14px 34px rgba(0, 0, 0, 0.2); + --shadow-glow: 0 12px 28px rgba(56, 189, 248, 0.08); + --radius: 8px; + --container: 1180px; +} + +@media (prefers-color-scheme: light) { + :root:not([data-theme]) { + color-scheme: light; + --color-bg: #f7f9fc; + --color-surface: #ffffff; + --color-surface-elevated: #ffffff; + --color-border: rgba(15, 23, 42, 0.14); + --color-text: #111827; + --color-muted: #4b5563; + --color-accent: #0284c7; + --color-accent-strong: #0369a1; + --color-button-text: #ffffff; + --color-nav-bg: rgba(247, 249, 252, 0.92); + --color-hero-start: rgba(255, 255, 255, 0.98); + --color-hero-end: rgba(232, 240, 248, 0.92); + --color-award-bg: rgba(255, 255, 255, 0.82); + --color-card-bg: rgba(255, 255, 255, 0.94); + --color-chip-text: #075985; + --color-chip-bg: rgba(2, 132, 199, 0.12); + --color-chip-border: rgba(2, 132, 199, 0.36); + --icon-filter: none; + --shadow-soft: 0 14px 34px rgba(15, 23, 42, 0.1); + --shadow-glow: 0 12px 28px rgba(2, 132, 199, 0.08); + } +} + +:root[data-theme="light"] { + color-scheme: light; + --color-bg: #f7f9fc; + --color-surface: #ffffff; + --color-surface-elevated: #ffffff; + --color-border: rgba(15, 23, 42, 0.14); + --color-text: #111827; + --color-muted: #4b5563; + --color-accent: #0284c7; + --color-accent-strong: #0369a1; + --color-button-text: #ffffff; + --color-nav-bg: rgba(247, 249, 252, 0.92); + --color-hero-start: rgba(255, 255, 255, 0.98); + --color-hero-end: rgba(232, 240, 248, 0.92); + --color-award-bg: rgba(255, 255, 255, 0.82); + --color-card-bg: rgba(255, 255, 255, 0.94); + --color-chip-text: #075985; + --color-chip-bg: rgba(2, 132, 199, 0.12); + --color-chip-border: rgba(2, 132, 199, 0.36); + --icon-filter: none; + --shadow-soft: 0 14px 34px rgba(15, 23, 42, 0.1); + --shadow-glow: 0 12px 28px rgba(2, 132, 199, 0.08); +} + +:root[data-theme="dark"] { + color-scheme: dark; +} + +* { box-sizing: border-box; } + +html { + background: var(--color-bg); + scroll-behavior: smooth; + scroll-padding-top: 96px; +} + +body { + margin: 0; + padding: 0; + color: var(--color-text); + font-family: "Inter", Arial, sans-serif; + background: linear-gradient(180deg, var(--color-surface) 0%, var(--color-bg) 42rem); +} + +.site-shell { + width: min(var(--container), calc(100% - 40px)); + margin: 0 auto; +} + +.site-nav { + position: sticky; + top: 0; + z-index: 100; + display: grid; + grid-template-columns: auto 1fr auto; + align-items: center; + gap: 24px; + width: min(var(--container), calc(100% - 40px)); + margin: 0 auto; + padding: 14px 22px; + background: var(--color-nav-bg); + border: 1px solid var(--color-border); + border-top: 0; + border-radius: 0 0 var(--radius) var(--radius); + backdrop-filter: blur(16px); +} + +.site-mark { + color: var(--color-text); + font-weight: 800; + letter-spacing: 0; + text-decoration: none; +} + +.site-nav-links { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 18px; +} + +.site-nav a { + position: relative; + color: var(--color-muted); + font-size: 0.95rem; + font-weight: 700; + text-decoration: none; + transition: color 0.2s ease; +} + +.site-nav a:hover, +.site-nav a:focus-visible, +.site-nav a[aria-current="page"] { + color: var(--color-accent); +} + +.site-nav-links > a::after, +.nav-dropdown-trigger::after { + content: ""; + position: absolute; + left: 0; + right: 0; + bottom: -6px; + height: 2px; + background: var(--color-accent); + transform: scaleX(0); + transform-origin: left; + transition: transform 0.2s ease; +} + +.site-nav-links > a:hover::after, +.site-nav-links > a:focus-visible::after, +.site-nav-links > a[aria-current="page"]::after, +.nav-dropdown:hover .nav-dropdown-trigger::after, +.nav-dropdown:focus-within .nav-dropdown-trigger::after { + transform: scaleX(1); +} + +.nav-dropdown { + position: relative; + display: inline-flex; + align-items: center; + padding: 8px 0; +} + +.nav-dropdown-menu { + display: none; + position: absolute; + top: 100%; + left: 0; + min-width: 220px; + background: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + text-align: left; +} + +.nav-dropdown:hover .nav-dropdown-menu, +.nav-dropdown:focus-within .nav-dropdown-menu { + display: block; +} + +.nav-dropdown-menu a { + padding: 12px 16px; + color: var(--color-muted); + transition: color 0.2s ease, background 0.2s ease; +} + +.nav-dropdown-menu .dropdown-sub { + position: relative; +} + +.nav-dropdown-menu .dropdown-sub > a { + display: block; + padding: 12px 16px; + color: var(--color-muted); +} + +.nav-dropdown-menu .dropdown-sub > a:hover, +.nav-dropdown-menu .dropdown-sub > a:focus-visible { + color: var(--color-text); + background: rgba(56, 189, 248, 0.12); +} + +.nav-dropdown .dropdown-sub-content { + display: none; + position: absolute; + top: 0; + left: 100%; + min-width: 200px; + background: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + z-index: 100; +} + +.nav-dropdown .dropdown-sub:hover .dropdown-sub-content, +.nav-dropdown .dropdown-sub:focus-within .dropdown-sub-content { + display: block; +} + +.nav-dropdown .dropdown-sub-content a { + padding: 12px 16px; + color: var(--color-muted); + font-weight: 400; + display: block; +} + +.nav-dropdown .dropdown-sub-content a:hover, +.nav-dropdown .dropdown-sub-content a:focus-visible { + color: var(--color-text); + background: rgba(56, 189, 248, 0.12); +} + +.nav-dropdown-menu a:hover, +.nav-dropdown-menu a:focus-visible { + color: var(--color-text); + background: rgba(56, 189, 248, 0.12); +} + +.theme-toggle { + display: inline-flex; + align-items: center; + gap: 8px; + margin: 0 0 0 2px; + padding: 6px 0; + color: var(--color-muted); + background: transparent; + border: 0; + box-shadow: none; +} + +.theme-toggle:hover { + color: var(--color-accent); + background: transparent; + box-shadow: none; + transform: none; +} + +.theme-toggle-track { + position: relative; + width: 42px; + height: 24px; + background: rgba(148, 163, 184, 0.24); + border: 1px solid var(--color-border); + border-radius: 999px; +} + +.theme-toggle-thumb { + position: absolute; + top: 3px; + left: 3px; + width: 16px; + height: 16px; + background: var(--color-accent); + border-radius: 999px; + transition: transform 0.2s ease; +} + +.theme-toggle[aria-pressed="true"] .theme-toggle-thumb { + transform: translateX(18px); +} + +.theme-toggle-label { + min-width: 34px; + font-size: 0.86rem; + font-weight: 800; +} + +.back-to-top { + position: fixed; + right: clamp(16px, 3vw, 28px); + bottom: clamp(16px, 3vw, 28px); + z-index: 90; + display: inline-grid; + place-items: center; + width: 42px; + height: 42px; + margin: 0; + padding: 0; + color: var(--color-button-text); + background: var(--color-accent); + border: 1px solid color-mix(in srgb, var(--color-accent) 70%, var(--color-border)); + border-radius: 999px; + box-shadow: var(--shadow-soft); + font-size: 1.2rem; + line-height: 1; + opacity: 0; + pointer-events: none; + transform: translateY(10px); + transition: opacity 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease; +} + +.back-to-top.is-visible { + opacity: 1; + pointer-events: auto; + transform: translateY(0); +} + +.back-to-top:hover, +.back-to-top:focus-visible { + background: var(--color-accent-strong); + transform: translateY(-2px); + box-shadow: var(--shadow-glow); +} + +footer { background: transparent; } + +h1, h2, h3, h4, h5, h6 { + color: var(--color-text); + line-height: 1.12; + letter-spacing: 0; +} + +h1 { font-size: clamp(2.4rem, 5vw, 4.25rem); font-weight: 800; } +h2 { font-size: clamp(1.45rem, 2.4vw, 2rem); font-weight: 800; margin: 0; } +h3 { font-size: 1.15rem; font-weight: 700; } + +p { + color: var(--color-muted); + line-height: 1.7; + margin-bottom: 1rem; +} + +a { + color: var(--color-accent); + text-decoration: none; +} + +a:hover { color: var(--color-text); } + +a:focus-visible, +button:focus-visible { + outline: 3px solid rgba(56, 189, 248, 0.45); + outline-offset: 3px; +} + +.content-section { + margin-top: 64px; +} + +.section-heading { + margin-bottom: 32px; +} + +.section-heading h2 { + font-size: clamp(2.4rem, 5vw, 4.25rem); + font-weight: 800; + margin: 0; +} + +.section-kicker { + margin: 0 0 10px; + color: var(--color-accent); + font-size: 0.82rem; + font-weight: 800; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.award-list { + display: grid; + gap: 12px; + margin: 20px 0 0; + padding: 0; + list-style: none; +} + +.award-list li { + padding: 16px 18px; + color: var(--color-muted); + background: var(--color-award-bg); + border: 1px solid var(--color-border); + border-radius: var(--radius); +} + +ol { padding-left: 1.5rem; } +ul { padding-left: 1.5rem; } +li { margin-bottom: 0.5rem; } + +hr { + height: 2px; + border-width: 0; + background-color: var(--color-accent); +} + +@media (max-width: 640px) { + html { + scroll-padding-top: 140px; + } + + .site-shell, + .site-nav { + width: min(100% - 28px, var(--container)); + padding: 0px; + } + + .site-nav { + grid-template-columns: 1fr auto; + gap: 8px 14px; + padding: 12px 14px; + } + + .site-nav-links { + grid-column: 1 / -1; + grid-row: 2; + justify-content: flex-start; + width: auto; + gap: 18px; + } + + .site-nav a { + font-size: 0.88rem; + } + + .site-mark { + grid-column: 1; + grid-row: 1; + } + + .theme-toggle { + grid-column: 2; + grid-row: 1; + justify-self: end; + } + + .theme-toggle-label { + display: none; + } + + .nav-dropdown { + padding: 0; + } + + .nav-dropdown-menu { + left: 50%; + right: auto; + min-width: min(230px, calc(100vw - 42px)); + transform: translateX(-50%); + } +} diff --git a/css/buttons-and-dropdowns.css b/css/buttons-and-dropdowns.css new file mode 100644 index 0000000..b849df9 --- /dev/null +++ b/css/buttons-and-dropdowns.css @@ -0,0 +1,167 @@ +/* Buttons */ +button { + background-color: var(--color-accent); + color: var(--color-button-text); + font-size: 1rem; + font-weight: 700; + border: 1px solid rgba(56, 189, 248, 0.45); + border-radius: var(--radius); + padding: 13px 28px; + cursor: pointer; + transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease; + box-shadow: 0 8px 18px rgba(56, 189, 248, 0.08); + white-space: normal; + word-break: break-word; + min-width: 0; +} + +button:hover { + background-color: #7dd3fc; + transform: translateY(-2px); + box-shadow: var(--shadow-glow); +} + +.light { + background-color: var(--color-text); + color: var(--color-bg); +} + +.red { + background-color: rgb(206, 73, 73); + color: #2e2e2e; + font-weight: 900; +} + +.red:hover { + background-color: rgb(219, 0, 0); +} + +.medium { + padding: 13px 22px; + margin: 5px; +} + +.small { + font-size: 0.9rem; + padding: 12px 24px 12px 24px; + margin: 5px; +} + +.project-link-button { + display: inline-flex; + align-items: center; + gap: 0.55rem; + flex-wrap: wrap; + justify-content: center; + white-space: normal; + word-break: break-word; + min-width: 0; +} + +.back-to-top { + position: fixed; + right: 24px; + bottom: 24px; + display: inline-flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + margin: 0; + padding: 0; + border-radius: 50%; + border: 1px solid var(--color-border); + background: var(--color-surface-elevated); + color: var(--color-text); + box-shadow: var(--shadow-soft); + opacity: 0; + visibility: hidden; + transform: translateY(12px); + transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s ease, background 0.2s ease; + z-index: 999; +} + +.back-to-top.is-visible { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.back-to-top:hover, +.back-to-top:focus-visible { + background: var(--color-accent); + color: var(--color-button-text); + border-color: rgba(56, 189, 248, 0.45); +} + +.back-to-top i { + font-size: 1rem; +} + +/* Dropdown */ +.dropdown { position: relative; display: inline-block; } + +.dropdown-content { + display: none; + position: absolute; + top: 100%; + min-width: 220px; + background-color: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + z-index: 20; + overflow: visible; + text-align: left; +} + +.dropdown-content a { + color: var(--color-muted); + text-align: left; + padding: 12px 16px; + text-decoration: none; + display: block; + font-weight: 700; + transition: color 0.2s ease, background 0.2s ease; +} + +.dropdown-content a:hover { + color: var(--color-text); + background-color: rgba(56, 189, 248, 0.12); +} + +.dropdown:hover .dropdown-content, +.dropdown:focus-within .dropdown-content { display: block; } + +.dropdown-sub { position: relative; } + +.dropdown-sub-content { + display: none; + position: absolute; + left: 100%; + top: 0; + min-width: 240px; + background-color: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + z-index: 1; +} + +.dropdown-sub:hover .dropdown-sub-content, +.dropdown-sub:focus-within .dropdown-sub-content { + display: block; +} + +.dropdown-sub-content a { + color: var(--color-muted); + padding: 12px 16px; + text-decoration: none; + display: block; +} + +.dropdown-sub-content a:hover, +.dropdown-sub-content a:focus-visible { + color: var(--color-text); + background-color: rgba(56, 189, 248, 0.12); +} diff --git a/css/footer.css b/css/footer.css new file mode 100644 index 0000000..388212d --- /dev/null +++ b/css/footer.css @@ -0,0 +1,48 @@ +footer { + margin-top: 60px; + padding: 40px 0; + background-color: transparent; + border-top: 1px solid var(--color-border); + text-align: center; +} + +.footer-content { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.footer-content p { + color: var(--color-muted); + margin-bottom: 15px; + font-size: 0.9rem; +} + +.footer-icons { + display: flex; + gap: 25px; + /* Space between icons */ + justify-content: center; + align-items: center; +} + +.footer-icons a { + text-decoration: none !important; + border: none; + display: block; + transition: transform 0.2s ease, opacity 0.2s ease; + opacity: 0.82; +} + +.footer-icons a:hover { + transform: translateY(-3px); + opacity: 1; +} + +.footer-icons img { + width: 30px; + height: auto; + display: block; + filter: var(--icon-filter); +} diff --git a/css/header-and-profile.css b/css/header-and-profile.css new file mode 100644 index 0000000..a6d3f0e --- /dev/null +++ b/css/header-and-profile.css @@ -0,0 +1,98 @@ +/* Home Page Header */ +.home-hero { + position: relative; + z-index: 10; + padding-top: 16px; +} + +.header-content { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + gap: 24px; + margin: 0 auto; + padding: clamp(8px, 1.4vw, 18px); + align-items: flex-start; + background: linear-gradient(135deg, var(--color-hero-start), var(--color-hero-end)); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + overflow: visible; +} + +.profile, .about { + flex: 1; + min-width: 300px; + margin: 0; + padding: clamp(28px, 5vw, 56px); +} + +@media (max-width: 459px) { + .header-content { + display: block; + } + .profile, .about { min-width: 0; padding: 26px; } + .about > div { grid-template-columns: 1fr !important; } +} + +/* Nav buttons: two equal columns on desktop, one column on mobile */ +.about > div { display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; gap: 12px; } +.about > div > .dropdown { display: block; min-width: 0; } +.about > div > .project-link-button { min-width: 0; } +.about .dropbtn, +.about .project-link-button { width: 100%; box-sizing: border-box; } + +.profile { text-align: center; } + +.profile-picture { + width: min(210px, 62%); + aspect-ratio: 1; + object-fit: cover; + border: 3px solid color-mix(in srgb, var(--color-accent) 55%, transparent); + border-radius: 50%; + box-shadow: 0 18px 42px rgba(0, 0, 0, 0.28); +} + +.profile h1, +.about h2 { + margin: 24px 0 14px; +} + +.hero-role { + margin: 0 0 18px; + color: var(--color-accent); + font-size: 1.25rem; + font-weight: 700; +} + +.social-links { + gap: 6px !important; + display: flex; + justify-content: center; +} + +.social-links img { + width: 45px; + height: 45px; + padding: 10px; + object-fit: contain; + background: color-mix(in srgb, var(--color-text) 8%, transparent); + border: 1px solid var(--color-border); + border-radius: 999px; + cursor: pointer; + transition: transform 0.2s ease, border-color 0.2s ease, background 0.2s ease; +} + +.social-links a { + display: inline-flex; +} + +.social-links img:hover { + background: color-mix(in srgb, var(--color-accent) 16%, transparent); + border-color: color-mix(in srgb, var(--color-accent) 55%, transparent); + transform: translateY(-3px); +} + +.about p { font-size: 1.08rem; } +.about div { text-align: center; } +.about .dropdown-content { text-align: left; } diff --git a/css/projects.css b/css/projects.css new file mode 100644 index 0000000..565d2e5 --- /dev/null +++ b/css/projects.css @@ -0,0 +1,224 @@ +/* Skills */ +.skills-container { display: flex; flex-wrap: wrap; gap: 20px; } +.skill-column { flex: 1; min-width: 200px; } + +/* Project Cards */ +.project-group { + margin-top: 48px; +} + +.project-group h2 { + margin-bottom: 22px; +} + +.project-container { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 28px; +} + +.project-card { + display: flex; + flex-direction: column; + min-height: 100%; + overflow: hidden; + background: var(--color-card-bg); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: 0 10px 24px rgba(0, 0, 0, 0.14); + transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease; +} + +.project-card:hover, +.project-card:focus-within { + border-color: color-mix(in srgb, var(--color-accent) 34%, var(--color-border)); + box-shadow: 0 12px 28px rgba(0, 0, 0, 0.18); + transform: translateY(-3px) scale(1.01); +} + +.project-card-media { + display: block; + aspect-ratio: 16 / 9; + overflow: hidden; + background: #0b1017; +} + +.project-card-media img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.35s ease; +} + +.project-card:hover .project-card-media img { + transform: scale(1.05); +} + +.project-card-body { + display: flex; + flex: 1; + flex-direction: column; + gap: 16px; + padding: 24px; +} + +.project-card-heading { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; +} + +.project-title { + margin: 0; + font-size: 1.2rem; +} + +.project-title a { + color: var(--color-text); + font-weight: 800; + text-decoration: none; + transition: color 0.2s ease; +} + +.project-title a:hover, +.project-title a:focus-visible { + color: var(--color-accent); +} + +.project-card-logos { + display: flex; + flex: 0 0 auto; + gap: 6px; +} + +.project-card-logos img { + width: 28px; + height: 28px; + object-fit: contain; + padding: 4px; + background: rgba(237, 242, 247, 0.08); + border: 1px solid var(--color-border); + border-radius: 7px; +} + +.project-summary { + min-height: 3.4em; + margin: 0; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; + line-clamp: 2; + -webkit-box-orient: vertical; +} + +.project-tags { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: auto; +} + +.project-tags span { + display: inline-flex; + align-items: center; + min-height: 28px; + padding: 5px 10px; + color: var(--color-chip-text); + font-size: 0.78rem; + font-weight: 800; + background: var(--color-chip-bg); + border: 1px solid var(--color-chip-border); + border-radius: 999px; +} + +.project-learn-more { + align-self: flex-start; + margin-top: 2px; + color: var(--color-accent); + font-weight: 800; + text-decoration: none; +} + +.project-learn-more i { + margin-left: 6px; + transition: transform 0.2s ease; +} + +.project-learn-more:hover i, +.project-learn-more:focus-visible i { + transform: translateX(2px); +} + +@media (max-width: 980px) { + .project-container { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 640px) { + .project-container { + grid-template-columns: 1fr; + gap: 22px; + } + + .project-card-body { + padding: 20px; + } +} + +/* Project Page */ +.project-page-container { + display: flex; + flex-direction: row; + gap: clamp(32px, 4vw, 64px); + padding-top: 30px; + align-items: flex-start; +} + +@media (max-width: 900px) { + .right-column { + gap: 18px; + } +} + +@media (max-width: 459px) { + .project-page-container { flex-direction: column; gap: 30px; } +} + +.project-page-container > .left-column, +.project-page-container > .right-column { + min-width: 0; +} + +.left-column { + flex: 1; + min-width: 0; +} + +.left-column iframe, +.left-column img, +.left-column video { + width: 100%; + max-width: 100%; + height: auto; +} + +.right-column { + flex: 1; + display: flex; + flex-direction: column; + gap: 10px; +} + +.right-column img, +.right-column iframe, +.right-column video { + width: 100%; + aspect-ratio: 16 / 9; + height: auto; + border: 0px; + border-radius: var(--radius); + margin: 10px 0; +} diff --git a/css/utilities.css b/css/utilities.css new file mode 100644 index 0000000..d7f2670 --- /dev/null +++ b/css/utilities.css @@ -0,0 +1,145 @@ +/* Utilities */ + +/* Carousel and image viewer */ +.carousel-container { + position: relative; + background: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: 16px; + box-shadow: var(--shadow-soft); +} + +.carousel-slide { + display: none; + width: 100%; + height: auto; + border-radius: var(--radius); + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04); +} + +.carousel-slide:hover, +#FullImage:hover { + transform: scale(1.002); +} + +.dot-container { + text-align: center; + padding: 14px 0 0; +} + +.dot { + display: inline-block; + height: 11px; + width: 11px; + margin: 0 5px; + border-radius: 999px; + background-color: rgba(148, 163, 184, 0.4); + cursor: pointer; + transition: transform 0.2s ease, background-color 0.2s ease; +} + +.dot:hover, +.dot:focus-visible { + transform: scale(1.15); + background-color: rgba(56, 189, 248, 0.8); +} + +.dot.active { + background-color: var(--color-accent); +} + +.carousel-nav { + display: flex; + justify-content: center; + gap: 10px; + flex-wrap: wrap; + margin-top: 14px; +} + +.carousel-button, +.overlay-button { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 46px; + min-height: 46px; + padding: 0.8rem; + border-radius: 999px; + border: 1px solid var(--color-border); + background: var(--color-surface-elevated); + color: var(--color-text); + transition: transform 0.2s ease, border-color 0.2s ease, background-color 0.2s ease; + cursor: pointer; +} + +.carousel-button:hover, +.carousel-button:focus-visible, +.overlay-button:hover, +.overlay-button:focus-visible { + transform: translateY(-1px); + border-color: var(--color-accent); + background: rgba(56, 189, 248, 0.15); +} + +.overlay-button i, +.carousel-button i { + font-size: 1rem; +} + +#FullImageView { + display: none; + position: fixed; + inset: 0; + z-index: 9999; + background: rgba(0, 0, 0, 0.9); + backdrop-filter: blur(6px); + padding: 30px 16px; + overflow: auto; + text-align: center; +} + +#FullImageView::before { + content: ""; + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.75)); + z-index: 1; +} + +#FullImage { + position: relative; + z-index: 2; + max-width: min(100%, 1440px); + max-height: 82vh; + width: auto; + height: auto; + margin: auto; + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + cursor: zoom-out; +} + +.fullscreen-controls { + position: absolute; + z-index: 2; + left: 50%; + bottom: 30px; + transform: translateX(-50%); + display: flex; + gap: 12px; + align-items: center; + justify-content: center; + flex-wrap: wrap; +} + +.overlay-button.close-button { + background: rgba(206, 73, 73, 0.95); + border-color: rgba(255, 80, 80, 0.35); + color: #fff; +} + +.overlay-button.close-button:hover, +.overlay-button.close-button:focus-visible { + background: rgb(219, 0, 0); +} diff --git a/html/3DAnim.html b/html/3DAnim.html new file mode 100644 index 0000000..1a9ca65 --- /dev/null +++ b/html/3DAnim.html @@ -0,0 +1,45 @@ +--- +layout: layout.njk +title: Unity 3D Animation +seo_title: "Unity 3D Animation — 'Why Are We Here?' (Unity HDRP)" +seo_description: "3D animation satire inspired by Halo and Red vs. Blue, produced in Unity HDRP. Showcases storyboarding, character animation, lighting, rendering and VFX." +image: "Images/Project Screenshots/Why are we here.webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Unity 3D Animation

+
+
+ +
+
+

About the project

+

+ "Why are we here?" is a 3D animation satire on first-person shooters, heavily inspired by Halo and Red + vs. Blue. + It was developed over a few weeks in Unity using the HDRP rendering pipeline for a group project, where we used + existing 3D models. + Throughout the process, I gained hands-on experience with the complete 3D animation production pipeline, + from storyboarding and pre-production planning to animation, lighting, rendering, and VFX. + This project helped me develop a stronger understanding of motion analysis, character animation, and scene + composition, + while also giving me the opportunity to collaborate on production management and post-production tasks to deliver + a polished final piece. +

+
+ +
+ +
+
+ +{% block scripts %} + +{% endblock %} \ No newline at end of file diff --git a/html/Blender.html b/html/Blender.html new file mode 100644 index 0000000..6e553d6 --- /dev/null +++ b/html/Blender.html @@ -0,0 +1,78 @@ +--- +layout: layout.njk +title: 3D Modelling Project +seo_title: "3D Modelling Project — Blender House Model" +seo_description: "Detailed 3D house model created in Blender showcasing modelling, UV unwrapping, texturing, lighting and rendering techniques." +image: "Images/Project Screenshots/Blender/Blender Shot (1).webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

3D Modelling Project

+
+
+ +
+
+

About the project

+

+ This personal project involved creating a detailed 3D model of a house using Blender to develop my modelling, UV + unwrapping, texturing, lighting and rendering skills. + I focused on achieving realistic textures and materials by using my own photographs and free textures sourced + online. +

+

What I learned

+

+ In the course of this project, I learned how to UV unwrap models, which allowed me to apply textures accurately + and realistically across different surfaces. + Working on lighting setups and camera positioning taught me how to enhance the final render, bringing out the + model's textures and structure. + This project helped me understand the end-to-end process of creating a 3D environment, from modelling and + texturing to lighting and rendering. +

+
+ +
+ + +
+
+ + +
+ + +
+ + + +
+
+ +{% block scripts %} + +{% endblock %} \ No newline at end of file diff --git a/html/CarRentalSystem.html b/html/CarRentalSystem.html new file mode 100644 index 0000000..d18a2ba --- /dev/null +++ b/html/CarRentalSystem.html @@ -0,0 +1,79 @@ +--- +layout: layout.njk +title: Online Car Rental +seo_title: "Online Car Rental System — Full-Stack Web Project" +seo_description: "Interactive car rental platform built with HTML, CSS, JavaScript, PHP and MySQL. Features search, availability, AJAX-driven bookings and AWS deployment." +image: "Images/Project Screenshots/Car Rental System/HomePage.webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Car Rental System

+
+
+ +
+
+

About the project

+

+ I developed an interactive online car rental system as a solo project, using HTML, CSS, JavaScript, PHP, AJAX, and + JSON. + The platform allows users to browse and search cars by type or brand, check availability, and make or cancel + rental reservations. + I implemented dynamic features such as asynchronous data loading via AJAX, session-based reservation persistence, + and real-time availability updates using JSON and MySQL. + User input validation and exception handling were built in to ensure a seamless user experience. + For data management, I designed a structured JSON file to store car details and integrated a MySQL database to + handle rental orders. + The site was deployed on AWS Elastic Beanstalk, showcasing my ability to build and deploy full-stack web + applications with rich interactivity and robust backend integration. +

+ +
+ +
+ + +
+
+ + +
+ + +
+ + + +
+
+ +{% block scripts %} + + +{% endblock %} \ No newline at end of file diff --git a/html/Caved-In.html b/html/Caved-In.html new file mode 100644 index 0000000..878d097 --- /dev/null +++ b/html/Caved-In.html @@ -0,0 +1,100 @@ +--- +layout: layout.njk +title: Caved In +seo_title: "Caved In — Cooperative Survival Extraction (Unreal Engine)" +seo_description: "Cooperative first-person survival-extraction game built in Unreal Engine. Team-based sample collection, infection mechanics, inventory and UI systems." +image: "Images/Project Screenshots/Caved In/Caved In Menu.webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Caved In

+
+
+ +
+
+

About the project

+

+ Caved In is a cooperative first-person survival extraction game, developed over three months in Unreal Engine as + part of a university group project. + Set within a cave system, 4-8 players must collect plant samples and transport them back to the exit to open the + elevator door and escape. + However, while exploring the mine, players risk infection—forcing them to hide their condition from others. + Infected players can secretly sabotage the team by laying traps to spread the infection further. + We had the chance to collaborate with a sound design student, which helped us achieve our vision of an immersive + survival horror experience. +

+

What I contributed

+

+ I developed the player inventory and character selection systems, along with their user interfaces. + I also implemented nearly all the player items in the game, including both their functionality and animations. + Additionally, I created the user interface for the lobby's host/join screen. +

+

Difficulties in development

+

+ The ambitious scope of implementing networked multiplayer presented significant challenges for us. + This complexity extended the development time of each feature, as we had to address numerous edge cases in + client-server interactions. + As a result, our final submission wasn't as polished as we had hoped. +

+ +
+ +
+
+ +
+ +
+
+ + +
+ + +
+ + + +
+
+ +{% block scripts %} + +{% endblock %} \ No newline at end of file diff --git a/html/ClashOfCommands.html b/html/ClashOfCommands.html new file mode 100644 index 0000000..d9bde75 --- /dev/null +++ b/html/ClashOfCommands.html @@ -0,0 +1,82 @@ +--- +layout: layout.njk +title: Clash of Commands +seo_title: "Clash of Commands — Learn UNIX Commands Through Gamification" +seo_description: "Web-based educational game that teaches UNIX terminal commands with gamification, leaderboards and realistic command-line challenges for students." +image: "Images/Project Screenshots/Clash of Commands/ClashOfCommands1.webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Clash of Commands

+
+
+ +
+
+

About the Project

+

+ Clash of Commands is a web-based educational game designed to help IT students at UTS master + UNIX terminal commands through gamification. The Web Systems 31268 course is known for its difficulty, and this + game makes + learning more interactive and engaging. Inspired by Kahoot!, it includes points, leaderboards, and increasing + difficulty levels to + boost motivation. The game simulates a UNIX terminal, offering realistic command-line challenges that align with + course content. Originally + planned as a multiplayer experience, it was adapted into a single-player format with a high-score system. Future + updates could introduce + advanced topics like scripting, text processing, and command chaining. Designed for both classroom and independent + learning, this tool + enhances engagement, progress tracking, and knowledge retention. +

+

What I Learned

+

+ Developing Clash of Commands gave me hands-on experience in serious game design and gamification for education. + I learned how to create targeted game mechanics to support students struggling with UNIX commands, ensuring the + game was + both fun and effective. The project strengthened my understanding of iterative design, as playtesting and feedback + drove improvements. I also gained insight into ethical and user-centered design, focusing on accessibility and + engagement. + This experience has sharpened my ability to build purpose-driven interactive experiences that solve real-world + learning challenges. +

+ +
+ +
+ +
+ + +
+ + +
+ + + +
+
+ + {% block scripts %} + + {% endblock %} \ No newline at end of file diff --git a/html/DualWield.html b/html/DualWield.html new file mode 100644 index 0000000..134e648 --- /dev/null +++ b/html/DualWield.html @@ -0,0 +1,96 @@ +--- +layout: layout.njk +title: Dual Wield +seo_title: "Dual Wield — Unity FPS Project (UTS 2024 Showcase Nominee)" +seo_description: "Unity first-person shooter developed as a university group project. Dual-wield mechanics with up to 10 weapon combinations, 3D weapon modelling and a UTS 2024 showcase nomination." +image: "Images/Project Screenshots/Dual Wield/Dual Wield Title Screen.webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Dual Wield

+
+
+ +
+
+

About the project

+

+ Dual Wield is a first-person shooter developed over three months using the Unity Game Engine as part of a + university group project. + Players can wield two firearms simultaneously, allowing for up to 10 unique weapon combinations to tackle the + enemies they encounter. + Our project was honoured with a nomination for the UTS Tech Festival 2024 Student Games Showcase. +

+

What I contributed

+

+ Throughout the project's development, I contributed to various gameplay features and systems. + Additionally, I worked on 3D modelling for several of the weapons and some elements of the levels. +

+

What I learned

+

+ As a collaborative project, Dual Wield provided me the opportunity to apply the project management principles I + studied in my university course. + Regular reflection on our development process allowed us to adapt and improve our work continuously. + I gained valuable experience in integrating design, programming, and artistic skills from different team members + to create a cohesive final product. + We also received feedback from playtests, which guided our development and strengthened our project. +

+ + + +
+ +
+
+ +
+ +
+
+ + +
+ + +
+ + + +
+
+ +{% block scripts %} + + +{% endblock %} \ No newline at end of file diff --git a/html/GroceryStore.html b/html/GroceryStore.html new file mode 100644 index 0000000..2195d78 --- /dev/null +++ b/html/GroceryStore.html @@ -0,0 +1,70 @@ +--- +layout: layout.njk +title: Online Grocery Store +seo_title: "Online Grocery Store — Full-Stack Web Project" +seo_description: "Full-featured online grocery store built with HTML, CSS, JavaScript, PHP and SQL. Supports product browsing, filtering, cart and cloud deployment on AWS." +image: "Images/Project Screenshots/Grocery Store/Grocery Store (1).webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Online Grocery Store

+
+
+ +
+
+

About the project

+

+ I developed a fully functional Online Grocery Store as a solo project, utilising a stack that included HTML, CSS, + JavaScript, PHP, and SQL. + The website features a user-friendly interface that allows customers to browse products, add items to their cart, + and complete purchases seamlessly. + I implemented dynamic functionalities such as product filtering and search options using JavaScript, while PHP and + SQL were used for backend processes, including database management for inventory and orders. + As part of the assessment I deployed the website on AWS, allowing users to access it from anywhere. + This project not only enhanced my technical skills but also provided valuable experience in full-stack development + and cloud deployment. +

+ +
+ +
+ +
+ + +
+ + +
+ + + +
+
+ + {% block scripts %} + + {% endblock %} \ No newline at end of file diff --git a/html/OnTaskPro.html b/html/OnTaskPro.html new file mode 100644 index 0000000..465d2a0 --- /dev/null +++ b/html/OnTaskPro.html @@ -0,0 +1,83 @@ +--- +layout: layout.njk +title: Task Tracker App +seo_title: "OnTaskPro — Productivity iOS App (SwiftUI)" +seo_description: "OnTaskPro is an iOS task-tracking app built with Swift and SwiftUI (MVVM). Provides task logging, intelligent suggestions and a goal-oriented interface to boost productivity." +image: "Images/Project Screenshots/OnTaskPro/TaskTracker.webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Task Tracker App

+
+
+ +
+
+

About the project

+

+ OnTaskPro is an iOS app I developed as part of an individual assessment, where I was tasked with brainstorming, + designing, and building an app to address a real-world problem for a specific target audience. + I chose to focus on individuals struggling with productivity and motivation. + The goal of OnTaskPro is to help users stay on track by reducing distractions and boosting their drive to complete + tasks. + The app allows users to log their tasks, receive intelligent suggestions on what to work on, and stay focused + through a simplified, goal-oriented interface. +

+

Technical Details

+

+ OnTaskPro was built using Swift and SwiftUI, and follows the Model-View-ViewModel (MVVM) architecture to ensure a + clean and maintainable codebase. +

+

Brainstorm & Design

+

+ Attached are images showcasing my initial brainstorming and design process, which helped shape the app's features + and user experience before development began. +

+ +
+ +
+ + +
+
+ + +
+ + +
+ + + +
+
+ +{% block scripts %} + +{% endblock %} \ No newline at end of file diff --git a/html/PacStudent.html b/html/PacStudent.html new file mode 100644 index 0000000..1f7d805 --- /dev/null +++ b/html/PacStudent.html @@ -0,0 +1,68 @@ +--- +layout: layout.njk +title: PacStudent +seo_title: "PacStudent — Pac‑Man Recreation (Unity)" +seo_description: "Recreation of the classic Pac‑Man built in Unity. A learning project that demonstrates core Unity concepts, object transforms and gameplay programming." +image: "Images/Project Screenshots/PacStudent/PacStudent1.webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

PacStudent

+
+
+ +
+
+

About the project

+

+ PacStudent is a recreation of the classic 1980 game Pac-Man, developed as part of an introductory game development + subject. + This project served as a case study while I learned to navigate and utilise the Unity Game Engine for the first + time. + Through this process, I gained hands-on experience with Unity's interface, applied vector and matrix mathematics + for object transformations, and developed core programming skills using the engine's API. + The project challenged me to solve intermediate development problems, identify my own knowledge gaps, and design + minor gameplay variations, helping me build both technical and creative skills in game development. +

+ +
+ +
+ +
+
+ + +
+ + +
+ + + +
+
+ +{% block scripts %} + +{% endblock %} \ No newline at end of file diff --git a/html/Quiz-App.html b/html/Quiz-App.html new file mode 100644 index 0000000..3ca2a18 --- /dev/null +++ b/html/Quiz-App.html @@ -0,0 +1,52 @@ +--- +layout: layout.njk +title: Quiz App +seo_title: "Quiz App — SwiftUI iOS Quiz Application" +seo_description: "SwiftUI iOS app that fetches quizzes via API, offering difficulty and category selection. Demonstrates API integration, JSON parsing and dynamic UI." +image: "Images/Project Screenshots/Quiz App/Quiz App.webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Quiz App

+
+
+ +
+
+

About the project

+

+ Quiz App is an iOS application developed over a few weeks as part of a group project using the SwiftUI framework. + The app fetches quizzes on various topics via an API, providing users with a range of quiz options. +

+

What I contributed

+

+ I integrated the API to retrieve new questions and answers each time a user begins a quiz. + This involved using JSON parsing to display the data effectively within the app. + Additionally, I developed the UI that allows users to select the quiz difficulty, number of questions, and + category. +

+

What I learned

+

+ This was one of my early projects while I was learning iOS development for the first time. + As a result, the UI design wasn't fully refined, and some interface issues emerged, particularly with dynamic + content, which occasionally caused the layout to appear inconsistent. + Despite these challenges, the project helped me build a solid foundation in SwiftUI and working with APIs. +

+ +
+ +
+ +
+
+ +{% block scripts %} + +{% endblock %} \ No newline at end of file diff --git a/html/Snaked-Together.html b/html/Snaked-Together.html new file mode 100644 index 0000000..92a40a0 --- /dev/null +++ b/html/Snaked-Together.html @@ -0,0 +1,71 @@ +--- +layout: layout.njk +title: Snaked Together +seo_title: "Snaked Together — Cooperative 2D Game (SXSW Snake Jam)" +seo_description: "Cooperative 2D climbing game created for the SXSW Snake Jam. Players control opposite ends of a two-headed snake in rapid-prototype, team-driven gameplay." +image: "Images/Project Screenshots/Snaked/Snaked-Together-16x9.webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Snaked Together

+
+
+ +
+
+

About the project

+

+ Snaked Together is a 2D cooperative climbing game created by a small, focused team over the course of roughly two weeks. + The game was developed for a game jam hosted by SXSW Sydney, challenging us to rapidly prototype, refine, and polish a unique gameplay concept within a tight timeframe. + The result is a light-hearted yet mechanically engaging experience centered around teamwork, coordination, and movement-based problem-solving. + Players control opposite ends of a two-headed snake, navigating hazards, color-based obstacles, and increasingly tricky platforming sections that demand precise communication and timing. +

+

What I contributed

+

+ I played a key role in shaping the core direction of the game, collaborating closely with the team to brainstorm and refine its central mechanics. + I designed the level layout and progression, ensuring that each section supported cooperative play, introduced new challenges, and encouraged players to strategize together. + In addition to design work, I also contributed to some of the programming of the project using Unity and C#. + I also assisted with testing and refining the game's difficulty curve to make the experience both challenging and enjoyable for players. +

+ +
+ +
+ +
+
+ + +
+ + +
+ + + +
+
+ +{% block scripts %} + + +{% endblock %} \ No newline at end of file diff --git a/html/Wormy.html b/html/Wormy.html new file mode 100644 index 0000000..a2d468b --- /dev/null +++ b/html/Wormy.html @@ -0,0 +1,91 @@ +--- +layout: layout.njk +title: Wormy +seo_title: "Wormy — 2D Puzzle Game (Unity)" +seo_description: "Wormy is a 2D puzzle game developed in Unity where players navigate tunnels to fertilise seeds. Features team level design and unique mechanics." +image: "Images/Project Screenshots/Wormy/Wormy (1).webp" +permalink: "{{ page.fileSlug }}.html" +--- + + +
+
+

Wormy

+
+
+ +
+
+

About the project

+

+ Wormy is a 2D puzzle game developed in Unity as part of a group assessment task. + It was our first opportunity to design a game based entirely on our own ideas. + The goal was to create a small digital game that met specific design constraints and thematic requirements. + In Wormy, you play as a worm navigating a maze of underground tunnels to fertilize and grow a seed. +

+

What I contributed

+

+ While the game was designed collaboratively, each team member was responsible for creating their own level, with + each level introducing a unique gameplay mechanic. + I designed the first level following the tutorial, which introduced the portal mechanic. +

+

What I learned

+

+ This project taught me how challenging it can be to maintain a cohesive game experience when multiple people + contribute different design styles. + Each of our levels felt very distinct, which sometimes disrupted the flow of the game. I also learned the value of + “finding the fun” during development. + Based on early playtester feedback, we significantly changed the player movement system from a traditional 2D + platformer to something that better suited our game's concept. +

+ + +
+ +
+
+ +
+ +
+
+ + +
+ + +
+ + + +
+
+ +{% block scripts %} + + +{% endblock %} \ No newline at end of file diff --git a/html/index.html b/html/index.html new file mode 100644 index 0000000..15ca482 --- /dev/null +++ b/html/index.html @@ -0,0 +1,151 @@ +--- +layout: layout.njk +title: Dylan Archer — Software Developer +seo_title: "Dylan Archer — Software Developer (Games, Web, Mobile)" +seo_description: "Full-stack web developer with a Games Development degree, building web, mobile and game projects. Checkout my work and links to GitHub and Itch.io." +permalink: "index.html" +--- +{% from "components/project-card.njk" import projectCard %} + +
+
+
+ Dylan Archer +

Dylan Archer

+

Software Developer - Games, Web, Mobile

+ +
+ +
+

About Me

+

+ Hi, I'm Dylan Archer, a full-stack web developer with a year of professional experience, backed by a + Bachelor of Science in Games Development with Distinction from UTS. +

+

+ My background in games gave me a strong foundation in problem-solving, performance, and user experience, + which I now bring to web, mobile, and software development, allowing me to build polished, reliable + products across a range of platforms. +

+
+ + +
+
+
+
+ +
+

Awards

+
    +
  • 2025 Dean's List (UTS Faculty of Engineering and Information Technology)
  • +
  • Nominated for UTS Tech Festival 2024 Student Games Showcase (Game Design Studio 1)
  • +
  • Nominated for UTS Tech Festival 2023 Student Games Showcase (Game Design Methodologies)
  • +
+
+ +
+
+

Projects

+
+ +
+

Game Development

+
+ {% for project in projects.games %} + {{ projectCard(project) }} + {% endfor %} +
+
+ +
+

Web Development

+
+ {% for project in projects.web %} + {{ projectCard(project) }} + {% endfor %} +
+
+ +
+

Mobile Development

+
+ {% for project in projects.mobile %} + {{ projectCard(project) }} + {% endfor %} +
+
+ +
+

3D Modelling & Animation

+
+ {% for project in projects.modelling %} + {{ projectCard(project) }} + {% endfor %} +
+
+ +
+

Other Projects

+
+ {% for project in projects.other %} + {{ projectCard(project) }} + {% endfor %} +
+
+
+ diff --git a/index.html b/index.html deleted file mode 100644 index d297aca..0000000 --- a/index.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - Dylan Archer Portfolio - - - - - - - - -
-
-
- -
- Dylan Archer -

Dylan Archer

-

Software Developer (Games, Web, Mobile)

-
- -
- -
- - -
-

About Me

-

- Hi, my name is Dylan Archer and I am a recent graduate of Bachelor of Games Development at UTS. -

-

- While I am passionate about making and playing games, my skill set also spans software, web, and mobile development, - allowing me to bring ideas to life across a range of platforms. -

-

- This portfolio showcases solo and group projects I have worked on. Take a look around, and feel free to get in touch if anything sparks your interest! -

- -
-
-
- - -

Awards

-
    -
  • 2025 Dean's List (UTS Faculty of Engineering and Information Technology)
  • -
  • Nominated for UTS Tech Festival 2024 Student Games Showcase (Game Design Studio 1)
  • -
  • Nominated for UTS Tech Festival 2023 Student Games Showcase (Game Design Methodologies)
  • -
- - -

Skills

-
-
-

Programming Languages

-
    -
  • C++
  • -
  • C#
  • -
  • Java
  • -
  • Python
  • -
  • Swift
  • -
  • JavaScript
  • -
  • PHP
  • -
  • MySQL
  • -
  • HTML, CSS
  • -
-
-
-

Project Management

-
    -
  • Git / GitHub
  • -
  • Trello
  • -
  • Jira
  • -
  • Confluence
  • -
-

Cloud & DevOps

-
    -
  • CI/CD with GitHub Actions
  • -
  • Cloud Deployment (AWS)
  • -
-
-
-

Game Development Tools

-
    -
  • Unity
  • -
  • Unreal Engine 5
  • -
  • Blender
  • -
-

Game Development Fields

-
    -
  • Gameplay Programming
  • -
  • Networking/Multiplayer
  • -
  • UI/UX Development
  • -
  • 3D Modelling
  • -
-
-
- -

Projects

- -

Game Development

-
- {% ProjectCard "DualWield.html", "Images/Project Screenshots/Dual Wield/Dual Wield Title Screen.png", "Dual Wield", "Images/Logos/Unity-Logo.png", "Images/Logos/CSharp.png", "", "Dual Wield is a first-person shooter developed over three months using the Unity Game Engine as part of a university group project. Players wield two firearms simultaneously, allowing up to 10 unique weapon combinations to tackle the enemies they encounter." %} - {% ProjectCard "Caved-In.html","Images/Project Screenshots/Caved In/Caved In Menu.png","Caved In","Images/Logos/UE5-Logo.png", "", "Images/Logos/C++.png","Caved In is a cooperative first-person survival extraction game, developed over three months in Unreal Engine as part of a university group project. Players must work together to collect samples and escape the cave, all while avoiding infection." %} - {% ProjectCard "PacStudent.html","Images/Project Screenshots/PacStudent/PacStudent1.png","PacStudent","Images/Logos/Unity-Logo.png","Images/Logos/CSharp.png", "", "PacStudent is a recreation of the classic 1980 game Pac-Man, developed as part of an introductory game development subject. This project served as a case study while I learned to navigate and utilise the Unity Game Engine for the first time." %} - {% ProjectCard "Wormy.html", "Images/Project Screenshots/Wormy/Wormy (1).png", "Wormy", "Images/Logos/Unity-Logo.png", "Images/Logos/CSharp.png", "", "Wormy is a 2D puzzle game developed in Unity as part of a group assessment task. It was our first opportunity to design a game based entirely on our own ideas. In Wormy, you play as a worm navigating a maze of underground tunnels to fertilize and grow a seed." %} - -
-
- -

Web Development

-
- {% ProjectCard "GroceryStore.html","Images/Project Screenshots/Grocery Store/Grocery Store (1).png","Online Grocery Store","Images/Logos/HTML.png","Images/Logos/CSS.png","", "I developed a fully functional Online Grocery Store as a solo project, utilising HTML, CSS, JavaScript, PHP, and SQL. The website features a user-friendly interface that allows customers to browse products, add items to their cart, and complete purchases seamlessly." %} - {% ProjectCard "CarRentalSystem.html","Images/Project Screenshots/Car Rental System/HomePage.png","Online Car Rental","Images/Logos/HTML.png","Images/Logos/CSS.png","", "I developed an interactive online car rental system as a solo project, using HTML, CSS, JavaScript, PHP, AJAX, and JSON. The platform allows users to browse and search cars by type or brand, check availability, and make or cancel rental reservations." %} - -
-
- -

Mobile Development

-
- {% ProjectCard "Quiz-App.html","Images/Project Screenshots/Quiz App/Quiz App.png","Quiz App","Images/Logos/swift.svg","Images/Logos/iOS-Logo.png","", "Quiz App is an iOS application developed over a few weeks as part of a group project using the SwiftUI framework. The app fetches quizzes on various topics via an API, providing users with a range of quiz options." %} - {% ProjectCard "OnTaskPro.html","Images/Project Screenshots/OnTaskPro/TaskTracker.png","Task Tracker App","Images/Logos/swift.svg","Images/Logos/iOS-Logo.png","", "OnTaskPro is an iOS app I developed as part of an individual assessment, where I was tasked with brainstorming, designing, and building an app to address a real-world problem for a specific target audience." %} - -
-
- -

3D Creative

-
- {% ProjectCard "Blender.html","Images/Project Screenshots/Blender/Blender Shot (1).png","3D Modelling Project","Images/Logos/Blender-Logo.png","","", "This personal project involved creating a detailed 3D model of a house using Blender to develop my modelling, UV unwrapping, texturing, lighting and rendering skills. I focused on achieving realism by using my own photographs and free textures sourced online." %} - {% ProjectCard "3DAnim.html","Images/Project Screenshots/Why are we here.webp","Unity 3D Animation","Images/Logos/Unity-Logo.png","","", "\"Why are we here?\" is a 3D animation satire on first-person shooters, heavily inspired by Halo and Red vs. Blue. It was developed over a few weeks in Unity using the HDRP rendering pipeline for a group project, where we used existing 3D models." %} - -
-
- -

Other Projects

-
- {% ProjectCard "ClashOfCommands.html","Images/Project Screenshots/Clash of Commands/ClashOfCommands1.png","Clash of Commands","Images/Logos/Unity-Logo.png","","", "Clash of Commands is an educational game that helps IT students learn UNIX terminal commands through gamification. I gained hands-on experience in serious game design, user-centered development, and iterative improvements based on feedback." %} - -
-
-
- - - \ No newline at end of file diff --git a/llms.txt b/llms.txt new file mode 100644 index 0000000..c374e21 --- /dev/null +++ b/llms.txt @@ -0,0 +1,42 @@ +# Dylan Archer + +> Full-stack software developer with a Bachelor of Science in Games Development (Distinction) from UTS. Builds games, web apps, and mobile apps, with one year of professional full-stack experience. + +Dylan's background in games development gives him a strong foundation in problem-solving, performance, and user experience, which carries over into web, mobile, and software projects. This site is a portfolio: an About section, awards, and a catalogue of projects grouped by discipline (games, web, mobile, 3D modelling/animation, other). + +## Pages + +- [About](https://dylan-archer-dev.com/index.html): Bio, awards, and the full project catalogue. + +## Game Development Projects + +- [Dual Wield](https://dylan-archer-dev.com/DualWield.html): Unity FPS built around dual-weapon combat and 10 weapon combinations. Unity, C#. +- [Caved In](https://dylan-archer-dev.com/Caved-In.html): Cooperative Unreal Engine extraction game about sampling, survival, and escape. Unreal, C++. +- [PacStudent](https://dylan-archer-dev.com/PacStudent.html): Unity recreation of Pac-Man built while learning core game systems. Unity, C#. +- [Wormy](https://dylan-archer-dev.com/Wormy.html): 2D Unity puzzle game about navigating tunnels to grow a seed. Unity, C#. +- [Snaked Together](https://dylan-archer-dev.com/Snaked-Together.html): Cooperative climbing game where two players share one snake body. Unity, C#. + +## Web Development Projects + +- [Online Grocery Store](https://dylan-archer-dev.com/GroceryStore.html): Full-stack grocery storefront with browsing, cart, and checkout. HTML/CSS, PHP, SQL. +- [Online Car Rental](https://dylan-archer-dev.com/CarRentalSystem.html): Car rental platform with filtering, availability checks, and bookings. HTML/CSS, PHP, AJAX. + +## Mobile Development Projects + +- [Quiz App](https://dylan-archer-dev.com/Quiz-App.html): SwiftUI iOS quiz app that fetches topic-based quizzes from an API. SwiftUI, iOS. +- [Task Tracker App (OnTaskPro)](https://dylan-archer-dev.com/OnTaskPro.html): iOS productivity app designed around a real user problem. SwiftUI, iOS. + +## 3D Modelling & Animation + +- [3D Modelling Project](https://dylan-archer-dev.com/Blender.html): Blender environment study focused on modelling, UVs, materials, and lighting. +- [Unity 3D Animation](https://dylan-archer-dev.com/3DAnim.html): Unity HDRP animation project inspired by FPS machinima comedy. + +## Other Projects + +- [Clash of Commands](https://dylan-archer-dev.com/ClashOfCommands.html): Serious game that teaches UNIX terminal commands through gamification. Unity. + +## Optional + +- [GitHub](https://www.github.com/Dylan-KA?tab=repositories): Source repositories. +- [Itch.io](https://dylanka.itch.io/): Playable game builds. +- [LinkedIn](https://www.linkedin.com/in/dylan-archer-44a783338): Professional profile. diff --git a/package.json b/package.json index bfdaf31..ccdb2f0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "version": "1.0.0", "main": "index.html", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "resume": "./resume/build-pdf.sh" }, "author": "", "license": "ISC", diff --git a/resume/README.txt b/resume/README.txt new file mode 100644 index 0000000..814889a --- /dev/null +++ b/resume/README.txt @@ -0,0 +1,17 @@ +Editing your resume +=================== + +1. Open resume.html in VS Code (or any text editor) and change the text. + Keep this folder structure: resume.html needs the fonts/ and img/ folders beside it. + +2. Open resume.html in Google Chrome to preview. Refresh after each save. + +3. Export to PDF: from the repo root run + + npm run resume (or ./resume/build-pdf.sh) + + This renders resume.html with headless Chrome and overwrites Resume.pdf + at the repo root. It warns if the result is more than 1 page; if so, + shorten some text or reduce spacing. + + This folder is listed in .eleventyignore, so it is not published to the site. diff --git a/resume/build-pdf.sh b/resume/build-pdf.sh new file mode 100755 index 0000000..736107b --- /dev/null +++ b/resume/build-pdf.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# Renders resume/resume.html to Resume.pdf at the repo root using headless Chrome. +# Usage: ./resume/build-pdf.sh (or: npm run resume) +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(dirname "$SCRIPT_DIR")" +INPUT="$SCRIPT_DIR/resume.html" +OUTPUT="$REPO_ROOT/Resume.pdf" + +find_chrome() { + if [[ -n "${CHROME:-}" ]]; then echo "$CHROME"; return; fi + local candidates=( + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" + "/Applications/Chromium.app/Contents/MacOS/Chromium" + "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge" + "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" + ) + for c in "${candidates[@]}"; do + [[ -x "$c" ]] && { echo "$c"; return; } + done + for c in google-chrome google-chrome-stable chromium chromium-browser; do + command -v "$c" >/dev/null 2>&1 && { command -v "$c"; return; } + done + echo "Chrome not found. Set CHROME=/path/to/chrome and retry." >&2 + exit 1 +} + +CHROME_BIN="$(find_chrome)" +TMP_DIR="$(mktemp -d)" +TMP_PDF="$TMP_DIR/Resume.pdf" +trap 'rm -rf "$TMP_DIR"' EXIT + +"$CHROME_BIN" \ + --headless \ + --disable-gpu \ + --no-pdf-header-footer \ + --virtual-time-budget=5000 \ + --print-to-pdf="$TMP_PDF" \ + "file://$INPUT" >/dev/null 2>&1 + +if [[ ! -s "$TMP_PDF" ]]; then + echo "PDF generation failed." >&2 + exit 1 +fi + +PAGES="$(grep -a -o "/Count [0-9]*" "$TMP_PDF" | head -1 | cut -d" " -f2 || true)" +mv "$TMP_PDF" "$OUTPUT" +echo "Wrote $OUTPUT (${PAGES} page(s))" +if [[ "$PAGES" != "1" ]]; then + echo "Warning: resume is not 1 page. Shorten text or reduce spacing." >&2 +fi diff --git a/resume/fonts/Inter-Bold.ttf b/resume/fonts/Inter-Bold.ttf new file mode 100644 index 0000000..15e908f Binary files /dev/null and b/resume/fonts/Inter-Bold.ttf differ diff --git a/resume/fonts/Inter-ExtraBold.ttf b/resume/fonts/Inter-ExtraBold.ttf new file mode 100644 index 0000000..c1449e8 Binary files /dev/null and b/resume/fonts/Inter-ExtraBold.ttf differ diff --git a/resume/fonts/Inter-Medium.ttf b/resume/fonts/Inter-Medium.ttf new file mode 100644 index 0000000..9342730 Binary files /dev/null and b/resume/fonts/Inter-Medium.ttf differ diff --git a/resume/fonts/Inter-Regular.ttf b/resume/fonts/Inter-Regular.ttf new file mode 100644 index 0000000..c544be4 Binary files /dev/null and b/resume/fonts/Inter-Regular.ttf differ diff --git a/resume/fonts/Inter-SemiBold.ttf b/resume/fonts/Inter-SemiBold.ttf new file mode 100644 index 0000000..a32e2b8 Binary files /dev/null and b/resume/fonts/Inter-SemiBold.ttf differ diff --git a/resume/img/profile.jpg b/resume/img/profile.jpg new file mode 100644 index 0000000..1e5b4f7 Binary files /dev/null and b/resume/img/profile.jpg differ diff --git a/resume/resume.html b/resume/resume.html new file mode 100644 index 0000000..bdd7374 --- /dev/null +++ b/resume/resume.html @@ -0,0 +1,296 @@ + + + + +Dylan Archer - Resume + + + +
+ +
+ Dylan Archer +
+

Dylan Archer

+
Software Developer (Games, Web, Mobile)
+ +
+
+ +
+ + +
+
+
Profile
+

+ Junior Full Stack Developer at a Sydney marketing agency, building and maintaining WordPress and Shopify websites alongside design and SEO teams. Games Development graduate (Distinction) from UTS, with a background across web, mobile and game development. I build sites that clients can update themselves, and use AI tools deliberately to work faster without cutting corners. Projects and case studies at dylan-archer-dev.com. +

+
+ +
+
Work Experience
+
+
+

Junior Full Stack DeveloperCOG Marketing

Aug 2025 - Present
+
    +
  • Build new WordPress websites and maintain and update existing client sites, working alongside the design and SEO teams.
  • +
  • Build and update Shopify stores for e-commerce clients.
  • +
  • Structure builds so non-technical clients and staff can update content themselves through the CMS, rather than relying on hard-coded changes that need a developer.
  • +
  • Provide managed IT support for clients, including email, domains and website hosting.
  • +
+
+
+

Community Tech Support AssistantYoungster.co

Mar 2025 - Aug 2025
+
    +
  • Provided personalised technology assistance to seniors, helping them navigate smartphones, tablets and computers.
  • +
+
+
+

Crew Member (Casual)McDonald's Menai

May 2020 - Aug 2025
+
    +
  • Prepared food orders efficiently in a fast-paced kitchen, consistently meeting quality and hygiene standards.
  • +
  • Supported team operations by maintaining cleanliness, restocking supplies and following food safety protocols.
  • +
+
+
+
+
+
AI-Assisted Development
+
    +
  • Use AI tools daily to speed up development, debugging and maintenance work across WordPress and Shopify projects.
  • +
  • Decide task by task when AI is the right tool, and when a job is faster or safer done by hand.
  • +
  • Manage context deliberately: breaking work into focused tasks and giving the model the right code, constraints and requirements to get reliable results.
  • +
  • Review and test AI-generated code before it ships, and stay responsible for the result.
  • +
+
+ + +
+
+
+ + diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..fe88622 --- /dev/null +++ b/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://dylan-archer-dev.com/sitemap.xml diff --git a/sitemap.njk b/sitemap.njk new file mode 100644 index 0000000..52a989e --- /dev/null +++ b/sitemap.njk @@ -0,0 +1,14 @@ +--- +permalink: sitemap.xml +eleventyExcludeFromCollections: true +--- + + +{%- for item in collections.all %} + {%- if item.url and (item.url == "/" or item.url.endsWith(".html")) %} + + {{ site.url }}{{ item.url }} + + {%- endif %} +{%- endfor %} + diff --git a/stylesheet.css b/stylesheet.css index 4adf5b0..f7de792 100644 --- a/stylesheet.css +++ b/stylesheet.css @@ -1,382 +1,1163 @@ -/* HTML5 Elements */ -* { box-sizing: border-box; } +/* HTML5 Elements & Base styles */ +:root { + color-scheme: dark; + --color-bg: #0f141b; + --color-surface: #161d27; + --color-surface-elevated: #1d2633; + --color-border: rgba(148, 163, 184, 0.22); + --color-text: #edf2f7; + --color-muted: #a8b3c2; + --color-accent: #38bdf8; + --color-accent-strong: #0ea5e9; + --color-button-text: #07111c; + --color-nav-bg: rgba(15, 20, 27, 0.9); + --color-hero-start: rgba(29, 38, 51, 0.94); + --color-hero-end: rgba(22, 29, 39, 0.84); + --color-award-bg: rgba(22, 29, 39, 0.72); + --color-card-bg: rgba(22, 29, 39, 0.92); + --color-chip-text: #c7eaff; + --color-chip-bg: rgba(56, 189, 248, 0.1); + --color-chip-border: rgba(56, 189, 248, 0.28); + --icon-filter: invert(1); + --shadow-soft: 0 14px 34px rgba(0, 0, 0, 0.2); + --shadow-glow: 0 12px 28px rgba(56, 189, 248, 0.08); + --radius: 8px; + --container: 1180px; +} + +@media (prefers-color-scheme: light) { + :root:not([data-theme]) { + color-scheme: light; + --color-bg: #f7f9fc; + --color-surface: #ffffff; + --color-surface-elevated: #ffffff; + --color-border: rgba(15, 23, 42, 0.14); + --color-text: #111827; + --color-muted: #4b5563; + --color-accent: #0284c7; + --color-accent-strong: #0369a1; + --color-button-text: #ffffff; + --color-nav-bg: rgba(247, 249, 252, 0.92); + --color-hero-start: rgba(255, 255, 255, 0.98); + --color-hero-end: rgba(232, 240, 248, 0.92); + --color-award-bg: rgba(255, 255, 255, 0.82); + --color-card-bg: rgba(255, 255, 255, 0.94); + --color-chip-text: #075985; + --color-chip-bg: rgba(2, 132, 199, 0.12); + --color-chip-border: rgba(2, 132, 199, 0.36); + --icon-filter: none; + --shadow-soft: 0 14px 34px rgba(15, 23, 42, 0.1); + --shadow-glow: 0 12px 28px rgba(2, 132, 199, 0.08); + } +} -html { background: #ffffff; } +:root[data-theme="light"] { + color-scheme: light; + --color-bg: #f7f9fc; + --color-surface: #ffffff; + --color-surface-elevated: #ffffff; + --color-border: rgba(15, 23, 42, 0.14); + --color-text: #111827; + --color-muted: #4b5563; + --color-accent: #0284c7; + --color-accent-strong: #0369a1; + --color-button-text: #ffffff; + --color-nav-bg: rgba(247, 249, 252, 0.92); + --color-hero-start: rgba(255, 255, 255, 0.98); + --color-hero-end: rgba(232, 240, 248, 0.92); + --color-award-bg: rgba(255, 255, 255, 0.82); + --color-card-bg: rgba(255, 255, 255, 0.94); + --color-chip-text: #075985; + --color-chip-bg: rgba(2, 132, 199, 0.12); + --color-chip-border: rgba(2, 132, 199, 0.36); + --icon-filter: none; + --shadow-soft: 0 14px 34px rgba(15, 23, 42, 0.1); + --shadow-glow: 0 12px 28px rgba(2, 132, 199, 0.08); +} + +:root[data-theme="dark"] { + color-scheme: dark; +} + +* { box-sizing: border-box; } + +html { + background: var(--color-bg); + scroll-behavior: smooth; + scroll-padding-top: 96px; +} body { margin: 0; - padding: 0px 50px 50px 50px; - max-width: 1500px; - margin: auto; - font-family: sans-serif; - background: #ffffff; + padding: 0; + color: var(--color-text); + font-family: "Inter", Arial, sans-serif; + background: linear-gradient(180deg, var(--color-surface) 0%, var(--color-bg) 42rem); } -footer { background: #ffffff; } +.site-shell { + width: min(var(--container), calc(100% - 40px)); + margin: 0 auto; +} -h1, h2, h3, h4, h5, h6 { - color: #000000; +.site-nav { + position: sticky; + top: 0; + z-index: 100; + display: grid; + grid-template-columns: auto 1fr auto; + align-items: center; + gap: 24px; + width: min(var(--container), calc(100% - 40px)); + margin: 0 auto; + padding: 14px 22px; + background: var(--color-nav-bg); + border: 1px solid var(--color-border); + border-top: 0; + border-radius: 0 0 var(--radius) var(--radius); + backdrop-filter: blur(16px); } -h1 { - font-size: 3rem; - font-weight: 600; - color: #1e5c84; +.site-mark { + color: var(--color-text); + font-weight: 800; + letter-spacing: 0; + text-decoration: none; } -h2 { - font-size: 1.7rem; - font-weight: 700; - margin-top: 60px; +.site-nav-links { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 18px; } -h3 { - font-size: 1rem; - font-weight: 600; +.site-nav a { + position: relative; + color: var(--color-muted); + font-size: 0.95rem; + font-weight: 700; + text-decoration: none; + transition: color 0.2s ease; } -p { line-height: 1.5; margin-bottom: 1rem; } -a { color: #000000; text-decoration: underline; } -ol { padding-left: 1.5rem; } -ul { padding-left: 1.5rem; } -li { margin-bottom: 0.5rem; } +.site-nav a:hover, +.site-nav a:focus-visible, +.site-nav a[aria-current="page"] { + color: var(--color-accent); +} -hr { +.site-nav-links > a::after, +.nav-dropdown-trigger::after { + content: ""; + position: absolute; + left: 0; + right: 0; + bottom: -6px; height: 2px; - border-width: 0; - background-color: #1e5c84; + background: var(--color-accent); + transform: scaleX(0); + transform-origin: left; + transition: transform 0.2s ease; } -button { - background-color: #2e2e2e; - color: white; - font-size: 1rem; - font-weight: 700; - border-style: none; - padding: 15px 90px; - margin: 10px; - cursor: pointer; - transition: transform 0.3s ease-in-out; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.35); +.site-nav-links > a:hover::after, +.site-nav-links > a:focus-visible::after, +.site-nav-links > a[aria-current="page"]::after, +.nav-dropdown:hover .nav-dropdown-trigger::after, +.nav-dropdown:focus-within .nav-dropdown-trigger::after { + transform: scaleX(1); } -button:hover { - background-color: #1e5c84; - transform: scale(1.05); - transition: filter 0.3s ease, transform 0.3s ease; +.nav-dropdown { + position: relative; + display: inline-flex; + align-items: center; + padding: 8px 0; } -.light { - background-color: white; - color: #2e2e2e; +.nav-dropdown-menu { + display: none; + position: absolute; + top: 100%; + left: 0; + min-width: 220px; + background: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + text-align: left; } -.red { - background-color: rgb(206, 73, 73); - color: #2e2e2e; - font-weight: 900; +.nav-dropdown:hover .nav-dropdown-menu, +.nav-dropdown:focus-within .nav-dropdown-menu { + display: block; } -.red:hover { - background-color: rgb(219, 0, 0); +.nav-dropdown-menu a { + padding: 12px 16px; + color: var(--color-muted); + transition: color 0.2s ease, background 0.2s ease; } -.medium { - padding: 15px 30px 15px 30px; - margin: 5px; +.nav-dropdown-menu .dropdown-sub { + position: relative; } -.small { - font-size: 0.9rem; - padding: 12px 24px 12px 24px; - margin: 5px; +.nav-dropdown-menu .dropdown-sub > a { + display: block; + padding: 12px 16px; + color: var(--color-muted); } -/* Dropdown */ -.dropdown { - position: relative; - display: inline-block; +.nav-dropdown-menu .dropdown-sub > a:hover, +.nav-dropdown-menu .dropdown-sub > a:focus-visible { + color: var(--color-text); + background: rgba(56, 189, 248, 0.12); } -.dropdown-content { +.nav-dropdown .dropdown-sub-content { display: none; position: absolute; - background-color: #2e2e2e; - width: 100%; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); - z-index: 1; + top: 0; + left: 100%; + min-width: 200px; + background: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + z-index: 100; } -.dropdown-content a { - color: #f9f9f9; +.nav-dropdown .dropdown-sub:hover .dropdown-sub-content, +.nav-dropdown .dropdown-sub:focus-within .dropdown-sub-content { + display: block; +} + +.nav-dropdown .dropdown-sub-content a { padding: 12px 16px; - text-decoration: none; + color: var(--color-muted); + font-weight: 400; display: block; } -.dropdown-content a:hover {background-color: #1e5c84} +.nav-dropdown .dropdown-sub-content a:hover, +.nav-dropdown .dropdown-sub-content a:focus-visible { + color: var(--color-text); + background: rgba(56, 189, 248, 0.12); +} -.dropdown:hover .dropdown-content { - display: block; +.nav-dropdown-menu a:hover, +.nav-dropdown-menu a:focus-visible { + color: var(--color-text); + background: rgba(56, 189, 248, 0.12); } -.centred-horizontally { - display: flex; - justify-content: center; +.theme-toggle { + display: inline-flex; + align-items: center; + gap: 8px; + margin: 0 0 0 2px; + padding: 6px 0; + color: var(--color-muted); + background: transparent; + border: 0; + box-shadow: none; +} + +.theme-toggle:hover { + color: var(--color-accent); + background: transparent; + box-shadow: none; + transform: none; +} + +.theme-toggle-track { + position: relative; + width: 42px; + height: 24px; + background: rgba(148, 163, 184, 0.24); + border: 1px solid var(--color-border); + border-radius: 999px; +} + +.theme-toggle-thumb { + position: absolute; + top: 3px; + left: 3px; + width: 16px; + height: 16px; + background: var(--color-accent); + border-radius: 999px; + transition: transform 0.2s ease; +} + +.theme-toggle[aria-pressed="true"] .theme-toggle-thumb { + transform: translateX(18px); +} + +.theme-toggle-label { + min-width: 34px; + font-size: 0.86rem; + font-weight: 800; +} + +.back-to-top { + position: fixed; + right: clamp(16px, 3vw, 28px); + bottom: clamp(16px, 3vw, 28px); + z-index: 90; + display: inline-grid; + place-items: center; + width: 42px; + height: 42px; + margin: 0; + padding: 0; + color: var(--color-button-text); + background: var(--color-accent); + border: 1px solid color-mix(in srgb, var(--color-accent) 70%, var(--color-border)); + border-radius: 999px; + box-shadow: var(--shadow-soft); + font-size: 1.2rem; + line-height: 1; + opacity: 0; + pointer-events: none; + transform: translateY(10px); + transition: opacity 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease; +} + +.back-to-top.is-visible { + opacity: 1; + pointer-events: auto; + transform: translateY(0); +} + +.back-to-top:hover, +.back-to-top:focus-visible { + background: var(--color-accent-strong); + transform: translateY(-2px); + box-shadow: var(--shadow-glow); +} + +footer { background: transparent; } + +h1, h2, h3, h4, h5, h6 { + color: var(--color-text); + line-height: 1.12; + letter-spacing: 0; +} + +h1 { font-size: clamp(2.4rem, 5vw, 4.25rem); font-weight: 800; } +h2 { font-size: clamp(1.45rem, 2.4vw, 2rem); font-weight: 800; margin: 0; } +h3 { font-size: 1.15rem; font-weight: 700; } + +p { + color: var(--color-muted); + line-height: 1.7; + margin-bottom: 1rem; +} + +a { + color: var(--color-accent); + text-decoration: none; +} + +a:hover { color: var(--color-text); } + +a:focus-visible, +button:focus-visible { + outline: 3px solid rgba(56, 189, 248, 0.45); + outline-offset: 3px; +} + +.content-section { + margin-top: 64px; +} + +.section-heading { + margin-bottom: 32px; +} + +.section-heading h2 { + font-size: clamp(2.4rem, 5vw, 4.25rem); + font-weight: 800; + margin: 0; +} + +.section-kicker { + margin: 0 0 10px; + color: var(--color-accent); + font-size: 0.82rem; + font-weight: 800; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.award-list { + display: grid; + gap: 12px; + margin: 20px 0 0; + padding: 0; + list-style: none; +} + +.award-list li { + padding: 16px 18px; + color: var(--color-muted); + background: var(--color-award-bg); + border: 1px solid var(--color-border); + border-radius: var(--radius); +} + +ol { padding-left: 1.5rem; } +ul { padding-left: 1.5rem; } +li { margin-bottom: 0.5rem; } + +hr { + height: 2px; + border-width: 0; + background-color: var(--color-accent); +} + +@media (max-width: 640px) { + html { + scroll-padding-top: 140px; + } + + .site-shell, + .site-nav { + width: min(100% - 28px, var(--container)); + padding: 0px; + } + + .site-nav { + grid-template-columns: 1fr auto; + gap: 8px 14px; + padding: 12px 14px; + } + + .site-nav-links { + grid-column: 1 / -1; + grid-row: 2; + justify-content: flex-start; + width: auto; + gap: 18px; + } + + .site-nav a { + font-size: 0.88rem; + } + + .site-mark { + grid-column: 1; + grid-row: 1; + } + + .theme-toggle { + grid-column: 2; + grid-row: 1; + justify-self: end; + } + + .theme-toggle-label { + display: none; + } + + .nav-dropdown { + padding: 0; + } + + .nav-dropdown-menu { + left: 50%; + right: auto; + min-width: min(230px, calc(100vw - 42px)); + transform: translateX(-50%); + } } /* Home Page Header */ +.home-hero { + position: relative; + z-index: 10; + padding-top: 16px; +} + .header-content { display: flex; justify-content: space-between; flex-wrap: wrap; + gap: 24px; margin: 0 auto; - margin-top: 50px; + padding: clamp(8px, 1.4vw, 18px); align-items: flex-start; - background-color: #eff0f5; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + background: linear-gradient(135deg, var(--color-hero-start), var(--color-hero-end)); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + overflow: visible; } .profile, .about { flex: 1; - margin: auto; - padding: 50px; + min-width: 300px; + margin: 0; + padding: clamp(28px, 5vw, 56px); } -.profile { - text-align: center; +@media (max-width: 459px) { + .header-content { + display: block; + } + .profile, .about { min-width: 0; padding: 26px; } + .about > div { grid-template-columns: 1fr !important; } } -.profile img { - width: 250px; - height: 250px; +/* Nav buttons: two equal columns on desktop, one column on mobile */ +.about > div { display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; gap: 12px; } +.about > div > .dropdown { display: block; min-width: 0; } +.about > div > .project-link-button { min-width: 0; } +.about .dropbtn, +.about .project-link-button { width: 100%; box-sizing: border-box; } + +.profile { text-align: center; } + +.profile-picture { + width: min(210px, 62%); + aspect-ratio: 1; object-fit: cover; + border: 3px solid color-mix(in srgb, var(--color-accent) 55%, transparent); + border-radius: 50%; + box-shadow: 0 18px 42px rgba(0, 0, 0, 0.28); +} + +.profile h1, +.about h2 { + margin: 24px 0 14px; +} + +.hero-role { + margin: 0 0 18px; + color: var(--color-accent); + font-size: 1.25rem; + font-weight: 700; +} + +.social-links { + gap: 6px !important; + display: flex; + justify-content: center; } .social-links img { - padding: 10px; width: 45px; height: 45px; + padding: 10px; + object-fit: contain; + background: color-mix(in srgb, var(--color-text) 8%, transparent); + border: 1px solid var(--color-border); + border-radius: 999px; cursor: pointer; -} + transition: transform 0.2s ease, border-color 0.2s ease, background 0.2s ease; +} -.social-links img { - transition: transform 0.3s ease-in-out; +.social-links a { + display: inline-flex; } .social-links img:hover { - filter: invert(100%) grayscale(100%) brightness(30%); - transition: filter 0.3s ease, transform 0.3s ease; - transform: scale(1.2); + background: color-mix(in srgb, var(--color-accent) 16%, transparent); + border-color: color-mix(in srgb, var(--color-accent) 55%, transparent); + transform: translateY(-3px); } -.about p { - font-size: 1.2rem; +.about p { font-size: 1.08rem; } +.about div { text-align: center; } +.about .dropdown-content { text-align: left; } + +/* Buttons */ +button { + background-color: var(--color-accent); + color: var(--color-button-text); + font-size: 1rem; + font-weight: 700; + border: 1px solid rgba(56, 189, 248, 0.45); + border-radius: var(--radius); + padding: 13px 28px; + cursor: pointer; + transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease; + box-shadow: 0 8px 18px rgba(56, 189, 248, 0.08); + white-space: normal; + word-break: break-word; + min-width: 0; } -.about div { - text-align: center; +button:hover { + background-color: #7dd3fc; + transform: translateY(-2px); + box-shadow: var(--shadow-glow); } -/* Skills */ -.skills-container { - display: flex; - flex-wrap: wrap; - gap: 20px; +.light { + background-color: var(--color-text); + color: var(--color-bg); } -.skill-column { - flex: 1; - min-width: 200px; +.red { + background-color: rgb(206, 73, 73); + color: #2e2e2e; + font-weight: 900; } -/* Project Cards */ -.project-container { - display: flex; +.red:hover { + background-color: rgb(219, 0, 0); +} + +.medium { + padding: 13px 22px; + margin: 5px; +} + +.small { + font-size: 0.9rem; + padding: 12px 24px 12px 24px; + margin: 5px; +} + +.project-link-button { + display: inline-flex; + align-items: center; + gap: 0.55rem; flex-wrap: wrap; - gap: 1.3rem; + justify-content: center; + white-space: normal; + word-break: break-word; + min-width: 0; } -.project-item-outer { - flex: 1 1 calc(33.333% - 1rem); /* 3 columns */ - box-sizing: border-box; - transition: transform 0.2s ease-in-out; - border-radius: 10px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); +.back-to-top { + position: fixed; + right: 24px; + bottom: 24px; + display: inline-flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + margin: 0; + padding: 0; + border-radius: 50%; + border: 1px solid var(--color-border); + background: var(--color-surface-elevated); + color: var(--color-text); + box-shadow: var(--shadow-soft); + opacity: 0; + visibility: hidden; + transform: translateY(12px); + transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s ease, background 0.2s ease; + z-index: 999; } -.project-item-outer:hover { - transform: scale(1.03); +.back-to-top.is-visible { + opacity: 1; + visibility: visible; + transform: translateY(0); } -.project-item-outer:hover .project-item-inner { - background-color: #d6defa; +.back-to-top:hover, +.back-to-top:focus-visible { + background: var(--color-accent); + color: var(--color-button-text); + border-color: rgba(56, 189, 248, 0.45); } -@media (max-width: 900px) { - .project-item-outer { - flex: 1 1 calc(50% - 1rem); /* 2 columns on medium screens */ - } +.back-to-top i { + font-size: 1rem; } -@media (max-width: 600px) { - .project-item-outer { - flex: 1 1 100%; /* 1 column on small screens */ - } +/* Dropdown */ +.dropdown { position: relative; display: inline-block; } + +.dropdown-content { + display: none; + position: absolute; + top: 100%; + min-width: 220px; + background-color: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + z-index: 20; + overflow: visible; + text-align: left; +} + +.dropdown-content a { + color: var(--color-muted); + text-align: left; + padding: 12px 16px; + text-decoration: none; + display: block; + font-weight: 700; + transition: color 0.2s ease, background 0.2s ease; } -.project-item-outer a { - vertical-align: top; +.dropdown-content a:hover { + color: var(--color-text); + background-color: rgba(56, 189, 248, 0.12); } -.project-item-outer a img{ +.dropdown:hover .dropdown-content, +.dropdown:focus-within .dropdown-content { display: block; } + +.dropdown-sub { position: relative; } + +.dropdown-sub-content { + display: none; + position: absolute; + left: 100%; + top: 0; + min-width: 240px; + background-color: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + z-index: 1; +} + +.dropdown-sub:hover .dropdown-sub-content, +.dropdown-sub:focus-within .dropdown-sub-content { display: block; - max-width: 100%; - height: auto; } -.project-item-inner { - height: 260px; - padding: 20px; +.dropdown-sub-content a { + color: var(--color-muted); + padding: 12px 16px; + text-decoration: none; + display: block; +} + +.dropdown-sub-content a:hover, +.dropdown-sub-content a:focus-visible { + color: var(--color-text); + background-color: rgba(56, 189, 248, 0.12); +} + +/* Skills */ +.skills-container { display: flex; flex-wrap: wrap; gap: 20px; } +.skill-column { flex: 1; min-width: 200px; } + +/* Project Cards */ +.project-group { + margin-top: 48px; +} + +.project-group h2 { + margin-bottom: 22px; +} + +.project-container { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 28px; +} + +.project-card { display: flex; flex-direction: column; - justify-content: flex-start; + min-height: 100%; overflow: hidden; - background-color: #eff0f5; + background: var(--color-card-bg); + border: 1px solid var(--color-border); + border-radius: var(--radius); + box-shadow: 0 10px 24px rgba(0, 0, 0, 0.14); + transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease; } -.project-title a { - font-weight: 700; - font-size: 1.5rem; - text-decoration: none; +.project-card:hover, +.project-card:focus-within { + border-color: color-mix(in srgb, var(--color-accent) 34%, var(--color-border)); + box-shadow: 0 12px 28px rgba(0, 0, 0, 0.18); + transform: translateY(-3px) scale(1.01); } -.project-item-inner p { +.project-card-media { + display: block; + aspect-ratio: 16 / 9; overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 6; - line-clamp: 6; - -webkit-box-orient: vertical; - margin: 0; + background: #0b1017; } -.project-learn-more { - margin-top: auto; /* Push the "Learn More" link to the bottom */ - font-weight: 700; +.project-card-media img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.35s ease; } -.project-filler { - flex: 1 1 calc(33.333% - 1rem); /* 3 columns */ - box-sizing: border-box; +.project-card:hover .project-card-media img { + transform: scale(1.05); } -/* Contact Page */ -.contact-page-container { +.project-card-body { display: flex; - flex-wrap: nowrap; - align-items: stretch; - justify-content: center; + flex: 1; + flex-direction: column; + gap: 16px; + padding: 24px; } -.contact-page-item { - padding: 14px; - text-align: left; - box-sizing: border-box; - flex: 1; +.project-card-heading { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; } -.contact-page-item img{ - border-radius: 10px; - width: 100%; +.project-title { + margin: 0; + font-size: 1.2rem; } -.contact-page-item p, -.contact-page-item a { - margin-top: 13px; - margin-bottom: 13px; - display: inline-block; +.project-title a { + color: var(--color-text); + font-weight: 800; + text-decoration: none; + transition: color 0.2s ease; } -.contact-left-column { - flex: 0 1 calc(10% - 20px); +.project-title a:hover, +.project-title a:focus-visible { + color: var(--color-accent); +} + +.project-card-logos { display: flex; - flex-direction: column; - width: 100%; + flex: 0 0 auto; + gap: 6px; +} + +.project-card-logos img { + width: 28px; + height: 28px; + object-fit: contain; + padding: 4px; + background: rgba(237, 242, 247, 0.08); + border: 1px solid var(--color-border); + border-radius: 7px; +} + +.project-summary { + min-height: 3.4em; + margin: 0; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; + line-clamp: 2; + -webkit-box-orient: vertical; } -.contact-right-column { - flex: 0 1 calc(90% - 20px); +.project-tags { display: flex; - flex-direction: column; - width: 100%; + flex-wrap: wrap; + gap: 8px; + margin-top: auto; +} + +.project-tags span { + display: inline-flex; + align-items: center; + min-height: 28px; + padding: 5px 10px; + color: var(--color-chip-text); + font-size: 0.78rem; + font-weight: 800; + background: var(--color-chip-bg); + border: 1px solid var(--color-chip-border); + border-radius: 999px; +} + +.project-learn-more { + align-self: flex-start; + margin-top: 2px; + color: var(--color-accent); + font-weight: 800; + text-decoration: none; +} + +.project-learn-more i { + margin-left: 6px; + transition: transform 0.2s ease; +} + +.project-learn-more:hover i, +.project-learn-more:focus-visible i { + transform: translateX(2px); +} + +@media (max-width: 980px) { + .project-container { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 640px) { + .project-container { + grid-template-columns: 1fr; + gap: 22px; + } + + .project-card-body { + padding: 20px; + } } /* Project Page */ .project-page-container { display: flex; flex-direction: row; - gap: 100px; + gap: clamp(32px, 4vw, 64px); padding-top: 30px; + align-items: flex-start; +} + +@media (max-width: 900px) { + .right-column { + gap: 18px; + } +} + +@media (max-width: 459px) { + .project-page-container { flex-direction: column; gap: 30px; } +} + +.project-page-container > .left-column, +.project-page-container > .right-column { + min-width: 0; } .left-column { flex: 1; + min-width: 0; +} + +.left-column iframe, +.left-column img, +.left-column video { + width: 100%; + max-width: 100%; + height: auto; } .right-column { flex: 1; display: flex; flex-direction: column; - gap: 0px; + gap: 10px; } .right-column img, .right-column iframe, -.right-column video{ +.right-column video { width: 100%; aspect-ratio: 16 / 9; height: auto; border: 0px; - border-radius: 10px; - margin: 10px; + border-radius: var(--radius); + margin: 10px 0; +} + +footer { + margin-top: 60px; + padding: 40px 0; + background-color: transparent; + border-top: 1px solid var(--color-border); + text-align: center; +} + +.footer-content { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.footer-content p { + color: var(--color-muted); + margin-bottom: 15px; + font-size: 0.9rem; +} + +.footer-icons { + display: flex; + gap: 25px; + /* Space between icons */ + justify-content: center; + align-items: center; +} + +.footer-icons a { + text-decoration: none !important; + border: none; + display: block; + transition: transform 0.2s ease, opacity 0.2s ease; + opacity: 0.82; +} + +.footer-icons a:hover { + transform: translateY(-3px); + opacity: 1; +} + +.footer-icons img { + width: 30px; + height: auto; + display: block; + filter: var(--icon-filter); +} + +/* Utilities */ + +/* Carousel and image viewer */ +.carousel-container { + position: relative; + background: var(--color-surface-elevated); + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: 16px; + box-shadow: var(--shadow-soft); +} + +.carousel-slide { + display: none; + width: 100%; + height: auto; + border-radius: var(--radius); + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04); +} + +.carousel-slide:hover, +#FullImage:hover { + transform: scale(1.002); } -/* Dot styling */ .dot-container { text-align: center; - padding: 10px 0; + padding: 14px 0 0; } .dot { display: inline-block; - height: 12px; - width: 12px; - margin: 0 4px; - border-radius: 50%; - background-color: #bbb; + height: 11px; + width: 11px; + margin: 0 5px; + border-radius: 999px; + background-color: rgba(148, 163, 184, 0.4); cursor: pointer; + transition: transform 0.2s ease, background-color 0.2s ease; } -.active { - background-color: #717171; +.dot:hover, +.dot:focus-visible { + transform: scale(1.15); + background-color: rgba(56, 189, 248, 0.8); +} + +.dot.active { + background-color: var(--color-accent); +} + +.carousel-nav { + display: flex; + justify-content: center; + gap: 10px; + flex-wrap: wrap; + margin-top: 14px; +} + +.carousel-button, +.overlay-button { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 46px; + min-height: 46px; + padding: 0.8rem; + border-radius: 999px; + border: 1px solid var(--color-border); + background: var(--color-surface-elevated); + color: var(--color-text); + transition: transform 0.2s ease, border-color 0.2s ease, background-color 0.2s ease; + cursor: pointer; +} + +.carousel-button:hover, +.carousel-button:focus-visible, +.overlay-button:hover, +.overlay-button:focus-visible { + transform: translateY(-1px); + border-color: var(--color-accent); + background: rgba(56, 189, 248, 0.15); +} + +.overlay-button i, +.carousel-button i { + font-size: 1rem; } -/* Fullscreen Image */ #FullImageView { display: none; position: fixed; + inset: 0; z-index: 9999; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.8); + background: rgba(0, 0, 0, 0.9); + backdrop-filter: blur(6px); + padding: 30px 16px; + overflow: auto; text-align: center; } +#FullImageView::before { + content: ""; + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.75)); + z-index: 1; +} + #FullImage { - margin-top: 100px; - max-width: 70%; - text-align: center; -} \ No newline at end of file + position: relative; + z-index: 2; + max-width: min(100%, 1440px); + max-height: 82vh; + width: auto; + height: auto; + margin: auto; + border-radius: var(--radius); + box-shadow: var(--shadow-soft); + cursor: zoom-out; +} + +.fullscreen-controls { + position: absolute; + z-index: 2; + left: 50%; + bottom: 30px; + transform: translateX(-50%); + display: flex; + gap: 12px; + align-items: center; + justify-content: center; + flex-wrap: wrap; +} + +.overlay-button.close-button { + background: rgba(206, 73, 73, 0.95); + border-color: rgba(255, 80, 80, 0.35); + color: #fff; +} + +.overlay-button.close-button:hover, +.overlay-button.close-button:focus-visible { + background: rgb(219, 0, 0); +}