Token导航 LogoToken导航

Agent Skill · 研究检索

frontend-razor(前端剃须刀)

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

frontend-razor 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为权限未标注;许可证信息还不明确,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 56,028。

总安装 465周安装 19GitHub Stars 1下载 149核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:frontend-razor(前端剃须刀)
来源仓库:https://github.com/twofoldtech-dakota/claude-marketplace
仓库路径:skills/frontend-razor
安装命令:
npx skills add https://github.com/twofoldtech-dakota/claude-marketplace --skill frontend-razor
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/twofoldtech-dakota/claude-marketplace --skill frontend-razor

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

针对 Razor Pages 技术栈的代码辅助工具。支持 C# 后端与前端脚本的混合开发场景。生成页面模型绑定与 AJAX 调用示例。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。需确认宿主是否具备 .NET 运行时环境。

frontend-razor 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/frontend-razor

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/twofoldtech-dakota/claude-marketplace --skill…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    权限没有明确标注,第一次使用时只给一个无关紧要的任务,观察它到底读了哪些文件和网络。

常见问题

6 条

frontend-razor 怎么安装?

在终端执行 npx skills add https://github.com/twofoldtech-dakota/claude-marketplace --skill frontend-r…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

frontend-razor 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

frontend-razor 需要什么权限?

权限级别没有明确标注。第一次使用时建议只给无关紧要的任务,观察它实际读写了哪些内容。

frontend-razor 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

frontend-razor 用的人多吗?

公开数据是累计安装 465 次,近一周安装 19 次,下载 149 次,GitHub 1 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

frontend-razor 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
frontend-razor

前端剃须刀 · 本页

4651权限未标注未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Razor View Development Patterns

View Structure

Project Layout

Views/
├── Shared/
│   ├── _Layout.cshtml          # Main layout template
│   ├── _LayoutEmpty.cshtml     # Minimal layout (no header/footer)
│   ├── _Header.cshtml          # Header partial
│   ├── _Footer.cshtml          # Footer partial
│   ├── _Navigation.cshtml      # Navigation partial
│   ├── _Pagination.cshtml      # Reusable pagination
│   └── Components/             # View components
│       └── SearchBox/
│           └── Default.cshtml
├── Home/
│   ├── Index.cshtml
│   └── About.cshtml
├── Products/
│   ├── Index.cshtml
│   ├── Details.cshtml
│   └── _ProductCard.cshtml     # Page-specific partial
├── _ViewImports.cshtml         # Shared imports and tag helpers
└── _ViewStart.cshtml           # Default layout assignment

_ViewImports.cshtml

@using MyApp.Web
@using MyApp.Web.Models
@using MyApp.Core.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, MyApp.Web

_ViewStart.cshtml

@{
    Layout = "_Layout";
}

Layout Templates

Main Layout

@* Views/Shared/_Layout.cshtml *@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - My Application</title>

    @* Head section for page-specific styles *@
    @await RenderSectionAsync("Styles", required: false)

    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</head>
<body class="@ViewData["BodyClass"]">
    <header>
        @await Html.PartialAsync("_Header")
        @await Html.PartialAsync("_Navigation")
    </header>

    <main class="container">
        @RenderBody()
    </main>

    <footer>
        @await Html.PartialAsync("_Footer")
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @* Scripts section for page-specific JavaScript *@
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Page Using Layout

@model ProductListViewModel
@{
    ViewData["Title"] = "Products";
    ViewData["BodyClass"] = "products-page";
}

@section Styles {
    <link rel="stylesheet" href="~/css/products.css" asp-append-version="true" />
}

<h1>@ViewData["Title"]</h1>

<div class="product-grid">
    @foreach (var product in Model.Products)
    {
        @await Html.PartialAsync("_ProductCard", product)
    }
</div>

@section Scripts {
    <script src="~/js/products.js" asp-append-version="true"></script>
}

Nested Layouts

@* Views/Shared/_LayoutAdmin.cshtml *@
@{
    Layout = "_Layout";
}

<div class="admin-container">
    <aside class="admin-sidebar">
        @await Html.PartialAsync("_AdminNav")
    </aside>
    <div class="admin-content">
        @RenderBody()
    </div>
</div>

