Skip to content

Commit

Permalink
..
Browse files Browse the repository at this point in the history
  • Loading branch information
donPuerto committed Oct 8, 2024
1 parent 648d96a commit 20e4ecd
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 28 deletions.
4 changes: 0 additions & 4 deletions components/blog/Render.vue
Original file line number Diff line number Diff line change
Expand Up @@ -543,10 +543,6 @@ const handleVideoStateChange = (event: MessageEvent) => {
filter: grayscale(100%);
}
.hover\:grayscale-0:hover {
filter: grayscale(0%);
}
.transition-all {
transition: all 0.3s ease;
}
Expand Down
57 changes: 57 additions & 0 deletions content/projects/portfolio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: "Don Puerto - Full Stack Developer Portfolio"
description: Showcasing over a decade of experience in full-stack development
tags:
- Nuxt
- Vue
- Vercel
production_url: "https://my-portfolio-nu-nine-54.vercel.app/"
repository_url: "https://github.com/donPuerto/nuxt3-content2-tailwind-portfolio"
image: "/content/projects/portfolio.png"
icon: mdi:briefcase
---

#### What is Portfolio? 👨‍💻

This portfolio is a comprehensive showcase of my journey as a full-stack developer. It highlights my skills, experience, and projects accumulated over more than a decade in the tech industry. As Don Puerto, I've dedicated my career to turning complex problems into elegant solutions, armed with a BS in Computer Engineering and a passion for continuous learning and innovation.

#### Why Did You Build It? 🎯

I created this portfolio with several key objectives in mind:

1. **Showcase Expertise**: To demonstrate my proficiency in various technologies and my ability to handle complex projects.
2. **Career Progression**: To illustrate my growth from a backend support role to a full-stack developer.
3. **Project Highlights**: To feature significant projects, like the CRM system for Revival Group, showcasing real-world problem-solving.
4. **Skill Presentation**: To present my diverse skill set, spanning frontend, backend, mobile development, and database management.
5. **Professional Networking**: To connect with like-minded professionals and potential collaborators in the tech industry.

#### How Did You Build It? 🛠️

This portfolio was built using Nuxt.js, a powerful Vue.js framework. Here's an overview of the development process:

1. **Nuxt.js Setup**: Initialized a new Nuxt project, leveraging its built-in features for server-side rendering and optimized performance.

2. **Content Management**: Utilized Nuxt Content module to manage markdown files, making it easy to update portfolio information.

3. **Responsive Design**: Implemented a mobile-first approach using Tailwind CSS for a sleek, responsive layout.

4. **Dynamic Routing**: Took advantage of Nuxt's file-based routing system to create dynamic project pages.

5. **SEO Optimization**: Used Nuxt's head management to ensure each page is optimized for search engines.

6. **Performance Tuning**: Employed Nuxt's automatic code splitting and lazy loading for optimal load times.

7. **Deployment**: Set up continuous deployment using Netlify or Vercel, connected to the GitHub repository.

The use of Nuxt.js allowed for a smooth development process, resulting in a fast, SEO-friendly, and easily maintainable portfolio site.

### What Tools Did You Use? 🧰

- **Framework**: `Nuxt.js` 🚀 - For server-side rendering and enhanced performance
- **UI Library**: `Vue.js` 💚 - The progressive JavaScript framework
- **Styling**: `Tailwind CSS` 🎨 - For rapid UI development
- **Content Management**: `Nuxt Content` 📝 - For easy management of markdown files
- **Version Control**: `Git` 🔄 - For source code management
- **Deployment**: `Vercel` 🌐 - For seamless deployment and hosting

This tech stack ensures a modern, performant, and easily maintainable portfolio that showcases my skills effectively.
1 change: 1 addition & 0 deletions content/projects/revivalgroup.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ tags:
production_url: "https://github.com/BayBreezy/ui-thing"
repository_url: "https://github.com/BayBreezy/ui-thing"
image: "/content/projects/revivalgroup.png"
icon: icon-park-outline:push-door
---

