Files
davidaragon-portfolio/ARCHITECTURE.md
T
2026-05-08 12:49:22 +02:00

15 KiB

Personal Portfolio Architecture - davidaragon.impresion3d.pro

Project: Personal Tech Portfolio & Dev Blog
Tech Stack: Astro + Tailwind CSS
Deploy: Docker + Portainer on 192.168.1.30
Investment: €8,100 (4-week sprint)
Strategic Value: €45-95K 3-year value (477-1,118% ROI)


1. Technology Stack

Core Framework

  • Astro 4.x: Static site generator optimized for content-first sites
    • Ultra-fast static HTML generation
    • Markdown-first content workflow
    • Minimal JavaScript (island architecture)
    • Built-in SEO optimization
    • Zero-config TypeScript support

Styling & UI

  • Tailwind CSS 3.x: Utility-first CSS framework
    • Dark mode optimized
    • Responsive design system
    • Custom color palette
    • Typography plugin for blog content

Content Management

  • Astro Content Collections: Type-safe content management
    • Blog posts (Markdown + frontmatter)
    • Project case studies
    • Schema validation with Zod
    • Automatic type generation

Build & Deploy

  • Docker: Containerized deployment
    • Nginx as static file server
    • Multi-stage build (node build + nginx serve)
    • Optimized image size (<50MB)
  • Portainer: Container orchestration on 192.168.1.30
    • Stack deployment via docker-compose
    • Environment variable management
    • Persistent volume for logs

2. Project Structure

davidaragon-portfolio/
├── src/
│   ├── components/          # Reusable UI components
│   │   ├── layout/
│   │   │   ├── Header.astro
│   │   │   ├── Footer.astro
│   │   │   └── Navigation.astro
│   │   ├── blog/
│   │   │   ├── PostCard.astro
│   │   │   ├── PostList.astro
│   │   │   └── PostLayout.astro
│   │   ├── projects/
│   │   │   ├── ProjectCard.astro
│   │   │   └── ProjectGrid.astro
│   │   └── ui/
│   │       ├── Button.astro
│   │       ├── Card.astro
│   │       └── Tag.astro
│   ├── content/             # Content collections
│   │   ├── config.ts        # Collection schemas
│   │   ├── blog/            # Blog posts (Markdown)
│   │   │   ├── building-in-public.md
│   │   │   ├── spanish-saas.md
│   │   │   └── warrantyhub-pwa.md
│   │   └── projects/        # Project case studies
│   │       ├── warrantyhub.md
│   │       └── garage61.md
│   ├── layouts/             # Page layouts
│   │   ├── BaseLayout.astro
│   │   ├── BlogLayout.astro
│   │   └── ProjectLayout.astro
│   ├── pages/               # Routes (file-based routing)
│   │   ├── index.astro      # Homepage
│   │   ├── about.astro      # About page
│   │   ├── projects/
│   │   │   ├── index.astro  # Projects listing
│   │   │   └── [slug].astro # Individual project
│   │   ├── blog/
│   │   │   ├── index.astro  # Blog listing
│   │   │   └── [slug].astro # Individual post
│   │   └── rss.xml.ts       # RSS feed generator
│   ├── styles/              # Global styles
│   │   ├── global.css       # Base styles + Tailwind
│   │   └── syntax.css       # Code syntax highlighting
│   └── utils/               # Helper functions
│       ├── dateFormat.ts
│       └── readingTime.ts
├── public/                  # Static assets
│   ├── images/
│   │   ├── avatar.jpg
│   │   └── projects/
│   ├── favicon.ico
│   └── robots.txt
├── .docker/
│   ├── Dockerfile           # Multi-stage build
│   ├── nginx.conf           # Nginx configuration
│   └── docker-compose.yml   # Portainer stack
├── astro.config.mjs         # Astro configuration
├── tailwind.config.cjs      # Tailwind configuration
├── tsconfig.json            # TypeScript configuration
└── package.json             # Dependencies

3. Content Collections Schema

Blog Posts

// src/content/config.ts
const blog = defineCollection({
  schema: z.object({
    title: z.string(),
    description: z.string(),
    publishDate: z.date(),
    author: z.string().default('David Aragón'),
    tags: z.array(z.string()),
    category: z.enum(['technical', 'business', 'personal']),
    featured: z.boolean().default(false),
    draft: z.boolean().default(false),
    image: z.string().optional(),
  }),
});

Projects

const projects = defineCollection({
  schema: z.object({
    title: z.string(),
    description: z.string(),
    url: z.string().url(),
    github: z.string().url().optional(),
    status: z.enum(['active', 'development', 'completed']),
    tags: z.array(z.string()),
    startDate: z.date(),
    featured: z.boolean().default(false),
    image: z.string().optional(),
  }),
});

4. Design System

Color Palette (Dark Mode Optimized)

/* Tailwind config */
colors: {
  background: '#0a0e27',      // Deep navy
  surface: '#131729',         // Card backgrounds
  primary: '#60a5fa',         // Blue accent
  secondary: '#a78bfa',       // Purple accent
  text: {
    primary: '#f1f5f9',       // Light text
    secondary: '#94a3b8',     // Muted text
    tertiary: '#64748b',      // Subtle text
  },
  accent: {
    green: '#34d399',         // Success
    red: '#f87171',           // Error
    yellow: '#fbbf24',        // Warning
  }
}

