Portfolio personal + sitio de identidad de marca del Opita Developer. Canal público de Opita Code: product architect, stream en vivo, sin filtros. Personal portfolio + brand identity site for the Opita Developer. Opita Code's public channel: product architect, live streaming, unfiltered.
ES — Portfolio público de Nicolás Urrutia, "Arquitecto de Producto", canal público de Opita Code. Single-page Astro con estética "cyberpunk/gamer": terminal interactiva con tabs (
architect.ts,streamer.yml,metrics.json) y un diagrama de arquitectura animado en SVG. Pensado para mostrar trabajo técnico real con animaciones premium (Lenis smooth scroll + Framer Motion), zero tracking, mobile-first.
EN — Public portfolio for Nicolás Urrutia, "Product Architect", Opita Code's public channel. Single-page Astro site with a "cyberpunk/gamer" aesthetic: interactive tabbed terminal (
architect.ts,streamer.yml,metrics.json) and an animated SVG architecture diagram. Built to show real technical work with premium animations (Lenis smooth scroll + Framer Motion), zero tracking, mobile-first.
Texto sugerido para el campo "About" en GitHub (actualmente vacío):
Portfolio personal + canal de marca de Nicolás Urrutia (Product Architect, Opita Code). Single-page Astro + React + Tailwind 4 + Framer Motion.
| Producción | https://developer.opitacode.com (subdominio · CloudFront EHQLGHNKD091K → S3 dev.opitacode.com raíz) |
| Stack | Astro 6.3.2 · React 19.2.6 (islands) · Tailwind 4.3.0 · Framer Motion 12.38 · Lenis 1.3 · Lucide React 1.14 |
| Runtime | Node ≥ 22.12 |
| Estilo arquitectónico | Single-page portfolio (src/pages/index.astro único); 4 componentes (2 .astro + 2 .tsx) |
| Animación | Lenis (smooth scroll) + Framer Motion (terminal + diagrama SVG) |
| Tracking | Sin analytics, sin cookies, sin third-party JS |
| Deploy | Push a main → GitHub Actions → aws s3 sync . s3://dev.opitacode.com --delete + CloudFront invalidation → servido en https://developer.opitacode.com |
El deploy sincroniza a la raíz del bucket compartido dev.opitacode.com con --delete. Con un prefix /developer/ se aísla correctamente; sin él, cualquier deploy pisa otras apps en el mismo bucket (vibe-studio en /app/, Trabajos en /trabajos/, Cuenta en /cuenta/). Ver sección "Staging isolation" más abajo. |
| Capa | Tecnología | Versión (package.json) |
|---|---|---|
| Framework | Astro | ^6.3.2 |
| UI interactivo | React + ReactDOM (islands) | ^19.2.6 |
| Estilos | Tailwind CSS (Vite plugin) | ^4.3.0 |
| Animaciones | Framer Motion | ^12.38.0 |
| Smooth scroll | Lenis | ^1.3.23 |
| Iconos | Lucide React | ^1.14.0 |
| Lenguaje | TypeScript | 5.x (@types/react ^19.2.14) |
| Build config | astro.config.mjs integra Tailwind via @tailwindcss/vite + @astrojs/react |
— |
| Runtime | Node | >=22.12.0 |
| Hosting | S3 + CloudFront (EHQLGHNKD091K) |
us-east-1 |
| CI/CD | GitHub Actions en push a main |
.github/workflows/deploy.yml |
opita-developer-web/
├── src/
│ ├── components/
│ │ ├── Nav.astro barra de navegación (top, fija)
│ │ ├── Footer.astro pie de página
│ │ ├── ArchitectureDiagram.tsx diagrama SVG animado (Framer Motion)
│ │ └── InteractiveTerminal.tsx terminal con 3 tabs (`architect.ts`, `streamer.yml`, `metrics.json`)
│ ├── layouts/
│ │ └── Layout.astro layout base con Nav + Footer + meta description
│ ├── pages/
│ │ └── index.astro única página (single-page portfolio, ~16 KB)
│ └── styles/global.css Tailwind layers + custom CSS variables (--bg-base, --text-secondary, etc.)
├── public/
│ ├── assets/fonts/dm-sans-latin.woff2
│ ├── assets/img/ logos opita-code (v4 horizontal black/white, stacked, symbol, og, vibe-logo)
│ ├── favicon.ico + favicon.svg
│ └── opita_code_favicon_assets.zip empaquetado histórico de favicons
├── .github/workflows/deploy.yml build + s3 sync + CloudFront invalidation
├── astro.config.mjs astro + tailwindcss (Vite plugin) + react()
├── tsconfig.json
├── package.json · package-lock.json
└── README.md
Lay-out "esqueleto" en Astro (sin JS en el cliente salvo lo que cada componente inyecte). Wrapper alrededor de la única página; Layout.astro los importa y los compone junto con <slot />.
Tres tabs simulando snippets de código (con resaltado por color de Framer Motion + clases Tailwind):
architect.ts— pseudo-mock con imports desde@opita/corey@daily/fuelstreamer.yml— configuración de streamingmetrics.json— métricas en vivo
Tabla declarativa arriba ({ id: 'architect.ts', icon: Server, color: 'text-violet-400' }, etc.). Iconos desde lucide-react. Animación de typing con motion + AnimatePresence.
SVG (viewBox="0 0 800 400") con tres nodos conectados por paths animados. Filtros <defs> para glow cyan/violeta. Background con grid radial (backgroundSize: '24px 24px'). Capas: nodos estáticos + paths animados con motion. Sin librerías externas de gráficos — todo SVG crudo.
git clone https://github.com/Opita-Code/opita-developer-web.git
cd opita-developer-web
npm install
npm run dev # → http://localhost:4321Verificá engines: ">=22.12.0" en package.json antes de empezar — usar una versión menor genera warnings.
npm run preview # preview del build local
npm run build # → dist/Push a main ejecuta .github/workflows/deploy.yml:
npm ci+npm run build(generadist/)aws s3 sync . s3://dev.opitacode.com --delete --cache-control "max-age=14400"aws cloudfront create-invalidation --distribution-id EHQLGHNKD091K --paths "/*"
⚠️ STAGING ISOLATION — DRIFT PENDIENTE: El deploy.yml NO usa un prefix en el bucket (s3://dev.opitacode.comsin/developer/). El flag--deleteborra cualquier objeto en la raíz del bucket que no esté endist/. Esto viola la convención deOpita-Code/opita-vibe-studio/AGENTS.md("Aislamiento en Staging") que prescribes3 sync dist/ s3://dev.opitacode.com/<prefix>/ --delete. Consecuencia: cualquier push de opita-developer-web puede borrar rutas/app/(vibe-studio),/trabajos/(opita-trabajos),/cuenta/(opita-account-ui) que vivan en el mismo bucket. Fix recomendado: cambiar el target as3://dev.opitacode.com/developer/ --deletey configurarbase: '/developer/'enastro.config.mjs. VerRUNBOOKS.mdcuando se arregle.
| Sección | Componente | Notas |
|---|---|---|
| Hero | Layout.astro + index.astro inline |
Headline "Construyendo sistemas. En vivo y sin filtros." + LEDs animados; badges de stack + CTA a #arquitectura y #trabajo |
| Terminal interactiva | InteractiveTerminal.tsx |
Tabs architect.ts / streamer.yml / metrics.json con typing animation; iconos Lucide |
| Arquitectura en vivo | ArchitectureDiagram.tsx |
SVG con tres nodos: Frontend → Backend → Cloud, paths animados |
| Stack / proyectos | inline (index.astro) |
Cards con monorepos de Opita Code |
| Live streaming | inline | Link a Twitch/YouTube + métricas |
| Contacto | inline | Email + redes |
Diseño mobile-first; sin framework JS en el cliente fuera de los islands React; sin cookies; sin tracking.
Propietario · © 2026 Opita Code · Hecho en Colombia 🇨🇴
Última revisión del README: 2026-07-28 — auditoría org-wide contra package.json (Astro 6.3.2, Tailwind 4.3.0, Framer Motion 12.38, Lenis 1.3, Lucide 1.14), astro.config.mjs, deploy.yml, código fuente. Cambios: (1) UTF-8 limpio (el original tenía mojibake); (2) "CSS vanilla" → Tailwind 4 (verificado por @tailwindcss/vite en astro.config.mjs); (3) estructura completa (4 componentes, no 2); (4) deps reales (lenis + lucide-react); (5) staging isolation drift ahora explícito en vez de enterrado en "Hosting"; (6) "About" sugerido para GitHub; (7) URL canónica corregida a developer.opitacode.com (subdominio) — antes había quedado como dev.opitacode.com que es el bucket S3 compartido, cosa distinta. Pendientes separados: (a) fix staging isolation (cambiar deploy.yml a s3://dev.opitacode.com/developer/ + base: '/developer/' en astro.config — el sync al raíz pisa el bucket compartido); (b) pegar el "About" sugerido en la descripción del repo (eso es un setting de GitHub, no de archivos); (c) documentar opita_code_favicon_assets.zip (es un residuo histórico que probablemente no se necesita).