Update prompt-builder.html

D David Veksler · 1 year ago 88f1ee424f33c60a7b2e89ba9178ea2ca6b7c8a4
Parent: 5bb32135e

1 file changed +221 −52

Diff

diff --git a/prompt-builder.html b/prompt-builder.html
index d95ecf4..978878b 100644
--- a/prompt-builder.html
+++ b/prompt-builder.html
@@ -3,17 +3,64 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>System Prompt Builder & Guide</title>
+    <title>System Prompt Builder & Engineering Guide</title>
+
+    <!-- SEO and Core Metadata -->
+    <meta
+      name="description"
+      content="An interactive tool to build and engineer effective system prompts for Large Language Models (LLMs), complete with a comprehensive prompting guide and useful templates."
+    />
+    <meta
+      name="keywords"
+      content="system prompt, prompt engineering, LLM, AI, prompt builder, prompt guide, generative AI, large language models, AI assistant, prompt templates, AI tools"
+    />
+    <meta name="author" content="David Vekslers Cheatsheets" />
     <link rel="canonical" href="http://cheatsheets.davidveksler.com/prompt-builder.html" />
+
+    <!-- Favicons -->
+    <link rel="icon" href="./assets/favicon.ico" sizes="any" />
+    <link rel="icon" href="./assets/favicon.svg" type="image/svg+xml" />
+    <link rel="apple-touch-icon" href="./assets/apple-touch-icon.png" /> <!-- 180x180 ideally -->
+    <!-- User-requested custom meta tag with role="icon" -->
+    <!-- Note: This is a non-standard way to declare an icon. Standard methods are above. -->
+    <meta name="application-icon" content="./assets/favicon.svg" role="icon" />
+
+    <!-- Open Graph / Facebook Meta Tags -->
+    <meta property="og:title" content="System Prompt Builder & Engineering Guide" />
+    <meta
+      property="og:description"
+      content="Build effective system prompts for LLMs and learn prompt engineering techniques with this interactive tool and guide."
+    />
+    <meta property="og:type" content="website" />
+    <meta property="og:url" content="http://cheatsheets.davidveksler.com/prompt-builder.html" />
+    <meta property="og:image" content="http://cheatsheets.davidveksler.com/assets/prompt-builder-og-image.png" /> <!-- Ideal: 1200x630px -->
+    <meta property="og:image:alt" content="Screenshot of the System Prompt Builder & Guide Tool Interface" />
+    <meta property="og:site_name" content="David Vekslers Cheatsheets" />
+
+    <!-- Twitter Card Meta Tags -->
+    <meta name="twitter:card" content="summary_large_image" />
+    <meta name="twitter:title" content="System Prompt Builder & Engineering Guide" />
+    <meta
+      name="twitter:description"
+      content="Build effective system prompts for LLMs and learn prompt engineering techniques with this interactive tool and guide."
+    />
+    <meta name="twitter:image" content="http://cheatsheets.davidveksler.com/assets/prompt-builder-og-image.png" /> <!-- Same as OG Image -->
+    <meta name="twitter:image:alt" content="Screenshot of the System Prompt Builder & Guide Tool Interface" />
+    <!-- <meta name="twitter:creator" content="@YourTwitterHandle"> --> <!-- Optional: Twitter username -->
+
+    <!-- Stylesheets -->
     <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css" />
     <style>
       body {
         padding-top: 20px;
-        background-color: #f8f9fa;
+        background-color: #f8f9fa; /* Light gray background */
+        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+          Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
+          "Segoe UI Symbol"; /* Modern system font stack */
       }
       .container-main {
-        max-width: 960px; /* Slightly wider for guide content */
+        max-width: 980px; /* Slightly wider for better content flow */
       }
       .form-check-input[type="checkbox"] {
         cursor: pointer;
@@ -29,57 +76,147 @@
         z-index: 10;
       }
       .advisor-panel {
-        background-color: #eef7ff;
-        border-left: 5px solid #0d6efd;
+        background-color: #eef7ff; /* Light blue */
+        border-left: 5px solid #0d6efd; /* Primary blue */
         padding: 15px;
         margin-bottom: 20px;
         font-size: 0.9em;
+        border-radius: 0.375rem; /* Added subtle rounding */
       }
       .advisor-panel ul {
         padding-left: 20px;
         margin-bottom: 0;
       }
