Token导航 LogoToken导航

Agent Skill · 前端设计

js-gof(js 高尔夫球)

js-gof 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

js-gof 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 8,040。

总安装 318周安装 13GitHub Stars 35下载 102核验 2026-05-01

安装说明

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

安装方式

通过对话安装

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

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

命令行安装

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

skills.shnpx skills
npx skills add https://github.com/metarhia/metaskills --skill js-gof

这个 Skill 是做什么的

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

模拟高尔夫球运动相关的 UI 交互演示。展示特定布局与动画效果的实现方式。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。主要用于教学或原型设计阶段的体验验证。实际产品集成时应考虑性能与移动端适配。

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

来源仓库内路径:skills/js-gof

上手步骤

4 步
  1. 1

    确认自己的宿主工具

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

  2. 2

    拿到安装命令

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

  3. 3

    安装后重启宿主

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

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

js-gof 怎么安装?

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

js-gof 支持哪些 AI 工具?

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

js-gof 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

js-gof 是免费的吗?

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

js-gof 用的人多吗?

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

js-gof 安全吗?

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

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

值得选的地方

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

先想清楚的地方

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

适不适合你

更适合

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

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 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只读未明确通过
js-gof

js 高尔夫球 · 本页

31835需要联网未明确通过

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

SKILL.md 原文

GoF Patterns

  • Use structural composition over inheritance
  • Use multiparadigm code and contract-programming
  • Use domain-specific languages (DSLs), prefer declarative way
  • Separate and do not mix system and domain code
  • Use GRASP and SOLID principles; especially reduce coupling
  • Remember about referential transparency
  • Prefer platform-agnostic code
  • Implement isolation and layer borders with IoC & DI
  • Use object/Map lookup for Strategy and polymorphic/dynamic dispatch
  • Keep patterns simple
  • Do not over-engineer for the sake of the pattern name

Creational patterns

Abstract factory

Creates related objects belonging to one family without specifying their concrete classes, e.g., UI components for different platforms.

Refs: https://github.com/HowProgrammingWorks/AbstractFactory

const dataAccess = {
  fs: {
    createDatabase: (...args) => new FileStorage(...args),
    createCursor: (...args) => new FileLineCursor(...args),
  },
  minio: {
    // factories collection for minio
  },
  // other implementations
};

// Usage

const accessLayer = dataAccess.fs;
const storage = accessLayer.createDatabase('./storage.dat');
const cursor = accessLayer.createCursor({ city: 'Roma' }, storage);
for await (const record of cursor) {
  console.dir(record);
}

Builder

Step-by-step assembly of a complex configurable object, often using chaining, e.g., Query Builder or Form Generator.

Refs: https://github.com/HowProgrammingWorks/Builder

class QueryBuilder {
  #options;

  constructor(table) {
    this.#options = { table, where: {}, limit: null, order: null };
  }

  where(cond) {
    Object.assign(this.#options.where, cond);
    return this;
  }

  order(field) {
    this.#options.order = field;
    return this;
  }

  limit(n) {
    this.#options.limit = n;
    return this;
  }

  build() {
    return { ...this.#options };
  }
}
const query = new QueryBuilder('User')
  .where({ active: true })
  .order('name')
  .limit(10)
  .build();

Alternatively we can create async constructor to be invoked with await new QueryBuilder, or put all steps into declarative structure like:

const query = await new QueryBuilder({
  entity: 'User',
  where: { active: true },
  order: 'name',
  limit: 10,
});

Factory

Function or method that creates objects using different techniques: assembling from literals and methods, mixins, setPrototypeOf.

Refs: https://github.com/HowProgrammingWorks/Factory

const createUser = (name, role) => ({ name, role, createdAt: Date.now() });
const createAdmin = (name) => createUser(name, 'admin');

Or following:

class Connection {
  constructor(url) {
    // implementation
  }
  // implementation
}

const factory = (() => {
  let index = 0;
  return () => new Connection(`http://10.0.0.1/${index++}`);
})();

Factory Method

Chooses the correct abstraction to create an instance; in JavaScript, this can be implemented using if, switch, or selection from a collection (dictionary).

Refs: https://github.com/HowProgrammingWorks/FactoryMethod

class Person {
  constructor(name) {
    this.name = name;
  }

  static factory(name) {
    return new Person(name);
  }
}
class Product {
  constructor(value) {
    this.field = value;
  }
}

class Creator {
  factoryMethod(...args) {
    return new Product(...args);
  }
}

Prototype

Creates objects by cloning a prepared instance to save resources (not to be confused with Prototype-programming, which is closer to Flyweight).

Refs: https://github.com/HowProgrammingWorks/PrototypePattern

const proto = { type: 'widget', color: 'blue' };
const clone = () => ({ ...proto });
class Point {
  #x;
  #y;

  constructor(x, y) {
    this.#x = x;
    this.#y = y;
  }

  move(x, y) {
    this.#x += x;
    this.#y += y;
  }

  clone() {
    return new Point(this.#x, this.#y);
  }
}

class Line {
  #start;
  #end;

  constructor(start, end) {
    this.#start = start;
    this.#end = end;
  }

  move(x, y) {
    this.#start.move(x, y);
    this.#end.move(x, y);
  }

  clone() {
    const start = this.#start.clone();
    const end = this.#end.clone();
    return new Line(start, end);
  }
}

// Usage

const p1 = new Point(0, 0);
const p2 = new Point(10, 20);
const line = new Line(p1, p2);
const cloned = line.clone();
cloned.move(2, 3);
const point = (x, y) => {
  const move = (dx, dy) => {
    x += dx;
    y += dy;
  };
  const clone = () => point(x, y);
  return { move, clone };
};

// Usage

const { move, clone } = point(10, 20);
const c1 = clone();
move(-5, 10);

Flyweight

Saves memory allocation by sharing common state among multiple instances.

Refs: https://github.com/HowProgrammingWorks/Flyweight

const flyweightPool = new Map();

const getFlyweight = (shared) => {
  const { char, font, size } = shared;
  const key = `${char}:${font}:${size}`;
  let flyweight = flyweightPool.get(key);
  if (!flyweight) {
    flyweight = Object.freeze({ ...shared });
    flyweightPool.set(key, flyweight);
  }
  return flyweight;
};

const createChar = (char, font, size, row, col) => {
  const intrinsic = getFlyweight({ char, font, size });
  return { intrinsic, row, col };
};

const a1 = createChar('A', 'Arial', 12, 0, 0);
const a2 = createChar('A', 'Arial', 12, 0, 5);
console.log(a1.intrinsic === a2.intrinsic); // true

Singleton

Provides global access to a single instance; often considered an anti-pattern, easiest implemented via ESM/CJS module caching exported refs.

Refs: https://github.com/HowProgrammingWorks/Singleton

Everywhere we import this state will be the same collection

const connections = new Map(); // shared state
const nop = () => {}; // pure function with no state
module.exports = { connections, nop };
class Singleton {
  static #instance;

  constructor() {
    const instance = Singleton.#instance;
    if (instance) return instance;
    Singleton.#instance = this;
  }
}
function Singleton() {
  const { instance } = Singleton;
  if (instance) return instance;
  Singleton.instance = this;
}
const Singleton = new (function () {
  const single = this;
  return function () {
    return single;
  };
})();
const Singleton = (() => {
  let instance;

  class Singleton {
    constructor() {
      if (instance) return instance;
      instance = this;
    }
  }

  return Singleton;
})();
const singleton = (() => {
  const instance = {};
  return () => instance;
})();
const singleton = (
  (instance) => () =>
    instance
)({});

Object Pool

Reuses pre-created objects to save resources during frequent creation and destruction.

Refs: https://github.com/HowProgrammingWorks/Pool

class Pool {
  #available = [];
  #factory = null;

  constructor(factory, size) {
    this.#factory = factory;
    for (let i = 0; i < size; i++) this.#available.push(factory());
  }

  acquire() {
    return this.#available.pop() || this.#factory();
  }

  release(obj) {
    this.#available.push(obj);
  }
}

Structural patterns

Adapter

Converts an incompatible interface into a compatible one, enabling third-party component usage without altering its code; can even transform a function contract into an object or vice versa.

Refs: https://github.com/HowProgrammingWorks/Adapter

const promisify =
  (fn) =>
  (...args) =>
    new Promise((resolve, reject) => {
      fn(...args, (err, data) => (err ? reject(err) : resolve(data)));
    });
const timer = new Timer(1000); // wraps setInterval
for await (const step of timer) {
  // gives [Symbol.asyncIterator] contract
  console.log({ step });
}
class ArrayToQueueAdapter {
  #array = null;

  constructor(array) {
    if (!Array.isArray(array)) {
      throw new Error('Array instance expected');
    }
    this.#array = array;
  }

  enqueue(data) {
    this.#array.push(data);
  }

  dequeue() {
    return this.#array.pop();
  }

  get count() {
    return this.#array.length;
  }
}

Wrapper

Function wrapper that delegates calls and adds behavior; a specialized case of Adapter.

Refs: https://github.com/HowProgrammingWorks/Wrapper

const withLogging =
  (fn, label) =>
  (...args) => {
    console.log(`${label} called`, args);
    const result = fn(...args);
    console.log(`${label} returned`, result);
    return result;
  };
const wrapInterface = (anInterface) => {
  const wrapped = {};
  for (const key in anInterface) {
    const fn = anInterface[key];
    wrapped[key] = wrapFunction(fn);
  }
  return wrapped;
};
class Timeout {
  constructor(fn, msec) {
    this.function = fn;
    this.timer = setTimeout(() => {
      this.timer = null;
    }, msec);
  }

  execute(...args) {
    let result = undefined;
    if (!this.timer) return result;
    clearTimeout(this.timer);
    this.timer = null;
    result = this.function(...args);
    return result;
  }
}

Boxing

Wraps primitives into object types to add methods or unify interfaces, e.g., narrowing String to AddressString.

Refs: https://github.com/HowProgrammingWorks/ADT

Box, Container or Value-Object examples:

class AddressString {
  #value;

  constructor(value) {
    if (typeof value !== 'string') {
      throw new TypeError('Address must be a string');
    }
    const str = value.trim();
    if (str === '') throw new TypeError('Address must be a non-empty');
    this.#value = str;
  }

  get city() {
    const index = this.#value.indexOf(',');
    return this.#value.slice(0, index).trim();
  }

  toString() {
    return this.#value;
  }

  valueOf() {
    return this.#value;
  }
}

// Usage

const address = new AddressString('London, 221B Baker Street');
console.log(address.city); // 'London'
console.log(`Delivery to: ${address}`);

Value-Object examples:

const KMH_TO_MPH = 0.621371;

class SpeedValue {
  #kmh;

  constructor(value, unit = 'kmh') {
    if (typeof value !== 'number') {
      throw new TypeError('Speed must be a number');
    }
    if (value < 0) throw new TypeError('Speed must be non-negative');
    if (unit !== 'kmh' && unit !== 'mph') {
      throw new TypeError('Unit must be kmh or mph');
    }
    this.#kmh = unit === 'mph' ? value / KMH_TO_MPH : value;
  }

  get kmh() {
    return this.#kmh;
  }

  get mph() {
    return this.#kmh * KMH_TO_MPH;
  }

  toString() {
    return `${this.#kmh} km/h`;
  }

  valueOf() {
    return this.#kmh;
  }
}

Decorator

Dynamically extends behavior without inheritance, typically via composition and declarative syntax, effectively adding metadata.

Refs: https://github.com/HowProgrammingWorks/Decorator

const add = (a, b) => a + b;
const loggedAdd = withLogging(add, 'add');

Not a good idea to use classical decorator in JavaScript/TypeScript

const validator = new MinLengthValidator(
  new EmailValidator(new RequiredValidator(new BaseValidator())),
  20,
);

const input = 'timur.shemsedinov@gmail.com';
const result = validator.validate(input);

We can add metadata to an instance in several JS-idiomatic ways:

Symbol property on instance:

const VALIDATOR_META = Symbol('validatorMeta');

class EmailValidator {
  constructor(next) {
    this.next = next;
    this[VALIDATOR_META] = { type: 'email' };
  }
}

Wrapper that attaches metadata as own property.

JSDoc annotation (zero runtime cost):

/**
 * @typedef {{ type: string, label: string }} ValidatorMeta
 * @typedef {{ validate(v: string): boolean, meta: ValidatorMeta }} Validator
 */

/** @type {Validator} */
const validator = Object.assign(
  new EmailValidator(new RequiredValidator(new BaseValidator())),
  { meta: { type: 'email', label: 'Email field' } },
);

Module-local WeakMap (fully private, no shape pollution):

const metadata = new WeakMap();

const createValidator = ({ args, meta }) => {
  const instance = new Validator(...args);
  metadata.set(instance, meta);
  return instance;
};

module.exports = { createValidator };

Proxy

Controls access to an object by intercepting calls, reads, and writes; useful for lazy initialization, caching, and security; can be implemented via GoF or native JavaScript Proxy.

Refs: https://github.com/HowProgrammingWorks/Proxy

Do not use the built-in JS Proxy class unless a developer asks you directly because of deopts. Use GoF Proxy instead as a container with additional behavior.

const fs = require('node:fs');

const statistics = { bytes: 0, chunks: 0, events: {} };

class StatReadStream extends fs.ReadStream {
  emit(name, data) {
    if (name === 'data') {
      statistics.bytes += data.length;
      statistics.chunks++;
    }
    const counter = statistics.events[name] || 0;
    statistics.events[name] = counter + 1;
    super.emit(name, data);
  }
}

const getStatistics = () => structuredClone(statistics);

const createReadStream = (path, options) => new StatReadStream(path, options);

module.exports = { ...fs, createReadStream, getStatistics };

Bridge

Separates two or more abstraction hierarchies via composition or aggregation, allowing them to evolve independently.

Refs: https://github.com/HowProgrammingWorks/Bridge

class CommunicationProtocol {
  sendCommand(device, command) {
    console.log({ device, command });
    throw new Error('sendCommand() must be implemented');
  }
}

class MQTTProtocol extends CommunicationProtocol {
  sendCommand(device, command) {
    console.log(`[MQTT] Sending '${command}' to ${device}`);
  }
}

class HTTPProtocol extends CommunicationProtocol {
  sendCommand(device, command) {
    console.log(`[HTTP] Sending '${command}' to ${device}`);
  }
}

class IoTDevice {
  constructor(name, protocol) {
    this.name = name;
    this.protocol = protocol;
  }

  operate(command) {
    this.protocol.sendCommand(this.name, command);
  }
}

class SmartLight extends IoTDevice {
  turnOn() {
    this.operate('Turn On Light');
  }

  turnOff() {
    this.operate('Turn Off Light');
  }
}

class SmartThermostat extends IoTDevice {
  setTemperature(temp) {
    this.operate(`Set Temperature to ${temp}°C`);
  }
}

Composite

Implements a common interface to uniformly handle individual objects and their tree structures, e.g., DOM or file systems.

Refs: https://github.com/HowProgrammingWorks/Composite

Recursive composite with reduce:

const calculateTotal = (order) => {
  const items = Array.isArray(order) ? order : Object.values(order);
  return items.reduce((sum, item) => {
    if (typeof item.price === 'number') return sum + item.price;
    else return sum + calculateTotal(item);
  }, 0);
};

JSON as a nested composite structure:

const json = `{
  "electronics": {
    "laptop": { "price": 1200 },
    "accessories": {
      "mouse": { "price": 25 },
      "keyboard": { "price": 75 }
    }
  },
  "books": {
    "fiction": { "price": 15 },
    "technical": { "price": 60 }
  }
}`;

const order = JSON.parse(json);
console.log(calculateTotal(order));

Facade

Simplifies access to a complex system, providing a unified and clear interface, hiding and protecting internal complexity.

Refs: https://github.com/HowProgrammingWorks/Facade

const createApi = (db, cache, logger) => ({
  async getUser(id) {
    const cached = cache.get(id);
    if (cached) return cached;
    const user = await db.row('User', ['*'], { id });
    cache.set(id, user);
    logger.info(`User ${id} loaded`);
    return user;
  },
});

This hides classes Timer, Logger, Task and so on:

scheduler.task('name2', '2019-03-12T14:37Z', (done) => {
  setTimeout(() => {
    done(new Error('task failed'));
  }, 1100);
});

Context

Exchanges state and dependencies between different components (abstractions, modules, layers) that do not share a common environment, without tightly coupling them.

Refs: https://github.com/HowProgrammingWorks/Context

class AccountService {
  constructor(context) {
    this.context = context;
  }

  getBalance(accountId) {
    const { console, accessPolicy, user } = this.context;
    console.log(`User ${user.name} requesting balance for ${accountId}`);
    if (!accessPolicy.check(user.role, 'read:balance')) {
      console.error('Access denied: insufficient permissions');
      return null;
    }
    const balance = 15420.5;
    console.log('Access granted');
    return balance;
  }
}

class AccessPolicy {
  constructor() {
    this.permissions = {
      admin: ['read:balance', 'read:transactions', 'write:transactions'],
      user: ['read:balance'],
      guest: [],
    };
  }

  check(role, permission) {
    return this.permissions[role]?.includes(permission);
  }
}

class User {
  constructor(name, role) {
    this.name = name;
    this.role = role;
  }
}

const accessPolicy = new AccessPolicy();
const user = new User('Marcus', 'admin');
const context = { console, accessPolicy, user };

const accountService = new AccountService(context);
const balance = accountService.getBalance('Account-123');
console.log(`Balance = $${balance}`);

Alternative way with closure:

const createAccountService = (context) => {
  const { console, accessPolicy, user } = context;

  const getBalance = (accountId) => {
    console.log(`User ${user.name} requesting balance for ${accountId}`);
    if (!accessPolicy.check(user.role, 'read:balance')) {
      console.error('Access denied: insufficient permissions');
      return null;
    }
    return 15420.5;
  };

  const getTransactions = (accountId) => {
    if (!accessPolicy.check(user.role, 'read:transactions')) {
      console.error('Access denied: insufficient permissions');
      return null;
    }
    console.log(`User ${user.name} reading transactions for ${accountId}`);
    return ['TR-123', 'TR-456', 'TR-789'];
  };

  return { getBalance, getTransactions };
};

const accessPolicy = {
  permissions: {
    admin: ['read:balance', 'read:transactions', 'write:transactions'],
    user: ['read:balance'],
    guest: [],
  },
  check: (role, permission) =>
    accessPolicy.permissions[role]?.includes(permission),
};

const context = {
  console,
  accessPolicy,
  user: { name: 'Marcus', role: 'admin' },
};

const accountService = createAccountService(context);

console.log('Balance:', accountService.getBalance('ACC-001'));
console.log('Transactions:', accountService.getTransactions('ACC-001'));

平台分布

Codex

37.3%
按下载量换算38

Claude

30.65%
按下载量换算31

Cursor

19.75%
按下载量换算20

Gemini CLI

8.41%
按下载量换算9

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

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

继续浏览同类 Skills