Skip to main content

Overview

The portfolio includes an interactive macOS-style Calendar app that displays important career milestones. Events can come from two sources:
  1. Local events - Defined in app/textos.ts
  2. MongoDB events - Fetched from a MongoDB collection (NFQ category only)
Local events are for static milestones (internships, major projects). MongoDB events are ideal for ongoing updates, especially for current employers.

CalEvent Interface

All calendar events follow this TypeScript interface:
app/textos.ts
export interface CalEvent {
  id: string;          // Unique identifier
  title: string;       // Event title
  category: CalCategory; // "everis" | "inetum" | "nfq" | "personal"
  problema: string;    // Problem/challenge faced
  solucion: string;    // Solution implemented
  aprendizaje: string; // Key learning/takeaway
  start: Date;         // Start date
  end?: Date;          // Optional end date
  color: string;       // Hex color for the event
}

Event Categories

Categories organize events by company or type:
app/textos.ts
export type CalCompany = "everis" | "inetum" | "nfq";
export type CalCategory = CalCompany | "personal";

export const calendarCompanies: { key: CalCompany; label: string; color: string }[] = [
  { key: "everis", label: "Everis", color: "#07f1b7" },
  { key: "inetum", label: "Inetum", color: "#818cf8" },
  { key: "nfq",    label: "NFQ",    color: "#c084fc" },
];

Adding a New Company Category

1

Update the type definition

app/textos.ts
export type CalCompany = "everis" | "inetum" | "nfq" | "mycompany";
2

Add to calendarCompanies array

app/textos.ts
export const calendarCompanies = [
  { key: "everis", label: "Everis", color: "#07f1b7" },
  { key: "inetum", label: "Inetum", color: "#818cf8" },
  { key: "nfq",    label: "NFQ",    color: "#c084fc" },
  { key: "mycompany", label: "My Company", color: "#ff6b6b" },
];
3

Choose a color

Pick a distinct hex color that stands out. The color is used for:
  • Event indicators in the calendar grid
  • Category filter buttons in the sidebar
  • Event detail panels

Local Calendar Events

Local events are defined in the calendarEvents array in app/textos.ts.

Real Examples from Source

app/textos.ts
export const calendarEvents: CalEvent[] = [
  {
    id: "everis",
    title: "Prácticas — Everis",
    category: "everis",
    problema: "Gestión manual de bajas de líneas móviles de Orange, proceso lento y propenso a errores.",
    solucion: "Desarrollé un proceso automatizado que detectaba las bajas y ejecutaba las acciones necesarias sin intervención manual.",
    aprendizaje: "Primera toma de contacto con entornos empresariales reales y automatización de procesos de negocio.",
    start: new Date(2018, 2, 1),  // March 1, 2018
    end: new Date(2018, 5, 30),   // June 30, 2018
    color: "#07f1b7",
  },
  {
    id: "optimus",
    title: "Optimus Price — Inetum",
    category: "inetum",
    problema: "Los precios se fijaban sin un modelo cuantitativo claro, lo que generaba pérdidas de margen.",
    solucion: "Construí pipelines de análisis y modelado de datos para identificar patrones de precio óptimos.",
    aprendizaje: "Aprendí a estructurar proyectos de datos orientados a negocio y a comunicar insights a stakeholders no técnicos.",
    start: new Date(2024, 9, 1),   // October 1, 2024
    end: new Date(2025, 6, 31),    // July 31, 2025
    color: "#818cf8",
  },
  {
    id: "Incorporacion_NFQ",
    title: "Incorporación a NFQ - New Joiner",
    category: "nfq",
    problema: "Inicio de una nueva etapa profesional con el reto de adaptarme a una nueva empresa, conocer la cultura organizacional, los procesos internos y establecer relaciones con el equipo.",
    solucion: "La empresa organizó un onboarding en una casa rural con otros compañeros para facilitar la interacción y el conocimiento del equipo.",
    aprendizaje: "La experiencia permitió entender la importancia de la comunicación y la confianza para colaborar eficazmente en proyectos técnicos.",
    start: new Date(2025, 9, 27),  // October 27, 2025
    end: new Date(2025, 10, 31),   // November 31, 2025
    color: "#c084fc",
  },
];
JavaScript Date months are 0-indexed: January = 0, February = 1, …, December = 11

Adding a Local Event

export const calendarEvents: CalEvent[] = [
  {
    id: "optimus",
    title: "Optimus Price — Inetum",
    category: "inetum",
    problema: "Los precios se fijaban sin un modelo cuantitativo claro...",
    solucion: "Construí pipelines de análisis y modelado de datos...",
    aprendizaje: "Aprendí a estructurar proyectos de datos...",
    start: new Date(2024, 9, 1),
    end: new Date(2025, 6, 31),
    color: "#818cf8",
  },
];

MongoDB Calendar Events

For the NFQ category, events can be dynamically loaded from MongoDB. This is useful for adding events without redeploying the application.

MongoDB Configuration

Configure your MongoDB connection in .env:
.env
MONGODB_URI=mongodb+srv://username:[email protected]/
MONGODB_DB=portafolio
MONGODB_COLLECTION_NFQ=nfq

MongoDB Document Structure

Each MongoDB document should follow this structure:
{
  "_id": "unique-id",
  "titulo": "NFQ Event Title",
  "problema": "Description of the problem or challenge",
  "solucion": "How you solved it",
  "aprendizaje": "What you learned from this experience",
  "fecha": "2025-10-27T00:00:00.000Z"
}

How MongoDB Events are Fetched

The mongodb.server.ts file handles fetching NFQ events:
app/lib/mongodb.server.ts
export interface NfqEventRaw {
  id: string;
  title: string;
  category: "nfq";
  problema: string;
  solucion: string;
  aprendizaje: string;
  start: string; // ISO string
  color: string;
}

export async function getNfqEvents(): Promise<NfqEventRaw[]> {
  const client = await getClient();
  const db = process.env.MONGODB_DB ?? "portafolio";
  const col = process.env.MONGODB_COLLECTION_NFQ ?? "nfq";
  const docs = await client
    .db(db)
    .collection(col)
    .find({})
    .sort({ fecha: 1 })
    .toArray();

  return docs.map((doc) => ({
    id: doc._id.toString(),
    title: doc.titulo as string,
    category: "nfq" as const,
    problema: doc.problema as string,
    solucion: doc.solucion as string,
    aprendizaje: doc.aprendizaje as string,
    start: new Date(doc.fecha as string | Date).toISOString(),
    color: "#c084fc",
  }));
}

Event Merging Logic

The Calendar component merges local and MongoDB events:
app/components/Calendar.tsx
const EVENTS: CalEvent[] = useMemo(() => {
  const staticNonNfq = calendarEvents.filter((e) => e.category !== "nfq");
  const mongoNfq: CalEvent[] = nfqEvents.map((e) => ({
    ...e,
    start: new Date(e.start),
  }));
  return [...staticNonNfq, ...mongoNfq];
}, [nfqEvents]);
Key points:
  • Static NFQ events in textos.ts are filtered out
  • MongoDB NFQ events are converted from ISO strings to Date objects
  • Both arrays are merged into a single EVENTS array

Adding a MongoDB Event

1

Connect to your MongoDB database

Use MongoDB Compass, mongosh, or your preferred client.
2

Insert a new document

{
  "titulo": "New NFQ Project Launch",
  "problema": "We needed to migrate legacy systems to a modern cloud architecture.",
  "solucion": "Designed and implemented a phased migration strategy using AWS services.",
  "aprendizaje": "Gained deep understanding of cloud architecture patterns and team coordination.",
  "fecha": ISODate("2025-12-01T00:00:00Z")
}
3

Refresh the application

The event will automatically appear in the calendar on the next page load.

Ongoing Events

Events without an end date (or with end far in the future) are marked as “ongoing”:
const isOngoing = (e: CalEvent) => !e.end || e.end.getFullYear() >= 2099;
Ongoing events display “Actualidad” (Present) as the end date.

Creating an Ongoing Event

{
  id: "current-project",
  title: "Current Long-term Project",
  category: "personal",
  problema: "Building a complex system over time...",
  solucion: "Iterative development and continuous improvement...",
  aprendizaje: "Learning to balance long-term vision with short-term wins...",
  start: new Date(2025, 0, 1),
  // No end date = ongoing
  color: "#34d399",
}
Or explicitly set a far-future date:
{
  id: "ongoing-role",
  title: "Current Position",
  category: "nfq",
  start: new Date(2025, 9, 1),
  end: new Date(2099, 11, 31),  // Far future = ongoing
  // ...
}

Event Colors

Colors should match the company colors defined in calendarCompanies:
everis:  "#07f1b7"  // Teal/green
inetum:  "#818cf8"  // Purple/blue
nfq:     "#c084fc"  // Pink/purple
personal: "#34d399" // Green (suggested)
Use consistent colors across categories to maintain visual coherence in the calendar UI.

Event Display in Calendar

Events are displayed:
  1. In the calendar grid - As colored indicators on the start date
  2. In the sidebar - Filterable by category
  3. In the detail panel - Full information when a date is selected

What Gets Displayed

When a user clicks a date with events:
// Event card shows:
- Title
- Time period (formatted: "Oct 2024 — Actualidad")
- Problema section
- Solución section
- Aprendizaje section

Optimus Price — Inetum

Oct 2024 — Jul 2025

PROBLEMA

Los precios se fijaban sin un modelo cuantitativo claro…

Best Practices

Use descriptive IDs

Event IDs should be unique and descriptive: everis-internship, nfq-onboarding

Write clear problema/solucion

Focus on the challenge, your approach, and the outcome. Keep it concise but informative.

Match category colors

Always use the color from calendarCompanies for consistency

Use MongoDB for frequent updates

If you’re actively adding events for your current employer, use MongoDB instead of redeploying

Troubleshooting

Check:
  • The date is correct (remember months are 0-indexed)
  • The category exists in calendarCompanies
  • The category filter is enabled in the sidebar
  • The event’s color matches the category color
Verify:
  • MONGODB_URI is correctly set in .env
  • Database and collection names match
  • MongoDB documents have all required fields: titulo, problema, solucion, aprendizaje, fecha
  • The server has successfully connected (check logs)
Remember:
  • JavaScript months are 0-indexed: January = 0, December = 11
  • Use new Date(year, month, day) format
  • For MongoDB, use ISO date strings: "2025-10-27T00:00:00.000Z"
Ensure:
  • All three sections (problema, solucion, aprendizaje) have content
  • The start date is a valid Date object
  • The event’s category matches one of the defined categories

Portfolio Content

Learn about all content sections

Terminal Data

Understand data structures and navigation

MongoDB Setup

Configure MongoDB for dynamic events

Build docs developers (and LLMs) love