agentleFS
Robot-InventorRobot-Inventor/agent-skills/skills/web-master/SKILL.md

web-master

Skill3 starsChanged 3 months agoMITView on GitHub

A skill outlining the fundamental principles to keep in mind when writing or editing web-related code. Read this skill before developing an implementation plan or writing or reviewing code for web-related tasks, and apply it to your work.

The file

Show its rules and text

We split this skill into the rules it gives an agent

14 rules. About 0 are common, 12 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈12

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Follow these instructions when writing web-related code.

    line 11
  2. Distinctive:

    Do not reach for type assertions unless you need one.

    line 17
  3. Very specific:

    Do not use ReturnType unless you need it.

    line 25
  4. Distinctive:

    If you need to use the return type of a specific function defined in the project somewhere other than that function:

    line 27
  5. Distinctive:

    If you need the return type of a library function:

    line 32
  6. Distinctive:

    Check the function's type definitions first.

    line 34
  7. Distinctive:

    If the library exports that type, use the exported type.

    line 35
  8. Very specific:

    If you need to pass the return type of another library function as a type argument and the library does not export that function's return …

    line 36
  9. Distinctive:

    If the library does not export the type:

    line 37
  10. Distinctive:

    Write the type directly if it is a simple primitive type.

    line 38
  11. Distinctive:

    Do not disable ESLint rules as an easy workaround.

    line 81
  12. Distinctive:

    Check the project dependencies to see if a validation library is installed.

    line 121
  13. Distinctive:

    If a UI component library is available, actively use its components and reduce custom implementations unless absolutely necessary.

    line 198
  14. Distinctive:

    Do not mock application-owned modules.

    line 206

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Web Master

Follow these instructions when writing web-related code.

TypeScript

Do not use type assertions

Do not reach for type assertions unless you need one. Never add a type assertion up front because you think you might need it later. You may use a type assertion only when all of these conditions apply:

  • You first write the code without a type assertion and encounter a type error.
  • You cannot resolve that type error by improving type definitions elsewhere.
  • Adding the type assertion does not compromise type safety.

Do not use ReturnType

Do not use ReturnType unless you need it. Use the following approaches instead.

If you need to use the return type of a specific function defined in the project somewhere other than that function:

  • For a simple primitive type such as boolean or string, write the type directly.
  • For a complex type, define a named type, specify it as the function's return type ((): T => {}), and reuse T.

If you need the return type of a library function:

  • Check the function's type definitions first.
  • If the library exports that type, use the exported type.
    • If you need to pass the return type of another library function as a type argument and the library does not export that function's return type, you may use ReturnType inside the type argument.
  • If the library does not export the type:
    • Write the type directly if it is a simple primitive type.
    • Otherwise, you may use ReturnType.
// Incorrect
import foo from "foo";

const myFunc = (): string => {...};

const myFunc2 = (arg: ReturnType<typeof foo>, arg2: ReturnType<typeof myFunc>): number => {...};

// Correct
import type { FooResult } from "foo";

const myFunc = (): string => {...};

const myFunc2 = (arg: FooResult, arg2: string): number => {...};

Prefer as const satisfies over type annotations

Do not add type annotations unless you need them. Start by writing the code without a type annotation. If that causes a type error, first try to resolve it by improving type definitions elsewhere. Use a type annotation only as a last resort when those changes cannot solve the problem.

When you write an object and need to guarantee that it conforms to a specific type, use satisfies. You don't need to use satisfies on values whose type is obvious, such as arrays of strings. You don't need to specify ReadOnly for the type of an as const satisfies value.

// Incorrect
const foo: T = {
    bar: "bar"
};

const foo = {
    bar: "bar"
} as const satisfies ReadOnly<T>;

// Correct
const foo = {
    bar: "bar"
} as const satisfies T;

Do not disable ESLint rules

Do not disable ESLint rules as an easy workaround. ESLint errors usually identify low-quality code rather than create pointless obstacles. Disabling a rule to silence an error leaves the underlying problem in place.

Disable an ESLint rule only as a last resort when no better option exists. Handle ESLint errors as follows:

  1. Understand what ESLint is reporting. Identify the affected code and the purpose behind the rule.
  2. Improve the code in a way that addresses that purpose.
  3. Disable the rule only when complying with it would make the code excessively complex, the warning is a clear false positive, you have another legitimate reason to disable it, or a possible fix would conflict with the rule's underlying intent.

Examples

The ESLint sort-imports rule defines a consistent import order. In properly modularized code, behavior should not depend on import order, so you should follow the rule.

// Incorrect
/* eslint-disable sort-imports */
import foo from "foo";
import bar from "bar";

