[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6E602WCF1HPCBTHYYZ9E5VC":3,"skill-same:01M6E602WCF1HPCBTHYYZ9E5VC":68},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":29,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":48,"repositoryHtmlUrl":49,"repositoryHomepageUrl":50,"ownerHtmlUrl":51,"ownerBlogUrl":6,"ownerDescription":52,"updatedAt":53,"install":54,"resources":67},"01M6E602WCF1HPCBTHYYZ9E5VC","verify-email-snapshots",null,"Snapshot test email templates using Verify to catch regressions. Validates rendered HTML output matches approved baseline. Works with MJML templates and any email renderer.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FAaronontheweb\u002Fdotnet-skills\u002Fverify-email-snapshots\u002FSKILL.md",[18,23,26],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000005","邮件与沟通","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[30,31,32,33,34,35,36,37,38,39],"email","verify","snapshots","verify email snapshots","test","templates","baseline","snapshot","html","false","2026-11-10 10:12:30",false,"---\nname: verify-email-snapshots\ndescription: Snapshot test email templates using Verify to catch regressions. Validates rendered HTML output matches approved baseline. Works with MJML templates and any email renderer.\ninvocable: false\n---\n\n# Snapshot Testing Email Templates with Verify\n\n## When to Use This Skill\n\nUse this skill when:\n- Testing email template rendering for regressions\n- Validating MJML templates compile to expected HTML\n- Reviewing email changes in code review (diffs are visual)\n- Ensuring variable substitution works correctly\n\n**Related skills:**\n- `aspnetcore\u002Fmjml-email-templates` - MJML template authoring\n- `aspire\u002Fmailpit-integration` - Test email delivery locally\n- `testing\u002Fsnapshot-testing` - General Verify patterns\n\n---\n\n## Why Snapshot Test Emails?\n\nEmail templates are:\n1. **Visual** - Small changes can break rendering across clients\n2. **Hard to unit test** - Output is complex HTML, not simple values\n3. **Prone to regression** - Template changes can have unintended effects\n\nSnapshot testing captures the rendered HTML and fails when it changes unexpectedly.\n\n---\n\n## Installation\n\n```bash\ndotnet add package Verify.Xunit  # or Verify.NUnit, Verify.MSTest\n```\n\n---\n\n## Basic Email Snapshot Test\n\n```csharp\n[Fact]\npublic async Task UserSignupInvitation_RendersCorrectly()\n{\n    \u002F\u002F Arrange\n    var renderer = _services.GetRequiredService\u003CIMjmlTemplateRenderer>();\n\n    var variables = new Dictionary\u003Cstring, string>\n    {\n        { \"PreviewText\", \"You've been invited to join Acme Corp\" },\n        { \"OrganizationName\", \"Acme Corporation\" },\n        { \"InviteeName\", \"John Doe\" },\n        { \"InviterName\", \"Jane Admin\" },\n        { \"InvitationLink\", \"https:\u002F\u002Fexample.com\u002Finvite\u002Fabc123\" },\n        { \"ExpirationDate\", \"December 31, 2025\" }\n    };\n\n    \u002F\u002F Act\n    var html = await renderer.RenderTemplateAsync(\n        \"UserInvitations\u002FUserSignupInvitation\",\n        variables);\n\n    \u002F\u002F Assert\n    await Verify(html, extension: \"html\");\n}\n```\n\nThis creates `UserSignupInvitation_RendersCorrectly.verified.html` on first run.\n\n---\n\n## Reviewing Email Changes\n\nWhen a template changes, the test fails with a diff. Review options:\n\n### 1. Visual Diff Tool\n\n```bash\n# Configure diff tool (one-time)\ndotnet tool install -g verify.tool\nverify accept  # Accept all pending changes\nverify review  # Open diff tool\n```\n\n### 2. Browser Preview\n\nOpen the `.received.html` file in a browser to see the actual rendering.\n\n### 3. IDE Integration\n\nMost IDEs show inline diffs for `.verified.html` vs `.received.html` files.\n\n---\n\n## Test Each Template Variant\n\nCreate tests for each email template to catch regressions:\n\n```csharp\npublic class EmailTemplateSnapshotTests : IClassFixture\u003CEmailTestFixture>\n{\n    private readonly IMjmlTemplateRenderer _renderer;\n\n    public EmailTemplateSnapshotTests(EmailTestFixture fixture)\n    {\n        _renderer = fixture.Services.GetRequiredService\u003CIMjmlTemplateRenderer>();\n    }\n\n    [Fact]\n    public async Task WelcomeEmail_NewUser() =>\n        await VerifyTemplate(\"Welcome\u002FNewUser\", new Dictionary\u003Cstring, string>\n        {\n            { \"UserName\", \"John Doe\" },\n            { \"LoginUrl\", \"https:\u002F\u002Fexample.com\u002Flogin\" }\n        });\n\n    [Fact]\n    public async Task WelcomeEmail_InvitedUser() =>\n        await VerifyTemplate(\"Welcome\u002FInvitedUser\", new Dictionary\u003Cstring, string>\n        {\n            { \"UserName\", \"John Doe\" },\n            { \"InviterName\", \"Jane Admin\" },\n            { \"OrganizationName\", \"Acme Corp\" }\n        });\n\n    [Fact]\n    public async Task PasswordReset() =>\n        await VerifyTemplate(\"PasswordReset\u002FPasswordReset\", new Dictionary\u003Cstring, string>\n        {\n            { \"UserName\", \"John Doe\" },\n            { \"ResetLink\", \"https:\u002F\u002Fexample.com\u002Freset\u002Fabc123\" },\n            { \"ExpirationMinutes\", \"30\" }\n        });\n\n    [Fact]\n    public async Task PaymentReceipt() =>\n        await VerifyTemplate(\"Billing\u002FPaymentReceipt\", new Dictionary\u003Cstring, string>\n        {\n            { \"UserName\", \"John Doe\" },\n            { \"Amount\", \"$10.00\" },\n            { \"InvoiceNumber\", \"INV-2025-001\" },\n            { \"Date\", \"January 15, 2025\" }\n        });\n\n    private async Task VerifyTemplate(\n        string templateName,\n        Dictionary\u003Cstring, string> variables)\n    {\n        var html = await _renderer.RenderTemplateAsync(templateName, variables);\n        await Verify(html, extension: \"html\")\n            .UseMethodName(templateName.Replace(\"\u002F\", \"_\"));\n    }\n}\n```\n\n---\n\n## Scrubbing Dynamic Values\n\nSome values change between test runs. Scrub them:\n\n```csharp\n[Fact]\npublic async Task EmailWithTimestamp_ScrubsDynamicValues()\n{\n    var html = await _renderer.RenderTemplateAsync(\"Welcome\", variables);\n\n    await Verify(html, extension: \"html\")\n        .ScrubLinesContaining(\"Generated at:\")\n        .ScrubInlineGuids();  \u002F\u002F Scrubs GUIDs in URLs\n}\n```\n\n### Common Scrubbers\n\n```csharp\n\u002F\u002F Scrub dates\n.ScrubLinesContaining(\"Date:\")\n.AddScrubber(s => Regex.Replace(s, @\"\\d{4}-\\d{2}-\\d{2}\", \"SCRUBBED-DATE\"))\n\n\u002F\u002F Scrub URLs with tokens\n.AddScrubber(s => Regex.Replace(s, @\"token=[a-zA-Z0-9]+\", \"token=SCRUBBED\"))\n\n\u002F\u002F Scrub GUIDs\n.ScrubInlineGuids()\n```\n\n---\n\n## Test Fixture for Email Tests\n\n```csharp\npublic class EmailTestFixture : IAsyncLifetime\n{\n    public IServiceProvider Services { get; private set; } = null!;\n\n    public async Task InitializeAsync()\n    {\n        var services = new ServiceCollection();\n\n        services.AddSingleton\u003CIConfiguration>(new ConfigurationBuilder()\n            .AddInMemoryCollection(new Dictionary\u003Cstring, string?>\n            {\n                [\"SiteUrl\"] = \"https:\u002F\u002Fexample.com\"\n            })\n            .Build());\n\n        services.AddSingleton\u003CIMjmlTemplateRenderer, MjmlTemplateRenderer>();\n\n        Services = services.BuildServiceProvider();\n\n        await Task.CompletedTask;\n    }\n\n    public Task DisposeAsync() => Task.CompletedTask;\n}\n```\n\n---\n\n## Composer Snapshot Tests\n\nTest the full composer output including subject and metadata:\n\n```csharp\n[Fact]\npublic async Task SignupInvitation_ComposesCorrectEmail()\n{\n    var composer = _services.GetRequiredService\u003CIUserEmailComposer>();\n\n    var email = await composer.ComposeSignupInvitationAsync(\n        recipientEmail: new EmailAddress(\"john@example.com\"),\n        recipientName: new PersonName(\"John Doe\"),\n        inviterName: new PersonName(\"Jane Admin\"),\n        organizationName: new OrganizationName(\"Acme Corp\"),\n        invitationUrl: new AbsoluteUri(\"https:\u002F\u002Fexample.com\u002Finvite\u002Fabc123\"),\n        expiresAt: new DateTimeOffset(2025, 12, 31, 0, 0, 0, TimeSpan.Zero));\n\n    \u002F\u002F Verify the full email object (subject, to, body)\n    await Verify(new\n    {\n        email.To,\n        email.Subject,\n        HtmlBody = email.HtmlBody  \u002F\u002F Will be stored as .html extension\n    });\n}\n```\n\n---\n\n## CI Integration\n\n### Fail on Missing Baseline\n\nIn CI, fail if no `.verified.html` file exists (prevents accidental acceptance):\n\n```csharp\n\u002F\u002F In test setup or ModuleInitializer\nVerifierSettings.ThrowOnMissingVerifiedFile();\n```\n\n### Git Configuration\n\nAdd to `.gitattributes` to improve diff handling:\n\n```gitattributes\n*.verified.html linguist-language=HTML\n*.verified.html diff=html\n```\n\n---\n\n## Best Practices\n\n### DO\n\n```csharp\n\u002F\u002F DO: Test each template variant\n[Fact] Task WelcomeEmail_NewUser_RendersCorrectly()\n[Fact] Task WelcomeEmail_InvitedUser_RendersCorrectly()\n\n\u002F\u002F DO: Use descriptive test names\n[Fact] Task PaymentReceipt_WithRefund_ShowsRefundAmount()\n\n\u002F\u002F DO: Scrub dynamic values consistently\n.ScrubLinesContaining(\"Generated at:\")\n\n\u002F\u002F DO: Review diffs carefully before accepting\nverify review\n```\n\n### DON'T\n\n```csharp\n\u002F\u002F DON'T: Skip email testing\n\u002F\u002F DON'T: Auto-accept changes without review\nverify accept --all  \u002F\u002F Dangerous!\n\n\u002F\u002F DON'T: Test only happy path\n\u002F\u002F DON'T: Ignore snapshot test failures\n```\n\n---\n\n## Workflow\n\n1. **Create template** - Write MJML template\n2. **Write test** - Add snapshot test with sample variables\n3. **Run test** - First run creates `.verified.html`\n4. **Review** - Open in browser, verify rendering\n5. **Commit** - Include `.verified.html` in source control\n6. **Iterate** - Changes fail test, review diff, accept if correct\n\n---\n\n## Resources\n\n- **Verify**: https:\u002F\u002Fgithub.com\u002FVerifyTests\u002FVerify\n- **Verify.Xunit**: https:\u002F\u002Fgithub.com\u002FVerifyTests\u002FVerify#xunit\n- **Diff Tools**: https:\u002F\u002Fgithub.com\u002FVerifyTests\u002FDiffEngine\n\n","# Snapshot Testing Email Templates with Verify\n\n## When to Use This Skill\n\nUse this skill when:\n- Testing email template rendering for regressions\n- Validating MJML templates compile to expected HTML\n- Reviewing email changes in code review (diffs are visual)\n- Ensuring variable substitution works correctly\n\n**Related skills:**\n- `aspnetcore\u002Fmjml-email-templates` - MJML template authoring\n- `aspire\u002Fmailpit-integration` - Test email delivery locally\n- `testing\u002Fsnapshot-testing` - General Verify patterns\n\n---\n\n## Why Snapshot Test Emails?\n\nEmail templates are:\n1. **Visual** - Small changes can break rendering across clients\n2. **Hard to unit test** - Output is complex HTML, not simple values\n3. **Prone to regression** - Template changes can have unintended effects\n\nSnapshot testing captures the rendered HTML and fails when it changes unexpectedly.\n\n---\n\n## Installation\n\n```bash\ndotnet add package Verify.Xunit  # or Verify.NUnit, Verify.MSTest\n```\n\n---\n\n## Basic Email Snapshot Test\n\n```csharp\n[Fact]\npublic async Task UserSignupInvitation_RendersCorrectly()\n{\n    \u002F\u002F Arrange\n    var renderer = _services.GetRequiredService\u003CIMjmlTemplateRenderer>();\n\n    var variables = new Dictionary\u003Cstring, string>\n    {\n        { \"PreviewText\", \"You've been invited to join Acme Corp\" },\n        { \"OrganizationName\", \"Acme Corporation\" },\n        { \"InviteeName\", \"John Doe\" },\n        { \"InviterName\", \"Jane Admin\" },\n        { \"InvitationLink\", \"https:\u002F\u002Fexample.com\u002Finvite\u002Fabc123\" },\n        { \"ExpirationDate\", \"December 31, 2025\" }\n    };\n\n    \u002F\u002F Act\n    var html = await renderer.RenderTemplateAsync(\n        \"UserInvitations\u002FUserSignupInvitation\",\n        variables);\n\n    \u002F\u002F Assert\n    await Verify(html, extension: \"html\");\n}\n```\n\nThis creates `UserSignupInvitation_RendersCorrectly.verified.html` on first run.\n\n---\n\n## Reviewing Email Changes\n\nWhen a template changes, the test fails with a diff. Review options:\n\n### 1. Visual Diff Tool\n\n```bash\n# Configure diff tool (one-time)\ndotnet tool install -g verify.tool\nverify accept  # Accept all pending changes\nverify review  # Open diff tool\n```\n\n### 2. Browser Preview\n\nOpen the `.received.html` file in a browser to see the actual rendering.\n\n### 3. IDE Integration\n\nMost IDEs show inline diffs for `.verified.html` vs `.received.html` files.\n\n---\n\n## Test Each Template Variant\n\nCreate tests for each email template to catch regressions:\n\n```csharp\npublic class EmailTemplateSnapshotTests : IClassFixture\u003CEmailTestFixture>\n{\n    private readonly IMjmlTemplateRenderer _renderer;\n\n    public EmailTemplateSnapshotTests(EmailTestFixture fixture)\n    {\n        _renderer = fixture.Services.GetRequiredService\u003CIMjmlTemplateRenderer>();\n    }\n\n    [Fact]\n    public async Task WelcomeEmail_NewUser() =>\n        await VerifyTemplate(\"Welcome\u002FNewUser\", new Dictionary\u003Cstring, string>\n        {\n            { \"UserName\", \"John Doe\" },\n            { \"LoginUrl\", \"https:\u002F\u002Fexample.com\u002Flogin\" }\n        });\n\n    [Fact]\n    public async Task WelcomeEmail_InvitedUser() =>\n        await VerifyTemplate(\"Welcome\u002FInvitedUser\", new Dictionary\u003Cstring, string>\n        {\n            { \"UserName\", \"John Doe\" },\n            { \"InviterName\", \"Jane Admin\" },\n            { \"OrganizationName\", \"Acme Corp\" }\n        });\n\n    [Fact]\n    public async Task PasswordReset() =>\n        await VerifyTemplate(\"PasswordReset\u002FPasswordReset\", new Dictionary\u003Cstring, string>\n        {\n            { \"UserName\", \"John Doe\" },\n            { \"ResetLink\", \"https:\u002F\u002Fexample.com\u002Freset\u002Fabc123\" },\n            { \"ExpirationMinutes\", \"30\" }\n        });\n\n    [Fact]\n    public async Task PaymentReceipt() =>\n        await VerifyTemplate(\"Billing\u002FPaymentReceipt\", new Dictionary\u003Cstring, string>\n        {\n            { \"UserName\", \"John Doe\" },\n            { \"Amount\", \"$10.00\" },\n            { \"InvoiceNumber\", \"INV-2025-001\" },\n            { \"Date\", \"January 15, 2025\" }\n        });\n\n    private async Task VerifyTemplate(\n        string templateName,\n        Dictionary\u003Cstring, string> variables)\n    {\n        var html = await _renderer.RenderTemplateAsync(templateName, variables);\n        await Verify(html, extension: \"html\")\n            .UseMethodName(templateName.Replace(\"\u002F\", \"_\"));\n    }\n}\n```\n\n---\n\n## Scrubbing Dynamic Values\n\nSome values change between test runs. Scrub them:\n\n```csharp\n[Fact]\npublic async Task EmailWithTimestamp_ScrubsDynamicValues()\n{\n    var html = await _renderer.RenderTemplateAsync(\"Welcome\", variables);\n\n    await Verify(html, extension: \"html\")\n        .ScrubLinesContaining(\"Generated at:\")\n        .ScrubInlineGuids();  \u002F\u002F Scrubs GUIDs in URLs\n}\n```\n\n### Common Scrubbers\n\n```csharp\n\u002F\u002F Scrub dates\n.ScrubLinesContaining(\"Date:\")\n.AddScrubber(s => Regex.Replace(s, @\"\\d{4}-\\d{2}-\\d{2}\", \"SCRUBBED-DATE\"))\n\n\u002F\u002F Scrub URLs with tokens\n.AddScrubber(s => Regex.Replace(s, @\"token=[a-zA-Z0-9]+\", \"token=SCRUBBED\"))\n\n\u002F\u002F Scrub GUIDs\n.ScrubInlineGuids()\n```\n\n---\n\n## Test Fixture for Email Tests\n\n```csharp\npublic class EmailTestFixture : IAsyncLifetime\n{\n    public IServiceProvider Services { get; private set; } = null!;\n\n    public async Task InitializeAsync()\n    {\n        var services = new ServiceCollection();\n\n        services.AddSingleton\u003CIConfiguration>(new ConfigurationBuilder()\n            .AddInMemoryCollection(new Dictionary\u003Cstring, string?>\n            {\n                [\"SiteUrl\"] = \"https:\u002F\u002Fexample.com\"\n            })\n            .Build());\n\n        services.AddSingleton\u003CIMjmlTemplateRenderer, MjmlTemplateRenderer>();\n\n        Services = services.BuildServiceProvider();\n\n        await Task.CompletedTask;\n    }\n\n    public Task DisposeAsync() => Task.CompletedTask;\n}\n```\n\n---\n\n## Composer Snapshot Tests\n\nTest the full composer output including subject and metadata:\n\n```csharp\n[Fact]\npublic async Task SignupInvitation_ComposesCorrectEmail()\n{\n    var composer = _services.GetRequiredService\u003CIUserEmailComposer>();\n\n    var email = await composer.ComposeSignupInvitationAsync(\n        recipientEmail: new EmailAddress(\"john@example.com\"),\n        recipientName: new PersonName(\"John Doe\"),\n        inviterName: new PersonName(\"Jane Admin\"),\n        organizationName: new OrganizationName(\"Acme Corp\"),\n        invitationUrl: new AbsoluteUri(\"https:\u002F\u002Fexample.com\u002Finvite\u002Fabc123\"),\n        expiresAt: new DateTimeOffset(2025, 12, 31, 0, 0, 0, TimeSpan.Zero));\n\n    \u002F\u002F Verify the full email object (subject, to, body)\n    await Verify(new\n    {\n        email.To,\n        email.Subject,\n        HtmlBody = email.HtmlBody  \u002F\u002F Will be stored as .html extension\n    });\n}\n```\n\n---\n\n## CI Integration\n\n### Fail on Missing Baseline\n\nIn CI, fail if no `.verified.html` file exists (prevents accidental acceptance):\n\n```csharp\n\u002F\u002F In test setup or ModuleInitializer\nVerifierSettings.ThrowOnMissingVerifiedFile();\n```\n\n### Git Configuration\n\nAdd to `.gitattributes` to improve diff handling:\n\n```gitattributes\n*.verified.html linguist-language=HTML\n*.verified.html diff=html\n```\n\n---\n\n## Best Practices\n\n### DO\n\n```csharp\n\u002F\u002F DO: Test each template variant\n[Fact] Task WelcomeEmail_NewUser_RendersCorrectly()\n[Fact] Task WelcomeEmail_InvitedUser_RendersCorrectly()\n\n\u002F\u002F DO: Use descriptive test names\n[Fact] Task PaymentReceipt_WithRefund_ShowsRefundAmount()\n\n\u002F\u002F DO: Scrub dynamic values consistently\n.ScrubLinesContaining(\"Generated at:\")\n\n\u002F\u002F DO: Review diffs carefully before accepting\nverify review\n```\n\n### DON'T\n\n```csharp\n\u002F\u002F DON'T: Skip email testing\n\u002F\u002F DON'T: Auto-accept changes without review\nverify accept --all  \u002F\u002F Dangerous!\n\n\u002F\u002F DON'T: Test only happy path\n\u002F\u002F DON'T: Ignore snapshot test failures\n```\n\n---\n\n## Workflow\n\n1. **Create template** - Write MJML template\n2. **Write test** - Add snapshot test with sample variables\n3. **Run test** - First run creates `.verified.html`\n4. **Review** - Open in browser, verify rendering\n5. **Commit** - Include `.verified.html` in source control\n6. **Iterate** - Changes fail test, review diff, accept if correct\n\n---\n\n## Resources\n\n- **Verify**: https:\u002F\u002Fgithub.com\u002FVerifyTests\u002FVerify\n- **Verify.Xunit**: https:\u002F\u002Fgithub.com\u002FVerifyTests\u002FVerify#xunit\n- **Diff Tools**: https:\u002F\u002Fgithub.com\u002FVerifyTests\u002FDiffEngine\n\n",{"name":5,"invocable":41,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FAaronontheweb\u002Fdotnet-skills\u002Fverify-email-snapshots",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill verify-email-snapshots",{"tool":60,"command":61},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill verify-email-snapshots",{"tool":63,"command":64},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill verify-email-snapshots","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FAaronontheweb\u002Fdotnet-skills\u002Fverify-email-snapshots\u002FSKILL.md",true,[],[69,79,89,98,104,111],{"skillNo":70,"name":71,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":75,"publishedAt":40},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[74],{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},[76,77,78],"model","model hierarchy","model hierarchy skill",{"skillNo":80,"name":81,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":85,"publishedAt":40},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[84],{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},[86,87,88],"MCP","zoom","zoom mcp",{"skillNo":90,"name":91,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":94,"publishedAt":40},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[95,96,97,87],"sdk","zoom apps sdk","apps",{"skillNo":99,"name":100,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":103,"publishedAt":40},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[100],{"skillNo":105,"name":106,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":110,"publishedAt":40},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[109],{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},[106],{"skillNo":112,"name":113,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":40},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[113]]