story-generator

安装量: 41
排名: #17616

安装

npx skills add https://github.com/dmccreary/claude-skills --skill story-generator

Story Generator This skill generates complete graphic novel narratives about key contributors to various subjects for intelligent textbooks built with MkDocs Material markdown. The stories are designed to be inspirational, engaging and educational for high school students, with a focus on historical accuracy and compelling storytelling. Each story includes detailed image prompts for AI image generation of each panel, ensuring a visually rich experience that complements the narrative. Each panel image is followed by a short 3-4 sentence narrative that provides context and emotional depth to the scene depicted, making the story accessible and engaging for high school students. When to Use This Skill Use this skill when: The user requests a new graphic novel story about a scientist or physicist Adding a story to a Physics History Graphic Novels section Creating educational narrative content with image prompts for AI image generation The user mentions "story", "graphic novel", or "narrative" about a historical scientist Story Structure Each story follows a consistent structure designed to engage high school students: Required Components YAML Frontmatter - Title, description, social media image paths Cover Image - With detailed generation prompt in

block Narrative Prompt - Background context for generating the story Prologue - Hook introducing the scientist's significance Chapters (12-14) - Each with narrative text, image placeholder, and image prompt for the panel Epilogue - Lessons table summarizing what made the scientist successful Call to Action - Inspiring message connecting to readers Quotes - 2-3 memorable quotes from the scientist References - Academic sources (can use placeholders initially) A template for the story structure can be found in skills/story-generator/references/index-template.md . Image Prompt Requirements Every image prompt must specify: Wide-landscape 16:9 format Period-appropriate art style (e.g., "Victorian", "Art Nouveau", "Renaissance") Specific scene details and characters Color palette guidance Emotional tone and mood Workflow Step 1: Gather Information and Plan the Story Before writing, identify: The scientist's name and birth/death years Key discoveries or contributions Central theme (e.g., "overcoming doubters", "persistence through failure") Historical period and appropriate art style 3-5 key life events that form the narrative arc Step 2: Create Story Directory mkdir -p docs/stories/ < scientist-name > Use lowercase with hyphens for directory names (e.g., nikola-tesla , marie-curie ). Step 3: Write the Story Create docs/stories//index.md with the following structure: --- title : - 's description : A graphic - novel story of how ... image : /stories/ /cover.png og:image : /stories/ /cover.png twitter:image : /stories/ /cover.png social : cards : false --- # : ! [ Cover image ]( ./cover.png ) < details > < summary > Cover Image Prompt [Detailed cover image generation prompt - 16:9 format, period style, composition details. Include specific characters, setting, color palette, and emotional tone.]

< details

< summary

Narrative Prompt </ summary

[Background context and style guide for the entire story] </ details

