diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md
new file mode 100644
index 0000000..02f0093
--- /dev/null
+++ b/DEPLOYMENT.md
@@ -0,0 +1,237 @@
+# ๐ ๋ฐฐํฌ ๊ฐ์ด๋
+
+## 1๏ธโฃ Resend ์ค์ (์ด๋ฉ์ผ ๋ฐ์ก)
+
+### 1๋จ๊ณ: Resend ๊ณ์ ์์ฑ
+1. [resend.com](https://resend.com) ์ ์
+2. "Sign Up" ํด๋ฆญ โ GitHub ๊ณ์ ์ผ๋ก ๊ฐ์
+3. ๋ฌด๋ฃ ํฐ์ด: ์ 3,000๊ฑด (์ถฉ๋ถํจ!)
+
+### 2๋จ๊ณ: API Key ๋ฐ๊ธ
+1. Dashboard โ "API Keys" ๋ฉ๋ด
+2. "Create API Key" ํด๋ฆญ
+3. Name: `jaengseung-made-production`
+4. Permission: `Sending access`
+5. ์์ฑ๋ ํค ๋ณต์ฌ (ํ ๋ฒ๋ง ํ์๋จ!)
+
+### 3๋จ๊ณ: ๋๋ฉ์ธ ์ธ์ฆ (์ ํ์ฌํญ)
+**์ต์
A: Resend ์๋ธ๋๋ฉ์ธ ์ฌ์ฉ (๊ฐ๋จ)**
+- `onboarding@resend.dev`์์ ๋ฐ์ก
+- ๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅ
+
+**์ต์
B: ์ปค์คํ
๋๋ฉ์ธ ์ฌ์ฉ (์ ๋ฌธ์ )**
+1. Resend Dashboard โ "Domains"
+2. "Add Domain" ํด๋ฆญ
+3. `jaengseung-made.com` ์
๋ ฅ
+4. DNS ๋ ์ฝ๋ ๋ณต์ฌ
+
+**๊ฐ๋น์ DNS ์ค์ :**
+1. [๊ฐ๋น์ My๊ฐ๋น์](https://my.gabia.com) ๋ก๊ทธ์ธ
+2. "๋๋ฉ์ธ" โ "jaengseung-made.com" ์ ํ
+3. "DNS ์ ๋ณด" โ "DNS ๊ด๋ฆฌ" ํด๋ฆญ
+4. Resend์์ ์ ๊ณตํ ๋ ์ฝ๋ ์ถ๊ฐ:
+ ```
+ Type: TXT
+ Host: _resend
+ Value: [Resend์์ ์ ๊ณตํ ๊ฐ]
+
+ Type: MX
+ Host: @
+ Value: [Resend์์ ์ ๊ณตํ ๊ฐ]
+ Priority: 10
+ ```
+5. ์ ์ฅ ํ 10~30๋ถ ๋๊ธฐ
+6. Resend์์ "Verify" ํด๋ฆญ
+
+### 4๋จ๊ณ: ๋ก์ปฌ ํ๊ฒฝ๋ณ์ ์ค์
+`.env.local` ํ์ผ ์์ :
+```bash
+RESEND_API_KEY=re_your_actual_api_key_here
+```
+
+---
+
+## 2๏ธโฃ Vercel ๋ฐฐํฌ
+
+### 1๋จ๊ณ: GitHub ์ฐ๋ (๊ถ์ฅ)
+
+**GitHub์ ํธ์:**
+```bash
+# GitHub์ ์ ์ ์ฅ์ ์์ฑ (jaengseung-made)
+git remote add github https://github.com/your-username/jaengseung-made.git
+git push github main
+```
+
+**Vercel ๋ฐฐํฌ:**
+1. [vercel.com](https://vercel.com) ๊ฐ์
(GitHub ์ฐ๋)
+2. "Add New Project" ํด๋ฆญ
+3. GitHub ์ ์ฅ์ ์ ํ: `jaengseung-made`
+4. Environment Variables ์ถ๊ฐ:
+ - `RESEND_API_KEY`: [๋ฐ๊ธ๋ฐ์ ํค ๋ถ์ฌ๋ฃ๊ธฐ]
+5. "Deploy" ํด๋ฆญ
+6. ๋ฐฐํฌ ์๋ฃ! (์ฝ 2๋ถ)
+
+### 2๋จ๊ณ: ๋๋ฉ์ธ ์ฐ๊ฒฐ (jaengseung-made.com)
+
+**Vercel ์ค์ :**
+1. Vercel Dashboard โ ํ๋ก์ ํธ ์ ํ
+2. "Settings" โ "Domains"
+3. "Add Domain" ํด๋ฆญ
+4. `jaengseung-made.com` ์
๋ ฅ
+5. DNS ์ค์ ์๋ด ํ์ธ
+
+**๊ฐ๋น์ DNS ์ค์ :**
+1. [๊ฐ๋น์ My๊ฐ๋น์](https://my.gabia.com) ๋ก๊ทธ์ธ
+2. "๋๋ฉ์ธ" โ "jaengseung-made.com" ์ ํ
+3. "DNS ์ ๋ณด" โ "DNS ๊ด๋ฆฌ" ํด๋ฆญ
+4. ๊ธฐ์กด A ๋ ์ฝ๋ ์ญ์ (์๋ค๋ฉด)
+5. ์ ๋ ์ฝ๋ ์ถ๊ฐ:
+
+**๋ฐฉ๋ฒ A: A ๋ ์ฝ๋ (๊ถ์ฅ)**
+```
+Type: A
+Host: @
+Value: 76.76.19.19
+TTL: 600
+```
+
+**๋ฐฉ๋ฒ B: CNAME ๋ ์ฝ๋**
+```
+Type: CNAME
+Host: @
+Value: cname.vercel-dns.com.
+TTL: 600
+```
+
+**www ์๋ธ๋๋ฉ์ธ ์ถ๊ฐ:**
+```
+Type: CNAME
+Host: www
+Value: cname.vercel-dns.com.
+TTL: 600
+```
+
+6. ์ ์ฅ ํ 10~30๋ถ ๋๊ธฐ
+7. Vercel์์ ์๋์ผ๋ก SSL ์ธ์ฆ์ ๋ฐ๊ธ (HTTPS)
+
+### 3๋จ๊ณ: ๋ฐฐํฌ ํ์ธ
+- https://jaengseung-made.com ์ ์
+- ๋ฌธ์ ํผ ํ
์คํธ (์ค์ ์ด๋ฉ์ผ ๋ฐ์ก ํ์ธ)
+
+---
+
+## 3๏ธโฃ ๋์: Gitea + Vercel CLI ์ง์ ๋ฐฐํฌ
+
+Vercel CLI๋ก ์ง์ ๋ฐฐํฌ:
+```bash
+# Vercel CLI ์ค์น
+npm install -g vercel
+
+# ํ๋ก์ ํธ ํด๋์์ ์คํ
+cd C:\Users\๋ฐ์ฌ์ค\Desktop\workspace\jaengseung-made
+
+# ๋ก๊ทธ์ธ
+vercel login
+
+# ๋ฐฐํฌ
+vercel --prod
+
+# ํ๊ฒฝ๋ณ์ ์ถ๊ฐ
+vercel env add RESEND_API_KEY
+# [๋ฐ๊ธ๋ฐ์ ํค ๋ถ์ฌ๋ฃ๊ธฐ]
+# Production, Preview, Development ๋ชจ๋ ์ ํ
+
+# ์ฌ๋ฐฐํฌ
+vercel --prod
+```
+
+---
+
+## 4๏ธโฃ Synology NAS ๋ฐฐํฌ (๋น์ถ์ฒ)
+
+์ฑ๋ฅ/์์ ์ฑ ์ด์ ๋ก ๋น์ถ์ฒํ์ง๋ง, ์ํ์๋ฉด:
+
+### Docker๋ก ๋ฐฐํฌ
+1. `Dockerfile` ์์ฑ (์ด๋ฏธ ์์)
+2. Docker ์ด๋ฏธ์ง ๋น๋:
+```bash
+docker build -t jaengseung-made .
+```
+3. ์ปจํ
์ด๋ ์คํ:
+```bash
+docker run -d -p 3000:3000 \
+ -e RESEND_API_KEY=your_key \
+ --name jaengseung-made \
+ jaengseung-made
+```
+4. ํฌํธ ํฌ์๋ฉ: ๋ผ์ฐํฐ์์ 80 โ NAS IP:3000
+5. ๊ฐ๋น์ DNS: A ๋ ์ฝ๋๋ฅผ ๊ณต์ธ IP๋ก ์ค์
+
+**๋ฌธ์ ์ :**
+- ๋๋ฆฐ ์๋ (๊ฐ์ ์ฉ ์ธํฐ๋ท)
+- ๋ค์ดํ์ (์ ์ , ์ฌ๋ถํ
)
+- HTTPS ์๋ ์ค์ ํ์ (Let's Encrypt)
+- ๋ณด์ ๊ด๋ฆฌ ํ์
+
+---
+
+## 5๏ธโฃ ์ต์ข
์ฒดํฌ๋ฆฌ์คํธ
+
+### ๋ฐฐํฌ ์
+- [ ] Resend ๊ณ์ ์์ฑ ๋ฐ API Key ๋ฐ๊ธ
+- [ ] `.env.local`์ API Key ์ค์
+- [ ] ๋ก์ปฌ์์ ๋ฌธ์ ํผ ํ
์คํธ (http://localhost:3000)
+- [ ] Git ์ปค๋ฐ ๋ฐ ํธ์
+
+### Vercel ๋ฐฐํฌ
+- [ ] Vercel ๊ณ์ ์์ฑ (GitHub ์ฐ๋)
+- [ ] ํ๋ก์ ํธ ๋ฐฐํฌ
+- [ ] ํ๊ฒฝ๋ณ์ ์ถ๊ฐ (RESEND_API_KEY)
+- [ ] ๋ฐฐํฌ URL์์ ํ
์คํธ
+
+### ๋๋ฉ์ธ ์ฐ๊ฒฐ
+- [ ] Vercel์ ๋๋ฉ์ธ ์ถ๊ฐ
+- [ ] ๊ฐ๋น์ DNS ์ค์ (A ๋ ์ฝ๋)
+- [ ] www ์๋ธ๋๋ฉ์ธ ์ถ๊ฐ (CNAME)
+- [ ] SSL ์ธ์ฆ์ ์๋ ๋ฐ๊ธ ํ์ธ (10~30๋ถ)
+- [ ] https://jaengseung-made.com ์ ์ ํ์ธ
+
+### ์ต์ข
ํ
์คํธ
+- [ ] ๋ฌธ์ ํผ ์ค์ ๋ฐ์ก ํ
์คํธ
+- [ ] bgg8988@gmail.com์ผ๋ก ์ด๋ฉ์ผ ์์ ํ์ธ
+- [ ] ๋ชจ๋ฐ์ผ์์ ์ ์ ํ
์คํธ
+- [ ] ๋ชจ๋ ๋งํฌ ๋์ ํ์ธ
+
+### ๋ง์ผํ
+- [ ] ํฌ๋ชฝ ์๋น์ค ๋ฑ๋ก (ํฌํธํด๋ฆฌ์ค URL ์ฒจ๋ถ)
+- [ ] ์จ๊ณ ํ๋กํ ์์ฑ
+- [ ] Google Search Console ๋ฑ๋ก
+- [ ] ๋ฉํ ํ๊ทธ ํ์ธ (์ด๋ฏธ ์ ์ฉ๋จ)
+
+---
+
+## ๐ ํธ๋ฌ๋ธ์ํ
+
+### ๋ฌธ์ ํผ์ด ์๋ํ์ง ์์์
+1. `.env.local`์ `RESEND_API_KEY` ํ์ธ
+2. Vercel ํ๊ฒฝ๋ณ์ ์ค์ ํ์ธ
+3. Resend Dashboard์์ "Logs" ํ์ธ
+4. ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ โ Network ํญ ํ์ธ
+
+### ๋๋ฉ์ธ์ด ์ฐ๊ฒฐ๋์ง ์์์
+1. DNS ์ ํ ๋๊ธฐ (์ต๋ 24์๊ฐ, ๋ณดํต 30๋ถ)
+2. DNS ์ ํ ํ์ธ: https://dnschecker.org
+3. ๊ฐ๋น์ DNS ์ค์ ์ฌํ์ธ
+4. Vercel Domain ์ํ ํ์ธ
+
+### ์ด๋ฉ์ผ์ด ์ค์ง ์์์
+1. Resend Dashboard โ "Logs" ํ์ธ
+2. ์คํธ ๋ฉ์ผํจ ํ์ธ
+3. API Key ๊ถํ ํ์ธ (Sending access)
+4. ๋๋ฉ์ธ ์ธ์ฆ ์ํ ํ์ธ (์ปค์คํ
๋๋ฉ์ธ ์ฌ์ฉ ์)
+
+---
+
+## ๐ ์ง์
+
+๋ฐฐํฌ ๊ด๋ จ ๋ฌธ์: bgg8988@gmail.com
diff --git a/app/api/contact/route.ts b/app/api/contact/route.ts
new file mode 100644
index 0000000..6ffadb2
--- /dev/null
+++ b/app/api/contact/route.ts
@@ -0,0 +1,52 @@
+import { NextResponse } from 'next/server';
+import { Resend } from 'resend';
+
+const resend = new Resend(process.env.RESEND_API_KEY);
+
+export async function POST(request: Request) {
+ try {
+ const body = await request.json();
+ const { name, phone, email, service, message } = body;
+
+ // ์
๋ ฅ ๊ฒ์ฆ
+ if (!name || !email || !message) {
+ return NextResponse.json(
+ { error: 'ํ์ ํญ๋ชฉ์ ๋ชจ๋ ์
๋ ฅํด์ฃผ์ธ์.' },
+ { status: 400 }
+ );
+ }
+
+ // ์ด๋ฉ์ผ ๋ฐ์ก
+ const data = await resend.emails.send({
+ from: 'contact@jaengseung-made.com', // Resend์์ ์ธ์ฆ๋ ๋๋ฉ์ธ
+ to: ['bgg8988@gmail.com'], // ๋ฐ๋ ์ด๋ฉ์ผ
+ subject: `[์์น๋ฉ์ด๋] ์๋ก์ด ๋ฌธ์: ${service || '๋ฌธ์'}`,
+ html: `
+
์๋ก์ด ํ๋ก์ ํธ ๋ฌธ์๊ฐ ๋์ฐฉํ์ต๋๋ค
+
+ ์ด๋ฆ: ${name}
+ ์ฐ๋ฝ์ฒ: ${phone || '๋ฏธ์
๋ ฅ'}
+ ์ด๋ฉ์ผ: ${email}
+ ์๋น์ค: ${service || '๋ฏธ์ ํ'}
+
+ ๋ฌธ์ ๋ด์ฉ:
+ ${message}
+
+
+ ์ด ๋ฉ์ผ์ jaengseung-made.com์ ๋ฌธ์ ํผ์์ ๋ฐ์ก๋์์ต๋๋ค.
+
+ `,
+ });
+
+ return NextResponse.json(
+ { success: true, message: '๋ฌธ์๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์ ์ก๋์์ต๋๋ค!' },
+ { status: 200 }
+ );
+ } catch (error) {
+ console.error('Email send error:', error);
+ return NextResponse.json(
+ { error: '๋ฉ์ผ ์ ์ก์ ์คํจํ์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.' },
+ { status: 500 }
+ );
+ }
+}
diff --git a/app/components/ContactForm.tsx b/app/components/ContactForm.tsx
new file mode 100644
index 0000000..fee32c2
--- /dev/null
+++ b/app/components/ContactForm.tsx
@@ -0,0 +1,186 @@
+'use client';
+
+import { useState } from 'react';
+
+export default function ContactForm() {
+ const [formData, setFormData] = useState({
+ name: '',
+ phone: '',
+ email: '',
+ service: 'RPA ์๋ํ',
+ message: '',
+ });
+ const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
+ const [errorMessage, setErrorMessage] = useState('');
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault();
+ setStatus('loading');
+ setErrorMessage('');
+
+ try {
+ const response = await fetch('/api/contact', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(formData),
+ });
+
+ const data = await response.json();
+
+ if (!response.ok) {
+ throw new Error(data.error || '๋ฌธ์ ์ ์ก์ ์คํจํ์ต๋๋ค.');
+ }
+
+ setStatus('success');
+ // ํผ ์ด๊ธฐํ
+ setFormData({
+ name: '',
+ phone: '',
+ email: '',
+ service: 'RPA ์๋ํ',
+ message: '',
+ });
+
+ // 3์ด ํ ์ฑ๊ณต ๋ฉ์์ง ์จ๊ธฐ๊ธฐ
+ setTimeout(() => setStatus('idle'), 5000);
+ } catch (error) {
+ setStatus('error');
+ setErrorMessage(error instanceof Error ? error.message : '๋ฌธ์ ์ ์ก์ ์คํจํ์ต๋๋ค.');
+ }
+ };
+
+ const handleChange = (
+ e: React.ChangeEvent
+ ) => {
+ setFormData((prev) => ({
+ ...prev,
+ [e.target.name]: e.target.value,
+ }));
+ };
+
+ return (
+
+
+
+
+
+
๋๋ ์๋ ์ฐ๋ฝ์ฒ๋ก ์ง์ ๋ฌธ์์ฃผ์ธ์
+
+
+
+
+ );
+}
diff --git a/app/page.tsx b/app/page.tsx
index f0c4541..0b1b7f7 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,3 +1,5 @@
+import ContactForm from './components/ContactForm';
+
export default function Home() {
return (
@@ -331,77 +333,7 @@ export default function Home() {
๋ฌด์์ด๋ ํธํ๊ฒ ์๋ดํด์ฃผ์ธ์. 24์๊ฐ ์ด๋ด ๋ต๋ณ๋๋ฆฝ๋๋ค.
-
-
-
-
-
-
๋๋ ์๋ ์ฐ๋ฝ์ฒ๋ก ์ง์ ๋ฌธ์์ฃผ์ธ์
-
-
-
-
+
diff --git a/package-lock.json b/package-lock.json
index 101564d..d640cfa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,8 @@
"dependencies": {
"next": "16.1.6",
"react": "19.2.3",
- "react-dom": "19.2.3"
+ "react-dom": "19.2.3",
+ "resend": "^6.9.1"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
@@ -1233,6 +1234,25 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@selderee/plugin-htmlparser2": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
+ "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "domhandler": "^5.0.3",
+ "selderee": "^0.11.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
+ "node_modules/@stablelib/base64": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz",
+ "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==",
+ "license": "MIT"
+ },
"node_modules/@swc/helpers": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -2113,6 +2133,17 @@
"win32"
]
},
+ "node_modules/@zone-eu/mailsplit": {
+ "version": "5.4.8",
+ "resolved": "https://registry.npmjs.org/@zone-eu/mailsplit/-/mailsplit-5.4.8.tgz",
+ "integrity": "sha512-eEyACj4JZ7sjzRvy26QhLgKEMWwQbsw1+QZnlLX+/gihcNH07lVPOcnwf5U6UAL7gkc//J3jVd76o/WS+taUiA==",
+ "license": "(MIT OR EUPL-1.1+)",
+ "dependencies": {
+ "libbase64": "1.3.0",
+ "libmime": "5.3.7",
+ "libqp": "2.1.1"
+ }
+ },
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
@@ -2718,6 +2749,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
@@ -2777,6 +2817,61 @@
"node": ">=0.10.0"
}
},
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -2806,6 +2901,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/encoding-japanese": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.2.0.tgz",
+ "integrity": "sha512-EuJWwlHPZ1LbADuKTClvHtwbaFn4rOD+dRAbWysqEOXRc2Uui0hJInNJrsdH0c+OhJA4nrCBdSkW4DD5YxAo6A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
"node_modules/enhanced-resolve": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz",
@@ -2820,6 +2924,18 @@
"node": ">=10.13.0"
}
},
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
"node_modules/es-abstract": {
"version": "1.24.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
@@ -3495,6 +3611,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-sha256": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz",
+ "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==",
+ "license": "Unlicense"
+ },
"node_modules/fastq": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
@@ -3873,6 +3995,15 @@
"node": ">= 0.4"
}
},
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "license": "MIT",
+ "bin": {
+ "he": "bin/he"
+ }
+ },
"node_modules/hermes-estree": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
@@ -3890,6 +4021,57 @@
"hermes-estree": "0.25.1"
}
},
+ "node_modules/html-to-text": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
+ "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==",
+ "license": "MIT",
+ "dependencies": {
+ "@selderee/plugin-htmlparser2": "^0.11.0",
+ "deepmerge": "^4.3.1",
+ "dom-serializer": "^2.0.0",
+ "htmlparser2": "^8.0.2",
+ "selderee": "^0.11.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
+ "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "entities": "^4.4.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz",
+ "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -4512,6 +4694,15 @@
"node": ">=0.10"
}
},
+ "node_modules/leac": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
+ "integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -4526,6 +4717,42 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/libbase64": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz",
+ "integrity": "sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==",
+ "license": "MIT"
+ },
+ "node_modules/libmime": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.3.7.tgz",
+ "integrity": "sha512-FlDb3Wtha8P01kTL3P9M+ZDNDWPKPmKHWaU/cG/lg5pfuAwdflVpZE+wm9m7pKmC5ww6s+zTxBKS1p6yl3KpSw==",
+ "license": "MIT",
+ "dependencies": {
+ "encoding-japanese": "2.2.0",
+ "iconv-lite": "0.6.3",
+ "libbase64": "1.3.0",
+ "libqp": "2.1.1"
+ }
+ },
+ "node_modules/libmime/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/libqp": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.1.1.tgz",
+ "integrity": "sha512-0Wd+GPz1O134cP62YU2GTOPNA7Qgl09XwCqM5zpBv87ERCXdfDtyKXvV7c9U22yWJh44QZqBocFnXN11K96qow==",
+ "license": "MIT"
+ },
"node_modules/lightningcss": {
"version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
@@ -4787,6 +5014,15 @@
"url": "https://opencollective.com/parcel"
}
},
+ "node_modules/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+ "license": "MIT",
+ "dependencies": {
+ "uc.micro": "^2.0.0"
+ }
+ },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -4843,6 +5079,24 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
+ "node_modules/mailparser": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.9.1.tgz",
+ "integrity": "sha512-6vHZcco3fWsDMkf4Vz9iAfxvwrKNGbHx0dV1RKVphQ/zaNY34Buc7D37LSa09jeSeybWzYcTPjhiZFxzVRJedA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zone-eu/mailsplit": "5.4.8",
+ "encoding-japanese": "2.2.0",
+ "he": "1.2.0",
+ "html-to-text": "9.0.5",
+ "iconv-lite": "0.7.0",
+ "libmime": "5.3.7",
+ "linkify-it": "5.0.0",
+ "nodemailer": "7.0.11",
+ "punycode.js": "2.3.1",
+ "tlds": "1.261.0"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -5036,6 +5290,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/nodemailer": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.11.tgz",
+ "integrity": "sha512-gnXhNRE0FNhD7wPSCGhdNh46Hs6nm+uTyg+Kq0cZukNQiYdnCsoQjodNP9BQVG9XrcK/v6/MgpAPBUFyzh9pvw==",
+ "license": "MIT-0",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -5240,6 +5503,19 @@
"node": ">=6"
}
},
+ "node_modules/parseley": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz",
+ "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==",
+ "license": "MIT",
+ "dependencies": {
+ "leac": "^0.6.0",
+ "peberminta": "^0.9.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -5267,6 +5543,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/peberminta": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz",
+ "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -5357,6 +5642,15 @@
"node": ">=6"
}
},
+ "node_modules/punycode.js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -5450,6 +5744,27 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/resend": {
+ "version": "6.9.1",
+ "resolved": "https://registry.npmjs.org/resend/-/resend-6.9.1.tgz",
+ "integrity": "sha512-jFY3qPP2cith1npRXvS7PVdnhbR1CcuzHg65ty5Elv55GKiXhe+nItXuzzoOlKeYJez1iJAo2+8f6ae8sCj0iA==",
+ "license": "MIT",
+ "dependencies": {
+ "mailparser": "3.9.1",
+ "svix": "1.84.1"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "peerDependencies": {
+ "@react-email/render": "*"
+ },
+ "peerDependenciesMeta": {
+ "@react-email/render": {
+ "optional": true
+ }
+ }
+ },
"node_modules/resolve": {
"version": "1.22.11",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
@@ -5581,12 +5896,30 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
"node_modules/scheduler": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
"license": "MIT"
},
+ "node_modules/selderee": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
+ "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==",
+ "license": "MIT",
+ "dependencies": {
+ "parseley": "^0.12.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@@ -5819,6 +6152,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/standardwebhooks": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz",
+ "integrity": "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==",
+ "license": "MIT",
+ "dependencies": {
+ "@stablelib/base64": "^1.0.0",
+ "fast-sha256": "^1.3.0"
+ }
+ },
"node_modules/stop-iteration-iterator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
@@ -6018,6 +6361,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/svix": {
+ "version": "1.84.1",
+ "resolved": "https://registry.npmjs.org/svix/-/svix-1.84.1.tgz",
+ "integrity": "sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ==",
+ "license": "MIT",
+ "dependencies": {
+ "standardwebhooks": "1.0.0",
+ "uuid": "^10.0.0"
+ }
+ },
"node_modules/tailwindcss": {
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
@@ -6087,6 +6440,15 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/tlds": {
+ "version": "1.261.0",
+ "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.261.0.tgz",
+ "integrity": "sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA==",
+ "license": "MIT",
+ "bin": {
+ "tlds": "bin.js"
+ }
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -6274,6 +6636,12 @@
"typescript": ">=4.8.4 <6.0.0"
}
},
+ "node_modules/uc.micro": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
+ "license": "MIT"
+ },
"node_modules/unbox-primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
@@ -6376,6 +6744,19 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/uuid": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
+ "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index 991bc2a..d4961b9 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,8 @@
"dependencies": {
"next": "16.1.6",
"react": "19.2.3",
- "react-dom": "19.2.3"
+ "react-dom": "19.2.3",
+ "resend": "^6.9.1"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",