Skip to content

Commit 7fd85f7

Browse files
authored
Merge pull request #2 from jedabero/refactor-2
Refactor 2
2 parents 552a9c9 + c8bf8c9 commit 7fd85f7

36 files changed

+7208
-329
lines changed

.github/workflows/pages.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Pages deploy (prod & preview)
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
workflow_dispatch: {}
8+
9+
concurrency:
10+
group: pages-deploy
11+
cancel-in-progress: true
12+
13+
env:
14+
NEXT_TELEMETRY_DISABLED: 1
15+
16+
jobs:
17+
build-and-deploy:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Setup Node
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: 20
27+
cache: npm
28+
29+
- name: Install dependencies (include dev)
30+
run: npm install --include=dev
31+
32+
- name: Build static export
33+
run: |
34+
unset NEXT_BASE_PATH
35+
unset NEXT_ASSET_PREFIX
36+
NODE_ENV=production npm run export
37+
38+
- name: Deploy to gh-pages
39+
uses: peaceiris/actions-gh-pages@v4
40+
with:
41+
github_token: ${{ secrets.GITHUB_TOKEN }}
42+
publish_branch: gh-pages
43+
publish_dir: ./out
44+
keep_files: false
45+
destination_dir: .
46+
user_name: github-actions[bot]
47+
user_email: github-actions[bot]@users.noreply.github.com
48+
commit_message: "deploy: ${{ github.ref_name }}"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules/
2+
.next/
3+
out/

AGENTS.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
### ROL
2+
3+
Actúa como un **Senior Frontend Architect y UI/UX Strategist** especializado en modernización de sistemas legacy. Eres experto en el ecosistema React (Next.js/Vite), Tailwind CSS y Shadcn UI, así como en patrones de migración desde Angular.
4+
5+
### CONTEXTO
6+
7+
Actualmente tengo un portafolio estático construido en **Angular + Bootstrap** alojado en GitHub Pages.
8+
**Mi Objetivo:** Migrar completamente este proyecto a un stack moderno usando **React + Tailwind CSS + Shadcn UI**.
9+
**Mi Perfil:** Soy desarrollador Full Stack (NodeJS, Express/NestJS, PostgreSQL), pero quiero que este portafolio siga siendo una solución estática/ligera (sin backend dedicado para el sitio en sí) para mantener la eficiencia y bajo costo.
10+
11+
### TAREA
12+
13+
Analiza el código Angular proporcionado y guía el proceso de refactorización y rediseño en 3 fases:
14+
15+
#### FASE 1: Estrategia de Migración (Angular -> React)
16+
17+
Analiza la estructura de mis componentes y servicios en Angular y propón su equivalencia en React:
18+
19+
1. **Mapeo de Componentes:** Identifica qué componentes de Angular pueden fusionarse o dividirse al pasar a React (Functional Components + Hooks).
20+
2. **Routing:** Cómo traducir mi configuración de rutas actual a `react-router` o al App Router de Next.js (si recomiendas Next.js para SSG).
21+
3. **Gestión de Estado:** Si ves complejidad innecesaria en Angular, sugiere cómo simplificarla con React Context o Zustand, o simplemente props.
22+
23+
#### FASE 2: Modernización de UI (Bootstrap -> Tailwind/Shadcn)
24+
25+
No quiero una traducción literal del diseño. Propón un "Look & Feel" moderno:
26+
27+
1. **Reemplazo de Bootstrap:** Identifica los elementos de Bootstrap (Grid, Modals, Navbars) y dime qué componentes exactos de **Shadcn UI** debo usar para reemplazarlos.
28+
2. **Estilizado:** Sugiere una paleta de colores y tipografía que combine profesionalismo con modernidad, aprovechando las utilidades de Tailwind.
29+
3. **Showcase de Backend:** Dado que soy experto en Backend (Node/Postgres), sugiere cómo puedo representar visualmente estas habilidades en el frontend (ej. ¿debería incluir diagramas de arquitectura de mis proyectos en lugar de solo capturas de pantalla?).
30+
31+
#### FASE 3: Validación de Contenido y Datos
32+
33+
ANTES de generar código final, realiza una entrevista de validación. Hazme preguntas para actualizar la data:
34+
35+
- Pregunta sobre proyectos recientes en Node/NestJS que no estén en el portafolio antiguo.
36+
- Pregunta qué secciones del portafolio actual ya no me representan y deberíamos eliminar.
37+
- Pregunta sobre mis preferencias de estructura de carpetas para el nuevo proyecto React (ej. Feature-based vs Type-based).
38+
39+
### FORMATO DE SALIDA
40+
41+
- Usa **Markdown** con jerarquía clara.
42+
- En las sugerencias de código, usa comentarios para explicar _por qué_ este enfoque de React es mejor que el original de Angular.
43+
- Piensa paso a paso: Primero analiza la arquitectura, luego el diseño visual, y finalmente el contenido.