Typography

  • Headings: Inter (font-weight: 600-800)
  • Body: Inter (font-weight: 400-500)
  • Code: JetBrains Mono (font-weight: 400)
  • Scale:
    • H1: 3rem (48px)
    • H2: 2.25rem (36px)
    • H3: 1.875rem (30px)
    • Body: 1rem (16px)
    • Small: 0.875rem (14px)

Component System

  • Cards: Glassmorphism effect with subtle backdrop blur
  • Buttons: Hover transitions, focus states
  • Navigation: Sticky header with scroll-based styling
  • Links: Underline on hover, smooth transitions
  • Code blocks: Syntax highlighting with Shiki (VS Code Dark+ theme)

5. SEO Strategy

Meta Tags

  • Title template: {page} | David Aragón - Indie Builder
  • Description: Dynamic per page
  • Open Graph: Images for all blog posts and projects
  • Twitter Cards: Summary with large image

Sitemap

  • Auto-generated via Astro integration
  • Includes all pages, blog posts, projects
  • Priority: Homepage (1.0), Blog/Projects (0.8), Posts (0.6)

RSS Feed

  • Full-text feed at /rss.xml
  • Includes title, description, content, publish date
  • Auto-updated on build

Performance

  • Target Lighthouse score: 95+ across all metrics
  • Core Web Vitals:
    • LCP: <2.5s
    • FID: <100ms
    • CLS: <0.1

6. Docker Deployment Architecture

Multi-Stage Dockerfile

# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Serve
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY .docker/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Nginx Configuration

  • Serve static files from /usr/share/nginx/html
  • Gzip compression for text assets
  • Cache-Control headers (1 year for assets, 1 hour for HTML)
  • 404 fallback to custom 404.html
  • Security headers (CSP, X-Frame-Options, etc.)

Docker Compose (Portainer Stack)

version: '3.8'
services:
  portfolio:
    build: 
      context: .
      dockerfile: .docker/Dockerfile
    container_name: davidaragon-portfolio
    restart: unless-stopped
    ports:
      - "3010:80"
    environment:
      - NODE_ENV=production
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portfolio.rule=Host(`davidaragon.impresion3d.pro`)"
      - "traefik.http.services.portfolio.loadbalancer.server.port=80"

Deployment on 192.168.1.30

  1. Portainer stack deployment:

    • Create new stack "davidaragon-portfolio"
    • Upload docker-compose.yml
    • Configure environment variables
    • Deploy stack
  2. Domain configuration:

    • DNS A record: davidaragon.impresion3d.pro → 192.168.1.30
    • Traefik reverse proxy for HTTPS
    • Let's Encrypt SSL certificate
  3. CI/CD (future):

    • Gitea Actions on push to main branch
    • Build Docker image
    • Push to local registry or rebuild on server
    • Portainer webhook to redeploy stack

7. Content Strategy

Launch Content (5 Blog Posts)

  1. "Building in Public: My €4M ARR Portfolio Plan"

    • Category: Business
    • Tags: indie hacker, SaaS portfolio, build-in-public
    • Length: 1,500-2,000 words
  2. "Why I'm Building Spanish-First SaaS Products"

    • Category: Business
    • Tags: Spanish SaaS, European market, compliance
    • Length: 1,200-1,500 words
  3. "WarrantyHub: Building a PWA with 79% AI-Assisted Development"

    • Category: Technical
    • Tags: PWA, AI-assisted coding, React, IndexedDB
    • Length: 2,000-2,500 words
  4. "Validating Business Ideas: My €4M Research Framework"

    • Category: Business
    • Tags: business validation, market research
    • Length: 1,800-2,200 words
  5. "From Concept to €502K ARR: WarrantyHub Financial Model"

    • Category: Business
    • Tags: SaaS financial model, ARR projections
    • Length: 1,500-2,000 words

Project Case Studies (2)

  1. WarrantyHub: Problem, solution, architecture, status
  2. Garage61 API: Platform strategy, Python library, future plans

8. Pages Architecture

Homepage (/)

  • Hero section: Personal tagline + CTA
  • Featured projects: 3-4 project cards
  • Latest blog posts: 3 most recent posts
  • Newsletter signup: Email collection form
  • Social links: X, LinkedIn, GitHub

About Page (/about)

  • Personal story: 400-600 word narrative
  • Professional photo: Authentic builder vibe
  • Technical skills: Tech stack showcase
  • Current focus: Portfolio goals and timeline
  • Contact: Email, social media

Projects Page (/projects)

  • Project grid: All projects with filters (status, tech)
  • Project cards: Title, description, tech stack, links
  • Featured projects: Highlighted at top
  • Case study links: Deep-dive for each project

Blog Page (/blog)

  • Post listing: All posts with pagination (10 per page)
  • Category filters: Technical, Business, Personal
  • Tag cloud: Popular tags
  • Search: Client-side search with Fuse.js
  • RSS link: Subscribe to feed

