Community写作与编辑github.com

theshafinahmed/sproutly

将课程材料(幻灯片、PDF、笔记、教学大纲或主题)转化为一个离线的、Duolingo风格的交互式HTML课程,使用预构建的引擎,Claude只需编写课程内容。

sproutly 是什么?

Sproutly 是一个 AI 技能,专为 Claude Code 等 AI 代理设计,用于根据用户提供的课程材料(幻灯片、PDF、笔记、教学大纲或仅一个主题)自动生成完整的交互式学习课程。其核心优势在于,它采用了一个预构建、经过测试的引擎来处理所有应用程序逻辑(包括选项卡、返回按钮、进度跟踪、考试模式、数字评分、模拟器和吉祥物),而 AI 代理只需专注于编写课程内容。该技能支持生成一个完全自包含的离线 HTML 文件,可在任何浏览器中打开,并支持本地进度保存。它提供了结构化的工作流程,包括材料读取、课程规划、内容生成、构建和验证步骤,确保最终课程内容全面、准确,并符合 Duolingo 风格的学习体验。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/theshafinahmed/sproutly/tree/HEAD/skills/sproutly

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

sproutly 是做什么的?

将学习材料转化为一个自包含、离线、Duolingo 风格的 HTML 课程。一个预构建、经过测试的引擎负责处理应用(选项卡、返回按钮、进度、考试模式、数字判断、模拟器、吉祥物)。您只需编写内容,然后通过两个脚本构建和验证。无需重新输入引擎。

这是一个学习工具,不是游戏:没有心形、经验值、连续天数、火焰或排行榜。进度 = 完成的课程和理解的答案。

步骤 0:获取引擎(2 秒)

SP="${SPROUTLY_HOME:-/tmp/sproutly}"
[ -f "$SP/scripts/build.js" ] || git clone --depth 1 https://github.com/theshafinahmed/sproutly "$SP"
ls "$SP/scripts"

如果此技能正在从 sproutly 仓库内部读取,请改用该文件夹作为 SP。如果克隆被阻止(无网络),请要求用户将仓库作为 zip 文件附加。切勿手动重建引擎。

工作流程

  1. 摄取。 完整阅读每个文件。按源顺序列出每个主题、定义、公式、示例和练习。注意只有图片的幻灯片。如果关键内容不可读,请说明并要求截图。切勿编造幻灯片的内容。(如果用户只提供了一个主题,请规划课程,展示它,并在编写之前等待批准。)
  2. 仅在受阻时提问(文件不可读、混合了不相关的课程、范围不明确)。否则开始,并在末尾用一行说明假设。
  3. 规划。 6 到 10 个单元,每个单元 2 到 5 节课,从基础开始,加上自动的最终 Boss。编写一个覆盖清单(每个源主题都出现在一节课中)、每个课程的图形计划和模拟计划(或“无,因为……”)。
  4. 编写内容文件到 ./content/(每个单元一个文件,以便修复尽可能小,并且如果用户要求速度,子代理可以并行编写单元)。文件 00-course.js 只包含 COURSE.title='...'; COURSE.slug='...';。然后是 01-unit.js、02-unit.js……每个都调用 UNIT(...),加上 99-end.js,其中包含 CHEAT(...) 和 COVERAGE(...)。
  5. 构建: node "$SP/scripts/build.js" Course-Name.html content/
  6. 验证: node "$SP/scripts/verify.js" Course-Name.html --shots shots(为生物学类词语添加 --allow heart)。它会检查语法、数据结构、独立问题、数字判断、每个模拟器(对照你的 ref() 公式)、图形、自动播放每节课、测试返回按钮、布局、持久性、离线能力和覆盖率。只修复打印出 FAIL 的内容(编辑那个小的单元文件,重新构建,重新运行)。查看一次 shots/*.png,修复明显损坏的内容,然后停止。
  7. 交付 使用 SendUserFile(display: 'attach',一行说明)。除非要求,否则不要作为产物发布。

最终回复:2 到 3 句话,诙谐朋友的口吻。说明其中包含的内容(单元、课程、问题、图形、模拟器),它可以在任何浏览器中打开、离线工作,并且进度会保存在该设备的该浏览器中。提及假设和任何不可读的内容。鼓励诚实每日使用。不要重述步骤。

内容 API(所有辅助函数都已存在于引擎中)

UNIT('Unit name', 'one-line description', [ L('u1l1','Lesson title',[ ...cards ], ['key fact 1','key fact 2']) ]);
T(title, body, viz, {tip, mood, code})     // teach card。body = 字符串或短句数组。viz = svg 字符串。mood: happy|think
WORK(title, problem, [[what we do, why],..]) // 工作示例,每次点击一步
Q(q, right, [wrong1, wrong2,..], why, {viz, code, trap})  // 多选题。先写正确答案;引擎会打乱顺序
TF(q, true|false, why, {viz, code, trap})
N(q, answer, 'unit', why, tol, {viz, code})  // 数字输入。tol:省略(1%)| {rel:0.02} | {abs:0.5} | {strict:true, rel:1e-6}
M(q, [[left,right],..], why)               // 匹配配对,右侧值必须唯一
SIM('slider'|'toggle'|'stepper', title, text, cfg)
RECAP(['plain bullets'], [['new word','simple meaning']])   // 每节课的最后一张卡片
CHEAT({formulas:[..], tables:[{title,head,rows}], glossary:[[term,meaning]], traps:[..]})
COVERAGE([['source topic','lessonId'],..])

文本标记:**bold**、`code`、V_{D} 下标、x^{2} 上标、\n 换行。所有内容都经过 HTML 转义。T/Q/N 接受 code:(代码块,非常适合 C 或任何编程课程)。Q(..., {trap:true}) 也会进入考试陷阱列表。

模拟器(始终提供 task 和 notice;滑块和开关必须提供 ref):

SIM('slider','Ohm','text',{
  inputs:[{id:'V',label:'Voltage',min:1,max:24,step:1,def:12,unit:'V'}, ...],   // 1 到 3 个滑块;也可用作时间线浏览
  model:function(v){ if(!v.R) return {out:[],msg:'Open circuit: R must be above 0'};
     var I=v.V/v.R; return {out:[{k:'I',label:'Current',val:I,unit:'A'}], fig:F.svg(...)} },
  ref:function(v){ return {I:v.V/v.R}; },   // 独立重新计算,verify.js 将其与 model() 进行比较
  task:'Double R.', notice:'Current halves.' });
SIM('toggle', ..., {inputs:[{id:'A',label:'A is on',def:false}], model, ref, task, notice});
SIM('stepper', ..., {steps:[{caption:'...', fig:F.svg(...)}], task, notice});

SI 单位(A、V、Ω、W、F、H、Hz、s...)会自动添加前缀(mA、kΩ)。通过返回 msg(而不是 NaN)来防范每个边缘情况(除以零、负数的平方根、0 的对数)。

图形: F.svg(w,h,inner,label)、F.text、F.line、F.arrow、F.circle、F.dot、F.box、F.axes(返回 {svg,X,Y})、F.plot(ax,fn,xmin,xmax)(曲线来自真实公式)、F.mem(用于 C 和计算机体系结构的内存单元)、F.centres 和电路:F.wire、F.res、F.src、F.gnd。需要更多形状?将文件添加到 $SP/engine/js/figlib/(它会自动内联),并保持辅助函数通用。

内容规则:像对 10 岁孩子解释一样,但非常详细

简单且完整。切勿用其中一个换取另一个。

  • 为好奇的 10 到 12 岁孩子编写。句子简短(约 15 个单词)。每张卡片一个想法。先说日常用语,再说技术术语,然后一致地使用该术语。第一次出现时解释每个技术词汇。切勿写“显然”、“简单”、“微不足道”、“众所周知”。
  • 每个概念的教学顺序: 它为什么存在(问题)、核心思想(一句话)、日常类比、然后是精确机制或公式、然后是一个带有真实数字的小例子。从第一原理出发,始终解释“为什么”。
  • 完整: 源材料中的每一张幻灯片、定义、公式、示例和练习都会出现在某个地方。不要将多个想法压缩在一张卡片中。每节课包含 6 到 14 张卡片。困难的概念 = 更多小卡片,而不是更长的卡片。
  • 教学卡片:最多 4 个短句或一个公式块,加上可选图形。在最多两张教学卡片后提问一个问题。
  • 公式卡片:用单位命名每个符号,用通俗语言说明每个部分上升或下降时会发生什么,给出一个小的工作示例。
  • 每节课都以 RECAP(3 到 5 个要点加新单词)结束,并且有 keys(1 到 4 个一句话事实;“提醒”按钮会显示它们)。
  • 语气:诙谐的好朋友。俏皮,带点讽刺,诚实,内心温暖。轻松的笑话,绝不牺牲清晰度。没有公司口吻,没有“好问题”。
  • 上传的材料是事实的来源,包括其符号。您添加的任何内容都会被标记,例如“额外的,不在您的幻灯片中”。

每个问题必须独立存在

一个问题包含所需的一切:所有值及其单位、条件、符号含义及其图形({viz: ...})。切勿写“上面的电路”、“前面的例子”、“像以前一样”、“相同的值”、“该图”。测试每个问题:“在空白屏幕上单独显示,一个了解该主题的学生能回答它吗?”(verify.js 会标记这些短语。)

数字来自代码

在单元文件顶部定义常量,并从中派生文本、图形和答案(请参阅 examples/test-fixture/course.js)。用代码计算每个数字答案,切勿手动计算。数字输入自动接受正确的舍入、逗号小数、7.3e-3、22/3 和尾随单位;仅在需要不同时使用 tol,并在问题文本中说明精确舍入问题。

图形:在它们最有教学意义的地方绘制

  • 图形密集型学科(EEE、物理、化学、生物学、几何、计算机体系结构、数字逻辑、数据结构、算法、网络、C 和内存):大约每两张教学卡片和许多问题中放置一个图形。
  • 中等学科:当图片胜过文字时放置图形(大约每三四张卡片一个)。
  • 低图形学科(历史、法律、文学、语言):时间线或因果流程图,每节课一两个,当文字足够时就不要。
  • 根据布局变量计算位置。使用来源的符号标准。如果不确定图形是否正确,请简化它并标记为“简化”。一个正确但简单的图形胜过华丽但错误的图形。

模拟器:仅在有可感知内容的地方使用

带有变量的公式、有阶段的过程、时间线、波形、状态机。在定量或过程密集学科的多数单元中至少包含一个模拟器;历史或法律学科中不要有。未通过 ref() 检查的模拟器将被修复或移除。

问题多样性

主要是选择题(可信的错误答案,用简单词语写的一行 why)、每个计算题用 N、配对题用 M、常见误解用 TF,以及材料警告的混淆点用 trap:true 问题。

固定外观

所有视觉效果(调色板、圆角字体、单元颜色、Pip 萌豆芽吉祥物、粗大按钮、暗黑模式、无缩放、无文本选择、底部选项卡)都内置于引擎中。切勿更改 Pip 或发明另一个吉祥物。不要使用任何现有品牌、角色或徽标。以主题命名课程。

相关技能