README.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
11
# [jedabero.github.io](http://jedabero.github.io)
22

33
This is my github presentation page.
4-
5-
#TODO:
6-
- Add a list of the projects I'm working on which code is hosted on github.
7-
- About me
8-
- Random stuff

app/globals.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
4+
5+
:root {
6+
color-scheme: dark;
7+
--page-bg: radial-gradient(circle at 20% 20%, rgba(95, 227, 192, 0.08), transparent 35%),
8+
radial-gradient(circle at 80% 20%, rgba(122, 162, 255, 0.08), transparent 35%),
9+
radial-gradient(circle at 50% 80%, rgba(95, 227, 192, 0.06), transparent 35%);
10+
}
11+
12+
body {
13+
min-height: 100vh;
14+
background-color: #0b1021;
15+
background-image: var(--page-bg, none);
16+
color: #e4e7f5;
17+
}
18+
19+
.bg-grid {
20+
background-image:
21+
linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
22+
linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
23+
background-size: 48px 48px, 48px 48px;
24+
background-position: center;
25+
}

app/layout.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { Metadata } from 'next';
2+
import { Space_Grotesk, Manrope } from 'next/font/google';
3+
import './globals.css';
4+
5+
const display = Space_Grotesk({
6+
subsets: ['latin'],
7+
variable: '--font-display'
8+
});
9+
10+
const body = Manrope({
11+
subsets: ['latin'],
12+
variable: '--font-body'
13+
});
14+
15+
export const metadata: Metadata = {
16+
title: 'Jedabero | Full Stack Engineer',
17+
description:
18+
'Portafolio enfocado en React, React Native, Node/Nest/Express y PostgreSQL. Casos de estudio privados.'
19+
};
20+
21+
export default function RootLayout({
22+
children
23+
}: {
24+
children: React.ReactNode;
25+
}) {
26+
return (
27+
<html lang="es">
28+
<body className={`${display.variable} ${body.variable} font-body bg-page-gradient bg-base-bg text-base-text`}>
29+
{children}
30+
</body>
31+
</html>
32+
);
33+
}

app/page.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { About } from '@/components/sections/about';
2+
import { Architecture } from '@/components/sections/architecture';
3+
import { Contact } from '@/components/sections/contact';
4+
import { Hero } from '@/components/sections/hero';
5+
import { Projects } from '@/components/sections/projects';
6+
7+
export default function HomePage() {
8+
return (
9+
<main className="min-h-screen">
10+
<Navbar />
11+
<div className="bg-page-gradient bg-grid">
12+
<Hero />
13+
<About />
14+
<Projects />
15+
<Architecture />
16+
<Contact />
17+
</div>
18+
</main>
19+
);
20+
}
21+
import { Navbar } from '@/components/sections/navbar';

app/projects/[slug]/page.tsx

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { CompanyLogo } from '@/components/company-logo';
2+
import { Badge } from '@/components/ui/badge';
3+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
4+
import { Tabs } from '@/components/ui/tabs';
5+
import { caseStudies } from '@/lib/data/case-studies';
6+
import { notFound } from 'next/navigation';
7+
8+
type Params = { slug: string };
9+
10+
export function generateStaticParams() {
11+
return caseStudies.map((item) => ({ slug: item.slug }));
12+
}
13+
14+
export default function CaseStudyPage({ params }: { params: Params }) {
15+
const study = caseStudies.find((item) => item.slug === params.slug);
16+
if (!study) return notFound();
17+
18+
const tabs = [
19+
{ id: 'context', label: 'Contexto', content: study.problem },
20+
{ id: 'solution', label: 'Solución', content: study.solution },
21+
{
22+
id: 'impact',
23+
label: 'Impacto',
24+
content: (
25+
<ul className="list-disc pl-4 space-y-1">
26+
{study.impact.map((item) => (
27+
<li key={item}>{item}</li>
28+
))}
29+
</ul>
30+
)
31+
}
32+
];
33+
34+
return (
35+
<main className="min-h-screen py-16 md:py-20">
36+
<div className="max-w-4xl mx-auto px-4 space-y-8">
37+
<div className="flex items-center gap-3">
38+
<CompanyLogo companyId={study.companyId} size={40} />
39+
<div>
40+
<p className="text-sm text-base-muted uppercase tracking-[0.2em]">{study.company}</p>
41+
<h1 className="text-3xl font-semibold font-display text-base-text">{study.title}</h1>
42+
</div>
43+
</div>
44+
<div className="flex flex-wrap gap-2">
45+
<Badge variant="blue">{study.domain}</Badge>
46+
{study.frontend.map((item) => (
47+
<Badge key={item} variant="mint">
48+
Frontend: {item}
49+
</Badge>
50+
))}
51+
{study.backend.map((item) => (
52+
<Badge key={item} variant="mint">
53+
Backend: {item}
54+
</Badge>
55+
))}
56+
{study.infra.map((item) => (
57+
<Badge key={item} variant="muted">
58+
{item}
59+
</Badge>
60+
))}
61+
</div>
62+
<Card>
63+
<CardHeader>
64+
<CardTitle>Detalles</CardTitle>
65+
</CardHeader>
66+
<CardContent>
67+
<Tabs tabs={tabs} />
68+
</CardContent>
69+
</Card>
70+
</div>
71+
</main>
72+
);
73+
}

