nodejs-development — Claude Code skill: what it does, how to install
Guidelines for Node.js and TypeScript development. Teaches the agent patterns for Payload CMS with Next.js, Vue 3 components, and Zod validation.
npx skills add Mindrally/skills --skill nodejs-development -a claude-codeWhat nodejs-development does
This skill guides AI agents through full-stack TypeScript conventions. It lays out directory structures and access control configs for Payload CMS inside the Next.js App Router, alongside database querying patterns via getPayloadClient.
Client-side instructions focus on Vue 3 with <script setup lang="ts">, typed composables, and Pinia stores. For backend requests, it details schema definitions with Zod, safe parsing, and request body validation middleware in Express.
The skill supplies architectural templates rather than executable scripts. Your agent will rely entirely on packages installed in your local project workspace.
What it helps with
- define Payload CMS collections with role checks for Next.js
- build typed Vue 3 components using script setup syntax
- create reusable API composables with loading and error states
- set up Express request validation middleware using Zod
- scaffold Pinia stores with typed state, getters, and auth actions
Example prompts for the agent
- Generate a Payload CMS collection for blog posts with title, richText, and publishedDate fields.
- Write a Vue 3 useApi composable with error handling and reactive state.
- Create an Express middleware function that validates the body against a Zod schema.
How to install nodejs-development
1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill nodejs-development -a claude-code2Manually: put the files in place
~/.claude/skills/nodejs-development/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/nodejs-development/
1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill nodejs-development -a codex2Manually: put the files in place
.agents/skills/nodejs-development/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill nodejs-development -a cursor2Manually: put the files in place
.cursor/skills/nodejs-development/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install Mindrally/skills nodejs-development2Manually: put the files in place
.github/skills/nodejs-development/SKILL.md1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill nodejs-development -a gemini-cli2Platform CLI
gemini skills install https://github.com/Mindrally/skills --path nodejs-developmentManually: put the files in place
.devin/skills/nodejs-development/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add Mindrally/skills --skill nodejs-development -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about nodejs-development
How do I install nodejs-development in Claude Code?
Run npx skills add Mindrally/skills --skill nodejs-development -a claude-code in your terminal. You can also place the file directly at ~/.claude/skills/nodejs-development/SKILL.md.
What does nodejs-development do?
It provides prompt guidelines and code structures for Node.js and TypeScript. The model uses them to write consistent Payload CMS models, Next.js routes, Vue 3 code, and Zod schemas.
What frameworks and libraries are covered by this skill?
It includes conventions for Payload CMS, Next.js, Vue 3, Pinia, Express, and Zod. You only need the packages that match the stack you are building.
Source text
SKILL.md · Apache-2.0
---
name: nodejs-development
description: Node.js development guidelines covering Payload CMS, Vue.js with TypeScript, and general TypeScript best practices
metadata:
maintainer: Mindrally
source: https://github.com/Mindrally/skills
---
# Node.js Development Guidelines
You are an expert in Node.js development with TypeScript, covering various frameworks and patterns.
## Payload CMS with Next.js
### Project Setup
```
project/
├── src/
│ ├── app/ # Next.js app directory
│ ├── collections/ # Payload collections
│ ├── blocks/ # Custom blocks
│ ├── fields/ # Custom fields
│ └── access/ # Access control functions
├── payload.config.ts # Payload configuration
└── next.config.js # Next.js configuration
```
### Collection Definition
```typescript
import { CollectionConfig } from 'payload/types';
const Posts: CollectionConfig = {
slug: 'posts',
admin: {
useAsTitle: 'title',
},
access: {
read: () => true,
create: ({ req: { user } }) => Boolean(user),
update: ({ req: { user } }) => Boolean(user),
delete: ({ req: { user } }) => Boolean(user),
},
fields: [
{
name: 'title',
type: 'text',
required: true,
},
{
name: 'content',
type: 'richText',
},
{
name: 'publishedDate',
type: 'date',
},
],
};
export default Posts;
```
### API Routes
```typescript
// app/api/posts/route.ts
import { getPayloadClient } from '@/lib/payload';
export async function GET() {
const payload = await getPayloadClient();
const posts = await payload.find({
collection: 'posts',
limit: 10,
});
return Response.json(posts);
}
```
## Vue.js with TypeScript
### Component Structure
```vue
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
interface User {
id: number;
name: string;
email: string;
}
const props = defineProps<{
userId: number;
}>();
const emit = defineEmits<{
(e: 'update', user: User): void;
}>();
const user = ref<User | null>(null);
const isLoading = ref(false);
const displayName = computed(() => user.value?.name ?? 'Unknown');
async function fetchUser() {
isLoading.value = true;
try {
const response = await fetch(`/api/users/${props.userId}`);
user.value = await response.json();
} finally {
isLoading.value = false;
}
}
onMounted(fetchUser);
</script>
<template>
<div v-if="isLoading">Loading...</div>
<div v-else-if="user">
<h2>{{ displayName }}</h2>
<p>{{ user.email }}</p>
</div>
</template>
```
### Composables
```typescript
// composables/useApi.ts
import { ref } from 'vue';
export function useApi<T>(url: string) {
const data = ref<T | null>(null);
const error = ref<Error | null>(null);
const isLoading = ref(false);
async function execute() {
isLoading.value = true;
error.value = null;
try {
const response = await fetch(url);
if (!response.ok) throw new Error('Request failed');
data.value = await response.json();
} catch (e) {
error.value = e as Error;
} finally {
isLoading.value = false;
}
}
return { data, error, isLoading, execute };
}
```
### Pinia Store
```typescript
// stores/user.ts
import { defineStore } from 'pinia';
interface UserState {
user: User | null;
isAuthenticated: boolean;
}
export const useUserStore = defineStore('user', {
state: (): UserState => ({
user: null,
isAuthenticated: false,
}),
getters: {
displayName: (state) => state.user?.name ?? 'Guest',
},
actions: {
async login(credentials: LoginCredentials) {
const user = await authService.login(credentials);
this.user = user;
this.isAuthenticated = true;
},
logout() {
this.user = null;
this.isAuthenticated = false;
},
},
});
```
## TypeScript with Zod
### Schema Definition
```typescript
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
name: z.string().min(1),
email: z.string().email(),
role: z.enum(['user', 'admin']),
createdAt: z.date(),
});
type User = z.infer<typeof UserSchema>;
const CreateUserSchema = UserSchema.omit({ id: true, createdAt: true });
type CreateUserInput = z.infer<typeof CreateUserSchema>;
```
### Validation
```typescript
function createUser(input: unknown): User {
const validatedInput = CreateUserSchema.parse(input);
// Input is now typed as CreateUserInput
return {
...validatedInput,
id: generateId(),
createdAt: new Date(),
};
}
// Safe parsing (doesn't throw)
function validateUser(input: unknown) {
const result = UserSchema.safeParse(input);
if (!result.success) {
console.error(result.error.issues);
return null;
}
return result.data;
}
```
### API Validation Middleware
```typescript
import { z } from 'zod';
import { Request, Response, NextFunction } from 'express';
function validate<T extends z.ZodSchema>(schema: T) {
return (req: Request, res: Response, next: NextFunction) => {
const result = schema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ errors: result.error.issues });
}
req.body = result.data;
next();
};
}
// Usage
app.post('/users', validate(CreateUserSchema), createUserHandler);
```
## General Best Practices
### Error Handling
- Use custom error classes
- Implement global error handlers
- Log errors with context
- Return appropriate status codes
### Async Patterns
- Use async/await consistently
- Handle promise rejections
- Implement proper timeouts
- Use Promise.all for parallel operations
### Testing
- Write unit tests for utilities
- Integration tests for APIs
- Use test fixtures
- Mock external dependencies
© Mindrally · Apache-2.0 · Mindrally/skills