Token导航 LogoToken导航

Agent Skill · 前端设计

tcbs-stack(tcbs 堆栈)

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

tcbs-stack 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为接触敏感数据;许可证为 MIT,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 8,386。

总安装 291周安装 12GitHub Stars 1下载 95核验 2026-05-01

安装说明

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

安装方式

通过对话安装

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

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

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/sebastiaanwouters/dotagents --skill tcbs-stack

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

用于辅助安全审计与权限检查,识别凭据风险和认证漏洞。适合梳理敏感配置、分析鉴权逻辑或生成安全复核清单。结合具体业务场景使用,不能将工具输出直接视为最终结论。涉及密钥或生产系统时需确认最小权限与脱敏策略。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

tcbs-stack 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/tcbs-stack

上手步骤

4 步
  1. 1

    确认自己的宿主工具

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

  2. 2

    拿到安装命令

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

  3. 3

    安装后重启宿主

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

  4. 4

    按最小权限试用

    它需要接触敏感数据,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

tcbs-stack 怎么安装?

在终端执行 npx skills add https://github.com/sebastiaanwouters/dotagents --skill tcbs-stack。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

tcbs-stack 支持哪些 AI 工具?

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

tcbs-stack 需要什么权限?

权限级别是接触敏感数据。该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

tcbs-stack 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

tcbs-stack 用的人多吗?

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

tcbs-stack 安全吗?

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

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

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 需要接触敏感数据,装到常用环境前要先评估影响面。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 环境里有大量密钥、凭证,不方便给第三方 Skill 读取的人。
  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

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

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
tcbs-stack

tcbs 堆栈 · 本页

2911接触敏感数据MIT通过

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

SKILL.md 原文

TCBS Stack

Build production-ready full-stack TypeScript applications with TanStack Start + Convex + Better-Auth + Shadcn UI.

Stack Overview

LayerTechnologyPurpose
FrontendTanStack StartFull-stack React framework with SSR
BackendConvexReal-time database & serverless functions
AuthBetter-AuthFlexible authentication with Convex adapter
UIShadcn UIAccessible component library

Quick Start

# Create new TanStack Start project with Shadcn (recommended)
bun create @tanstack/start@latest --tailwind --add-ons shadcn
cd my-app

# Add Convex (requires v1.25.0+)
bun add convex@latest @convex-dev/react-query
bunx convex dev --once

# Add Better-Auth with Convex
bun add better-auth @convex-dev/better-auth

Alternative manual setup:

bun create @tanstack/start@latest
bun add tailwindcss @tailwindcss/vite
bunx shadcn@latest init

Project Structure

project/
├── src/
│   ├── lib/
│   │   ├── auth-client.tsx      # Client auth setup
│   │   ├── auth-server.ts       # Server auth handler
│   │   └── utils.ts             # cn() helper
│   ├── routes/
│   │   ├── __root.tsx           # Root layout + providers
│   │   ├── _authed.tsx          # Protected route guard
│   │   ├── _authed/
│   │   │   └── index.tsx        # Dashboard
│   │   ├── sign-in.tsx
│   │   └── sign-up.tsx
│   ├── components/
│   │   └── ui/                  # Shadcn components
│   └── router.tsx
├── convex/
│   ├── auth.ts                  # Better-Auth instance
│   ├── auth.config.ts           # Auth providers config
│   ├── http.ts                  # HTTP routes
│   ├── schema.ts                # Database schema
│   └── convex.config.ts         # App config
├── components.json              # Shadcn config
└── vite.config.ts

Core Setup Files

1. Convex Configuration

convex/convex.config.ts

import { defineApp } from "convex/server";
import betterAuth from "@convex-dev/better-auth/convex.config";

const app = defineApp();
app.use(betterAuth);
export default app;

convex/auth.config.ts

import { getAuthConfigProvider } from "@convex-dev/better-auth/auth-config";
import { AuthConfig } from "@auth/core";

export default {
  providers: [getAuthConfigProvider()],
} satisfies AuthConfig;

convex/auth.ts

import { createClient, GenericCtx } from "@convex-dev/better-auth";
import { convex } from "@convex-dev/better-auth/plugins";
import { betterAuth } from "better-auth";
import { DataModel } from "./_generated/dataModel";
import { components, internal } from "./_generated/api";
import authConfig from "./auth.config";

const siteUrl = process.env.SITE_URL!;

export const authComponent = createClient<DataModel>(components.betterAuth, {
  authFunctions: internal.auth,
  triggers: {
    user: {
      onCreate: async (ctx, authUser) => {
        // Sync to your users table
        const userId = await ctx.db.insert("users", { email: authUser.email });
        await authComponent.setUserId(ctx, authUser._id, userId);
      },
    },
  },
});

export const createAuth = (ctx: GenericCtx<DataModel>) => {
  return betterAuth({
    baseURL: siteUrl,
    database: authComponent.adapter(ctx),
    emailAndPassword: { enabled: true },
    plugins: [convex({ authConfig })],
  });
};