@section Scripts {
    <script src="~/js/admin.js" asp-append-version="true"></script>
    @await RenderSectionAsync("AdminScripts", required: false)
}

Partial Views

Rendering Partials

@* Async (recommended) *@
@await Html.PartialAsync("_ProductCard", product)

@* With explicit view path *@
@await Html.PartialAsync("~/Views/Shared/_Header.cshtml")

@* Synchronous (avoid for I/O operations) *@
@Html.Partial("_Sidebar")

@* As tag helper *@
<partial name="_ProductCard" model="product" />

@* With view-data *@
<partial name="_Pagination" model="Model.Pagination" view-data="ViewData" />

Partial View Example

@* Views/Products/_ProductCard.cshtml *@
@model Product

<article class="product-card">
    <a asp-action="Details" asp-route-id="@Model.Id" class="product-card__link">
        <img src="@Model.ImageUrl"
             alt="@Model.Name"
             class="product-card__image" />
        <div class="product-card__content">
            <h3 class="product-card__title">@Model.Name</h3>
            <p class="product-card__price">@Model.Price.ToString("C")</p>
            @if (Model.IsOnSale)
            {
                <span class="product-card__badge">Sale</span>
            }
        </div>
    </a>
</article>

View Components

Component Class

// ViewComponents/RecentArticlesViewComponent.cs
public class RecentArticlesViewComponent : ViewComponent
{
    private readonly IArticleService _articleService;

    public RecentArticlesViewComponent(IArticleService articleService)
    {
        _articleService = articleService;
    }

    public async Task<IViewComponentResult> InvokeAsync(int count = 5)
    {
        var articles = await _articleService.GetRecentAsync(count);
        return View(articles);
    }
}

Component View

@* Views/Shared/Components/RecentArticles/Default.cshtml *@
@model IEnumerable<Article>

<section class="recent-articles">
    <h3>Recent Articles</h3>
    <ul>
        @foreach (var article in Model)
        {
            <li>
                <a asp-controller="Articles"
                   asp-action="Details"
                   asp-route-slug="@article.Slug">
                    @article.Title
                </a>
                <time datetime="@article.PublishedDate.ToString("yyyy-MM-dd")">
                    @article.PublishedDate.ToString("MMM dd, yyyy")
                </time>
            </li>
        }
    </ul>
</section>

Invoking Components

@* Tag helper syntax (preferred) *@
<vc:recent-articles count="5" />

@* Async syntax *@
@await Component.InvokeAsync("RecentArticles", new { count = 5 })

@* With cache *@
<cache expires-after="@TimeSpan.FromMinutes(10)">
    <vc:recent-articles count="5" />
</cache>

Tag Helpers

Built-in Tag Helpers

@* Anchor tag helper *@
<a asp-controller="Products"
   asp-action="Details"
   asp-route-id="@product.Id"
   asp-route-category="@product.Category">
    View Details
</a>

@* Form tag helpers *@
<form asp-controller="Contact" asp-action="Submit" method="post">
    <div class="form-group">
        <label asp-for="Name"></label>
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>

    <div class="form-group">
        <label asp-for="Email"></label>
        <input asp-for="Email" class="form-control" />
        <span asp-validation-for="Email" class="text-danger"></span>
    </div>

    <div class="form-group">
        <label asp-for="Category"></label>
        <select asp-for="Category" asp-items="Model.Categories" class="form-control">
            <option value="">Select a category</option>
        </select>
        <span asp-validation-for="Category" class="text-danger"></span>
    </div>

    <button type="submit" class="btn btn-primary">Submit</button>
</form>

@* Image with cache busting *@
<img src="~/images/logo.png" asp-append-version="true" alt="Logo" />

@* Environment-specific rendering *@
<environment include="Development">
    <link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
    <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>

Custom Tag Helper

// TagHelpers/EmailTagHelper.cs
[HtmlTargetElement("email")]
public class EmailTagHelper : TagHelper
{
    public string Address { get; set; }
    public string Subject { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "a";

        var href = $"mailto:{Address}";
        if (!string.IsNullOrEmpty(Subject))
        {
            href += $"?subject={Uri.EscapeDataString(Subject)}";
        }

        output.Attributes.SetAttribute("href", href);
        output.Content.SetContent(Address);
    }
}
@* Usage *@
<email address="support@example.com" subject="Help Request" />

