Skip to main content
All personal content lives in the data/ directory. Each file exports typed arrays that feed directly into the portfolio’s components — no configuration files, no CMS. Update the TypeScript source and your changes are reflected immediately.
1

Update your experience and education

Edit data/experience.ts to reflect your own education and work history.
2

Add your projects

Edit data/projects.ts with your own work, images, and links.
3

Customise skill categories

Edit data/skills.ts to match your actual technology stack.
4

Update social links

Edit data/socials.ts with your own profile URLs.

experience.ts

The file exports two separate arrays: educations and experiences. Both use the same TimelineItem interface.

TimelineItem interface

// types/index.ts
export interface TimelineItem {
  title: string;       // Role, degree, or certification name
  sub_title: string;   // Company, institution, or location
  years: string;       // Date range displayed on the timeline
  details: string;     // Description of responsibilities or achievements
  japanese?: string;   // Optional katakana/kanji label (displayed in serif font)
}

Field reference

FieldRequiredDescription
titleYesThe job title or degree name
sub_titleYesEmployer or educational institution
yearsYesAny string — "2024 - Present", "2022", etc.
detailsYesA sentence or two describing the role
japaneseNoShort Japanese label shown in serif font on the card

Example entries

// data/experience.ts
import type { TimelineItem } from "@/types";

export const educations: TimelineItem[] = [
  {
    title: "Desarrollo de Aplicaciones Web",
    sub_title: "IES Hermenegildo Lanz, Granada",
    years: "2022 - 2024",
    details:
      "Obtuve el título de Técnico Superior en Desarrollo de Aplicaciones Web, "
      + "adquiriendo las bases necesarias y habilidades avanzadas para la programación y desarrollo web.",
    japanese: "ウェブ開発",
  },
  {
    title: "Sistemas Microinformáticos y Redes",
    sub_title: "IES Padre Suárez, Granada",
    years: "2020 - 2022",
    details:
      "Obtuve el título de Técnico en Sistemas Microinformáticos y Redes.",
    japanese: "ネットワーク",
  },
];

export const experiences: TimelineItem[] = [
  {
    title: "Desarrollador Web Freelance",
    sub_title: "Freelance",
    years: "2024 - Presente",
    details:
      "Desarrollo de sitios web personalizados para pequeñas y medianas empresas, "
      + "enfocándome en diseño responsive, optimización SEO y experiencia de usuario.",
    japanese: "フリーランス",
  },
  {
    title: "Desarrollador Web en Prácticas",
    sub_title: "ATI Soluciones",
    years: "2024",
    details:
      "Contribuí en la ampliación y mejora del ERP de la empresa utilizando Laravel, JQUERY y Bootstrap.",
    japanese: "インターン",
  },
];
educations[] and experiences[] are rendered in separate timeline sections on the page. Keep them in separate arrays — do not merge them into one.

projects.ts

Projects are displayed in the Works section as a responsive card grid. Each card shows the image, Japanese label, description, tech tags, and links.

Project interface

// types/index.ts
export interface Project {
  title: string;           // Project display name
  japanese: string;        // Japanese subtitle shown in serif font
  description: string;     // One- or two-sentence summary
  image: StaticImageData;  // Imported with Next.js static import
  tags: string[];          // Technology tags rendered as pills
  github: string;          // GitHub URL — use "#" to hide the link
  demo: string;            // Live demo URL
}

Field reference

FieldRequiredDescription
titleYesThe project name
japaneseYesShort Japanese description shown below the title
descriptionYesPlain text summary
imageYesImport your image as a static asset (.avif, .webp, .png)
tagsYesArray of technology strings
githubYesFull URL or "#" if the repo is private
demoYesFull URL to the live deployment

Example entries

// data/projects.ts
import diversiaImage from "@/public/images/projects/diversia.avif";
import recursosWebImage from "@/public/images/projects/recursos.avif";
import type { Project } from "@/types";

export const projects: Project[] = [
  {
    title: "Diversia Interiorismo",
    japanese: "インテリアデザイン",
    description: "Sitio web corporativo especializado en neuroarquitectura y diseño biofílico.",
    image: diversiaImage,
    tags: ["NextJS", "TailwindCSS", "Prisma", "Turso", "Cloudflare", "Vercel"],
    github: "#",
    demo: "https://diversiainteriorismo.com",
  },
  {
    title: "Recursos Web",
    japanese: "開発者リソース",
    description: "Directorio curado de recursos y herramientas para desarrolladores web.",
    image: recursosWebImage,
    tags: ["Astro", "TailwindCSS"],
    github: "https://github.com/RogerCiv/web-resources",
    demo: "https://web-recursos.vercel.app",
  },
];