// Auth helpers for queries/mutations
export const { getUser, safeGetUser } = authComponent.authHelpers(createAuth);

convex/http.ts

import { httpRouter } from "convex/server";
import { authComponent, createAuth } from "./auth";

const http = httpRouter();
authComponent.registerRoutes(http, createAuth);
export default http;

convex/schema.ts

import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";

export default defineSchema({
  users: defineTable({
    email: v.string(),
    authId: v.optional(v.string()),
  }).index("email", ["email"]),
});

2. Client Auth Setup

src/lib/auth-client.tsx

import { createAuthClient } from "better-auth/react";
import { convexClient } from "@convex-dev/better-auth/client/plugins";

export const authClient = createAuthClient({
  plugins: [convexClient()],
});

export const { signIn, signUp, signOut, useSession } = authClient;

3. Server Auth Setup

src/lib/auth-server.ts

import { convexBetterAuthReactStart } from "@convex-dev/better-auth/react-start";

export const {
  handler,
  getToken,
  fetchAuthQuery,
  fetchAuthMutation,
  fetchAuthAction,
} = convexBetterAuthReactStart({
  convexUrl: process.env.VITE_CONVEX_URL!,
  convexSiteUrl: process.env.VITE_CONVEX_SITE_URL!,
});

3b. Mount Auth Route Handler

src/routes/api/auth/$.ts

import { handler } from "~/lib/auth-server";

export const { GET, POST } = handler;

4. Root Route with Providers

src/routes/__root.tsx

import { createRootRouteWithContext, Outlet } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react";
import { QueryClient } from "@tanstack/react-query";
import { ConvexQueryClient } from "@convex-dev/react-query";
import { getToken } from "~/lib/auth-server";
import { authClient } from "~/lib/auth-client";

const getAuth = createServerFn({ method: "GET" }).handler(async () => {
  return await getToken();
});

export const Route = createRootRouteWithContext<{
  queryClient: QueryClient;
  convexQueryClient: ConvexQueryClient;
}>()({
  beforeLoad: async (ctx) => {
    const token = await getAuth();
    if (token) {
      ctx.context.convexQueryClient.serverHttpClient?.setAuth(token);
    }
    return { isAuthenticated: !!token, token };
  },
  component: RootComponent,
});

function RootComponent() {
  const { convexQueryClient, token } = Route.useRouteContext();
  return (
    <ConvexBetterAuthProvider
      client={convexQueryClient.convexClient}
      authClient={authClient}
      initialToken={token}
    >
      <Outlet />
    </ConvexBetterAuthProvider>
  );
}

5. Protected Route Guard

src/routes/_authed.tsx

import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";

export const Route = createFileRoute("/_authed")({
  beforeLoad: ({ context }) => {
    if (!context.isAuthenticated) {
      throw redirect({ to: "/sign-in" });
    }
  },
  component: () => <Outlet />,
});

6. Vite Configuration

vite.config.ts

import { defineConfig } from "vite";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import path from "path";

export default defineConfig({
  plugins: [tanstackStart(), react(), tailwindcss()],
  resolve: {
    alias: { "@": path.resolve(__dirname, "./src") },
  },
  ssr: {
    // Required: Bundle @convex-dev/better-auth during SSR
    noExternal: ["@convex-dev/better-auth"],
  },
});

7. Router Configuration

src/router.tsx

import { createRouter } from "@tanstack/react-router";
import { routeTree } from "./routeTree.gen";
import { QueryClient } from "@tanstack/react-query";
import { ConvexQueryClient } from "@convex-dev/react-query";
import { ConvexReactClient } from "convex/react";

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);

export function createAppRouter() {
  const queryClient = new QueryClient();
  const convexQueryClient = new ConvexQueryClient(convex, { expectAuth: true });
  queryClient.setDefaultOptions({
    queries: { queryKeyHashFn: convexQueryClient.hashFn() },
  });
  convexQueryClient.connect(queryClient);

  return createRouter({
    routeTree,
    context: { queryClient, convexQueryClient },
    defaultPreload: "intent",
  });
}

Environment Variables

.env.local

# Convex deployment (set by `npx convex dev`)
CONVEX_DEPLOYMENT=dev:your-deployment
VITE_CONVEX_URL=https://your-deployment.convex.cloud
VITE_CONVEX_SITE_URL=https://your-deployment.convex.site

# App URL
VITE_SITE_URL=http://localhost:3000

Convex environment variables (set via CLI):

# Generate and set secret
npx convex env set BETTER_AUTH_SECRET=$(openssl rand -base64 32)

# Set site URL
npx convex env set SITE_URL http://localhost:3000

# OAuth (optional)
npx convex env set GITHUB_CLIENT_ID your-id
npx convex env set GITHUB_CLIENT_SECRET your-secret

Common Patterns

Protected Queries

// convex/todos.ts
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
import { getUser, safeGetUser } from "./auth";

export const get = query({
  handler: async (ctx) => {
    const user = await safeGetUser(ctx);
    if (!user) return [];
    return ctx.db.query("todos").withIndex("userId", (q) => q.eq("userId", user._id)).collect();
  },
});

export const create = mutation({
  args: { text: v.string() },
  handler: async (ctx, args) => {
    const user = await getUser(ctx); // Throws if unauthenticated
    await ctx.db.insert("todos", { text: args.text, userId: user._id, completed: false });
  },
});

Sign In Component

import { authClient } from "~/lib/auth-client";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";

export function SignIn() {
  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const form = new FormData(e.currentTarget);
    await authClient.signIn.email({
      email: form.get("email") as string,
      password: form.get("password") as string,
    });
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <Input name="email" type="email" placeholder="Email" required />
      <Input name="password" type="password" placeholder="Password" required />
      <Button type="submit">Sign In</Button>
      <Button type="button" variant="outline" onClick={() => authClient.signIn.social({ provider: "github" })}>
        Sign in with GitHub
      </Button>
    </form>
  );
}

Optimistic Updates

import { useMutation } from "@convex-dev/react-query";
import { api } from "convex/_generated/api";

const createTodo = useMutation(api.todos.create).withOptimisticUpdate(
  (localStore, args) => {
    const todos = localStore.getQuery(api.todos.get);
    if (!todos) return;
    localStore.setQuery(api.todos.get, {}, [
      { _id: crypto.randomUUID(), text: args.text, completed: false },
      ...todos,
    ]);
  }
);

Auth Methods

Better-Auth supports multiple authentication methods:

// Email/Password
authClient.signIn.email({ email, password });
authClient.signUp.email({ email, password, name });

// OAuth
authClient.signIn.social({ provider: "github" });
authClient.signIn.social({ provider: "google" });

// Magic Link
authClient.signIn.magicLink({ email });

// Sign Out
authClient.signOut();

// Session
const { data: session } = authClient.useSession();

Commands

# Development
bun dev               # Start frontend
bunx convex dev       # Start Convex (separate terminal)

# Add Shadcn components
bunx shadcn@latest add button input card form dialog

# Add all Shadcn components
bunx shadcn@latest add --all

# Build & Deploy
bun run build
bunx convex deploy

SSR with TanStack Query

Use ensureQueryData and useSuspenseQuery for SSR:

// src/routes/_authed/index.tsx
import { createFileRoute } from "@tanstack/react-router";
import { convexQuery } from "@convex-dev/react-query";
import { useSuspenseQuery } from "@tanstack/react-query";
import { api } from "convex/_generated/api";

export const Route = createFileRoute("/_authed/")({
  loader: async ({ context }) => {
    await context.queryClient.ensureQueryData(convexQuery(api.todos.get, {}));
  },
  component: Dashboard,
});

function Dashboard() {
  const { data: todos } = useSuspenseQuery(convexQuery(api.todos.get, {}));
  return <TodoList todos={todos} />;
}

Sign Out (with expectAuth: true)

When using expectAuth: true, reload the page on sign out:

import { authClient } from "~/lib/auth-client";

function SignOutButton() {
  const handleSignOut = async () => {
    await authClient.signOut();
    window.location.reload(); // Required with expectAuth: true
  };
  return <Button onClick={handleSignOut}>Sign Out</Button>;
}

TanStack Server Functions vs Convex: When to Use What

Use CaseUse ThisWhy
Database CRUDConvex query/mutationTransactional, real-time
Real-time dataConvex queryAuto subscriptions
Third-party APIsConvex actionRuns close to data
Auth handlersTanStack server routeHTTP cookies/redirects
SSR preloadingTanStack loaderPre-fetch for SSR
WebhooksTanStack server routeHTTP endpoints

Core principle: Convex = database & business logic. TanStack Start = HTTP & rendering.

See reference/server-functions-vs-convex.md for detailed guidelines.

Key Integration Points

IntegrationKey FilePurpose
Auth Clientsrc/lib/auth-client.tsxClient-side auth methods
Auth Serversrc/lib/auth-server.tsSSR token handling
Root Providersrc/routes/__root.tsxAuth context + Convex client
Route Guardsrc/routes/_authed.tsxRedirect unauthenticated users
Backend Authconvex/auth.tsBetter-Auth instance
HTTP Routesconvex/http.tsAuth endpoint registration
Databaseconvex/schema.tsType-safe schema

平台分布

Claude Code

28.17%
按下载量换算27

windsurf

23.46%
按下载量换算22

trae

18%
按下载量换算17

OpenCode

12.32%
按下载量换算12

Codex

7.41%
按下载量换算7

github-copilot

3.33%
按下载量换算3

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

接触敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills