Skip to content

Commit 82ec2dd

Browse files
committed
feat: update portafolio
1 parent 64f388e commit 82ec2dd

2 files changed

Lines changed: 49 additions & 11 deletions

File tree

portfolio/app/api/send/route.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,30 @@ const contactSchema = z.object({
1414
});
1515

1616
export async function POST(req: NextRequest) {
17+
// Configuración de CORS
18+
const headers = new Headers();
19+
headers.set('Access-Control-Allow-Origin', '*'); // O pon 'https://javiernuma.github.io' para más seguridad
20+
headers.set('Access-Control-Allow-Methods', 'POST, OPTIONS');
21+
headers.set('Access-Control-Allow-Headers', 'Content-Type');
22+
23+
// Manejo de preflight request (OPTIONS)
24+
if (req.method === 'OPTIONS') {
25+
return new NextResponse(null, { status: 200, headers });
26+
}
27+
1728
try {
18-
// Inicializamos Resend DENTRO de la función POST
1929
const resend = new Resend(process.env.RESEND_API_KEY);
20-
2130
const body = await req.json();
2231

2332
if (body.honeypot) {
24-
return NextResponse.json({ message: 'Message received!' }, { status: 200 });
33+
return NextResponse.json({ message: 'Message received!' }, { status: 200, headers });
2534
}
2635

2736
const parsed = contactSchema.safeParse(body);
2837

2938
if (!parsed.success) {
3039
const { errors } = parsed.error;
31-
return NextResponse.json({ error: 'Datos inválidos.', details: errors }, { status: 400 });
40+
return NextResponse.json({ error: 'Datos inválidos.', details: errors }, { status: 400, headers });
3241
}
3342

3443
const { name, email, message } = parsed.data;
@@ -40,19 +49,28 @@ export async function POST(req: NextRequest) {
4049
to: ['ing.javiernuma@gmail.com'],
4150
subject: `Nuevo mensaje de ${name} desde tu portafolio`,
4251
html: emailHtml,
43-
reply_to: email, // <-- Corregido: reply_to en lugar de replyTo
52+
reply_to: email,
4453
text: `Nombre: ${name}\nEmail: ${email}\nMensaje: ${message}`,
4554
});
4655

4756
if (error) {
4857
console.error('Error al enviar el correo:', error);
49-
return NextResponse.json({ error: 'Error al enviar el correo.' }, { status: 500 });
58+
return NextResponse.json({ error: 'Error al enviar el correo.' }, { status: 500, headers });
5059
}
5160

52-
return NextResponse.json({ message: 'Mensaje enviado con éxito.', data }, { status: 200 });
61+
return NextResponse.json({ message: 'Mensaje enviado con éxito.', data }, { status: 200, headers });
5362

5463
} catch (error) {
5564
console.error('Error en la API:', error);
56-
return NextResponse.json({ error: 'Error interno del servidor.' }, { status: 500 });
65+
return NextResponse.json({ error: 'Error interno del servidor.' }, { status: 500, headers });
5766
}
67+
}
68+
69+
// Manejador para OPTIONS explícito
70+
export async function OPTIONS() {
71+
const headers = new Headers();
72+
headers.set('Access-Control-Allow-Origin', '*');
73+
headers.set('Access-Control-Allow-Methods', 'POST, OPTIONS');
74+
headers.set('Access-Control-Allow-Headers', 'Content-Type');
75+
return new NextResponse(null, { status: 200, headers });
5876
}

portfolio/next.config.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,31 @@
11
/** @type {import('next').NextConfig} */
2+
3+
// Detectamos si estamos en Vercel
4+
const isVercel = process.env.VERCEL === '1';
5+
26
const nextConfig = {
3-
output: 'export',
7+
// Solo usamos 'export' si NO estamos en Vercel
8+
output: isVercel ? undefined : 'export',
9+
410
images: {
511
unoptimized: true,
612
},
7-
// basePath: process.env.NODE_ENV === 'production' ? '/portfolio' : '',
8-
// assetPrefix: process.env.NODE_ENV === 'production' ? '/portfolio/' : '',
13+
14+
// Configuración de CORS para las API Routes (solo aplica cuando se ejecuta en Vercel/Node)
15+
async headers() {
16+
return [
17+
{
18+
// Coincidir con todas las rutas de API
19+
source: "/api/:path*",
20+
headers: [
21+
{ key: "Access-Control-Allow-Credentials", value: "true" },
22+
{ key: "Access-Control-Allow-Origin", value: "*" },
23+
{ key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT,OPTIONS" },
24+
{ key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
25+
]
26+
}
27+
]
28+
}
929
}
1030

1131
export default nextConfig;

0 commit comments

Comments
 (0)