Spaces:
Running
Crée une application web SaaS nommée ShortForge AI : un générateur de vidéos courtes (YouTube Shorts, TikTok, Reels) à partir de texte/script/URL.
Browse filesObjectif principal
Transformer un input (texte, script, lien Reddit) en vidéo 9:16 MP4 (1080×1920) avec voix IA, sous-titres synchronisés, fond vidéo, musique libre de droits, et templates viraux.
Expérience rapide, claire, prête à publier.
Hero
Titre : “Crée des shorts viraux en 60 secondes”
Sous-titre : “Texte → Voix IA → Vidéo 9:16 avec captions”
CTA primaire : “Générer ma vidéo”
CTA secondaire : “Voir un exemple”
Fonctionnalités MVP
Inputs : champ texte, import .txt, URL Reddit.
Voix IA : intégration API TTS (ex. ElevenLabs/Play.ht) avec sélection voix/ton.
Captions : transcription/synchronisation automatiques (ex. Whisper/AssemblyAI).
Templates : 4 styles par défaut (Narration, Reddit Story, Educatif, Top 5).
Éditeur simplifié : choix voix, template, fond (vidéo/image), musique, intensité SFX.
Export : MP4 9:16, bitrate par défaut, preset “Social”.
Bibliothèque : quelques fonds libres (gameplay/abstrait) + upload utilisateur.
Flux utilisateur
Coller texte / coller URL Reddit
Choisir voix + template + fond + musique
Aperçu rapide (player intégré)
Générer et télécharger la vidéo
UI/UX
Design sombre, minimal, focus sur l’action.
Layout 2 colonnes : paramètres à gauche, preview à droite.
Boutons clairs, états de progression (génération, rendu, prêt).
Messages d’erreur explicites, validations côté client.
Stack suggérée (indicatif)
Frontend : Next.js + Tailwind + shadcn/ui
Backend : Node.js + FFmpeg pour rendu
IA : API TTS (ElevenLabs/Play.ht), STT/alignement (Whisper/AssemblyAI), LLM pour reformulation optionnelle
Stockage : Supabase/Firebase Storage
Auth : Clerk/Supabase Auth
Paiement : Stripe (crédits ou abonnements)
Monétisation (dans l’UI)
Gratuit : 1 export/jour avec watermark
Pro : abonnement mensuel sans watermark + voix premium
Pages/Sections
/ : Landing + démonstration
/app : Générateur (éditeur + preview)
/pricing : Plans et limites
/account : Profil, facturation, crédits
Qualité & contraintes
Gestion des files de rendu, timeouts, files d’attente.
Réessais côté serveur si FFmpeg échoue.
Journalisation basique des jobs (statut : queued, processing, done, failed).
Style
Typo moderne (Inter), coins arrondis, micro-animations sur CTA.
Icônes simples, pas de surcharges visuelles.
- app.html +104 -0
- app.js +101 -0
- components/navbar.js +6 -10
- index.html +72 -46
- pricing.html +72 -0
- script.js +5 -16
- style.css +11 -12
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>ShortForge AI – Générateur</title>
|
| 7 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 8 |
+
<link rel="stylesheet" href="style.css">
|
| 9 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 10 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 11 |
+
</head>
|
| 12 |
+
<body class="bg-gray-900 text-gray-100">
|
| 13 |
+
<custom-navbar></custom-navbar>
|
| 14 |
+
|
| 15 |
+
<main class="container mx-auto px-4 py-8 grid md:grid-cols-2 gap-6">
|
| 16 |
+
<!-- Left: Editor -->
|
| 17 |
+
<section class="bg-gray-800 rounded-xl p-6 space-y-6">
|
| 18 |
+
<h2 class="text-2xl font-bold">Éditeur</h2>
|
| 19 |
+
|
| 20 |
+
<!-- Input -->
|
| 21 |
+
<div>
|
| 22 |
+
<label class="block text-sm font-medium mb-2">Texte ou URL Reddit</label>
|
| 23 |
+
<textarea id="scriptInput" rows="5" placeholder="Copiez votre script ici…" class="w-full px-3 py-2 bg-gray-900 border border-gray-700 rounded-lg text-gray-100"></textarea>
|
| 24 |
+
<div class="mt-2 flex gap-2">
|
| 25 |
+
<button id="loadTxt" class="text-xs px-3 py-1 bg-gray-700 rounded hover:bg-gray-600">Importer .txt</button>
|
| 26 |
+
<button id="loadReddit" class="text-xs px-3 py-1 bg-gray-700 rounded hover:bg-gray-600">Coller URL Reddit</button>
|
| 27 |
+
</div>
|
| 28 |
+
</div>
|
| 29 |
+
|
| 30 |
+
<!-- Voice -->
|
| 31 |
+
<div>
|
| 32 |
+
<label class="block text-sm font-medium mb-2">Voix</label>
|
| 33 |
+
<select id="voiceSelect" class="w-full px-3 py-2 bg-gray-900 border border-gray-700 rounded-lg">
|
| 34 |
+
<option value="fr-lea">Lea – Français</option>
|
| 35 |
+
<option value="fr-remy">Rémy – Français</option>
|
| 36 |
+
<option value="en-bella">Bella – US Female</option>
|
| 37 |
+
<option value="en-mat">Mat – US Male</option>
|
| 38 |
+
</select>
|
| 39 |
+
</div>
|
| 40 |
+
|
| 41 |
+
<!-- Template -->
|
| 42 |
+
<div>
|
| 43 |
+
<label class="block text-sm font-medium mb-2">Template</label>
|
| 44 |
+
<div class="grid grid-cols-2 gap-3">
|
| 45 |
+
<button class="template-btn active" data-template="narration">Narration</button>
|
| 46 |
+
<button class="template-btn" data-template="reddit">Reddit Story</button>
|
| 47 |
+
<button class="template-btn" data-template="educatif">Educatif</button>
|
| 48 |
+
<button class="template-btn" data-template="top5">Top 5</button>
|
| 49 |
+
</div>
|
| 50 |
+
</div>
|
| 51 |
+
|
| 52 |
+
<!-- Background -->
|
| 53 |
+
<div>
|
| 54 |
+
<label class="block text-sm font-medium mb-2">Fond</label>
|
| 55 |
+
<select id="bgSelect" class="w-full px-3 py-2 bg-gray-900 border border-gray-700 rounded-lg">
|
| 56 |
+
<option value="gameplay1">Gameplay 1</option>
|
| 57 |
+
<option value="gameplay2">Gameplay 2</option>
|
| 58 |
+
<option value="abstract1">Abstract 1</option>
|
| 59 |
+
<option value="abstract2">Abstract 2</option>
|
| 60 |
+
<option value="upload">➕ Upload</option>
|
| 61 |
+
</select>
|
| 62 |
+
</div>
|
| 63 |
+
|
| 64 |
+
<!-- Music -->
|
| 65 |
+
<div>
|
| 66 |
+
<label class="block text-sm font-medium mb-2">Musique</label>
|
| 67 |
+
<select id="musicSelect" class="w-full px-3 py-2 bg-gray-900 border border-gray-700 rounded-lg">
|
| 68 |
+
<option value="none">Aucune</option>
|
| 69 |
+
<option value="lofi1">Lo-Fi Chill</option>
|
| 70 |
+
<option value="upbeat1">Upbeat Pop</option>
|
| 71 |
+
<option value="ambient1">Ambient</option>
|
| 72 |
+
</select>
|
| 73 |
+
</div>
|
| 74 |
+
|
| 75 |
+
<!-- Generate -->
|
| 76 |
+
<button id="generateBtn" class="w-full py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg hover:from-blue-600 hover:to-purple-700 transition-all">
|
| 77 |
+
Générer la vidéo
|
| 78 |
+
</button>
|
| 79 |
+
</section>
|
| 80 |
+
|
| 81 |
+
<!-- Right: Preview -->
|
| 82 |
+
<section class="bg-gray-800 rounded-xl p-6 flex flex-col items-center justify-center">
|
| 83 |
+
<h2 class="text-2xl font-bold mb-4">Aperçu</h2>
|
| 84 |
+
<div id="previewPlayer" class="w-full max-w-xs aspect-[9/16] bg-black rounded-xl overflow-hidden hidden">
|
| 85 |
+
<video id="previewVideo" class="w-full h-full object-cover" controls></video>
|
| 86 |
+
</div>
|
| 87 |
+
<div id="previewPlaceholder" class="text-gray-400 text-center">
|
| 88 |
+
<i data-feather="video" class="w-16 h-16 mx-auto mb-2"></i>
|
| 89 |
+
<p>Aperçu en attente</p>
|
| 90 |
+
</div>
|
| 91 |
+
<a id="downloadBtn" class="mt-6 hidden px-6 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-all">
|
| 92 |
+
Télécharger MP4
|
| 93 |
+
</a>
|
| 94 |
+
</section>
|
| 95 |
+
</main>
|
| 96 |
+
|
| 97 |
+
<custom-footer></custom-footer>
|
| 98 |
+
|
| 99 |
+
<script src="components/navbar.js"></script>
|
| 100 |
+
<script src="components/footer.js"></script>
|
| 101 |
+
<script src="app.js"></script>
|
| 102 |
+
<script>feather.replace();</script>
|
| 103 |
+
</body>
|
| 104 |
+
</html>
|
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// ShortForge AI – App logic
|
| 2 |
+
class ShortForgeApp {
|
| 3 |
+
constructor() {
|
| 4 |
+
this.currentTemplate = 'narration';
|
| 5 |
+
this.generated = false;
|
| 6 |
+
this.init();
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
init() {
|
| 10 |
+
this.bindEvents();
|
| 11 |
+
this.updateTemplateButtons();
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
bindEvents() {
|
| 15 |
+
// Template buttons
|
| 16 |
+
document.querySelectorAll('.template-btn').forEach(btn => {
|
| 17 |
+
btn.addEventListener('click', e => {
|
| 18 |
+
document.querySelectorAll('.template-btn').forEach(b => b.classList.remove('active'));
|
| 19 |
+
e.target.classList.add('active');
|
| 20 |
+
this.currentTemplate = e.target.dataset.template;
|
| 21 |
+
});
|
| 22 |
+
});
|
| 23 |
+
|
| 24 |
+
// Generate
|
| 25 |
+
document.getElementById('generateBtn').addEventListener('click', () => this.generate());
|
| 26 |
+
|
| 27 |
+
// Download
|
| 28 |
+
document.getElementById('downloadBtn').addEventListener('click', () => this.download());
|
| 29 |
+
|
| 30 |
+
// File upload
|
| 31 |
+
document.getElementById('loadTxt').addEventListener('click', () => this.loadTxt());
|
| 32 |
+
document.getElementById('loadReddit').addEventListener('click', () => this.loadReddit());
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
updateTemplateButtons() {
|
| 36 |
+
document.querySelectorAll('.template-btn').forEach(btn => {
|
| 37 |
+
btn.classList.toggle('active', btn.dataset.template === this.currentTemplate);
|
| 38 |
+
});
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
async loadTxt() {
|
| 42 |
+
const input = document.createElement('input');
|
| 43 |
+
input.type = 'file';
|
| 44 |
+
input.accept = '.txt';
|
| 45 |
+
input.onchange = e => {
|
| 46 |
+
const file = e.target.files[0];
|
| 47 |
+
if (!file) return;
|
| 48 |
+
const reader = new FileReader();
|
| 49 |
+
reader.onload = evt => {
|
| 50 |
+
document.getElementById('scriptInput').value = evt.target.result;
|
| 51 |
+
};
|
| 52 |
+
reader.readAsText(file);
|
| 53 |
+
};
|
| 54 |
+
input.click();
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
loadReddit() {
|
| 58 |
+
const url = prompt('Collez l’URL Reddit du post :');
|
| 59 |
+
if (!url) return;
|
| 60 |
+
// Mock fetch
|
| 61 |
+
document.getElementById('scriptInput').value = 'Mock Reddit story récupéré !';
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
async generate() {
|
| 65 |
+
const script = document.getElementById('scriptInput').value.trim();
|
| 66 |
+
if (!script) return alert('Veuillez entrer un script.');
|
| 67 |
+
|
| 68 |
+
const btn = document.getElementById('generateBtn');
|
| 69 |
+
const original = btn.innerHTML;
|
| 70 |
+
btn.disabled = true;
|
| 71 |
+
btn.innerHTML = '<i data-feather="loader" class="inline w-5 h-5 mr-2 animate-spin"></i>Génération…';
|
| 72 |
+
feather.replace();
|
| 73 |
+
|
| 74 |
+
// Simulate API
|
| 75 |
+
await new Promise(r => setTimeout(r, 3000));
|
| 76 |
+
|
| 77 |
+
// Fake video
|
| 78 |
+
const video = document.getElementById('previewVideo');
|
| 79 |
+
video.src = 'https://sample-videos.com/shorts/9-16/mp4/20.mp4';
|
| 80 |
+
document.getElementById('previewPlayer').classList.remove('hidden');
|
| 81 |
+
document.getElementById('previewPlaceholder').classList.add('hidden');
|
| 82 |
+
document.getElementById('downloadBtn').classList.remove('hidden');
|
| 83 |
+
|
| 84 |
+
this.generated = true;
|
| 85 |
+
btn.disabled = false;
|
| 86 |
+
btn.innerHTML = original;
|
| 87 |
+
feather.replace();
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
download() {
|
| 91 |
+
if (!this.generated) return;
|
| 92 |
+
const link = document.createElement('a');
|
| 93 |
+
link.href = 'https://sample-videos.com/shorts/9-16/mp4/20.mp4';
|
| 94 |
+
link.download = 'shortforge-video.mp4';
|
| 95 |
+
link.click();
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 100 |
+
new ShortForgeApp();
|
| 101 |
+
});
|
|
@@ -129,22 +129,18 @@ class CustomNavbar extends HTMLElement {
|
|
| 129 |
CanvasCraft
|
| 130 |
</a>
|
| 131 |
<div class="nav-links">
|
| 132 |
-
<a href="/
|
| 133 |
-
<a href="/
|
| 134 |
-
<a href="/
|
| 135 |
-
<a href="/about">About</a>
|
| 136 |
-
<a href="/contact">Contact</a>
|
| 137 |
</div>
|
| 138 |
<button class="mobile-menu-btn" id="mobileMenuBtn">
|
| 139 |
<i data-feather="menu"></i>
|
| 140 |
</button>
|
| 141 |
</div>
|
| 142 |
<div class="mobile-menu" id="mobileMenu">
|
| 143 |
-
<a href="/
|
| 144 |
-
<a href="/
|
| 145 |
-
<a href="/
|
| 146 |
-
<a href="/about">About</a>
|
| 147 |
-
<a href="/contact">Contact</a>
|
| 148 |
</div>
|
| 149 |
</div>
|
| 150 |
</nav>
|
|
|
|
| 129 |
CanvasCraft
|
| 130 |
</a>
|
| 131 |
<div class="nav-links">
|
| 132 |
+
<a href="/">Accueil</a>
|
| 133 |
+
<a href="/app.html">Générateur</a>
|
| 134 |
+
<a href="/pricing.html">Pricing</a>
|
|
|
|
|
|
|
| 135 |
</div>
|
| 136 |
<button class="mobile-menu-btn" id="mobileMenuBtn">
|
| 137 |
<i data-feather="menu"></i>
|
| 138 |
</button>
|
| 139 |
</div>
|
| 140 |
<div class="mobile-menu" id="mobileMenu">
|
| 141 |
+
<a href="/">Accueil</a>
|
| 142 |
+
<a href="/app.html">Générateur</a>
|
| 143 |
+
<a href="/pricing.html">Pricing</a>
|
|
|
|
|
|
|
| 144 |
</div>
|
| 145 |
</div>
|
| 146 |
</nav>
|
|
@@ -3,69 +3,96 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>
|
| 7 |
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 8 |
<link rel="stylesheet" href="style.css">
|
| 9 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 10 |
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 11 |
<script src="https://unpkg.com/feather-icons"></script>
|
| 12 |
</head>
|
| 13 |
-
<body class="bg-gray-
|
| 14 |
<custom-navbar></custom-navbar>
|
| 15 |
-
|
| 16 |
-
<main class="container mx-auto px-4 py-
|
| 17 |
-
<!--
|
| 18 |
-
<section class="text-center mb-
|
| 19 |
-
<h1 class="text-5xl font-
|
| 20 |
-
|
| 21 |
</h1>
|
| 22 |
-
<p class="text-xl text-gray-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
<button id="listView" class="px-6 py-3 bg-gray-300 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-400 dark:hover:bg-gray-600 transition-colors">
|
| 30 |
-
<i data-feather="list" class="inline w-4 h-4 mr-2"></i>List View
|
| 31 |
</button>
|
| 32 |
</div>
|
| 33 |
</section>
|
| 34 |
|
| 35 |
-
<!--
|
| 36 |
-
<section class="mb-
|
| 37 |
-
<div class="
|
| 38 |
-
<
|
| 39 |
-
|
| 40 |
-
<
|
| 41 |
-
|
| 42 |
-
<option value="people">People</option>
|
| 43 |
-
<option value="abstract">Abstract</option>
|
| 44 |
-
<option value="minimal">Minimal</option>
|
| 45 |
-
</select>
|
| 46 |
-
<select id="sizeFilter" class="px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-700 dark:text-gray-300">
|
| 47 |
-
<option value="">All Sizes</option>
|
| 48 |
-
<option value="200x200">200x200</option>
|
| 49 |
-
<option value="320x240">320x240</option>
|
| 50 |
-
<option value="640x360">640x360</option>
|
| 51 |
-
<option value="1024x576">1024x576</option>
|
| 52 |
-
<option value="1200x630">1200x630</option>
|
| 53 |
-
</select>
|
| 54 |
</div>
|
| 55 |
</section>
|
| 56 |
|
| 57 |
-
<!--
|
| 58 |
-
<section
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
</section>
|
| 61 |
|
| 62 |
-
<!--
|
| 63 |
-
<
|
| 64 |
-
<
|
| 65 |
-
|
| 66 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
</div>
|
| 68 |
-
</
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
</main>
|
| 70 |
|
| 71 |
<custom-footer></custom-footer>
|
|
@@ -74,6 +101,5 @@
|
|
| 74 |
<script src="components/footer.js"></script>
|
| 75 |
<script src="script.js"></script>
|
| 76 |
<script>feather.replace();</script>
|
| 77 |
-
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 78 |
</body>
|
| 79 |
</html>
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>ShortForge AI – Crée des shorts viraux en 60 secondes</title>
|
| 7 |
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 8 |
<link rel="stylesheet" href="style.css">
|
| 9 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 10 |
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 11 |
<script src="https://unpkg.com/feather-icons"></script>
|
| 12 |
</head>
|
| 13 |
+
<body class="bg-gray-900 text-gray-100">
|
| 14 |
<custom-navbar></custom-navbar>
|
| 15 |
+
|
| 16 |
+
<main class="container mx-auto px-4 py-12">
|
| 17 |
+
<!-- HERO -->
|
| 18 |
+
<section class="text-center mb-20">
|
| 19 |
+
<h1 class="text-5xl md:text-6xl font-extrabold mb-4 bg-gradient-to-r from-blue-400 to-purple-600 bg-clip-text text-transparent">
|
| 20 |
+
Crée des shorts viraux en 60 secondes
|
| 21 |
</h1>
|
| 22 |
+
<p class="text-xl text-gray-300 mb-8">Texte → Voix IA → Vidéo 9:16 avec captions</p>
|
| 23 |
+
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
| 24 |
+
<a href="/app.html" class="px-8 py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg hover:from-blue-600 hover:to-purple-700 transition-all">
|
| 25 |
+
Générer ma vidéo
|
| 26 |
+
</a>
|
| 27 |
+
<button id="demoBtn" class="px-8 py-3 bg-gray-800 text-gray-200 rounded-lg hover:bg-gray-700 transition-all">
|
| 28 |
+
Voir un exemple
|
|
|
|
|
|
|
| 29 |
</button>
|
| 30 |
</div>
|
| 31 |
</section>
|
| 32 |
|
| 33 |
+
<!-- DEMO -->
|
| 34 |
+
<section id="demoSection" class="hidden max-w-3xl mx-auto mb-20">
|
| 35 |
+
<div class="bg-gray-800 rounded-xl p-6 shadow-2xl">
|
| 36 |
+
<h2 class="text-2xl font-bold mb-4">Exemple de vidéo générée</h2>
|
| 37 |
+
<div class="aspect-[9/16] max-w-sm mx-auto rounded-xl overflow-hidden bg-black">
|
| 38 |
+
<video src="https://sample-videos.com/shorts/9-16/mp4/20.mp4" controls class="w-full h-full object-cover"></video>
|
| 39 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
</div>
|
| 41 |
</section>
|
| 42 |
|
| 43 |
+
<!-- FEATURES -->
|
| 44 |
+
<section class="mb-20">
|
| 45 |
+
<h2 class="text-3xl font-bold text-center mb-10">Fonctionnalités clés</h2>
|
| 46 |
+
<div class="grid md:grid-cols-3 gap-8">
|
| 47 |
+
<div class="bg-gray-800 rounded-lg p-6">
|
| 48 |
+
<i data-feather="mic" class="w-10 h-10 mb-4 text-blue-400"></i>
|
| 49 |
+
<h3 class="text-xl font-semibold mb-2">Voix IA réalistes</h3>
|
| 50 |
+
<p class="text-gray-300">Sélectionnez parmi une dizaine de voix naturelles en français et anglais.</p>
|
| 51 |
+
</div>
|
| 52 |
+
<div class="bg-gray-800 rounded-lg p-6">
|
| 53 |
+
<i data-feather="type" class="w-10 h-10 mb-4 text-purple-400"></i>
|
| 54 |
+
<h3 class="text-xl font-semibold mb-2">Captions synchronisés</h3>
|
| 55 |
+
<p class="text-gray-300">Sous-titres animés automatiquement, parfaits pour les réseaux sociaux.</p>
|
| 56 |
+
</div>
|
| 57 |
+
<div class="bg-gray-800 rounded-lg p-6">
|
| 58 |
+
<i data-feather="film" class="w-10 h-10 mb-4 text-green-400"></i>
|
| 59 |
+
<h3 class="text-xl font-semibold mb-2">Templates viraux</h3>
|
| 60 |
+
<p class="text-gray-300">Narration, Reddit Story, Educatif, Top 5… Prêt à exploser vos vues.</p>
|
| 61 |
+
</div>
|
| 62 |
+
</div>
|
| 63 |
</section>
|
| 64 |
|
| 65 |
+
<!-- HOW IT WORKS -->
|
| 66 |
+
<section class="mb-20">
|
| 67 |
+
<h2 class="text-3xl font-bold text-center mb-10">Comment ça marche ?</h2>
|
| 68 |
+
<div class="grid md:grid-cols-4 gap-6 text-center">
|
| 69 |
+
<div>
|
| 70 |
+
<div class="bg-gray-800 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4 text-2xl">1</div>
|
| 71 |
+
<h4 class="font-semibold mb-2">Collez votre texte ou URL Reddit</h4>
|
| 72 |
+
</div>
|
| 73 |
+
<div>
|
| 74 |
+
<div class="bg-gray-800 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4 text-2xl">2</div>
|
| 75 |
+
<h4 class="font-semibold mb-2">Choisissez voix, template et fond</h4>
|
| 76 |
+
</div>
|
| 77 |
+
<div>
|
| 78 |
+
<div class="bg-gray-800 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4 text-2xl">3</div>
|
| 79 |
+
<h4 class="font-semibold mb-2">Prévisualisez en temps réel</h4>
|
| 80 |
+
</div>
|
| 81 |
+
<div>
|
| 82 |
+
<div class="bg-gray-800 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4 text-2xl">4</div>
|
| 83 |
+
<h4 class="font-semibold mb-2">Exportez votre MP4 9:16</h4>
|
| 84 |
+
</div>
|
| 85 |
</div>
|
| 86 |
+
</section>
|
| 87 |
+
|
| 88 |
+
<!-- PRICING PREVIEW -->
|
| 89 |
+
<section class="mb-20 text-center">
|
| 90 |
+
<h2 class="text-3xl font-bold mb-4">Commencez gratuitement</h2>
|
| 91 |
+
<p class="text-gray-300 mb-8">1 export par jour avec watermark. Passez Pro pour illimité et voix premium.</p>
|
| 92 |
+
<a href="/pricing.html" class="px-6 py-3 bg-gradient-to-r from-purple-500 to-pink-600 text-white rounded-lg hover:from-purple-600 hover:to-pink-700 transition-all">
|
| 93 |
+
Voir les plans
|
| 94 |
+
</a>
|
| 95 |
+
</section>
|
| 96 |
</main>
|
| 97 |
|
| 98 |
<custom-footer></custom-footer>
|
|
|
|
| 101 |
<script src="components/footer.js"></script>
|
| 102 |
<script src="script.js"></script>
|
| 103 |
<script>feather.replace();</script>
|
|
|
|
| 104 |
</body>
|
| 105 |
</html>
|
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Pricing – ShortForge AI</title>
|
| 7 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 8 |
+
<link rel="stylesheet" href="style.css">
|
| 9 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 10 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 11 |
+
</head>
|
| 12 |
+
<body class="bg-gray-900 text-gray-100">
|
| 13 |
+
<custom-navbar></custom-navbar>
|
| 14 |
+
|
| 15 |
+
<main class="container mx-auto px-4 py-12">
|
| 16 |
+
<section class="text-center mb-12">
|
| 17 |
+
<h1 class="text-4xl font-bold mb-4">Plans & Pricing</h1>
|
| 18 |
+
<p class="text-gray-300">Commencez gratuitement, passez Pro quand vous êtes prêt.</p>
|
| 19 |
+
</section>
|
| 20 |
+
|
| 21 |
+
<section class="grid md:grid-cols-3 gap-8 max-w-5xl mx-auto">
|
| 22 |
+
<!-- Free -->
|
| 23 |
+
<div class="bg-gray-800 rounded-xl p-6 flex flex-col">
|
| 24 |
+
<h3 class="text-2xl font-bold mb-2">Free</h3>
|
| 25 |
+
<p class="text-3xl font-extrabold mb-4">0 €<span class="text-lg font-normal text-gray-400">/mois</span></p>
|
| 26 |
+
<ul class="space-y-2 mb-6 text-gray-300">
|
| 27 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-400"></i>1 export par jour</li>
|
| 28 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-400"></i>Watermark ShortForge</li>
|
| 29 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-400"></i>Voix standard</li>
|
| 30 |
+
<li class="flex items-start"><i data-feather="x" class="w-4 h-4 mr-2 mt-1 text-red-400"></i>Pas d’upload perso</li>
|
| 31 |
+
</ul>
|
| 32 |
+
<button class="mt-auto px-4 py-2 bg-gray-700 rounded-lg hover:bg-gray-600">Current plan</button>
|
| 33 |
+
</div>
|
| 34 |
+
|
| 35 |
+
<!-- Pro -->
|
| 36 |
+
<div class="bg-gradient-to-br from-purple-600 to-blue-600 rounded-xl p-6 flex flex-col border-2 border-purple-400">
|
| 37 |
+
<span class="self-start px-2 py-1 bg-purple-700 text-xs rounded-full mb-2">POPULAIRE</span>
|
| 38 |
+
<h3 class="text-2xl font-bold mb-2">Pro</h3>
|
| 39 |
+
<p class="text-3xl font-extrabold mb-4">9 €<span class="text-lg font-normal opacity-80">/mois</span></p>
|
| 40 |
+
<ul class="space-y-2 mb-6">
|
| 41 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-300"></i>Exports illimités</li>
|
| 42 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-300"></i>Pas de watermark</li>
|
| 43 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-300"></i>Voix premium</li>
|
| 44 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-300"></i>Upload perso</li>
|
| 45 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-300"></i>Support prioritaire</li>
|
| 46 |
+
</ul>
|
| 47 |
+
<button class="mt-auto px-4 py-2 bg-white text-purple-700 font-semibold rounded-lg hover:bg-gray-100">Upgrade</button>
|
| 48 |
+
</div>
|
| 49 |
+
|
| 50 |
+
<!-- Enterprise -->
|
| 51 |
+
<div class="bg-gray-800 rounded-xl p-6 flex flex-col">
|
| 52 |
+
<h3 class="text-2xl font-bold mb-2">Enterprise</h3>
|
| 53 |
+
<p class="text-3xl font-extrabold mb-4">Sur mesure</p>
|
| 54 |
+
<ul class="space-y-2 mb-6 text-gray-300">
|
| 55 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-400"></i>Tout inclus</li>
|
| 56 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-400"></i>API & intégrations</li>
|
| 57 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-400"></i>Comptes d’équipe</li>
|
| 58 |
+
<li class="flex items-start"><i data-feather="check" class="w-4 h-4 mr-2 mt-1 text-green-400"></i>Succès client dédié</li>
|
| 59 |
+
</ul>
|
| 60 |
+
<button class="mt-auto px-4 py-2 bg-gray-700 rounded-lg hover:bg-gray-600">Contact sales</button>
|
| 61 |
+
</div>
|
| 62 |
+
</section>
|
| 63 |
+
</main>
|
| 64 |
+
|
| 65 |
+
<custom-footer></custom-footer>
|
| 66 |
+
|
| 67 |
+
<script src="components/navbar.js"></script>
|
| 68 |
+
<script src="components/footer.js"></script>
|
| 69 |
+
<script src="script.js"></script>
|
| 70 |
+
<script>feather.replace();</script>
|
| 71 |
+
</body>
|
| 72 |
+
</html>
|
|
@@ -1,20 +1,9 @@
|
|
| 1 |
-
// CanvasCraft JavaScript
|
| 2 |
-
class TemplateManager {
|
| 3 |
-
constructor() {
|
| 4 |
-
this.templates = [];
|
| 5 |
-
this.currentView = 'grid';
|
| 6 |
-
this.currentCategory = '';
|
| 7 |
-
this.currentSize = '';
|
| 8 |
-
this.init();
|
| 9 |
-
}
|
| 10 |
-
|
| 11 |
-
init() {
|
| 12 |
-
this.loadTemplates();
|
| 13 |
-
this.setupEventListeners();
|
| 14 |
-
this.setupThemeToggle();
|
| 15 |
-
}
|
| 16 |
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
this.showLoading(true);
|
| 19 |
|
| 20 |
// Simulate API call with generated images
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
|
| 2 |
+
// ShortForge AI – Landing page JS
|
| 3 |
+
document.getElementById('demoBtn').addEventListener('click', () => {
|
| 4 |
+
document.getElementById('demoSection').classList.toggle('hidden');
|
| 5 |
+
});
|
| 6 |
+
async loadTemplates() {
|
| 7 |
this.showLoading(true);
|
| 8 |
|
| 9 |
// Simulate API call with generated images
|
|
@@ -1,19 +1,18 @@
|
|
| 1 |
-
|
|
|
|
| 2 |
:root {
|
| 3 |
-
--primary-color: #
|
| 4 |
-
--secondary-color: #
|
| 5 |
-
--accent-color: #
|
| 6 |
}
|
| 7 |
|
| 8 |
-
/*
|
| 9 |
-
|
| 10 |
-
:
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
}
|
| 15 |
}
|
| 16 |
-
|
| 17 |
/* Smooth transitions */
|
| 18 |
* {
|
| 19 |
transition: background-color 0.3s ease, border-color 0.3s ease;
|
|
|
|
| 1 |
+
|
| 2 |
+
/* ShortForge AI – Global styles */
|
| 3 |
:root {
|
| 4 |
+
--primary-color: #60a5fa;
|
| 5 |
+
--secondary-color: #a78bfa;
|
| 6 |
+
--accent-color: #34d399;
|
| 7 |
}
|
| 8 |
|
| 9 |
+
/* Template buttons */
|
| 10 |
+
.template-btn {
|
| 11 |
+
@apply px-4 py-2 bg-gray-700 rounded-lg hover:bg-gray-600 transition-colors;
|
| 12 |
+
}
|
| 13 |
+
.template-btn.active {
|
| 14 |
+
@apply bg-gradient-to-r from-blue-500 to-purple-600 text-white;
|
|
|
|
| 15 |
}
|
|
|
|
| 16 |
/* Smooth transitions */
|
| 17 |
* {
|
| 18 |
transition: background-color 0.3s ease, border-color 0.3s ease;
|