## What is Revival Group? 🔨
Expand Down
5 changes: 3 additions & 2 deletions pages/about.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ const closingText = ref('In the vast realm of technology, I see a divine opportu
</script>

<template>
<div class="container mx-auto px-5 sm:px-6 lg:px-8 py-8 max-w-[912px]">
<div class="container mx-auto px-5 sm:px-6 lg:px-8 max-w-[912px]">
<div class="bg-background bg-opacity-80 p-8 rounded-lg">
<h1 class="text-2xl font-bold mb-4 text-foreground text-center">
<h1 class="text-xl font-bold my-4 text-foreground text-center flex items-center justify-center">
<Icon name="uil:user" class="h-6 w-6 text-primary mr-2" />
About Me
</h1>

Expand Down
4 changes: 2 additions & 2 deletions pages/blog/tag/[tag].vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ function changePage(page: number) {
</div>
<div class="p-4 flex flex-col flex-grow">
<NuxtLink :to="post._path" class="hover:text-primary transition-colors">
<h2 class="text-sm sm:text-base font-bold line-clamp-2 text-justify mb-2">
<h2 class="text-sm sm:text-base font-bold line-clamp-2 text-justify">
{{ post.title }}
</h2>
</NuxtLink>
<p class="text-xs sm:text-sm text-gray-500 mb-2">
<p class="text-xs text-gray-500 mt-1 mb-2">
Published at {{ new Date(post.published_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) }}
</p>
<p v-if="post.description" class="text-xs sm:text-sm text-gray-600 line-clamp-3 mb-4">
Expand Down
84 changes: 67 additions & 17 deletions pages/projects/[slug].vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
<script setup lang="ts">
const route = useRoute();
const { data: project } = await useAsyncData(`project-${route.params.slug}`, () => queryContent(`/projects/${route.params.slug}`).findOne());
// Add error handling
if (!project.value) {
throw createError({ statusCode: 404, message: 'Project not found' });
}
// Custom directive to style list items
const vStyleListItems = {
mounted: (el: HTMLElement) => {
const listItems = el.querySelectorAll('li');
listItems.forEach(li => {
const strong = li.querySelector('strong');
if (strong) {
const text = li.innerHTML.split(strong.outerHTML)[1];
li.innerHTML = `${strong.outerHTML}<span class="text-muted-foreground">${text}</span>`;
}
});
},
};
</script>

<template>
<div v-if="project" class="container mx-auto px-5 sm:px-6 lg:px-8 py-8">
<div class="mb-3 text-lg sm:text-xl md:text-2xl font-bold">
<div class="mb-3 text-sm sm:text-base md:text-lg lg:text-xl font-bold">
<NuxtLink to="/projects" class="hover:underline hover:scale-105 transition-transform duration-300 inline-block">Projects</NuxtLink>
<span class="text-gray-500 mx-2">&gt;</span>
<span>{{ project.title }}</span>
Expand Down Expand Up @@ -44,43 +64,73 @@ const { data: project } = await useAsyncData(`project-${route.params.slug}`, ()
:href="project.repository_url"
target="_blank"
rel="noopener noreferrer"
class="text-foreground hover:text-primary transition-colors duration-300 ease-in-out transform hover:scale-110"
class="bg-secondary text-secondary-foreground rounded-full p-1.5 hover:bg-primary hover:text-primary-foreground transition-colors duration-300 ease-in-out transform hover:scale-110 flex items-center justify-center w-8 h-8"
>
<Icon name="mdi:github" size="20" />
<Icon name="line-md:github" size="18" />
</a>
<a
v-if="project.production_url"
:href="project.production_url"
target="_blank"
rel="noopener noreferrer"
class="text-green-500 hover:text-green-400 transition-colors duration-300 ease-in-out transform hover:scale-110"
class="bg-secondary text-secondary-foreground rounded-full p-1.5 hover:bg-primary hover:text-primary-foreground transition-colors duration-300 ease-in-out transform hover:scale-110 flex items-center justify-center w-8 h-8"
>
<Icon name="mdi:link" size="20" />
<Icon name="line-md:external-link" size="18" />
</a>
<span v-if="!project.repository_url && !project.production_url" class="text-muted-foreground italic text-sm">
No external links available
</span>
</div>
</div>

<div class="prose prose-invert max-w-none">
<div v-style-list-items class="project-content max-w-none">
<ContentRenderer :value="project" />
</div>
</div>
<div v-else>Loading...</div>
</template>

<style scoped lang="postcss">
.prose h2 {
@apply text-2xl font-bold mb-4 mt-8;
}
.prose p {
@apply mb-4;
}
.prose a {
@apply text-green-500 hover:underline;
}
.prose blockquote {
@apply border-l-4 border-gray-600 pl-4 italic;
.project-content {
@apply text-foreground text-sm sm:text-base max-w-none;
:deep(h1), :deep(h2), :deep(h3), :deep(h4), :deep(h5), :deep(h6) {
@apply text-foreground font-bold mb-4 mt-6;
}
:deep(h1) { @apply text-xl sm:text-2xl md:text-3xl lg:text-4xl; }
:deep(h2) { @apply text-lg sm:text-xl md:text-2xl lg:text-3xl; }
:deep(h3) { @apply text-base sm:text-lg md:text-xl lg:text-2xl; }
:deep(h4) { @apply text-sm sm:text-base md:text-lg lg:text-xl; }
:deep(h5) { @apply text-sm sm:text-sm md:text-base lg:text-lg; }
:deep(h6) { @apply text-xs sm:text-sm md:text-sm lg:text-base; }
:deep(a) {
@apply text-primary hover:text-primary/80 transition-colors duration-200;
}
:deep(ul), :deep(ol) {
@apply pl-10 mb-4;
}
:deep(ul) {
@apply list-disc;
}
:deep(ol) {
@apply list-decimal;
}
:deep(li) {
@apply mb-2;
line-height: 1.2;
padding-left: 0.5em;
}
:deep(li::marker) {
@apply text-primary;
}
:deep(p) {
@apply mb-5 leading-relaxed;
text-align: justify;
line-height: 1.2;
}
}
</style>
17 changes: 14 additions & 3 deletions pages/projects/index.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
<script setup lang="ts">
const { data: projects } = await useAsyncData('projects', () => queryContent('/projects').find());
// Ensure all projects have an icon
if (projects.value) {
projects.value = projects.value.map(project => ({
...project,
icon: project.icon || 'uil:file-alt', // Fallback icon if none is specified
}));
}
</script>

<template>
<div class="container mx-auto px-5 sm:px-6 lg:px-8 py-8">
<div class="mb-8">
<h1 class="text-lg sm:text-xl md:text-2xl font-bold mb-1">Projects</h1>
<p class="text-md sm:text-lg text-muted-foreground">Explore our innovative solutions</p>
<h1 class="text-md sm:text-lg md:text-xl font-bold flex items-center">
<Icon name="uil:apps" class="h-6 w-6 text-primary mr-2" />
Projects
</h1>
<p class="text-sm sm:text-lg text-muted-foreground mt-1">Explore our innovative solutions</p>
</div>

<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
Expand All @@ -17,7 +28,7 @@ const { data: projects } = await useAsyncData('projects', () => queryContent('/p
class="bg-card rounded-lg p-4 sm:p-6 flex items-center space-x-6 hover:bg-accent transition-colors border border-border hover:border-primary"
>
<div class="bg-muted rounded-lg w-10 h-10 sm:w-12 sm:h-12 flex items-center justify-center flex-shrink-0">
<Icon name="icon-park-outline:push-door" class="w-5 h-5 sm:w-6 sm:h-6" />
<Icon :name="project.icon || 'uil:file-alt'" class="w-5 h-5 sm:w-6 sm:h-6" />
</div>
<div class="flex-grow overflow-hidden">
<h2 class="text-sm sm:text-base md:text-lg font-semibold mb-1 truncate">{{ project.title }}</h2>
Expand Down
Binary file added public/content/projects/portfolio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 20e4ecd

Please sign in to comment.