Model Binding

Strongly-Typed Views

@model ContactFormViewModel

<form asp-action="Submit" method="post">
    @Html.AntiForgeryToken()

    <div class="form-group">
        <label asp-for="Name" class="form-label"></label>
        <input asp-for="Name" class="form-control" placeholder="Your name" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>

    <div class="form-group">
        <label asp-for="Email" class="form-label"></label>
        <input asp-for="Email" class="form-control" type="email" />
        <span asp-validation-for="Email" class="text-danger"></span>
    </div>

    <div class="form-group">
        <label asp-for="Message" class="form-label"></label>
        <textarea asp-for="Message" class="form-control" rows="5"></textarea>
        <span asp-validation-for="Message" class="text-danger"></span>
    </div>

    <button type="submit" class="btn btn-primary">Send Message</button>
</form>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

ViewModel with Validation

public class ContactFormViewModel
{
    [Required(ErrorMessage = "Name is required")]
    [StringLength(100, ErrorMessage = "Name cannot exceed 100 characters")]
    [Display(Name = "Full Name")]
    public string Name { get; set; }

    [Required(ErrorMessage = "Email is required")]
    [EmailAddress(ErrorMessage = "Please enter a valid email address")]
    public string Email { get; set; }

    [Required(ErrorMessage = "Message is required")]
    [StringLength(2000, MinimumLength = 10,
        ErrorMessage = "Message must be between 10 and 2000 characters")]
    public string Message { get; set; }
}

Conditional Rendering

If/Else Statements

@if (Model.Products.Any())
{
    <div class="product-grid">
        @foreach (var product in Model.Products)
        {
            <partial name="_ProductCard" model="product" />
        }
    </div>
}
else
{
    <div class="empty-state">
        <p>No products found.</p>
        <a asp-action="Index" asp-controller="Home" class="btn btn-link">
            Return to Home
        </a>
    </div>
}

Switch Statements

@switch (Model.Status)
{
    case OrderStatus.Pending:
        <span class="badge badge-warning">Pending</span>
        break;
    case OrderStatus.Processing:
        <span class="badge badge-info">Processing</span>
        break;
    case OrderStatus.Shipped:
        <span class="badge badge-primary">Shipped</span>
        break;
    case OrderStatus.Delivered:
        <span class="badge badge-success">Delivered</span>
        break;
    default:
        <span class="badge badge-secondary">Unknown</span>
        break;
}

Null Checking

@* Null conditional *@
<p>Author: @Model.Author?.Name ?? "Unknown"</p>

@* With fallback *@
@if (Model.ImageUrl != null)
{
    <img src="@Model.ImageUrl" alt="@Model.Title" />
}
else
{
    <img src="~/images/placeholder.jpg" alt="No image available" />
}

@* Ternary operator *@
<div class="@(Model.IsActive ? "active" : "inactive")">
    @Model.Title
</div>

Loops and Collections

For Loop

@for (int i = 0; i < Model.Items.Count; i++)
{
    <div class="item @(i % 2 == 0 ? "even" : "odd")">
        <span class="item-number">@(i + 1)</span>
        <span class="item-name">@Model.Items[i].Name</span>
    </div>
}

Foreach with Index

@{ var index = 0; }
@foreach (var item in Model.Items)
{
    <div class="item" data-index="@index">
        @item.Name
    </div>
    index++;
}

Rendering Lists

<ul class="breadcrumb">
    @foreach (var crumb in Model.Breadcrumbs)
    {
        var isLast = crumb == Model.Breadcrumbs.Last();
        <li class="breadcrumb-item @(isLast ? "active" : "")">
            @if (isLast)
            {
                @crumb.Title
            }
            else
            {
                <a href="@crumb.Url">@crumb.Title</a>
            }
        </li>
    }
</ul>

HTML Helpers vs Tag Helpers

Prefer Tag Helpers

@* HTML Helper (older approach) *@
@Html.ActionLink("Details", "Details", "Products", new { id = product.Id }, new { @class = "btn btn-link" })

@* Tag Helper (modern, preferred) *@
<a asp-controller="Products" asp-action="Details" asp-route-id="@product.Id" class="btn btn-link">
    Details
</a>

