feat: recover portfolio pages from scratch workspaces
- Add base layouts (BaseLayout, BlogLayout, ProjectLayout) - Add UI components (Header, Footer, Navigation, Card, Tag) - Add About page with personal story - Add Projects pages (index, detail) - Add homepage content - Add SEO files (robots.txt, webmanifest) Work was done by agents in isolated workspaces. Consolidated into main repo for proper git tracking.
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import Header from '../components/layout/Header.astro';
|
||||
import Footer from '../components/layout/Footer.astro';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="Sobre mí"
|
||||
description="Indie builder español construyendo productos SaaS. De desarrollador a emprendedor, compartiendo el viaje hacia €4M ARR."
|
||||
>
|
||||
<Header />
|
||||
<main class="flex-1 max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<article class="prose prose-invert prose-lg max-w-none">
|
||||
<h1 class="text-4xl font-bold mb-8">Sobre mí</h1>
|
||||
|
||||
<div class="flex flex-col md:flex-row gap-8 mb-8 not-prose">
|
||||
<div class="flex-shrink-0">
|
||||
<img
|
||||
src="/images/avatar.jpg"
|
||||
alt="David Aragón"
|
||||
class="w-48 h-48 rounded-full object-cover border-4 border-primary/20"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<h2 class="text-2xl font-semibold mb-4 text-text-primary">Hola 👋</h2>
|
||||
<p class="text-text-secondary text-lg leading-relaxed">
|
||||
Soy David, desarrollador e indie builder español. Estoy construyendo
|
||||
un portfolio de productos SaaS enfocados en el mercado español y europeo,
|
||||
con el objetivo de alcanzar €4M ARR.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2 class="text-3xl font-semibold mb-4">Mi Historia</h2>
|
||||
<p class="text-text-secondary leading-relaxed mb-4">
|
||||
Después de años trabajando como desarrollador, decidí dar el salto al emprendimiento
|
||||
tecnológico. Vi una oportunidad en el mercado español: muchas soluciones B2B están
|
||||
dominadas por empresas extranjeras que no entienden las particularidades del mercado
|
||||
local, especialmente en temas de cumplimiento normativo.
|
||||
</p>
|
||||
<p class="text-text-secondary leading-relaxed mb-4">
|
||||
Mi enfoque es construir en público, compartiendo tanto los éxitos como los fracasos.
|
||||
Creo en la transparencia y en la comunidad indie, y quiero contribuir al ecosistema
|
||||
de emprendedores españoles compartiendo mi viaje.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2 class="text-3xl font-semibold mb-4">Filosofía de Construcción</h2>
|
||||
<ul class="space-y-3">
|
||||
<li class="flex items-start">
|
||||
<span class="text-primary mr-2">→</span>
|
||||
<span class="text-text-secondary">
|
||||
<strong class="text-text-primary">Spanish-first:</strong> Productos diseñados
|
||||
para el mercado español y europeo
|
||||
</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-primary mr-2">→</span>
|
||||
<span class="text-text-secondary">
|
||||
<strong class="text-text-primary">Build-in-public:</strong> Transparencia
|
||||
total en métricas, aprendizajes y decisiones
|
||||
</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-primary mr-2">→</span>
|
||||
<span class="text-text-secondary">
|
||||
<strong class="text-text-primary">AI-assisted:</strong> Aprovechando herramientas
|
||||
de IA para acelerar desarrollo (79% AI-assisted en WarrantyHub)
|
||||
</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-primary mr-2">→</span>
|
||||
<span class="text-text-secondary">
|
||||
<strong class="text-text-primary">Compliance-focused:</strong> Ventaja competitiva
|
||||
en regulaciones españolas y europeas
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2 class="text-3xl font-semibold mb-4">Stack Técnico</h2>
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 gap-4 not-prose">
|
||||
<div class="bg-surface px-4 py-3 rounded-lg border border-text-tertiary/20">React</div>
|
||||
<div class="bg-surface px-4 py-3 rounded-lg border border-text-tertiary/20">TypeScript</div>
|
||||
<div class="bg-surface px-4 py-3 rounded-lg border border-text-tertiary/20">Node.js</div>
|
||||
<div class="bg-surface px-4 py-3 rounded-lg border border-text-tertiary/20">Astro</div>
|
||||
<div class="bg-surface px-4 py-3 rounded-lg border border-text-tertiary/20">Tailwind CSS</div>
|
||||
<div class="bg-surface px-4 py-3 rounded-lg border border-text-tertiary/20">Docker</div>
|
||||
<div class="bg-surface px-4 py-3 rounded-lg border border-text-tertiary/20">PostgreSQL</div>
|
||||
<div class="bg-surface px-4 py-3 rounded-lg border border-text-tertiary/20">Python</div>
|
||||
<div class="bg-surface px-4 py-3 rounded-lg border border-text-tertiary/20">FastAPI</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2 class="text-3xl font-semibold mb-4">En Qué Estoy Trabajando</h2>
|
||||
<div class="bg-surface p-6 rounded-lg border border-primary/20">
|
||||
<h3 class="text-xl font-semibold mb-2 text-primary">Portfolio SaaS €4M ARR</h3>
|
||||
<p class="text-text-secondary mb-4">
|
||||
Construyendo un portfolio de productos SaaS en 3 fases:
|
||||
</p>
|
||||
<ul class="space-y-2">
|
||||
<li class="text-text-secondary">
|
||||
<strong class="text-text-primary">Fase 1 (0-8 meses):</strong> WarrantyHub,
|
||||
Verifactu compliance, análisis de contratos → €825K ARR
|
||||
</li>
|
||||
<li class="text-text-secondary">
|
||||
<strong class="text-text-primary">Fase 2 (8-18 meses):</strong> Plataforma
|
||||
de auditoría, integraciones → €1.8M ARR
|
||||
</li>
|
||||
<li class="text-text-secondary">
|
||||
<strong class="text-text-primary">Fase 3 (18+ meses):</strong> Expansión
|
||||
europea, liderazgo → €4M+ ARR
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 class="text-3xl font-semibold mb-4">Conecta Conmigo</h2>
|
||||
<p class="text-text-secondary mb-6">
|
||||
Siempre estoy abierto a conversar con otros builders, inversores, o simplemente
|
||||
personas interesadas en emprendimiento tecnológico español.
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-4 not-prose">
|
||||
<a
|
||||
href="https://twitter.com/davidaragon"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="bg-primary/10 hover:bg-primary/20 text-primary px-6 py-3 rounded-lg
|
||||
font-medium transition-colors border border-primary/20"
|
||||
>
|
||||
X (Twitter)
|
||||
</a>
|
||||
<a
|
||||
href="https://linkedin.com/in/davidaragon"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="bg-primary/10 hover:bg-primary/20 text-primary px-6 py-3 rounded-lg
|
||||
font-medium transition-colors border border-primary/20"
|
||||
>
|
||||
LinkedIn
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/davidaragon"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="bg-primary/10 hover:bg-primary/20 text-primary px-6 py-3 rounded-lg
|
||||
font-medium transition-colors border border-primary/20"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<a
|
||||
href="mailto:david@impresion3d.pro"
|
||||
class="bg-secondary/10 hover:bg-secondary/20 text-secondary px-6 py-3 rounded-lg
|
||||
font-medium transition-colors border border-secondary/20"
|
||||
>
|
||||
Email
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
import ProjectLayout from '../../layouts/ProjectLayout.astro';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const projects = await getCollection('projects');
|
||||
return projects
|
||||
.filter(p => !p.data.draft)
|
||||
.map(project => ({
|
||||
params: { slug: project.slug },
|
||||
props: { project },
|
||||
}));
|
||||
}
|
||||
|
||||
const { project } = Astro.props;
|
||||
const { Content } = await project.render();
|
||||
---
|
||||
|
||||
<ProjectLayout {...project.data}>
|
||||
<Content />
|
||||
</ProjectLayout>
|
||||
@@ -0,0 +1,127 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/layout/Header.astro';
|
||||
import Footer from '../../components/layout/Footer.astro';
|
||||
import Card from '../../components/ui/Card.astro';
|
||||
import Tag from '../../components/ui/Tag.astro';
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
const allProjects = (await getCollection('projects'))
|
||||
.filter(p => !p.data.draft)
|
||||
.sort((a, b) => b.data.startDate.getTime() - a.data.startDate.getTime());
|
||||
|
||||
const featured = allProjects.filter(p => p.data.featured);
|
||||
const active = allProjects.filter(p => p.data.status === 'active' && !p.data.featured);
|
||||
const others = allProjects.filter(p => p.data.status !== 'active' && !p.data.featured);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="Proyectos"
|
||||
description="Portfolio de productos SaaS: WarrantyHub, Garage61 API, y más proyectos en desarrollo"
|
||||
>
|
||||
<Header />
|
||||
<main class="flex-1 max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<header class="mb-12">
|
||||
<h1 class="text-4xl font-bold mb-4">Proyectos</h1>
|
||||
<p class="text-xl text-text-secondary max-w-3xl">
|
||||
Portfolio de productos SaaS construidos en público. Desde ideas hasta
|
||||
productos escalables generando revenue recurrente.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
{featured.length > 0 && (
|
||||
<section class="mb-16">
|
||||
<h2 class="text-2xl font-semibold mb-6 text-primary">🌟 Proyectos Destacados</h2>
|
||||
<div class="grid md:grid-cols-2 gap-6">
|
||||
{featured.map(project => (
|
||||
<Card href={`/projects/${project.slug}`} class="flex flex-col">
|
||||
{project.data.image && (
|
||||
<img
|
||||
src={project.data.image}
|
||||
alt={project.data.title}
|
||||
class="w-full h-48 object-cover rounded-t-lg -m-6 mb-4"
|
||||
/>
|
||||
)}
|
||||
<h3 class="text-2xl font-semibold mb-2 text-text-primary">
|
||||
{project.data.title}
|
||||
</h3>
|
||||
<p class="text-text-secondary mb-4 flex-1">
|
||||
{project.data.description}
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
{project.data.tags.slice(0, 4).map(tag => (
|
||||
<Tag label={tag} variant="primary" />
|
||||
))}
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-accent-green font-medium capitalize">
|
||||
{project.data.status}
|
||||
</span>
|
||||
<span class="text-primary text-sm font-medium">
|
||||
Ver proyecto →
|
||||
</span>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{active.length > 0 && (
|
||||
<section class="mb-16">
|
||||
<h2 class="text-2xl font-semibold mb-6">Proyectos Activos</h2>
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{active.map(project => (
|
||||
<Card href={`/projects/${project.slug}`}>
|
||||
<h3 class="text-xl font-semibold mb-2 text-text-primary">
|
||||
{project.data.title}
|
||||
</h3>
|
||||
<p class="text-text-secondary mb-4">
|
||||
{project.data.description}
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
{project.data.tags.slice(0, 3).map(tag => (
|
||||
<Tag label={tag} variant="neutral" />
|
||||
))}
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-accent-green font-medium">Activo</span>
|
||||
<span class="text-primary text-sm font-medium">Ver →</span>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{others.length > 0 && (
|
||||
<section>
|
||||
<h2 class="text-2xl font-semibold mb-6">Otros Proyectos</h2>
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{others.map(project => (
|
||||
<Card href={`/projects/${project.slug}`}>
|
||||
<h3 class="text-xl font-semibold mb-2 text-text-primary">
|
||||
{project.data.title}
|
||||
</h3>
|
||||
<p class="text-text-secondary mb-4">
|
||||
{project.data.description}
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
{project.data.tags.slice(0, 3).map(tag => (
|
||||
<Tag label={tag} variant="neutral" />
|
||||
))}
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-text-tertiary capitalize">
|
||||
{project.data.status}
|
||||
</span>
|
||||
<span class="text-primary text-sm font-medium">Ver →</span>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
||||
Reference in New Issue
Block a user