// Correct
import bar from "bar";
import foo from "foo";

The no-magic-numbers rule exists to give numeric values meaningful names when their purpose would otherwise be unclear. You do not need to force an obvious value, such as 60 when it represents the number of seconds in a minute, into a constant just to satisfy the rule. In that case, disabling the rule is acceptable. Replacing 1 with a constant named ONE also defeats the purpose of no-magic-numbers. Give the value a meaningful name instead, or disable the rule if its meaning is already obvious. Also consider whether the number needs to be hard-coded in the first place.

// Incorrect
// eslint-disable-next-line no-magic-numbers
if (myArray.length !== 0) {...}

// Correct
if (myArray.length) {...}

The max-lines and max-lines-per-function rules exist as indicators of code readability and maintainability. Warnings for these rules suggest that your code design may be poor. Simply removing line breaks to meet the rules is a superficial solution and actually makes the code harder to read, thus violating the essence of the rules. Instead, you should fix the problem by removing redundant code or properly restructuring and modularizing it. If you've only slightly exceeded the limit and your code is already well-designed, you should disable the rules rather than removing line breaks or forcing splits.

Do not validate it yourself

TypeScript types are not just an afterthought to JavaScript. Designing with types in mind keeps your code clean and efficient. With proper type design, validation is rarely needed except at project boundaries such as user input or web API responses. When code is properly designed based on types, function inputs and outputs are reliable, eliminating the need to validate values repeatedly.

Check the project dependencies to see if a validation library is installed. If one is installed, you should leverage the library's features rather than writing your own validator.

// Incorrect
const isRecord = (value: unknown): value is Record<string, unknown> =>
    typeof value === "object" && value !== null && !Array.isArray(value);
const isParson = (value: unknown): value is Person =>
    isRecord(value) && typeof value.name === "string" && typeof value.age === "number" && value.age >= 0;

isParson(externalValue) ? externalValue : "Unknown";

// Correct
import { type } from "arktype";

const Person = type({
    name: "string",
    age: "number >= 0"
});

const parsed = Person(externalValue);
parsed instanceof type.errors ? "Unknown" : parsed;

CSS

Define only the necessary styles

When writing CSS, first check if a reset CSS is loaded into your project and if that reset CSS is applied to the page or layout file you are currently working on. If a reset CSS is in place, you do not need to define styles that overlap with it, such as margin: 0 (this is an example, but not limited to this).

In CSS, you should only specify properties that need to be changed from the parent element, and you should not specify properties that do not need to be changed again. Remember that CSS has inheritance, and style accordingly.

/* reset.css */
* {
    margin: 0;
}
/* style.css */

/* Incorrect */
h1 {
    margin: 0;
    font-weight: bold;
}

h1 div {
    font-weight: bold;
}

/* Correct */
h1 {
    font-weight: bold;
}

Intentional typography design

Do not specify font-family outside the document root unless absolutely necessary, such as in code blocks. Also, as a general rule, do not change the font size unless there is a clear reason, such as making unimportant notices smaller or headings larger. Since the base font size may be overridden by browser settings, use em or rem instead of px for font size or areas that depend on font size.

/* Incorrect */
h1 {
    font-size: 32px;
}

/* Correct */
h1 {
    font-size: 2rem;
}

HTML and JSX

Avoid redundant definitions

If a UI component library is available, actively use its components and reduce custom implementations unless absolutely necessary.

Also, avoid adding unnecessary attributes. For example, icon component libraries may have aria-hidden set by default; in such cases, there's no need to set this attribute again when using the component.

Testing

Design tests properly

Do not mock application-owned modules. Prefer real implementations and test observable behavior rather than implementation wiring. Use mocks only at slow, nondeterministic, destructive, or external boundaries. Avoid tests whose assertions only verify mock calls or values configured on mocks.

Test the behavior from an external perspective, not the internal implementation. In other words, tests that require changes when refactoring are bad tests. Test the project's code, not the browser or external libraries. For example, it's obvious that a button element will be displayed in the browser when you write it; this tests the browser's behavior, not the project's code.

Add only the necessary tests. Ensure that your tests verify the correct operation of the code and are capable of detecting when the code breaks. Testing outcomes that are already expected to occur is pointless, and tests that fail to detect when the code is broken are worthless. Test the externally observable behavior of the code when provided with normal, boundary, and anomalous input values.

Do not export for testing purposes

You should not export functions, values, or other data solely for testing purposes. When testing things that are not used outside of the file except for testing, use in-source testing instead of exporting them and creating a separate test file.

Do not mock the external environment

For tests that require access to databases or external servers, use Testcontainers instead of mocking them. If a timer is needed, use the fake timer from the test library.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.