components/company-logo.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
type CompanyLogoProps = {
2+
companyId: 'fullstack-labs' | 'pluriza' | 'idi';
3+
size?: number;
4+
};
5+
6+
export function CompanyLogo({ companyId, size = 32 }: CompanyLogoProps) {
7+
const common = {
8+
width: size,
9+
height: size,
10+
viewBox: '0 0 64 64',
11+
role: 'img'
12+
};
13+
14+
if (companyId === 'fullstack-labs') {
15+
return (
16+
<svg {...common} aria-label="Fullstack Labs">
17+
<rect x="6" y="6" width="52" height="52" rx="12" fill="none" stroke="#5fe3c0" strokeWidth="4" />
18+
<path d="M16 20h20v8H16zM16 34h28v8H16zM16 48h16v8H16z" fill="#7aa2ff" />
19+
</svg>
20+
);
21+
}
22+
23+
if (companyId === 'pluriza') {
24+
return (
25+
<svg {...common} aria-label="Pluriza">
26+
<circle cx="22" cy="32" r="14" fill="none" stroke="#7aa2ff" strokeWidth="4" />
27+
<circle cx="42" cy="24" r="10" fill="none" stroke="#5fe3c0" strokeWidth="4" />
28+
<circle cx="42" cy="44" r="10" fill="none" stroke="#5fe3c0" strokeWidth="4" />
29+
</svg>
30+
);
31+
}
32+
33+
return (
34+
<svg {...common} aria-label="Fundación IDI">
35+
<rect x="10" y="10" width="44" height="44" rx="8" fill="none" stroke="#7aa2ff" strokeWidth="4" />
36+
<path d="M18 46c4-8 8-12 14-12s10 4 14 12" fill="none" stroke="#5fe3c0" strokeWidth="4" />
37+
<circle cx="32" cy="26" r="6" fill="#5fe3c0" />
38+
</svg>
39+
);
40+
}

components/sections/about.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Badge } from '@/components/ui/badge';
2+
import { getExperienceYears } from '@/lib/data/experience';
3+
4+
const coreStack = ['React', 'React Native', 'Node.js', 'NestJS', 'Express', 'PostgreSQL', 'GraphQL'];
5+
6+
export function About() {
7+
const years = getExperienceYears();
8+
return (
9+
<section id="about" className="py-16 md:py-20 bg-gradient-to-b from-base-surface/40 to-transparent">
10+
<div className="max-w-5xl mx-auto px-4 grid gap-10 md:grid-cols-[1.2fr_0.8fr] items-center">
11+
<div className="space-y-4">
12+
<p className="text-sm uppercase tracking-[0.2em] text-base-muted">Sobre mí</p>
13+
<h2 className="text-3xl font-semibold text-base-text font-display">Hola, soy Jedabero</h2>
14+
<p className="text-base text-base-muted">
15+
Ingeniero de Sistemas con {years}+ años construyendo productos web y móviles. Me enfoco en arquitecturas
16+
ligeras, DX y performance en React/React Native con backends en Express, Next.js o NestJS sobre PostgreSQL.
17+
</p>
18+
<p className="text-base text-base-muted">
19+
Trabajo con equipos distribuidos para entregar features sostenibles, con medición continua y buenas
20+
prácticas listas para escalar.
21+
</p>
22+
</div>
23+
<div className="flex flex-wrap gap-2">
24+
{coreStack.map((item) => (
25+
<Badge key={item} variant={item === 'PostgreSQL' ? 'blue' : 'mint'}>
26+
{item}
27+
</Badge>
28+
))}
29+
</div>
30+
</div>
31+
</section>
32+
);
33+
}

0 commit comments

Comments
 (0)