{"id":28,"date":"2026-01-27T23:44:19","date_gmt":"2026-01-27T23:44:19","guid":{"rendered":"https:\/\/recrea.dev\/?page_id=28"},"modified":"2026-01-27T23:46:43","modified_gmt":"2026-01-27T23:46:43","slug":"thumbnail-architect","status":"publish","type":"page","link":"https:\/\/recrea.dev\/index.php\/thumbnail-architect\/","title":{"rendered":"Thumbnail Architect"},"content":{"rendered":"\n<div class=\"wp-block-columns alignwide are-vertically-aligned-top is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-vertically-aligned-top is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:100%\">\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Thumbnail Architect<\/title>\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n    <style>\n        @import url('https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@300;400;600;700&display=swap');\n        body { font-family: 'Inter', sans-serif; background-color: #0f172a; color: #f8fafc; overflow-x: hidden; }\n        .glass { background: rgba(30, 41, 59, 0.7); backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.1); }\n        .loader { border: 3px solid rgba(255,255,255,0.2); border-top: 3px solid #3b82f6; border-radius: 50%; width: 24px; height: 24px; animation: spin 1s linear infinite; }\n        @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\n        .custom-scrollbar::-webkit-scrollbar { width: 6px; }\n        .custom-scrollbar::-webkit-scrollbar-thumb { background: #334155; border-radius: 10px; }\n        .btn-primary { background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%); transition: all 0.3s ease; }\n        .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 10px 15px -3px rgba(59, 130, 246, 0.5); }\n    <\/style>\n<\/head>\n<body class=\"min-h-screen p-4 md:p-8\">\n    <div id=\"app\" class=\"max-w-5xl mx-auto\">\n        <!-- API KEY CONFIGURATION (ONLY VISIBLE UNTIL SET) -->\n        <div id=\"config-panel\" class=\"mb-8 p-6 bg-yellow-500\/10 border border-yellow-500\/30 rounded-2xl\">\n            <h3 class=\"text-yellow-500 font-bold mb-2\">Setup Required<\/h3>\n            <p class=\"text-sm text-slate-300 mb-4\">To use this on your own site, enter your Gemini API Key from <a href=\"https:\/\/aistudio.google.com\/\" target=\"_blank\" class=\"underline\">Google AI Studio<\/a>.<\/p>\n            <div class=\"flex gap-2\">\n                <input type=\"password\" id=\"api-key-input\" class=\"flex-1 bg-slate-900 border border-slate-700 rounded-lg px-4 py-2 text-sm\" placeholder=\"Paste API Key here...\">\n                <button onclick=\"saveConfig()\" class=\"bg-yellow-600 hover:bg-yellow-700 px-4 py-2 rounded-lg text-sm font-bold\">Save Key<\/button>\n            <\/div>\n        <\/div>\n\n        <header class=\"mb-12 text-center\">\n            <h1 class=\"text-4xl md:text-5xl font-extrabold bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 bg-clip-text text-transparent mb-3\">\n                Thumbnail Architect\n            <\/h1>\n            <p class=\"text-slate-400 font-medium\">Design viral YouTube thumbnails using AI<\/p>\n        <\/header>\n\n        <main class=\"glass rounded-3xl p-6 md:p-10 shadow-2xl relative\">\n            <!-- STEP 1: SUBJECT -->\n            <section id=\"step-1\" class=\"space-y-6\">\n                <div class=\"space-y-2\">\n                    <label class=\"text-xl font-bold block\">1. What is your video about?<\/label>\n                <\/div>\n                <textarea id=\"subject-input\" class=\"w-full bg-slate-900 border border-slate-700 rounded-2xl p-5 outline-none h-40 text-lg\" placeholder=\"Example: I survived 50 hours in the world's quietest room...\"><\/textarea>\n                <button onclick=\"generateHooks()\" id=\"generate-btn\" class=\"w-full py-5 btn-primary rounded-2xl font-bold text-xl flex items-center justify-center gap-3\">\n                    <span id=\"btn-text\">Generate 30 Viral Hooks<\/span>\n                    <div id=\"btn-loader\" class=\"hidden loader\"><\/div>\n                <\/button>\n            <\/section>\n\n            <!-- STEP 2: HOOKS -->\n            <section id=\"step-2\" class=\"hidden space-y-8\">\n                <div class=\"flex items-center justify-between\">\n                    <h2 class=\"text-2xl font-bold\">Choose a Hook<\/h2>\n                    <button onclick=\"resetToStep1()\" class=\"text-sm text-blue-400 font-semibold\">\u2190 Change Subject<\/button>\n                <\/div>\n                <div id=\"hooks-grid\" class=\"grid grid-cols-1 md:grid-cols-2 gap-4 max-h-[50vh] overflow-y-auto pr-3 custom-scrollbar\"><\/div>\n            <\/section>\n\n            <!-- STEP 3: REFERENCES -->\n            <section id=\"step-3\" class=\"hidden space-y-8\">\n                <div class=\"flex items-center justify-between\">\n                    <h2 class=\"text-2xl font-bold\">Upload References<\/h2>\n                    <button onclick=\"backToHooks()\" class=\"text-sm text-blue-400 font-semibold\">\u2190 Back<\/button>\n                <\/div>\n                \n                <div class=\"p-6 bg-blue-500\/10 border border-blue-500\/20 rounded-2xl\">\n                    <p id=\"selected-hook-display\" class=\"text-xl font-bold text-white\"><\/p>\n                <\/div>\n\n                <div class=\"grid grid-cols-1 md:grid-cols-2 gap-8\">\n                    <div class=\"space-y-4\">\n                        <label class=\"block font-bold text-slate-300\">Your Face \/ Subject<\/label>\n                        <div onclick=\"document.getElementById('ref-photo-input').click()\" class=\"border-2 border-dashed border-slate-700 rounded-3xl h-56 flex flex-col items-center justify-center cursor-pointer bg-slate-800\/30 overflow-hidden\">\n                            <input type=\"file\" id=\"ref-photo-input\" class=\"hidden\" accept=\"image\/*\" onchange=\"previewFile(this, 'ref-preview', 'ref-label')\">\n                            <div id=\"ref-label\" class=\"text-center\">\n                                <div class=\"text-5xl mb-2\">\ud83d\udcf8<\/div>\n                                <p class=\"text-sm text-slate-400\">Upload Subject<\/p>\n                            <\/div>\n                            <img id=\"ref-preview\" class=\"hidden w-full h-full object-cover\">\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"space-y-4\">\n                        <label class=\"block font-bold text-slate-300\">Style Reference<\/label>\n                        <div onclick=\"document.getElementById('style-photo-input').click()\" class=\"border-2 border-dashed border-slate-700 rounded-3xl h-56 flex flex-col items-center justify-center cursor-pointer bg-slate-800\/30 overflow-hidden\">\n                            <input type=\"file\" id=\"style-photo-input\" class=\"hidden\" accept=\"image\/*\" onchange=\"previewFile(this, 'style-preview', 'style-label')\">\n                            <div id=\"style-label\" class=\"text-center\">\n                                <div class=\"text-5xl mb-2\">\ud83d\uddbc\ufe0f<\/div>\n                                <p class=\"text-sm text-slate-400\">Upload Vibe<\/p>\n                            <\/div>\n                            <img id=\"style-preview\" class=\"hidden w-full h-full object-cover\">\n                        <\/div>\n                    <\/div>\n                <\/div>\n\n                <button onclick=\"generateThumbnail()\" id=\"create-btn\" class=\"w-full py-5 bg-gradient-to-r from-pink-600 to-purple-600 rounded-2xl font-bold text-xl flex items-center justify-center gap-3\">\n                    <span id=\"create-btn-text\">Generate AI Thumbnail<\/span>\n                    <div id=\"create-btn-loader\" class=\"hidden loader\"><\/div>\n                <\/button>\n            <\/section>\n\n            <!-- RESULT -->\n            <section id=\"result-section\" class=\"hidden mt-10 space-y-8 text-center\">\n                <div class=\"relative mx-auto max-w-3xl rounded-3xl overflow-hidden border-8 border-slate-800 shadow-2xl\">\n                    <img decoding=\"async\" id=\"final-thumbnail\" class=\"w-full h-auto aspect-video object-cover\" src=\"\">\n                <\/div>\n                <button onclick=\"downloadThumbnail()\" class=\"bg-white text-black px-10 py-4 rounded-full font-black text-lg\">Download PNG<\/button>\n                <br>\n                <button onclick=\"resetToStep1()\" class=\"text-slate-400 hover:text-white\">Start New Project<\/button>\n            <\/section>\n        <\/main>\n    <\/div>\n\n    <div id=\"toast\" class=\"fixed bottom-8 left-1\/2 -translate-x-1\/2 bg-red-600 text-white px-6 py-3 rounded-xl opacity-0 transition-all z-50\"><\/div>\n\n    <script>\n        let USER_KEY = localStorage.getItem('gemini_api_key') || \"\";\n        let selectedHook = \"\", subjectB64 = null, styleB64 = null;\n\n        if (USER_KEY) document.getElementById('config-panel').classList.add('hidden');\n\n        function saveConfig() {\n            const val = document.getElementById('api-key-input').value.trim();\n            if (val) {\n                localStorage.setItem('gemini_api_key', val);\n                USER_KEY = val;\n                document.getElementById('config-panel').classList.add('hidden');\n            }\n        }\n\n        function showToast(msg) {\n            const t = document.getElementById('toast');\n            t.textContent = msg;\n            t.classList.add('opacity-100');\n            setTimeout(() => t.classList.remove('opacity-100'), 4000);\n        }\n\n        function previewFile(input, imgId, labelId) {\n            const file = input.files[0];\n            const reader = new FileReader();\n            reader.onload = (e) => {\n                const b64 = e.target.result.split(',')[1];\n                if (imgId === 'ref-preview') subjectB64 = b64; else styleB64 = b64;\n                document.getElementById(imgId).src = e.target.result;\n                document.getElementById(imgId).classList.remove('hidden');\n                document.getElementById(labelId).classList.add('hidden');\n            };\n            reader.readAsDataURL(file);\n        }\n\n        async function apiCall(url, body) {\n            if (!USER_KEY) throw new Error(\"Please set your API Key first.\");\n            const res = await fetch(url + `?key=${USER_KEY}`, {\n                method: 'POST',\n                headers: { 'Content-Type': 'application\/json' },\n                body: JSON.stringify(body)\n            });\n            const data = await res.json();\n            if (!res.ok) throw new Error(data.error?.message || \"API Error\");\n            return data;\n        }\n\n        async function generateHooks() {\n            const sub = document.getElementById('subject-input').value;\n            const btn = document.getElementById('generate-btn');\n            btn.disabled = true;\n            document.getElementById('btn-loader').classList.remove('hidden');\n\n            try {\n                const res = await apiCall(`https:\/\/generativelanguage.googleapis.com\/v1beta\/models\/gemini-2.5-flash-preview-09-2025:generateContent`, {\n                    contents: [{ parts: [{ text: `Subject: ${sub}. Generate 30 viral YouTube titles as a JSON array of strings only.` }] }],\n                    generationConfig: { responseMimeType: \"application\/json\" }\n                });\n                const hooks = JSON.parse(res.candidates[0].content.parts[0].text);\n                const grid = document.getElementById('hooks-grid');\n                grid.innerHTML = '';\n                hooks.forEach(h => {\n                    const d = document.createElement('div');\n                    d.className = \"p-5 glass border border-slate-700 rounded-2xl cursor-pointer hover:border-blue-500 font-medium\";\n                    d.textContent = h;\n                    d.onclick = () => { selectedHook = h; document.getElementById('selected-hook-display').textContent = h; document.getElementById('step-2').classList.add('hidden'); document.getElementById('step-3').classList.remove('hidden'); };\n                    grid.appendChild(d);\n                });\n                document.getElementById('step-1').classList.add('hidden');\n                document.getElementById('step-2').classList.remove('hidden');\n            } catch (e) { showToast(e.message); }\n            finally { btn.disabled = false; document.getElementById('btn-loader').classList.add('hidden'); }\n        }\n\n        async function generateThumbnail() {\n            if (!subjectB64 || !styleB64) return showToast(\"Upload both photos.\");\n            const btn = document.getElementById('create-btn');\n            btn.disabled = true;\n            document.getElementById('create-btn-loader').classList.remove('hidden');\n\n            try {\n                const analysis = await apiCall(`https:\/\/generativelanguage.googleapis.com\/v1beta\/models\/gemini-2.5-flash-preview-09-2025:generateContent`, {\n                    contents: [{ role: \"user\", parts: [\n                        { text: `Detailed prompt for YouTube thumbnail. Image 1 is subject, Image 2 is style. Text: \"${selectedHook}\".` },\n                        { inlineData: { mimeType: \"image\/png\", data: subjectB64 } },\n                        { inlineData: { mimeType: \"image\/png\", data: styleB64 } }\n                    ]}]\n                });\n                \n                \/\/ Note: Imagen 4.0 requires specific Google Cloud access. \n                \/\/ For standalone sites, we use the multimodal capability or DALL-E\/Midjourney APIs.\n                \/\/ Here we attempt a standard generation if available or use Flash to describe the scene.\n                showToast(\"Architecting... this may take 15-30 seconds.\");\n                \n                \/\/ Mocking visual completion for demonstration as Imagen endpoints are restricted per-domain\n                setTimeout(() => {\n                     showToast(\"Note: Direct Imagen access requires server-side authentication for public sites.\", true);\n                }, 2000);\n            } catch (e) { showToast(e.message); }\n            finally { btn.disabled = false; document.getElementById('create-btn-loader').classList.add('hidden'); }\n        }\n\n        function resetToStep1() { location.reload(); }\n        function backToHooks() { document.getElementById('step-3').classList.add('hidden'); document.getElementById('step-2').classList.remove('hidden'); }\n    <\/script>\n<\/body>\n<\/html>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Thumbnail Architect Setup Required To use this on your own site, enter your Gemini API Key from Google AI Studio. Save Key Thumbnail Architect Design viral YouTube thumbnails using AI 1. What is your video about? Generate 30 Viral Hooks Choose a Hook \u2190 Change Subject Upload References \u2190 Back Your Face \/ Subject \ud83d\udcf8 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-28","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/recrea.dev\/index.php\/wp-json\/wp\/v2\/pages\/28","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/recrea.dev\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/recrea.dev\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/recrea.dev\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/recrea.dev\/index.php\/wp-json\/wp\/v2\/comments?post=28"}],"version-history":[{"count":4,"href":"https:\/\/recrea.dev\/index.php\/wp-json\/wp\/v2\/pages\/28\/revisions"}],"predecessor-version":[{"id":32,"href":"https:\/\/recrea.dev\/index.php\/wp-json\/wp\/v2\/pages\/28\/revisions\/32"}],"wp:attachment":[{"href":"https:\/\/recrea.dev\/index.php\/wp-json\/wp\/v2\/media?parent=28"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}