Adding a project image

1

Place your image

Copy your screenshot or thumbnail to public/images/projects/. Prefer .avif for the smallest file size, but .webp, .jpg, and .png all work.
2

Import it at the top of the file

import myProjectImage from "@/public/images/projects/my-project.avif";
3

Reference it in the project object

{
  title: "My Project",
  image: myProjectImage,
  // ...
}
Do not pass a plain string path to image. The field type is StaticImageData, which requires a Next.js static import so that the image is optimized at build time.

skills.ts

Skills are displayed in the Habilidades section as a six-card grid. Each card has an icon, a title, a Japanese subtitle, and a list of technologies.

Skill interface

// types/index.ts
import type { LucideIcon } from "lucide-react";

export interface Skill {
  icon: LucideIcon;  // A Lucide React icon component (not JSX)
  title: string;     // Category title
  japanese: string;  // Japanese label in serif font
  techs: string[];   // List of technologies in this category
}

Field reference

FieldRequiredDescription
iconYesA LucideIcon — pass the component reference, not <Icon />
titleYesThe English category name
japaneseYesKatakana or kanji label
techsYesArray of technology/tool names

Example entry

// data/skills.ts
import {
  CodeXml,
  Database,
  GitBranch,
  Palette,
  Server,
  Wrench,
} from "lucide-react";
import type { Skill } from "@/types";

export const skills: Skill[] = [
  {
    icon: CodeXml,
    title: "Frontend",
    japanese: "フロントエンド",
    techs: ["React", "TypeScript", "Next.js", "Astro", "Tailwind CSS"],
  },
  {
    icon: Server,
    title: "Backend",
    japanese: "バックエンド",
    techs: ["Node.js", "Express", "PHP", "Laravel", "REST APIs"],
  },
  {
    icon: Database,
    title: "Database",
    japanese: "データベース",
    techs: ["PostgreSQL", "MongoDB", "MySQL", "SQLite", "Prisma"],
  },
  {
    icon: Palette,
    title: "Design",
    japanese: "デザイン",
    techs: ["Figma", "CSS", "Responsive Design", "UI Components"],
  },
  {
    icon: GitBranch,
    title: "DevOps",
    japanese: "デブオプス",
    techs: ["Git", "GitHub Actions", "Docker", "CI/CD"],
  },
  {
    icon: Wrench,
    title: "Tools",
    japanese: "ツール",
    techs: ["VS Code", "Postman", "Biome", "pnpm", "Vite"],
  },
];

Available Lucide icons

The following icons are already used in the file and are a good starting point. Any icon from the lucide-react package can be used.
Import nameVisual
CodeXmlCode brackets / frontend
ServerServer rack / backend
DatabaseCylinder / databases
PaletteArtist palette / design
GitBranchGit branch / version control
WrenchWrench / tooling
Pass the icon as a component reference — icon: CodeXml — not as JSX (icon: <CodeXml />). The component renders it with const Icon = skill.icon; <Icon className="..." />.

socials.ts

Social links appear in the contact section and hero area. Each entry links out to a social profile with a custom image icon.
// types/index.ts
import type { StaticImageData } from "next/image";

export interface SocialLink {
  image: StaticImageData;  // Icon image (imported as a static asset)
  label: string;           // Accessible label and display text
  href: string;            // Full URL to the profile
}

Example

// data/socials.ts
import githubImage from "@/public/images/socials/github-icon.avif";
import instagramImage from "@/public/images/socials/instagram-icon.avif";
import linkedinImage from "@/public/images/socials/linkedin-icon.avif";
import type { SocialLink } from "@/types";

export const socialLinks: SocialLink[] = [
  {
    image: githubImage,
    label: "GitHub",
    href: "https://github.com/rogerciv",
  },
  {
    image: linkedinImage,
    label: "LinkedIn",
    href: "https://linkedin.com/in/rogerciv",
  },
  {
    image: instagramImage,
    label: "Instagram",
    href: "https://instagram.com/tuusuario",
  },
];

Adding a new social network

1

Add an icon image

Place a square icon (e.g. .avif) in public/images/socials/.
2

Import the image

import twitterImage from "@/public/images/socials/twitter-icon.avif";
3

Add an entry to the array

{
  image: twitterImage,
  label: "Twitter",
  href: "https://twitter.com/yourhandle",
}

Theming

Customize colors, fonts, and dark mode

Japanese Patterns

Apply traditional Japanese background patterns

Build docs developers (and LLMs) love