Replace static Hello World with KenJim Technologies React app
- Vite + React frontend: hero, services grid, contact form - Express + nodemailer backend for contact form → kenji@kenjim.com - Multi-stage Docker builds; nginx inside frontend proxies /api to backend - SMTP config via .env (see .env.example) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
7
backend/Dockerfile
Normal file
7
backend/Dockerfile
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM node:20-alpine
|
||||
WORKDIR /app
|
||||
COPY package.json .
|
||||
RUN npm install --production
|
||||
COPY . .
|
||||
EXPOSE 3001
|
||||
CMD ["node", "server.js"]
|
||||
13
backend/package.json
Normal file
13
backend/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "kenjim-technologies-api",
|
||||
"version": "1.0.0",
|
||||
"type": "commonjs",
|
||||
"scripts": {
|
||||
"start": "node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.19.2",
|
||||
"nodemailer": "^6.9.14"
|
||||
}
|
||||
}
|
||||
48
backend/server.js
Normal file
48
backend/server.js
Normal file
@@ -0,0 +1,48 @@
|
||||
const express = require('express')
|
||||
const nodemailer = require('nodemailer')
|
||||
const cors = require('cors')
|
||||
|
||||
const app = express()
|
||||
app.use(cors())
|
||||
app.use(express.json())
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: process.env.SMTP_HOST,
|
||||
port: parseInt(process.env.SMTP_PORT || '587'),
|
||||
secure: process.env.SMTP_SECURE === 'true',
|
||||
auth: {
|
||||
user: process.env.SMTP_USER,
|
||||
pass: process.env.SMTP_PASS,
|
||||
},
|
||||
})
|
||||
|
||||
app.post('/contact', async (req, res) => {
|
||||
const { name, email, service, message } = req.body
|
||||
|
||||
if (!name || !email || !message) {
|
||||
return res.status(400).json({ error: 'Name, email, and message are required.' })
|
||||
}
|
||||
|
||||
try {
|
||||
await transporter.sendMail({
|
||||
from: `"KenJim Technologies" <${process.env.SMTP_USER}>`,
|
||||
to: process.env.CONTACT_TO,
|
||||
replyTo: email,
|
||||
subject: `[kenjim.com] ${service || 'General Inquiry'} — ${name}`,
|
||||
text: `Name: ${name}\nEmail: ${email}\nService: ${service || 'General Inquiry'}\n\n${message}`,
|
||||
html: `
|
||||
<p><strong>Name:</strong> ${name}</p>
|
||||
<p><strong>Email:</strong> <a href="mailto:${email}">${email}</a></p>
|
||||
<p><strong>Service:</strong> ${service || 'General Inquiry'}</p>
|
||||
<hr/>
|
||||
<p>${message.replace(/\n/g, '<br>')}</p>
|
||||
`,
|
||||
})
|
||||
res.json({ ok: true })
|
||||
} catch (err) {
|
||||
console.error('Mail error:', err)
|
||||
res.status(500).json({ error: 'Failed to send message. Please try again.' })
|
||||
}
|
||||
})
|
||||
|
||||
app.listen(3001, () => console.log('API listening on :3001'))
|
||||
Reference in New Issue
Block a user