Creando un sitio web de cartera desde cero con NextJS, TailwindCSS y Metricalp (2024)
Los sitios web de cartera son esenciales para mostrar tu trabajo y atraer clientes potenciales. En esta publicación, crearemos un sitio web de cartera desde cero con NextJS 14, TailwindCSS y Metricalp. Cubriremos todo para configurar el sitio web y cómo puedes usar Metricalp para aumentar tus conversiones.
Introducción
En esta publicación, vamos a crear un sitio web de portafolio con NextJS, TailwindCSS y Metricalp. También cubriremos cómo rastrear los comportamientos de los usuarios y cómo tomar decisiones basadas en datos con Metricalp, lo que puede impulsar tu crecimiento personal. El sitio web tendrá dos páginas: una página de inicio y una página de proyectos. Las personas pueden dejar sus correos electrónicos en la página de inicio para que podamos contactarlos. Además, verán y descubrirán nuestros proyectos recientes en la página de proyectos. ¡Comencemos viendo la vista final 🚀!
Bueno, basta de hablar, vamos a construirlo 🚀
Configurar el Proyecto
Primero, necesitamos crear un nuevo proyecto de NextJS:
npx create-next-app@latest
Gracias a los colaboradores y al equipo de NextJS, tienen un excelente instalador CLI. Te preguntará todas tus preferencias y configurará el proyecto.
Aquí están todas las configuraciones que elegí mientras estaba iniciando este proyecto:
Seleccionamos TailwindCSS y TypeScript, el CLI instalará todas las dependencias y configurará el proyecto para nosotros.
Instalaremos Metricalp adicionalmente para finalizar el proceso de instalación:
npm install metricalp
Crearemos algunas carpetas/archivos. Quiero compartir la vista final de la estructura del proyecto, la cual explicaremos cada archivo a continuación.
Dijimos que tenemos una página de inicio con un formulario para enviar correos electrónicos, y una página de proyectos. Supongamos que queremos recolectar dos cosas con Metricalp, submit_email, que se activará cada vez que un visitante haga clic en el botón de enviar en la página de inicio. view_project_details que se activará cada vez que un visitante haga clic en el botón de detalles de un proyecto en la pantalla de proyectos. Estas métricas nos pueden ayudar a saber qué proyecto está recibiendo más atención por parte de los visitantes. O incluso mejor, podemos ver qué visitantes de qué país/navegador están prestando más atención a qué proyecto. Definitivamente puede afectar nuestra estrategia de marketing. Hagamos esto más loco. Este es solo un sitio web de portafolio básico, por lo que no tenemos una base de datos/backend, etc. Entonces, ¿cómo recolectaremos correos electrónicos? Oh, espera. Estamos recolectando eventos de submit_email y en Metricalp puedes adjuntar propiedades personalizadas a los eventos, entonces, ¿qué pasaría si adjuntamos el correo electrónico ingresado al evento de submit_email? Entonces, ¿estaríamos usando Metricalp no solo como un proveedor de análisis, sino también como una base de datos básica? Guau, es asombroso. Sí, lo sabemos. Esta es la belleza de Metricalp, hay millones de escenarios de uso.
Bueno, veamos algunos códigos. Vamos a tener el mejor y más simple portafolio y a llegar a nuestros clientes potenciales.
Vamos a crear una carpeta de utilidades dentro de la carpeta src. Habrá dos archivos dentro de esta carpeta. Uno es metricalp-events.ts y el otro es constants.ts
Archivo src/utils/metricalp-events.ts:
export const MetricalpEvents = {
SubmitEmail: 'submit_email',
ViewProjectDetails: 'view_project_details',
};
Archivo src/utils/constants.ts:
export const METRICALP_TID = 'mam48'; // Reemplaza con tu Metricalp TID
Ahora, vamos a configurar Metricalp y crear nuestro diseño principal. Edita el archivo dentro de la ruta y nombre src/app/layout.tsx:
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
import { MetricalpReactProvider } from '@metricalp/react';
import Link from 'next/link';
import { METRICALP_TID } from '@/utils/constants';
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
title: 'Melanie | Desarrolladora Full-stack',
description:
'Soy Melanie, una desarrolladora full-stack con pasión por construir sitios web hermosos y funcionales.',
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="es">
<body className={inter.className}>
<MetricalpReactProvider allowLocalhost tid={METRICALP_TID}>
<div className="h-full p-4 md:p-0 my-4">
<div className="w-full container mx-auto">
<div className="w-full flex items-center justify-between">
<a
className="flex items-center text-indigo-400 no-underline hover:no-underline font-bold text-2xl lg:text-4xl"
href="#"
>
<span className="bg-clip-text text-transparent bg-gradient-to-r from-green-400 via-pink-500 to-purple-500">
Melanie‘s
</span>
</a>
<div className="flex w-1/2 justify-end content-center space-x-4">
<Link href="/">
<span className="bg-clip-text text-lg text-transparent bg-gradient-to-r from-green-400 via-pink-500 to-purple-500">
Inicio
</span>
</Link>
<Link href="/projects">
<span className="bg-clip-text text-lg text-transparent bg-gradient-to-r from-green-400 via-pink-500 to-purple-500">
Proyectos
</span>
</Link>
</div>
</div>
</div>
{children}
</div>
</MetricalpReactProvider>
</body>
</html>
);
}
Hemos configurado el proveedor de Metricalp y estamos envolviendo toda nuestra aplicación con él. También estamos usando clases de TailwindCSS para hacer nuestro diseño más atractivo. Estamos usando la fuente Inter de Google Fonts. También estamos usando la función de metadatos de NextJS para establecer el título y la descripción de nuestro sitio web. También estamos usando el componente Link de NextJS para navegar entre páginas.
Tenemos una barra de navegación superior, tiene el logo (como texto) a la izquierda y dos enlaces de navegación a la página de inicio y la página de proyectos a la derecha.
Estamos usando la última versión de NextJS, por lo que hay componentes de servidor y componentes de cliente. Básicamente, los componentes interactivos serán componentes de cliente y todos los demás serán componentes de servidor. Continuemos con el más básico. Crea un archivo dentro de la ruta y nombre src/components/shared/Button.tsx
'use client';
import { ReactNode } from 'react';
type Props = {
content: ReactNode;
onClick: () => void;
};
export const Button = ({ content, onClick }: Props) => {
return (
<button
onClick={onClick}
className="bg-gradient-to-r from-purple-800 to-green-500 hover:from-pink-500 hover:to-green-500 text-white font-bold py-2 px-4 rounded focus:ring transform transition hover:scale-105 duration-300 ease-in-out"
type="button"
>
{content}
</button>
);
};
Comienza con 'use client' porque está tomando/pasando una función como prop (onClick). Aparte de eso, es solo un botón básico. Pero, para tener un aspecto elegante, tenemos clases de TailwindCSS que están dando a nuestro botón una buena vista de degradado. Por último, estamos tomando el contenido como ReactNode, lo que significa que puede ser un texto simple o un componente React, por lo que esto hace que nuestro botón sea más personalizable. Este es nuestro componente de botón básico, por lo que está en la carpeta compartida. Otros lugares usarán este botón con personalización.
De acuerdo, vamos a crear un formulario de envío de correos electrónicos que se colocará en nuestra página de inicio. Crea un archivo dentro de la ruta y nombre src/components/route-specific/homepage/MailSubmitForm.tsx:
'use client';
import { Button } from '@/components/shared/Button';
import { MetricalpEvents } from '@/utils/metricalp-events';
import { metricalpEvent } from '@metricalp/react';
import { useState } from 'react';
export const MailSubmitForm = () => {
const [email, setEmail] = useState('');
return (
<form className="bg-gray-900 opacity-75 w-full shadow-lg rounded-lg px-8 pt-6 pb-8 mb-4">
<div className="mb-4">
<label
className="block text-blue-300 py-2 font-bold mb-2"
htmlFor="emailaddress"
>
Deja tu correo electrónico para contactar
</label>
<input
className="shadow appearance-none border rounded w-full p-3 text-gray-700 leading-tight focus:ring transform transition hover:scale-105 duration-300 ease-in-out"
id="emailaddress"
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="[email protected]"
/>
</div>
<div className="flex items-center justify-between pt-4">
<Button
content="Enviar"
onClick={() => {
metricalpEvent({ type: MetricalpEvents.SubmitEmail, email });
alert('Enviado');
}}
/>
</div>
</form>
);
};
Nuevamente, es un componente de cliente porque es interactivo. Básicamente, hay un campo de entrada y un botón de envío (nuestro componente Button). Cuando el usuario hace clic en enviar, estamos activando un evento de Metricalp, Metricalp.SubmitEmail y también pasamos el correo electrónico como prop a este evento.
Mantenemos el texto escrito en estado y aplicamos estilo con clases de TailwindCSS nuevamente.
Ahora veamos nuestro último componente de cliente, src/components/route-specific/projects/ProjectDetailsButton.tsx:
'use client';
import { Button } from '@/components/shared/Button';
import { MetricalpEvents } from '@/utils/metricalp-events';
import { metricalpEvent } from '@metricalp/react';
type Props = {
projectTitle: string;
};
export const ProjectDetailsButton = ({ projectTitle }: Props) => {
return (
<Button
content="Detalles"
onClick={() => {
metricalpEvent({
type: MetricalpEvents.ViewProjectDetails,
projectTitle,
});
alert('Detalles');
}}
/>
);
};
Entonces, cada vez que un visitante haga clic en el botón de detalles de un proyecto, estamos activando el evento Metricalp.ViewProjectDetails y pasando el título del proyecto como prop. Este es un ejemplo básico, pero puedes pasar más propiedades a este evento.
De acuerdo, ahora vamos a desarrollar la página de inicio, que no será difícil, todos los componentes funcionales ya están listos.
Edita el archivo dentro de la ruta y nombre src/app/page.tsx:
import { MailSubmitForm } from '@/components/route-specific/homepage/MailSubmitForm';
import Image from 'next/image';
export default function Home() {
return (
<div className="container pt-24 md:pt-36 mx-auto flex flex-wrap flex-col md:flex-row items-center">
<div className="flex flex-col w-full xl:w-2/5 justify-center lg:items-start overflow-y-hidden">
<h1 className="my-4 text-3xl md:text-5xl text-white opacity-75 font-bold leading-tight text-center md:text-left">
Hola,
<span className="bg-clip-text text-transparent bg-gradient-to-r from-green-400 via-pink-500 to-purple-500">
Cambiemos el mundo
</span>
juntos
</h1>
<p className="leading-normal text-base md:text-2xl mb-8 text-center md:text-left">
Soy Melanie, una desarrolladora full-stack con pasión por construir
sitios web hermosos y funcionales.
</p>
<MailSubmitForm />
</div>
<div className="w-full xl:w-3/5 p-12 overflow-hidden">
<Image
className="mx-auto w-full md:w-4/5 transform -rotate-6 transition hover:scale-105 duration-700 ease-in-out hover:rotate-6"
src="/cover.png"
alt="Imagen de portada"
width={1080}
height={1080}
/>
</div>
</div>
);
}
Tenemos nuestro texto principal, imagen de portada y el formulario de envío de correos. Este es un componente de servidor, así que no añadimos 'use client' en la parte superior. Nuevamente aplicamos clases de TailwindCSS para que luzca bien.
Ahora, solo queda una página. Página de proyectos. Vamos a crearla. Crea el archivo dentro de la ruta y nombre src/app/projects/page.tsx:
import { ProjectDetailsButton } from '@/components/route-specific/projects/ProjectDetailsButton';
import Image from 'next/image';
const projects = [
{
title: 'Aplicación ToDo',
description: 'Una aplicación de lista de tareas simple construida con React Native',
image: 'https://cdn.metricalp.com/web/assets/images/rn-app-example-1.png',
},
{
title: 'Sitio Web de Metricalp',
description: 'El sitio web de marketing para Metricalp',
image: 'https://cdn.metricalp.com/web/assets/images/hero-v4-light.webp',
},
];
export default function Projects() {
return (
<div className="p-8 flex justify-center flex-col items-center space-y-8">
{projects.map((project) => (
<div
key={project.title}
className="block rounded-lg bg-white shadow-secondary-1 text-black"
>
<div className="relative overflow-hidden bg-cover bg-no-repeat max-h-96">
<Image
className="rounded-t-lg"
src={project.image}
width={800}
height={400}
alt={project.title}
/>
</div>
<div className="p-6 text-surface ">
<h5 className="mb-2 text-xl font-medium leading-tight">
{project.title}
</h5>
<p className="mb-4 text-base">{project.description}</p>
<ProjectDetailsButton projectTitle={project.title} />
</div>
</div>
))}
</div>
);
}
Tenemos una matriz de proyectos que contiene nuestros proyectos. Estamos mapeando esta matriz y creando una tarjeta para cada proyecto. Cada tarjeta tiene una imagen, título, descripción y un botón de detalles. Cuando el usuario hace clic en el botón de detalles, estamos activando el evento Metricalp.ViewProjectDetails y pasando el título del proyecto como propiedad.
¿Simple, verdad? Creamos un sitio web de portafolio con buena apariencia, robusto y totalmente optimizado para SEO con NextJS, TailwindCSS y Metricalp. También añadimos eventos de Metricalp para rastrear los comportamientos de los usuarios y tomar decisiones basadas en datos. También usamos Metricalp como una base de datos básica para recolectar correos electrónicos. Este es solo un ejemplo básico, puedes hacer más con Metricalp. Puedes rastrear cada comportamiento del usuario, puedes recolectar cada dato que desees. Puedes hacer tu sitio web más personalizado y más fácil de usar. Puedes aumentar tus conversiones. Puedes llegar a tus clientes potenciales. Puedes cambiar el mundo. 🚀
Metricalp va a escuchar eventos de visita, cuántos visitantes únicos visitaron desde qué países, etc. automáticamente. También añadimos algunos eventos personalizados como submit_email y view_project_details.
Pero para las propiedades personalizadas adjuntas, utilizamos alias como correo electrónico y título del proyecto. Necesitamos configurar esto en el tablero de Metricalp en la configuración del rastreador - pestaña general. Hagámoslo como paso final.
Bueno, configuramos el correo electrónico como alias de propiedad personalizada 1 para el evento submit_email y el título del proyecto como alias de propiedad personalizada 1 para el evento view_project_details. Ahora, podemos activar y ver estas propiedades personalizadas de manera segura en el tablero de Metricalp.
Bueno, estamos recolectando cuántas personas visitaron nuestro portafolio. Desde dónde son, cuál es su sistema operativo, navegador, dispositivo (móvil o escritorio), etc. Pero además de estos datos analíticos estándar, estamos recolectando cuántos visitantes únicos nos dejaron su correo electrónico. Pero aún mejor, también estamos recolectando sus correos electrónicos aquí. Ni siquiera necesitamos una base de datos separada. Loco y asombroso. Además, estamos recolectando todos los eventos de vista de detalles de proyectos. Podemos ver qué proyecto está recibiendo más atención. Podemos ver qué proyecto está recibiendo más atención desde qué país, navegador, dispositivo, etc. Esto puede dar forma a nuestra carrera futura, estrategia de marketing, etc. Este es el poder de Metricalp 🚀 Estamos orgullosos de nuestro producto para ayudar a lograr esto de manera fácil.
Pero oye, leíste todo el artículo, también estamos orgullosos de ti. Espero que tengas el mejor sitio web de portafolio y llegues a tus clientes potenciales. Si tienes alguna pregunta, comentario o cualquier otra cosa, no dudes en contactarnos. Siempre estamos aquí para ayudarte. 💜 🤝