Individual Post (/blog/[slug])

  • Post metadata: Publish date, reading time, tags
  • Table of contents: Auto-generated from headings
  • Syntax highlighting: Code blocks with copy button
  • Share buttons: X, LinkedIn
  • Related posts: 3 similar posts by tags

Individual Project (/projects/[slug])

  • Project header: Title, status, links (live, GitHub)
  • Hero image: Screenshot or diagram
  • Overview: Problem statement and solution
  • Tech stack: Technologies used
  • Architecture: Technical deep-dive
  • Learnings: Challenges and insights
  • Next steps: Future roadmap

9. Performance Optimization

Build-Time Optimizations

  • Image optimization: Astro Image component with automatic format conversion (WebP/AVIF)
  • Code splitting: Per-route JavaScript bundles
  • CSS purging: Unused Tailwind classes removed
  • HTML minification: Whitespace removal
  • Asset hashing: Cache-busting for updated files

Runtime Optimizations

  • Lazy loading: Images load on scroll
  • Preload critical fonts: Inter and JetBrains Mono
  • DNS prefetch: External resources (analytics, CDN)
  • Service worker (future): Offline support and caching

Bundle Size Targets

  • Total JS: <50KB (gzipped)
  • Total CSS: <30KB (gzipped)
  • First load: <200KB total

10. Analytics & Monitoring

Analytics

  • Plausible Analytics: Privacy-friendly, GDPR-compliant
    • Deployed on 192.168.1.30 (Docker container)
    • Custom events: Newsletter signups, project clicks
    • Traffic sources, top pages, referrers

Monitoring

  • Uptime monitoring: Portainer health checks
  • Error tracking: Browser console errors (future: Sentry)
  • Performance monitoring: Lighthouse CI on builds

11. Security Considerations

Headers

  • Content-Security-Policy: Restrict script sources
  • X-Frame-Options: Prevent clickjacking
  • X-Content-Type-Options: Prevent MIME sniffing
  • Referrer-Policy: Control referrer information

HTTPS

  • Let's Encrypt certificate: Auto-renewal via Traefik
  • HSTS: Force HTTPS after first visit
  • Redirect HTTP → HTTPS: Automatic

Input Validation

  • Newsletter form: Email validation, CSRF protection
  • Contact form (future): Rate limiting, spam prevention

12. Acceptance Criteria

Foundation Complete

  • Astro project initialized with TypeScript
  • Tailwind CSS configured with custom design system
  • Content collections set up for blog and projects
  • All core pages implemented (Home, About, Projects, Blog)
  • Responsive design (mobile, tablet, desktop)
  • Dark mode fully implemented

Content Complete

  • 5 blog posts written and published
  • 2 project case studies complete
  • Visual assets created (images, diagrams, photos)
  • RSS feed functional
  • Sitemap generated

Deployment Complete

  • Docker image built (<50MB)
  • Nginx configured with security headers
  • Portainer stack deployed on 192.168.1.30
  • Domain davidaragon.impresion3d.pro resolves correctly
  • HTTPS working with valid certificate
  • Analytics tracking functional

Performance & SEO

  • Lighthouse score 95+ (all categories)
  • Core Web Vitals pass
  • All meta tags present
  • Open Graph images for all posts
  • Sitemap accessible at /sitemap.xml
  • RSS feed accessible at /rss.xml

13. Future Enhancements (Post-Launch)

Phase 2 (Month 2-3)

  • Newsletter automation (email drip campaigns)
  • Search functionality (Algolia or Fuse.js)
  • Comment system (giscus or custom)
  • Related posts algorithm improvement

Phase 3 (Month 4-6)

  • Interactive demos for projects (embedded CodeSandbox)
  • Video content (embedded YouTube)
  • Spanish/English language toggle
  • Progressive Web App features (offline support)

Phase 4 (Month 7+)

  • Guest blog posts from community
  • Podcast interviews (embedded player)
  • Community forum or discussion board
  • Advanced analytics dashboard

14. Maintenance Plan

Weekly (6-9 hours)

  • Content: 1 blog post (4-6 hours)
  • Engagement: Social media, comments (2-3 hours)

Monthly

  • Review analytics: Traffic, popular content
  • Update projects: Status, screenshots
  • Dependency updates: npm audit, security patches

Quarterly

  • Content audit: Update outdated posts
  • SEO review: Keyword performance, backlinks
  • Performance audit: Lighthouse scores, Core Web Vitals

15. Success Metrics

Launch (Month 1)

  • 500+ unique visitors
  • 50+ email subscribers
  • 20+ social shares
  • 5+ inbound inquiries

Growth (Month 3)

  • 2,000+ unique visitors
  • 100+ email subscribers
  • 5+ qualified leads

Long-term (Year 1)

  • 5,000+ monthly visitors
  • 300+ email subscribers
  • 50+ customers attributed to content
  • €15K+ customer acquisition value saved

Architecture designed by: wh-leader
Date: May 8, 2026
Status: Ready for implementation
Next: Break into atomic implementer tasks