caption-generator / server.js
VinOS Agent
feat: initial PAIPS caption generator — Instagram, LinkedIn, carousel, performance tracker
496ef98
const path = require('path');
// Load .env from repo root when running locally; on HF, secrets are injected as env vars
require('dotenv').config({ path: path.join(__dirname, '../../.env') });
require('dotenv').config({ path: path.join(__dirname, '.env') }); // local override
const express = require('express');
const captionGenerator = require('./caption_generator');
const app = express();
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
// ── Routes ────────────────────────────────────────────────────────────────────
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.post('/api/generate', async (req, res) => {
try {
const { tool, creation, beforeAfter, vibe } = req.body;
if (!tool || !creation || !beforeAfter || !vibe) {
return res.status(400).json({ error: 'Missing required fields: tool, creation, beforeAfter, vibe' });
}
const result = await captionGenerator.generateAll(tool, creation, beforeAfter, vibe);
res.json({ ok: true, ...result });
} catch (e) {
console.error('Generate error:', e.message);
res.status(500).json({ error: e.message });
}
});
app.post('/api/track', (req, res) => {
try {
const entry = captionGenerator.trackPost(req.body);
res.json({ ok: true, entry });
} catch (e) {
res.status(500).json({ error: e.message });
}
});
app.get('/api/insights', (req, res) => {
try {
res.json(captionGenerator.getInsights());
} catch (e) {
res.status(500).json({ error: e.message });
}
});
// ── Start ─────────────────────────────────────────────────────────────────────
const PORT = process.env.PORT || process.env.CAPTION_PORT || 3100;
app.listen(PORT, () => {
console.log(`✅ Caption Generator running at http://localhost:${PORT}`);
});