Este é o repositório do meu portfólio pessoal, um projeto desenvolvido com React e Vite para apresentar meus projetos, habilidades e experiências de forma interativa e moderna. Sinta-se à vontade para explorá-lo e utilizá-lo como desejar.
🖥️ O portfólio simula um terminal web, permitindo que visitantes explorem meu conteúdo através de comandos, tornando a navegação divertida e única. Entre os comandos disponíveis estão:
- 👤 sobre: Mostra uma breve descrição sobre mim.
- 📜 ajuda: Exibe a lista de comandos disponíveis.
- 🏢 experiencias: Mostra minha trajetória profissional e experiências.
- 📧 contato: Exibe minhas informações de contato e envia email.
- 📅 calendly: Agende uma reunião comigo via Calendly.
- 🧹 limpar: Limpa o histórico do terminal.
- 👍 recomendacoes: Exibe minhas recomendações do LinkedIn.
- 🏆 premios: Mostra prêmios e reconhecimentos.
- 📂 projetos: Lista meus projetos desenvolvidos (estáticos).
- 🐙 github: Exibe meus repositórios usando a GitHub API.
- 👨💻 habilidades: Exibe minhas habilidades em programação.
- 🎵 spotify: Mostra o que estou ouvindo e últimas reproduções.
- ⏱️ wakatime: Mostra quanto tempo passei programando e em quais linguagens.
- 📄 curriculo: Exibe meu currículo com visualização em PDF.
- 🕹️ game: Permite jogar o Flappy Plane diretamente no terminal web.
O portfólio integra componentes como ProjectCard e ExperienceCard, exibindo informações de forma dinâmica, além de suporte a múltiplos idiomas e visualização interativa de PDFs. Ele combina design moderno, navegação intuitiva e funcionalidades interativas, proporcionando uma experiência imersiva para quem deseja conhecer meu trabalho.
Este projeto surgiu durante a minha disciplina de Laboratório de Desenvolvimento de Software, no curso de Engenharia de Software da PUC Minas. A proposta era que cada aluno desenvolvesse seu próprio portfólio profissional, aplicando conceitos de engenharia de software aprendidos na disciplina de Projeto de Software, da qual também leciono.
O objetivo foi integrar teoria e prática, incentivando a experimentação e o aprendizado “mão na massa”, enquanto os alunos criavam uma apresentação interativa de suas habilidades e projetos.
O exercício completo pode ser encontrado aqui.
O grupo com o melhor portfólio ganhou como premiação um ano de domínio pago por mim (.dev, .io etc.) para cada integrante.
Grupo vencedor:
-
João Vitor Santana Lopes:
-
Gabriel Chagas Lage:
-
Pedro Maia da Costa Silva:
-
Arthur Henrique Santana Pedra:
A versão online deste projeto está hospedada e pode ser acessada através do link abaixo:
- ➡️ https://joaopauloaramuni-portfolio.vercel.app/
- ➡️ https://aramuni.dev/
- 🔹 O domínio
.dev
é uma extensão popular entre desenvolvedores e profissionais de tecnologia.
Em setembro de 2025, o custo de um domínio.dev
adquirido através da Vercel é de US$ 13 por ano.
Você pode adquirir o seu domínio diretamente no site da Vercel.
- 🔹 O domínio
- React: Biblioteca principal para a construção da interface.
- Vite: Ferramenta de build para um desenvolvimento rápido e otimizado.
O projeto utiliza várias dependências importantes para funcionalidades específicas:
- i18next & react-i18next: Para suporte a internacionalização e múltiplos idiomas.
- react-icons: Para adicionar ícones facilmente na interface.
- react-router-dom: Para navegação entre páginas dentro do React.
- react-terminal-ui: Um componente de terminal React com suporte a temas claros e escuros, baseado em termynal.js.
- react-type-animation: Para animações de digitação de texto.
- @react-pdf-viewer/core, @react-pdf-viewer/default-layout & pdfjs-dist: Para exibir PDFs diretamente na aplicação de forma interativa e estilizada.
- emailjs-com: Para enviar e-mails diretamente do frontend sem precisar de um backend próprio.
- react-calendly: (Opcional) Para integrar o Calendly diretamente no React, permitindo agendamento inline ou popup.
Essas dependências permitem funcionalidades avançadas como visualização de PDFs, animações de terminal e suporte multilíngue.
Existem duas formas principais de integrar o Calendly em uma aplicação React:
npm install react-calendly
-
O
react-calendly
é um wrapper React para o Calendly. -
Permite inserir o widget usando componentes React (
<InlineWidget>
ou<PopupWidget>
). -
É fácil de usar e se integra bem com o fluxo React.
-
Limitações:
- O controle de altura e responsividade não é tão refinado.
- Pode gerar espaço extra em dispositivos móveis.
- Menos flexível para rastrear eventos avançados ou pré-preencher campos.
Exemplo de uso:
import { InlineWidget } from "react-calendly";
<InlineWidget url="https://calendly.com/aramuni" styles={{ height: "100vh" }} />
- Carregamos o script oficial do Calendly diretamente no React.
- Permite usar atributos como
data-resize
para ajuste automático da altura. - Mais flexível: possibilita pré-preencher campos, rastrear eventos e personalizar o comportamento do widget.
- Melhor responsividade em dispositivos móveis, sem espaço extra.
Exemplo de uso:
import React, { useEffect } from "react";
useEffect(() => {
const script = document.createElement("script");
script.src = "https://assets.calendly.com/assets/external/widget.js";
script.async = true;
document.body.appendChild(script);
}, []);
<div
className="calendly-inline-widget"
data-url="https://calendly.com/aramuni"
data-resize="true"
style={{ minWidth: "320px", height: "700px" }}
></div>
Resumo:
react-calendly
: mais rápido e integrado ao React, porém menos flexível.- Embed oficial: mais controle, melhor responsividade e recursos avançados, mas requer incluir o script manualmente.
O portfólio utiliza a fonte Fira Code, uma fonte monoespaçada popular entre desenvolvedores.
Fira Code inclui ligaduras de programação, tornando a leitura de símbolos como =>
, ===
ou !=
mais agradável e estilizada, especialmente em ambientes de terminal ou editores de código.
Essa escolha de fonte melhora a estética do terminal web do portfólio e proporciona uma experiência mais fluida e moderna ao explorar comandos e visualizar códigos.
Este guia descreve o passo a passo para configurar o envio de e-mails no seu projeto React usando EmailJS. Com o EmailJS, você pode enviar até 500 e-mails por dia gratuitamente.
💡 No projeto, cada envio do formulário gera dois e-mails distintos:
-
Email de notificação para você (FOR ME)
- Contém as informações do usuário: nome, email, mensagem e horário.
- É enviado para o seu email fixo, configurado no template.
- Permite que você receba todas as mensagens enviadas pelo formulário.
-
Email de confirmação para o usuário (FOR SENDER)
- Contém uma mensagem de agradecimento, mostrando que a mensagem foi recebida.
- É enviado para o email que o usuário digitou no formulário (
{{email}}
no template). - Inclui o nome do usuário, a data/hora e pode exibir a própria mensagem como confirmação.
import EMAILJS_CONFIG from "../config/emailJsConfig";
// Email para você (notificação)
emailjs
.send(
EMAILJS_CONFIG.SERVICE_ID,
EMAILJS_CONFIG.TEMPLATE_ID_FOR_ME,
{
name: nome,
email: email,
message: mensagem,
title: `Nova mensagem do site de: ${nome}`, // assunto do email
time: time,
},
EMAILJS_CONFIG.PUBLIC_KEY
)
.then(
() => {
console.log("Email para você enviado!");
},
(err) => {
console.error("Erro ao enviar para você:", err);
setStatus(t("contato.erro"));
}
);
// Email de confirmação para o remetente
emailjs
.send(
EMAILJS_CONFIG.SERVICE_ID,
EMAILJS_CONFIG.TEMPLATE_ID_FOR_SENDER,
{
name: nome,
email: email,
message: mensagem,
title: "Recebemos sua mensagem!", // assunto do email de confirmação
time: time,
},
EMAILJS_CONFIG.PUBLIC_KEY
)
.then(
() => {
console.log("Email de confirmação enviado ao remetente!");
setStatus(t("contato.sucesso"));
e.target.reset();
},
(err) => {
console.error("Erro ao enviar confirmação:", err);
setStatus(t("contato.erro"));
}
);
- Acesse: https://www.emailjs.com/
- Clique em Sign Up e crie sua conta gratuita.
- Vá para Dashboard → Email Services.
- Clique em Add new service.
- Escolha seu provedor de e-mail (Gmail, Outlook, etc.) e conecte sua conta.
- Copie o Service ID gerado.
- Vá para Email Templates → Create New Template.
- Configure os campos que deseja enviar, por exemplo:
{{name}}
,{{email}}
,{{title}}
,{{message}}
,{{time}}
. - Copie o Template ID de cada um (para posteriormente colar nas variáveis de ambiente do Vercel ou localmente no arquivo
.env.local
.
Clique para exibir
<div style="
font-family: system-ui, sans-serif, Arial;
font-size: 14px;
color: #e2e8f0;
max-width: 600px;
margin: auto;
padding: 2rem;
border: 2px solid #00ff9d;
border-radius: 10px;
background-color: #0f172a;
line-height: 1.6;
">
<!-- Cabeçalho -->
<div style="text-align: center; margin-bottom: 1.5rem;">
<h2 style="color: #00ff9d; margin-bottom: 0.5rem;">Nova mensagem do site</h2>
<p style="color: #a0aec0; margin: 0;">
Você recebeu uma nova mensagem do formulário de contato.
</p>
</div>
<!-- Bloco da mensagem enviada -->
<div style="
margin-top: 20px;
padding: 15px;
border: 1px dashed #00ff9d;
border-radius: 8px;
background-color: #1e293b;
">
<table role="presentation" style="width: 100%; border-collapse: collapse;">
<tr>
<td style="vertical-align: top; width: 50px;">
<div style="
padding: 10px;
background-color: #00ff9d;
border-radius: 50%;
text-align: center;
font-size: 24px;
color: #0f172a;
" role="img">👤</div>
</td>
<td style="vertical-align: top; padding-left: 10px;">
<div style="color: #e2e8f0; font-size: 16px; font-weight: bold;">{{name}}</div>
<div style="color: #a0aec0; font-size: 13px;">{{email}} | {{time}}</div>
<p style="font-size: 15px; color: #e2e8f0;">{{message}}</p>
</td>
</tr>
</table>
</div>
<!-- Rodapé -->
<div style="margin-top: 20px; text-align: center; font-size: 14px; color: #a0aec0;">
<p>
Essa mensagem foi enviada pelo formulário do seu site.
</p>
</div>
</div>
Clique para exibir
<div style="
font-family: system-ui, sans-serif, Arial;
font-size: 14px;
color: #e2e8f0;
max-width: 600px;
margin: auto;
padding: 2rem;
border: 2px solid #00ff9d;
border-radius: 10px;
background-color: #0f172a;
line-height: 1.6;
">
<!-- Cabeçalho -->
<div style="text-align: center; margin-bottom: 1.5rem;">
<h2 style="color: #00ff9d; margin-bottom: 0.5rem;">Obrigado por entrar em contato!</h2>
<p style="color: #a0aec0; margin: 0;">
Recebi sua mensagem e responderei em até <strong>3 dias úteis</strong>.
</p>
</div>
<!-- Bloco da mensagem enviada -->
<div style="
margin-top: 20px;
padding: 15px;
border: 1px dashed #00ff9d;
border-radius: 8px;
background-color: #1e293b;
">
<table role="presentation" style="width: 100%; border-collapse: collapse;">
<tr>
<td style="vertical-align: top; width: 50px;">
<div style="
padding: 10px;
background-color: #00ff9d;
border-radius: 50%;
text-align: center;
font-size: 24px;
color: #0f172a;
" role="img">👤</div>
</td>
<td style="vertical-align: top; padding-left: 10px;">
<div style="color: #e2e8f0; font-size: 16px; font-weight: bold;">{{name}}</div>
<div style="color: #a0aec0; font-size: 13px;">{{time}}</div>
<p style="font-size: 15px; color: #e2e8f0;">{{message}}</p>
</td>
</tr>
</table>
</div>
<!-- Rodapé com links -->
<div style="margin-top: 20px; text-align: center; font-size: 14px; color: #a0aec0;">
<p>
Enquanto isso, fique à vontade para visitar meu
<a href="https://www.linkedin.com/in/joaopauloaramuni/" style="color: #00ff9d; text-decoration: none;">LinkedIn</a>
ou
<a href="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/joaopauloaramuni" style="color: #00ff9d; text-decoration: none;">GitHub</a>.
</p>
</div>
</div>
time
: deve ser gerada no envio (new Date().toLocaleString()
) e enviada como variável para aparecer nos templates.title
: título do email, enviado como variável{{title}}
para aparecer no assunto.- No template FOR ME, coloque seu email fixo no campo "To Email" para receber notificações de todas as mensagens.
- No template FOR SENDER (confirmação para usuário), coloque
{{email}}
no campo "To Email" para que o email seja enviado corretamente para o usuário que preencheu o formulário.
-
Acesse os seguintes links para obter os IDs necessários:
-
No Vercel, crie as seguintes variáveis de ambiente:
VITE_EMAILJS_SERVICE_ID
: seu Service IDVITE_EMAILJS_TEMPLATE_ID_FOR_ME
: seu Template ID FOR MEVITE_EMAILJS_TEMPLATE_ID_FOR_SENDER
: seu Template ID FOR SENDERVITE_EMAILJS_PUBLIC_KEY
: sua Public Key
Obs: As variáveis de ambiente em projetos Vite precisam começar com VITE_ para que o Vite as reconheça e as inclua no bundle do frontend; variáveis sem esse prefixo não ficam disponíveis no código do cliente.
Para adicionar essas variáveis:
- Acesse a página de Environment Variables do seu projeto no Vercel (ex.:
https://vercel.com/<seu-usuario>/<seu-projeto>/settings/environment-variables
) - Clique em "Add" para adicionar cada variável com o nome e valor correspondente.
Alternativamente, se estiver desenvolvendo localmente, crie um arquivo
.env.local
na raiz do seu projeto com o seguinte conteúdo:VITE_EMAILJS_SERVICE_ID=seu_service_id_aqui VITE_EMAILJS_TEMPLATE_ID_FOR_ME=seu_template_id_for_me_aqui VITE_EMAILJS_TEMPLATE_ID_FOR_SENDER=seu_template_id_for_sender_aqui VITE_EMAILJS_PUBLIC_KEY=sua_public_key_aqui
Crie ou edite o arquivo emailJsConfig.js
no seu projeto React e configure-o para usar as variáveis de ambiente definidas:
// emailJsConfig.js
const EMAILJS_CONFIG = {
SERVICE_ID: import.meta.env.VITE_EMAILJS_SERVICE_ID,
TEMPLATE_ID: import.meta.env.VITE_EMAILJS_TEMPLATE_ID_FOR_ME,
TEMPLATE_ID: import.meta.env.VITE_EMAILJS_TEMPLATE_ID_FOR_SENDER,
PUBLIC_KEY: import.meta.env.VITE_EMAILJS_PUBLIC_KEY,
};
export default EMAILJS_CONFIG;
Agora o projeto está pronto para enviar e-mails diretamente do frontend.
Este guia mostra como configurar o acesso à GitHub API para buscar seus repositórios e exibi-los no seu portfolio React.
- Acesse: Settings → Developer settings → Personal access tokens → Fine-grained tokens.
- Clique em Generate new token.
- Configure:
- Nome do token: ex.
Portfolio ReadOnly
. - Repositórios: selecione All public repositories (ou privados específicos se necessário).
- Permissões: apenas leitura para repositórios (
Read-only access
).
- Nome do token: ex.
- Clique em Generate token.
- Copie o token gerado.
⚠️ Importante: você não poderá ver novamente depois de sair da página.
Dica: prefira Fine-grained tokens para maior segurança. Tokens General use dão acesso mais amplo e são menos seguros.
Crie um arquivo .env.local
na raiz do projeto React:
VITE_GITHUB_TOKEN=seu_token_aqui
Observação: No Vite, todas as variáveis de ambiente expostas ao front-end devem começar com
VITE_
.
Crie um arquivo gitHubApiConfig.js
em src/config/
:
// gitHubApiConfig.js
const GITHUB_API_CONFIG = {
USERNAME: "joaopauloaramuni",
TOKEN: import.meta.env.VITE_GITHUB_TOKEN,
BASE_URL: "https://api.github.com",
PER_PAGE: 100, // quantidade máxima de repositórios por página
};
export default GITHUB_API_CONFIG;
- Acesse seu projeto no Vercel.
- Vá em Settings → Environment Variables.
- Adicione a variável:
- Name:
VITE_GITHUB_TOKEN
- Value: o token que você gerou
- Environment: Production / Preview / Development conforme necessário.
- Name:
- Salve as alterações.
No seu componente ProjetosGitHub.jsx
, você pode fazer algo como:
import GITHUB_API_CONFIG from "../config/gitHubApiConfig";
const { USERNAME, TOKEN, BASE_URL, PER_PAGE } = GITHUB_API_CONFIG;
const response = await fetch(
`${BASE_URL}/users/${USERNAME}/repos?sort=updated&per_page=${PER_PAGE}`,
{
headers: {
Authorization: `token ${TOKEN}`,
Accept: "application/vnd.github.mercy-preview+json", // para incluir topics
},
}
);
const data = await response.json();
- URL:
${BASE_URL}/users/${USERNAME}/repos
busca todos os repositórios do usuário. - Query params:
sort=updated
: ordena pelos mais recentemente atualizados.per_page=100
: quantidade máxima de repositórios por página.
- Headers:
Authorization
: envia o token para autenticação.Accept
: especifica a versão da API que inclui os topics dos repositórios.
- data: retorna um array de objetos com informações dos repositórios.
Depois de buscar os repositórios, você pode mapear para seu ProjectCard
:
const mappedRepos = data
.filter(repo => !repo.fork)
.map(repo => ({
id: repo.id,
title: repo.name,
description: repo.description || "Sem descrição disponível",
gif: `https://opengraph.githubassets.com/1/${USERNAME}/${repo.name}`,
repoLink: repo.html_url,
technologies: repo.topics || [],
}));
Dessa forma, cada
ProjectCard
recebe todas as informações necessárias: título, descrição, gif, link e tecnologias.
✅ Pronto! Agora seu portfolio consegue buscar e exibir seus repositórios públicos usando a GitHub API.
Para executar este projeto no seu ambiente de desenvolvimento, siga os passos abaixo.
Antes de começar, certifique-se de ter o Node.js instalado na sua máquina. Ele é essencial para gerenciar as dependências do projeto.
-
Clone o repositório:
git clone https://github.com/joaopauloaramuni/joaopauloaramuni-portfolio.git
-
Acesse o diretório do projeto:
cd joaopauloaramuni-portfolio
-
Instale as dependências:
npm install
-
Execute a aplicação:
npm run dev
-
Abra o endereço local exibido no terminal (geralmente
http://localhost:5173
) no seu navegador para ver o projeto em execução.
O Docker é uma plataforma que permite criar, executar e gerenciar aplicações de forma isolada através de containers.
- Containers são ambientes leves e portáteis que empacotam a aplicação junto com todas as suas dependências.
- Imagens são modelos imutáveis que descrevem como o container deve ser construído e executado.
- O Docker Hub é um repositório público (semelhante ao GitHub, mas para imagens Docker) onde desenvolvedores podem armazenar e compartilhar imagens prontas para uso.
⚠️ É importante destacar que projetos React + Vite não precisam de um Dockerfile para serem publicados no Vercel. O Vercel já cuida automaticamente do processo de build e deploy.
Nativamente, o Vercel suporta uma ampla gama de tecnologias modernas sem necessidade de Docker, incluindo React, Next.js, Vue, Svelte, Angular, Node.js, APIs Serverless, além de projetos estáticos gerados por ferramentas como Vite, Gatsby e Hugo.
Ele faz o build, gera os arquivos estáticos ou funções serverless e gerencia automaticamente o deploy, cache e CDN, permitindo que você publique aplicações complexas sem precisar configurar containers manualmente.
⚠️ Observação: o Vercel não oferece suporte nativo a aplicações Java (como Spring Boot ou Jakarta EE). Para rodar projetos Java, seria necessário usar Docker ou outra nuvem/serviço que suporte JVM, como AWS, Google Cloud, Heroku ou Render.
Aqui, o Dockerfile foi criado apenas a título de aprendizado, mas pode ser útil em cenários futuros, como:
- 📦 Hospedar o projeto em um servidor próprio usando DigitalOcean, AWS EC2 ou Google Cloud Run;
- 📦 Padronizar ambientes de desenvolvimento e testes com Docker Compose;
- 📦 Utilizar pipelines de CI/CD no GitHub Actions, GitLab CI ou Jenkins, garantindo que o build seja sempre reproduzível.
O Docker Compose é uma ferramenta que permite definir e gerenciar múltiplos containers Docker como parte de uma mesma aplicação.
Em vez de subir manualmente cada container com docker run
, você descreve todos os serviços da sua aplicação (ex.: frontend, backend, banco de dados, cache) em um único arquivo chamado docker-compose.yml
.
Com esse arquivo, você pode:
- Subir toda a aplicação de uma vez com
docker compose up
; - Derrubar todos os serviços com
docker compose down
; - Definir volumes, redes e variáveis de ambiente entre containers;
- Padronizar ambientes de desenvolvimento e testes sem depender da máquina do desenvolvedor.
📦 Exemplo prático:
Um projeto pode precisar de um frontend React, um backend Node.js e um banco PostgreSQL.
Com o Docker Compose, basta rodar um comando e todos esses serviços sobem juntos, prontos para se comunicarem entre si.
👉 Em resumo, o Docker Compose é como um “orquestrador simplificado” que facilita rodar aplicações multi-containers de forma prática e padronizada.
⚠️ Observação: Neste projeto, não há um arquivodocker-compose.yml
, pois ele utiliza apenas um container para servir a aplicação frontend com NGINX.
O NGINX é um servidor web de alta performance, leve e amplamente utilizado para servir arquivos estáticos, atuar como proxy reverso e balanceador de carga.
Neste Dockerfile, ele é usado para servir a aplicação frontend gerada pelo Vite (React).
📌 Funções principais no container:
- Imagem base:
nginx:stable-alpine
fornece uma versão leve e pronta do NGINX; - Limpeza de arquivos padrão: remove arquivos default do NGINX para evitar conflitos;
- Servir arquivos estáticos: copia os arquivos gerados pelo build da aplicação para o diretório do NGINX (
/usr/share/nginx/html
); - Exposição da porta 80: permite que o container receba requisições HTTP;
- Execução contínua:
nginx -g "daemon off;"
mantém o servidor em execução dentro do container.
✅ Em resumo: O NGINX neste Dockerfile atua como servidor web, entregando a aplicação frontend pronta de forma rápida, eficiente e confiável para qualquer cliente HTTP.
Clique para exibir
# ----------------------------
# Stage 1: Build da aplicação
# ----------------------------
FROM node:18-alpine AS build
WORKDIR /app
# Copiar package.json e package-lock.json (ou yarn.lock/pnpm-lock.yaml)
COPY package*.json ./
# Instalar dependências
RUN npm install
# Copiar todo o código
COPY . .
# Build do Vite (gera arquivos estáticos em /dist)
RUN npm run build
# ----------------------------
# Stage 2: Servir com Nginx
# ----------------------------
FROM nginx:stable-alpine
# Remover arquivos default do Nginx
RUN rm -rf /usr/share/nginx/html/*
# Copiar build do Vite
COPY --from=build /app/dist /usr/share/nginx/html
# Expor a porta padrão do Nginx
EXPOSE 80
# Comando de inicialização do Nginx
CMD ["nginx", "-g", "daemon off;"]
Antes de tudo, certifique-se de que o Docker Desktop (no Mac/Windows) ou o serviço Docker (em Linux) está em execução.
-
No Mac/Windows: basta abrir o aplicativo Docker Desktop.
-
No Linux: rode o comando abaixo para iniciar o serviço:
sudo systemctl start docker
-
Acesse a pasta do projeto:
cd /caminho/do/projeto/joaopauloaramuni-portfolio
-
Gere a imagem a partir do Dockerfile:
docker build -t portfolio .
-
Rode o container mapeando a porta 8080 do host para a porta 80 do Nginx:
docker run -p 8080:80 portfolio
⚠️ Observação: você pode escolher qualquer porta disponível no host, por exemplo5173:80
, para acessar no navegador usandohttp://localhost:5173
. -
Abra no navegador:
👉 http://localhost:8080 (ou a porta que você escolheu, como 5173) -
Para parar o container em execução, descubra o ID ou nome com:
docker ps
E então pare-o com:
docker stop <id_ou_nome_do_container>
✅ Em resumo: este Dockerfile não é necessário para deploys no Vercel, mas oferece conhecimento valioso e flexibilidade para cenários em que o projeto precise rodar em ambientes Dockerizados, seja em nuvem, seja em servidores próprios.
- react-terminal-ui: GitHub | Demo
- termynal.js (estilo do terminal): GitHub
- i18next & react-i18next (internacionalização): i18next Docs | react-i18next Docs
- @react-pdf-viewer/core & @react-pdf-viewer/default-layout: Documentação oficial
- pdfjs-dist (renderização de PDFs): Mozilla PDF.js GitHub
- react-calendly: (Opcional) NPM | GitHub
- EmailJS: Documentação oficial | Dashboard
- React Icons: React Icons
- Vercel: Documentação | Environment Variables
- Spotify e Last.fm: Spotify GitHub Profile - Kittinan | Spotify Recently Played Readme - JeffreyCA | Data Card for Spotify | Last.fm Recently Played Readme - JeffreyCA
- WakaTime: WakaTime Readme Stats - Anmol098 | WakaTime Stats API | WakaTime API Key Settings
- GitHubAPI: Documentação | Token
- Calendly (agendamento online): Embed options overview | How to add Calendly to your website | Embed Inline | Embed Options Overview | Advanced Calendly Embed for Developers
- Docker (containerização de aplicações): Documentação oficial
- Docker Desktop (ferramenta para rodar Docker no Mac e Windows; no Linux, use Docker Engine): Documentação oficial
- Docker Hub (repositório de imagens Docker): Documentação oficial
- NGINX (servidor web e proxy reverso): Documentação oficial
Este projeto é distribuído sob a MIT License.