-      .tab-content {
-        border: 1px solid #dee2e6;
-        border-top: none;
-        padding: 20px;
-        background-color: #fff;
-      }
       .nav-tabs .nav-link {
-        color: #0d6efd;
+        color: #0d6efd; /* Primary blue for inactive tabs */
+        font-weight: 500; /* Slightly bolder tab text */
       }
       .nav-tabs .nav-link.active {
-        color: #495057;
-        background-color: #fff;
+        color: #495057; /* Dark gray for active tab text */
+        background-color: #fff; /* White background for active tab */
         border-color: #dee2e6 #dee2e6 #fff;
       }
+      .tab-content {
+        border: 1px solid #dee2e6; /* Standard Bootstrap border color */
+        border-top: none;
+        padding: 25px; /* Increased padding for better spacing */
+        background-color: #fff; /* White background for tab content */
+        box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.05); /* Subtle shadow for depth */
+        border-bottom-left-radius: 0.375rem; /* Rounded bottom corners */
+        border-bottom-right-radius: 0.375rem; /* Rounded bottom corners */
+      }
       .guide-section h4 {
-        margin-top: 1.5rem;
+        margin-top: 1.75rem; /* Increased top margin */
         margin-bottom: 0.75rem;
-        color: #0d6efd;
+        color: #0d6efd; /* Primary blue */
+        border-bottom: 1px solid #e9ecef; /* Subtle separator */
+        padding-bottom: 0.5rem; /* Space below text, above border */
       }
       .guide-section h5 {
-        margin-top: 1rem;
+        margin-top: 1.25rem; /* Increased top margin */
         margin-bottom: 0.5rem;
-        color: #198754;
+        color: #198754; /* Success green */
       }
       .guide-section p,
       .guide-section li {
         font-size: 0.95rem;
-        line-height: 1.6;
+        line-height: 1.65; /* Slightly more line height */
       }
       .guide-section code {
         background-color: #e9ecef;
         padding: 0.2em 0.4em;
         border-radius: 3px;
         font-size: 0.9em;
+        color: #d63384; /* Bootstrap pink for code */
+      }
+      .guide-section pre > code { /* For multi-line code blocks in guide */
+        display: block;
+        padding: 1rem;
+        white-space: pre-wrap;
+        word-break: break-all;
+      }
+
+      /* Visual Appeal Enhancements */
+      .header-title-area {
+        padding-bottom: 1.5rem;
+        border-bottom: 1px solid #dee2e6; /* Separator line */
+        margin-bottom: 1.5rem !important;
+      }
+      .header-title-area h1 {
+        font-size: 2.2rem; /* Adjusted title size */
+        color: #343a40; /* Darker color for title */
+        font-weight: 600;
+      }
+      .header-title-area h1 .bi {
+        color: #0d6efd; /* Icon color match primary */
+        margin-right: 0.6rem; /* Space between icon and text */
+        vertical-align: -0.1em; /* Align icon better with text */
+      }
+
+      .accordion-button {
+        font-weight: 500;
+      }
+      .accordion-button:not(.collapsed) {
+        background-color: #e7f1ff; /* Lighter blue when open */
+        color: #0a58ca; /* Darker blue text for open accordion */
+      }
+      .accordion-button:focus {
+        box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); /* Bootstrap focus ring */
+      }
+      .accordion-item {
+        margin-bottom: 0.75rem; /* Spacing between accordion items */
+        border: 1px solid #dee2e6;
+        border-radius: 0.375rem !important; /* Rounded accordion items */
+        overflow: hidden; /* To make border-radius work with accordion buttons */
+      }
+      .accordion-item:first-of-type {
+        border-top-left-radius: 0.375rem !important;
+        border-top-right-radius: 0.375rem !important;
+      }
+      .accordion-item:last-of-type {
+        border-bottom-left-radius: 0.375rem !important;
+        border-bottom-right-radius: 0.375rem !important;
+      }
+      
+      #generatedPromptOutput {
+        background-color: #f1f3f5; /* Slightly different bg from tab content, less stark than f8f9fa */
+        border-radius: 0.25rem;
+        font-family: 'SFMono-Regular', Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* Monospace font */
+        font-size: 0.9em;
+        line-height: 1.5;
+      }
+
+      .config-buttons-wrapper {
+        display: flex;
+        justify-content: flex-start; /* Default for mobile */
+        gap: 0.5rem;
+      }
+      @media (min-width: 768px) { /* md breakpoint */
+        .config-buttons-wrapper {
+            justify-content: flex-end; /* Align to end on medium and larger screens */
+        }
+      }
+
+      footer.text-center {
+        padding-top: 2rem;
+        padding-bottom: 1rem;
+        border-top: 1px solid #e0e0e0;
+        color: #6c757d; /* Muted text color */
+        font-size: 0.9rem;
+      }
+      footer.text-center a {
+        color: #0d6efd; /* Primary blue for links */
+        text-decoration: none;
+      }
+      footer.text-center a:hover {
+        text-decoration: underline;
       }
     </style>
   </head>
   <body>
     <div class="container container-main">
-      <div class="text-center mb-4">
-        <h1><i class="bi bi-journal-richtext"></i> System Prompt Builder & Engineering Guide</h1>
+      <div class="text-center header-title-area"> <!-- mb-4 removed, handled by new class -->
+        <h1><i class="bi bi-journal-richtext"></i>System Prompt Builder &amp; Engineering Guide</h1>
       </div>
 
       <!-- Tabs Navigation -->
@@ -138,14 +275,16 @@
                 <option value="reset">Start Fresh / Clear Form</option>
               </select>
             </div>
-            <div class="col-md-6 text-md-end">
-              <button class="btn btn-sm btn-outline-secondary me-2 mt-2 mt-md-0" id="exportConfig">
-                <i class="bi bi-download"></i> Export
-              </button>
-              <input type="file" id="importConfigFile" accept=".json" style="display: none" />
-              <button class="btn btn-sm btn-outline-secondary mt-2 mt-md-0" id="importConfigTrigger">
-                <i class="bi bi-upload"></i> Import
-              </button>
+            <div class="col-md-6"> <!-- text-md-end removed -->
+              <div class="config-buttons-wrapper mt-2 mt-md-0">
+                  <button class="btn btn-sm btn-outline-secondary" id="exportConfig">
+                    <i class="bi bi-download"></i> Export
+                  </button>
+                  <input type="file" id="importConfigFile" accept=".json" style="display: none" />
+                  <button class="btn btn-sm btn-outline-secondary" id="importConfigTrigger">
+                    <i class="bi bi-upload"></i> Import
+                  </button>
+              </div>
             </div>
           </div>
 
@@ -502,7 +641,7 @@
                   <button type="button" class="btn btn-sm btn-outline-primary mt-2" id="addExampleButton">
                     <i class="bi bi-plus-circle"></i> Add Example
                   </button>
-                  <small class="form-text text-muted d-block">Provide 1-3 clear input/output pairs.</small>
+                  <small class="form-text text-muted d-block mt-1">Provide 1-3 clear input/output pairs.</small>
                 </div>
               </div>
             </div>
@@ -519,7 +658,7 @@
             <button id="copyPromptButton" class="btn btn-sm btn-outline-secondary" title="Copy to Clipboard">
               <i class="bi bi-clipboard"></i> Copy
             </button>
-            <pre><code id="generatedPromptOutput" class="p-3 border bg-light d-block" style="min-height: 200px; white-space: pre-wrap; word-wrap: break-word;">Your generated prompt will appear here...</code></pre>
+            <pre><code id="generatedPromptOutput" class="p-3 border d-block" style="min-height: 200px; white-space: pre-wrap; word-wrap: break-word;">Your generated prompt will appear here...</code></pre>
           </div>
         </div>
         <!-- End Builder Tab Pane -->
@@ -648,16 +787,16 @@ AI: Roger started with 5 balls. He bought 2 cans, and each can has 3 balls. So,
             <h5>B. Structuring Prompts with Delimiters/Tags</h5>
             <p>
               Use clear separators (e.g., triple quotes <code>"""</code>, XML tags
-              <code><instruction>...</instruction></code
+              <code>&lt;instruction&gt;...&lt;/instruction&gt;</code
               >, Markdown headings <code>## Input Data</code>) to distinguish instructions, context, examples, and input
               data. This helps the AI parse the prompt effectively.
             </p>
             <p>Anthropic's Claude models, for instance, are specifically trained to pay attention to XML tags.</p>
-            <pre><code><role>You are a helpful assistant.</role>
-<user_query>
+            <pre><code>&lt;role&gt;You are a helpful assistant.&lt;/role&gt;
+&lt;user_query&gt;
 What's the capital of France?
-</user_query>
-<instructions>Respond concisely.</instructions></code></pre>
+&lt;/user_query&gt;
+&lt;instructions&gt;Respond concisely.&lt;/instructions&gt;</code></pre>
 
             <h5>C. Breaking Down Complex Tasks (Prompt Chaining)</h5>
             <p>
@@ -683,7 +822,7 @@ What's the capital of France?
             <p>
               For complex reasoning, instruct the model to "think out loud" or use a scratchpad area (which you might
               instruct it to exclude from the final output). Some models benefit from being told to put intermediate
-              thoughts in specific tags (e.g., <code><thinking>...</thinking></code
+              thoughts in specific tags (e.g., <code>&lt;thinking&gt;...&lt;/thinking&gt;</code
               >).
             </p>
 
@@ -732,13 +871,15 @@ What's the capital of France?
       </div>
       <!-- End Tab Content -->
 
-      <footer class="text-center mt-5 mb-3">
-        <small class="text-muted"
+      <footer class="text-center mt-5 mb-3"> <!-- Original classes preserved -->
+        <small
           >Canonical URL:
           <a href="http://cheatsheets.davidveksler.com/prompt-builder.html"
             >cheatsheets.davidveksler.com/prompt-builder.html</a
           ></small
         >
+        <br/>
+        <small>Ensure you have `favicon.ico`, `favicon.svg`, `apple-touch-icon.png`, and `prompt-builder-og-image.png` in an `./assets/` folder relative to this HTML file for all icons and images to work.</small>
       </footer>
     </div>
     <!-- End Container -->
@@ -1031,9 +1172,17 @@ What's the capital of France?
 
         if (accordionButton) {
           accordionButton.addEventListener("click", function () {
+            // Bootstrap's collapse event might be more reliable, but setTimeout is simpler here
             setTimeout(() => {
+              const isCollapsed = !contentArea.classList.contains('show');
+              if (isCollapsed && toggle.checked) { // If it was open due to checkbox but button collapses it
+                 // This logic might need refinement if accordion state and checkbox state desync
+              } else if (!isCollapsed && !toggle.checked) { // If checkbox is off but accordion opens
+                 // This scenario might need attention too.
+              }
+              // For now, primarily driven by checkbox
               setInputsDisabledState(!toggle.checked);
-            }, 0);
+            }, 350); // Allow time for collapse animation
           });
         }
       });
@@ -1045,8 +1194,8 @@ What's the capital of France?
         }
         const exampleId = Date.now();
         const exampleDiv = document.createElement("div");
-        exampleDiv.classList.add("example-pair", "mb-3", "p-2", "border", "rounded");
-        exampleDiv.innerHTML = `<h6>Example Pair</h6><textarea class="form-control form-control-sm example-input" rows="2" placeholder="User: ...">${initialInput}</textarea><textarea class="form-control form-control-sm example-output mt-1" rows="3" placeholder="AI: ...">${initialOutput}</textarea><button type="button" class="btn btn-sm btn-outline-danger mt-1 remove-example" data-example-id="${exampleId}"><i class="bi bi-trash"></i> Remove</button>`;
+        exampleDiv.classList.add("example-pair", "mb-3", "p-2", "border", "rounded", "bg-light"); // Added bg-light for slight differentiation
+        exampleDiv.innerHTML = `<h6 class="small text-muted">Example Pair</h6><textarea class="form-control form-control-sm example-input" rows="2" placeholder="User: ...">${initialInput}</textarea><textarea class="form-control form-control-sm example-output mt-1" rows="3" placeholder="AI: ...">${initialOutput}</textarea><button type="button" class="btn btn-sm btn-outline-danger mt-2 remove-example" data-example-id="${exampleId}"><i class="bi bi-trash"></i> Remove</button>`;
         DOMElements.examplesContainer.appendChild(exampleDiv);
         exampleDiv.querySelector(".remove-example").addEventListener("click", function () {
           this.parentElement.remove();
@@ -1072,7 +1221,7 @@ What's the capital of France?
             } else if (sectionId === "keytasks" && getFieldValue("aiTasks")) {
               prompt += `## Key Tasks & Functions\n${getFieldValue("aiTasks").trim()}\n\n`;
             } else if (sectionId === "interactionstyle") {
-              if (getFieldValue("aiTone") !== "Neutral")
+              if (getFieldValue("aiTone") !== "Neutral") // Only add if not default neutral
                 sectionContent += `Your tone should be: ${getFieldValue("aiTone")}.\n`;
               if (getFieldValue("aiCommunicationStyle")) sectionContent += `${getFieldValue("aiCommunicationStyle")}\n`;
               if (sectionContent) prompt += `## Interaction Style & Tone\n${sectionContent.trim()}\n\n`;
@@ -1101,19 +1250,19 @@ What's the capital of France?
             } else if (sectionId === "reasoning") {
               if (getFieldValue("useCoT"))
                 sectionContent += `Employ step-by-step reasoning. ${
-                  getFieldValue("cotPhrase") ? getFieldValue("cotPhrase") + "\n" : "\n"
+                  getFieldValue("cotPhrase") ? getFieldValue("cotPhrase").trim() + "\n" : "\n"
                 }`;
               if (getFieldValue("useScratchpad"))
                 sectionContent += `Use an internal scratchpad. ${
                   getFieldValue("scratchpadTags")
-                    ? "Enclose thoughts in " + getFieldValue("scratchpadTags") + ".\n"
+                    ? "Enclose thoughts in " + getFieldValue("scratchpadTags").trim() + ".\n"
                     : "\n"
                 }`;
               if (getFieldValue("selfCritique"))
                 sectionContent += "Perform self-critique and refinement before finalizing.\n";
               if (getFieldValue("consultKnowledge"))
                 sectionContent += `Consult external knowledge if necessary. ${
-                  getFieldValue("knowledgeSourceHint") ? getFieldValue("knowledgeSourceHint") + "\n" : "\n"
+                  getFieldValue("knowledgeSourceHint") ? getFieldValue("knowledgeSourceHint").trim() + "\n" : "\n"
                 }`;
               if (sectionContent) prompt += `## Reasoning & Process\n${sectionContent.trim()}\n\n`;
             } else if (sectionId === "examples") {
@@ -1129,7 +1278,7 @@ What's the capital of France?
                     } ---\nUser: ${userInput}\nAI: ${aiOutput}\n--- End Example ${index + 1} ---\n\n`;
                   }
                 });
-                if (examplesText.length > "Here are some examples of ideal interactions:\n\n".length) {
+                if (examplesText.length > "Here are some examples of ideal interactions:\n\n".length) { // Check if any actual examples were added
                   prompt += `## Few-Shot Examples\n${examplesText.trim()}\n\n`;
                 }
               }
@@ -1157,7 +1306,12 @@ What's the capital of France?
               })
               .catch((err) => console.error("Failed to copy: ", err));
           } else {
-            alert("Nothing to copy yet. Generate a prompt first.");
+            // Provide feedback if nothing to copy
+            const originalText = DOMElements.copyPromptButton.innerHTML;
+            DOMElements.copyPromptButton.innerHTML = '<i class="bi bi-x-lg"></i> Nothing!';
+                setTimeout(() => {
+                  DOMElements.copyPromptButton.innerHTML = originalText;
+                }, 2000);
           }
         });
 
@@ -1195,6 +1349,8 @@ What's the capital of France?
             reader.onload = function (e) {
               try {
                 const config = JSON.parse(e.target.result);
+                resetFormAndEnableAllSections(); // Clear form before loading
+
                 ALL_FIELD_IDS.forEach((id) => {
                   if (config.hasOwnProperty(id)) setFieldValue(id, config[id]);
                 });
@@ -1209,24 +1365,37 @@ What's the capital of France?
                     DOMElements.addExampleButton.disabled = !toggle.checked;
                 });
 
-                if (DOMElements.examplesContainer) DOMElements.examplesContainer.innerHTML = "";
+                if (DOMElements.examplesContainer) DOMElements.examplesContainer.innerHTML = ""; // Clear again to be sure
                 if (config.examples && Array.isArray(config.examples)) {
                   config.examples.forEach((ex) => addExamplePair(ex.input, ex.output));
                 }
+                // Ensure accordion sections reflect checkbox state visually if they were closed
+                document.querySelectorAll(".section-toggle").forEach(toggle => {
+                    const collapseElement = document.getElementById(toggle.closest('.accordion-item').querySelector('.accordion-collapse').id);
+                    const bsCollapse = bootstrap.Collapse.getInstance(collapseElement) || new bootstrap.Collapse(collapseElement, {toggle: false});
+                    if (toggle.checked) {
+                        bsCollapse.show();
+                    } else {
+                        bsCollapse.hide();
+                    }
+                });
+
 
                 updateAdvisor();
+                DOMElements.promptTemplate.value = ""; // Reset template dropdown
                 alert("Configuration loaded successfully!");
               } catch (err) {
                 console.error("Error parsing/loading config:", err);
-                alert("Error loading config.");
+                alert("Error loading configuration file. Make sure it is a valid JSON export from this tool.");
               }
             };
             reader.readAsText(file);
-            DOMElements.importConfigFile.value = "";
+            DOMElements.importConfigFile.value = ""; // Reset file input
           }
         });
 
+      // Initial call to set up advisor if needed
       updateAdvisor();
     </script>
   </body>
-</html>
+</html>
\ No newline at end of file