Prologue – [Opening narrative establishing the scientist's importance] < details

< summary

Image Prompt </ summary

Please generate a 16:9 image in [period style] depicting the the first panel. The scene should include [specific characters], set in [specific setting including period in time and location], with a color palette of [color palette]. The emotional tone should be [emotional tone]. [Detailed image prompt for prologue scene with a minimum of 6 specific details to guide the AI image generation.] </ details

Panel N – < details

< summary

Image Prompt </ summary

Please generate a 16:9 image in [period style] depicting the panel N. The scene should include [specific characters], set in [specific setting including period in time and location], with a color palette of [color palette]. The emotional tone should be [emotional tone]. [Detailed image prompt for prologue scene with a minimum of 6 specific details to guide the AI image generation.] </ details

[Panel narrative text which is 3-4 sentences long. This is the text that will appear in the graphic novel panel. It should be engaging and move the story forward, while also being historically accurate and appropriate for high school students. The narrative should be written in a way that complements the image, providing context and emotional depth to the scene depicted. Use active voice and vivid descriptions to bring the story to life, while also ensuring that the language is accessible to the target audience.] [Continue for 12-14 chapters...]

Epilogue – What Made Different? [Summary of lessons learned] | Challenge | How < Scientist

Responded | Lesson for Today | |


|

|

| | ... | ... | ... |

Call to Action [Inspiring message connecting to readers]


* "Quote from scientist" * — < Scientist Name


References 1. Title - Description [Continue with 4-6 references] Important: Always use .png extension for image references (not .jpg ). Step 4: Add to Navigation Edit mkdocs.yml to add the story in chronological order by birth year : - Stories : - Overview : stories/index.md - - : stories/<scientist - name</p> <blockquote> <p>/index.md Reference chronological order: Archimedes (287 BC) Galileo (1564) Newton (1643) Faraday (1791) Tesla (1856) Marie Curie (1867) Rutherford (1871) Lise Meitner (1878) Einstein (1879) Chien-Shiung Wu (1912) Vera Rubin (1928) Step 5: Add Grid Card to Stories Index Edit docs/stories/index.md to add a card using MkDocs Material grid format: - ** <a href="<scientist-name>/index.md"> <Story Title> </a> ** <img alt="<Scientist Name>" src="./<scientist-name>/cover.png" /> <2-4 sentence compelling description emphasizing the story's theme> Writing Guidelines Target Audience High school students (grades 9-12) Age 14-18 Introductory physics background Reading level: accessible but not dumbed down Narrative Style Use active voice and vivid descriptions Include dialogue when historically appropriate Balance drama with educational accuracy Emphasize the human story behind discoveries Show struggles, failures, and persistence Connect historical events to modern technology Theme Development Choose a central theme that resonates with teenagers: Overcoming doubters and skeptics Persistence through failure Self-education and curiosity Fighting against discrimination Seeing what others couldn't see Staying humble despite success Historical Accuracy Research key dates, events, and relationships Use historically accurate details in image prompts Note any creative liberties in the narrative prompt Include verifiable quotes when possible Art Style Reference by Era Era Suggested Art Style Ancient (before 500 AD) Classical Mediterranean, mosaic-inspired Renaissance (1400-1600) Italian Renaissance, warm lighting Enlightenment (1600-1800) Baroque, Dutch Golden Age Victorian (1800-1900) Pre-Raphaelite, industrial Gilded Age (1870-1900) Art Nouveau, American industrial Early Modern (1900-1950) Art Deco, Modernist Mid-Century (1950-1980) Atomic Age, clean lines Contemporary Photorealistic with period elements Checklist After completing a story, verify: Story directory created: docs/stories/<name>/ index.md has full narrative and all image prompts All image references use .png extension YAML frontmatter has title, description, and image paths Added to mkdocs.yml navigation in chronological order Grid card added to docs/stories/index.md 12-14 chapters with consistent structure Epilogue includes lessons table References section present (placeholders OK initially) Image prompts specify 16:9 format and period style</p> </blockquote> </article> <a href="/" class="back-link">← <span data-i18n="detail.backToLeaderboard">返回排行榜</span></a> </div> <aside class="sidebar"> <section class="related-skills" id="relatedSkillsSection"> <h2 class="related-title" data-i18n="detail.relatedSkills">相关 Skills</h2> <div class="related-list" id="relatedSkillsList"> <div class="skeleton-card"></div> <div class="skeleton-card"></div> <div class="skeleton-card"></div> </div> </section> </aside> </div> </div> <script src="https://unpkg.com/i18next@23.11.5/i18next.min.js" defer></script> <script src="https://unpkg.com/i18next-browser-languagedetector@7.2.1/i18nextBrowserLanguageDetector.min.js" defer></script> <script defer> // Language resources - same pattern as index page const resources = { 'zh-CN': null, 'en': null, 'ja': null, 'ko': null, 'zh-TW': null, 'es': null, 'fr': null }; // Load language files (only current + fallback for performance) async function loadLanguageResources() { const savedLang = localStorage.getItem('i18nextLng') || 'en'; const langsToLoad = new Set([savedLang, 'en']); // current + fallback await Promise.all([...langsToLoad].map(async (lang) => { try { const response = await fetch(`/locales/${lang}.json`); if (response.ok) { resources[lang] = { translation: await response.json() }; } } catch (error) { console.warn(`Failed to load ${lang} language file:`, error); } })); } // Load a single language on demand (for language switching) async function loadLanguage(lang) { if (resources[lang]) return; try { const response = await fetch(`/locales/${lang}.json`); if (response.ok) { resources[lang] = { translation: await response.json() }; i18next.addResourceBundle(lang, 'translation', resources[lang].translation); } } catch (error) { console.warn(`Failed to load ${lang} language file:`, error); } } // Initialize i18next async function initI18n() { try { await loadLanguageResources(); // Filter out null values from resources const validResources = {}; for (const [lang, data] of Object.entries(resources)) { if (data !== null) { validResources[lang] = data; } } console.log('Loaded languages:', Object.keys(validResources)); console.log('zh-CN resource:', validResources['zh-CN']); console.log('detail.home in resource:', validResources['zh-CN']?.translation?.detail?.home); // 检查是否有保存的语言偏好 const savedLang = localStorage.getItem('i18nextLng'); // 如果没有保存的语言偏好,默认使用英文 const defaultLang = savedLang && ['zh-CN', 'en', 'ja', 'ko', 'zh-TW', 'es', 'fr'].includes(savedLang) ? savedLang : 'en'; await i18next .use(i18nextBrowserLanguageDetector) .init({ lng: defaultLang, // 强制设置初始语言 fallbackLng: 'en', supportedLngs: ['zh-CN', 'en', 'ja', 'ko', 'zh-TW', 'es', 'fr'], resources: validResources, detection: { order: ['localStorage'], // 只使用 localStorage,不检测浏览器语言 caches: ['localStorage'], lookupLocalStorage: 'i18nextLng' }, interpolation: { escapeValue: false } }); console.log('i18next initialized, language:', i18next.language); console.log('Test translation:', i18next.t('detail.home')); // Set initial language in selector const langSwitcher = document.getElementById('langSwitcher'); langSwitcher.value = i18next.language; // Update page language updatePageLanguage(); // Language switch event langSwitcher.addEventListener('change', async (e) => { await loadLanguage(e.target.value); // load on demand i18next.changeLanguage(e.target.value).then(() => { updatePageLanguage(); localStorage.setItem('i18nextLng', e.target.value); }); }); } catch (error) { console.error('i18next init failed:', error); } } // Translation helper function t(key, options = {}) { return i18next.t(key, options); } // Update all translatable elements function updatePageLanguage() { // Update HTML lang attribute document.documentElement.lang = i18next.language; // Update elements with data-i18n attribute document.querySelectorAll('[data-i18n]').forEach(el => { const key = el.getAttribute('data-i18n'); el.textContent = t(key); }); } // Copy command function function copyCommand() { const command = document.getElementById('installCommand').textContent; const btn = document.getElementById('copyBtn'); navigator.clipboard.writeText(command).then(() => { btn.textContent = t('copied'); btn.classList.add('copied'); setTimeout(() => { btn.textContent = t('copy'); btn.classList.remove('copied'); }, 2000); }).catch(() => { // Fallback for non-HTTPS const textArea = document.createElement('textarea'); textArea.value = command; textArea.style.position = 'fixed'; textArea.style.left = '-9999px'; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); btn.textContent = t('copied'); btn.classList.add('copied'); setTimeout(() => { btn.textContent = t('copy'); btn.classList.remove('copied'); }, 2000); }); } // Initialize document.getElementById('copyBtn').addEventListener('click', copyCommand); initI18n(); // 异步加载相关 Skills async function loadRelatedSkills() { const owner = 'dmccreary'; const skillName = 'story-generator'; const currentLang = 'es'; const listContainer = document.getElementById('relatedSkillsList'); const section = document.getElementById('relatedSkillsSection'); try { const response = await fetch(`/api/related-skills/${encodeURIComponent(owner)}/${encodeURIComponent(skillName)}?limit=6`); if (!response.ok) { throw new Error('Failed to load'); } const data = await response.json(); const relatedSkills = data.related_skills || []; if (relatedSkills.length === 0) { // 没有相关推荐时隐藏整个区域 section.style.display = 'none'; return; } // 渲染相关 Skills listContainer.innerHTML = relatedSkills.map(skill => { const desc = skill.description || ''; const truncatedDesc = desc.length > 60 ? desc.substring(0, 60) + '...' : desc; return ` <a href="${currentLang === 'en' ? '' : '/' + currentLang}/skill/${skill.owner}/${skill.repo}/${skill.skill_name}" class="related-card"> <div class="related-name">${escapeHtml(skill.skill_name)}</div> <div class="related-meta"> <span class="related-owner">${escapeHtml(skill.owner)}</span> <span class="related-installs">${skill.installs}</span> </div> <div class="related-desc">${escapeHtml(truncatedDesc)}</div> </a> `; }).join(''); } catch (error) { console.error('Failed to load related skills:', error); // 加载失败时显示提示或隐藏 listContainer.innerHTML = '<div class="related-empty">暂无相关推荐</div>'; } } // HTML 转义 function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // 页面加载完成后异步加载相关 Skills if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', loadRelatedSkills); } else { loadRelatedSkills(); } </script> </body> </html>