diff --git a/public/index.html b/public/index.html
index b96c181..99d54b4 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1349,13 +1349,13 @@ function saveHeroMeta() {
});
})();
-function uploadHeroImage(input) {
+async function uploadHeroImage(input) {
const file = input.files[0];
if (!file) return;
const reader = new FileReader();
- reader.onload = (e) => {
+ reader.onload = async (e) => {
const img = new Image();
- img.onload = () => {
+ img.onload = async () => {
const maxW = 1600;
let w = img.width, h = img.height;
if (w > maxW) { h = Math.round(h * maxW / w); w = maxW; }
@@ -1363,11 +1363,25 @@ function uploadHeroImage(input) {
canvas.width = w; canvas.height = h;
canvas.getContext('2d').drawImage(img, 0, 0, w, h);
const dataUrl = canvas.toDataURL('image/jpeg', 0.85);
- applyHeroImage(dataUrl);
- heroMeta.posY = 50;
- applyHeroMeta();
- saveVisionSection('hero-image', dataUrl);
- saveHeroMeta();
+
+ // Upload file to server (too large for NocoDB LongText)
+ try {
+ const res = await fetch('/api/hero-upload', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ dataUrl }),
+ });
+ const data = await res.json();
+ if (data.path) {
+ applyHeroImage(data.path);
+ heroMeta.posY = 50;
+ applyHeroMeta();
+ saveVisionSection('hero-image', data.path);
+ saveHeroMeta();
+ }
+ } catch (err) {
+ console.error('Hero upload error:', err);
+ }
};
img.src = e.target.result;
};
diff --git a/server.js b/server.js
index 0a7cfdf..fa6dbe3 100644
--- a/server.js
+++ b/server.js
@@ -239,6 +239,28 @@ app.put('/api/contenu/:sceneId', requireAuth, async (req, res) => {
}
});
+// ── Hero image upload (file too large for NocoDB LongText) ──
+const fs = require('fs');
+
+app.post('/api/hero-upload', requireAuth, (req, res) => {
+ try {
+ const { dataUrl } = req.body;
+ if (!dataUrl || !dataUrl.startsWith('data:image/')) return res.status(400).json({ error: 'Invalid image' });
+ const matches = dataUrl.match(/^data:image\/(\w+);base64,(.+)$/);
+ if (!matches) return res.status(400).json({ error: 'Invalid format' });
+ const ext = matches[1] === 'jpeg' ? 'jpg' : matches[1];
+ const buffer = Buffer.from(matches[2], 'base64');
+ const uploadDir = path.join(__dirname, 'public', 'uploads');
+ if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true });
+ const filename = `hero.${ext}`;
+ fs.writeFileSync(path.join(uploadDir, filename), buffer);
+ const publicPath = `/uploads/${filename}?t=${Date.now()}`;
+ res.json({ path: publicPath });
+ } catch (e) {
+ res.status(500).json({ error: e.message });
+ }
+});
+
// Auth gate — redirect to login page if not authenticated
app.get('/', (req, res) => {
if (isAuth(req)) {