@* HTML Helper for form *@
@Html.TextBoxFor(m => m.Name, new { @class = "form-control", placeholder = "Enter name" })

@* Tag Helper (cleaner) *@
<input asp-for="Name" class="form-control" placeholder="Enter name" />

When to Use HTML Helpers

@* Complex dynamic attributes *@
@Html.TextBoxFor(m => m.Name, Model.GetInputAttributes())

@* Raw HTML content *@
@Html.Raw(Model.HtmlContent)

@* Display templates *@
@Html.DisplayFor(m => m.CreatedDate)

@* Editor templates *@
@Html.EditorFor(m => m.Address)

ViewData, ViewBag, and TempData

ViewData (Dictionary)

@* In Controller *@
ViewData["Title"] = "Product Details";
ViewData["ShowSidebar"] = true;

@* In View *@
<h1>@ViewData["Title"]</h1>
@if ((bool?)ViewData["ShowSidebar"] == true)
{
    <partial name="_Sidebar" />
}

ViewBag (Dynamic)

@* In Controller *@
ViewBag.Categories = await _categoryService.GetAllAsync();

@* In View *@
<select asp-items="@(new SelectList(ViewBag.Categories, "Id", "Name"))">
    <option value="">All Categories</option>
</select>

TempData (Survives Redirect)

// In Controller
TempData["SuccessMessage"] = "Product saved successfully!";
return RedirectToAction("Index");
@* In View *@
@if (TempData["SuccessMessage"] != null)
{
    <div class="alert alert-success alert-dismissible">
        @TempData["SuccessMessage"]
        <button type="button" class="close" data-dismiss="alert">&times;</button>
    </div>
}

AJAX and Partial Rendering

AJAX Form Submission

<form id="contact-form" asp-action="SubmitAjax" method="post">
    @Html.AntiForgeryToken()

    <div class="form-group">
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>

    <button type="submit" class="btn btn-primary">Submit</button>
</form>

<div id="result"></div>

@section Scripts {
    <script>
    $('#contact-form').on('submit', function(e) {
        e.preventDefault();

        var $form = $(this);
        var $button = $form.find('button[type="submit"]');

        $button.prop('disabled', true).text('Sending...');

        $.ajax({
            url: $form.attr('action'),
            type: 'POST',
            data: $form.serialize(),
            success: function(response) {
                $('#result').html(response);
                $form[0].reset();
            },
            error: function(xhr) {
                $('#result').html('<div class="alert alert-danger">An error occurred.</div>');
            },
            complete: function() {
                $button.prop('disabled', false).text('Submit');
            }
        });
    });
    </script>
}

Returning Partial Views from Controller

[HttpGet]
public async Task<IActionResult> LoadMore(int page)
{
    var products = await _productService.GetPagedAsync(page, 10);
    return PartialView("_ProductGrid", products);
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> SubmitAjax(ContactFormViewModel model)
{
    if (!ModelState.IsValid)
    {
        return PartialView("_ContactFormErrors", model);
    }

    await _contactService.ProcessAsync(model);
    return PartialView("_ContactFormSuccess");
}

Accessibility Considerations

@* Semantic HTML with ARIA *@
<nav aria-label="Main navigation">
    <ul class="nav" role="menubar">
        @foreach (var item in Model.NavItems)
        {
            <li role="none">
                <a href="@item.Url"
                   role="menuitem"
                   aria-current="@(item.IsActive ? "page" : null)">
                    @item.Title
                </a>
            </li>
        }
    </ul>
</nav>

@* Form accessibility *@
<div class="form-group">
    <label asp-for="Email" id="email-label"></label>
    <input asp-for="Email"
           aria-labelledby="email-label"
           aria-describedby="email-help email-error" />
    <small id="email-help" class="form-text text-muted">
        We'll never share your email.
    </small>
    <span asp-validation-for="Email" id="email-error" class="text-danger" role="alert"></span>
</div>

@* Skip link for keyboard navigation *@
<a href="#main-content" class="skip-link">Skip to main content</a>

平台分布

Claude

34.01%
按下载量换算51

Codex

33.03%
按下载量换算49

Cursor

20.6%
按下载量换算31

Gemini CLI

9.38%
按下载量换算14

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

权限未标注

当前来源未能明确判断权限范围,默认进入异常复核队列。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills