agentsclimarketplace

Frontend mean

Skill endorphin-ai/claude-code-teams/mean-team/.claude/skills/frontend-mean

🍕 One Pizza Team [AI Agents Team ] | Claude Code Agent Squads

Install
npx -y skills add endorphin-ai/claude-code-teams --skill frontend-mean

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

React frontend development for MEAN stack apps. Use when implementing React components, pages, hooks, API integration, routing, state management, and responsive UI.

SKILL.md

6.9 KB, as published. Nobody here has run it

Frontend Mean

Purpose

Implement React frontends for MEAN stack applications. Translate React architecture designs into working code: components, pages, custom hooks, API client, routing, context providers, forms, and responsive layouts.

Key Patterns

Component Pattern

// components/common/Button.jsx
import styles from './Button.module.css';

const Button = ({ children, variant = 'primary', size = 'md', loading = false, disabled, onClick, type = 'button' }) => {
  return (
    <button
      type={type}
      className={`${styles.btn} ${styles[variant]} ${styles[size]}`}
      disabled={disabled || loading}
      onClick={onClick}
    >
      {loading ? <Spinner size="sm" /> : children}
    </button>
  );
};
export default Button;

Page Pattern

// pages/DashboardPage.jsx
import { useAuth } from '../hooks/useAuth';
import { useFetch } from '../hooks/useFetch';
import PageWrapper from '../components/layout/PageWrapper';
import StatCards from '../components/features/StatCards';
import ActivityFeed from '../components/features/ActivityFeed';
import Spinner from '../components/common/Spinner';
import ErrorMessage from '../components/common/ErrorMessage';

const DashboardPage = () => {
  const { user } = useAuth();
  const { data: stats, loading, error, refetch } = useFetch('/api/dashboard/stats');

  if (loading) return <Spinner />;
  if (error) return <ErrorMessage message={error} onRetry={refetch} />;

  return (
    <PageWrapper title="Dashboard">
      <h1>Welcome, {user.name}</h1>
      <StatCards stats={stats} />
      <ActivityFeed userId={user.id} />
    </PageWrapper>
  );
};
export default DashboardPage;

Custom Hook Patterns

// hooks/useAuth.js -- Authentication hook
import { useContext } from 'react';
import { AuthContext } from '../context/AuthContext';
export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) throw new Error('useAuth must be used within AuthProvider');
  return context;
};

// hooks/useFetch.js -- Data fetching hook
import { useState, useEffect, useCallback } from 'react';
import api from '../services/api';
export const useFetch = (url, options = {}) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const fetch = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);
      const response = await api.get(url, options);
      setData(response.data.data);
    } catch (err) {
      setError(err.response?.data?.error?.message || 'Something went wrong');
    } finally {
      setLoading(false);
    }
  }, [url]);
  useEffect(() => { fetch(); }, [fetch]);
  return { data, loading, error, refetch: fetch };
};

// hooks/useForm.js -- Form management hook
import { useState } from 'react';
export const useForm = (initialValues, validate) => {
  const [values, setValues] = useState(initialValues);
  const [errors, setErrors] = useState({});
  const [isSubmitting, setIsSubmitting] = useState(false);
  const handleChange = (e) => {
    const { name, value } = e.target;
    setValues(prev => ({ ...prev, [name]: value }));
    if (errors[name]) setErrors(prev => ({ ...prev, [name]: '' }));
  };
  const handleSubmit = async (onSubmit) => {
    const validationErrors = validate ? validate(values) : {};
    setErrors(validationErrors);
    if (Object.keys(validationErrors).length > 0) return;
    setIsSubmitting(true);
    try { await onSubmit(values); } catch (err) { setErrors({ submit: err.message }); }
    finally { setIsSubmitting(false); }
  };
  return { values, errors, isSubmitting, handleChange, handleSubmit, setValues, setErrors };
};

API Client Pattern

// services/api.js
import axios from 'axios';
const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL || 'http://localhost:5000',
  headers: { 'Content-Type': 'application/json' }
});
api.interceptors.request.use((config) => {
  const token = localStorage.getItem('token');
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});
api.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      localStorage.removeItem('token');
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);
export default api;

Auth Context Pattern

// context/AuthContext.jsx
import { createContext, useState, useEffect, useCallback } from 'react';
import api from '../services/api';
export const AuthContext = createContext(null);
export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    const token = localStorage.getItem('token');
    if (token) { api.get('/api/auth/me').then(res => setUser(res.data.data)).catch(() => localStorage.removeItem('token')).finally(() => setLoading(false)); }
    else setLoading(false);
  }, []);
  const login = useCallback(async (email, password) => {
    const res = await api.post('/api/auth/login', { email, password });
    localStorage.setItem('token', res.data.data.token);
    setUser(res.data.data.user);
    return res.data.data;
  }, []);
  const register = useCallback(async (userData) => {
    const res = await api.post('/api/auth/register', userData);
    localStorage.setItem('token', res.data.data.token);
    setUser(res.data.data.user);
    return res.data.data;
  }, []);
  const logout = useCallback(() => { localStorage.removeItem('token'); setUser(null); }, []);
  return (
    <AuthContext.Provider value={{ user, loading, login, register, logout, isAuthenticated: !!user }}>
      {children}
    </AuthContext.Provider>
  );
};

Conventions

  • Vite as build tool (NOT Create React App -- CRA is deprecated)
  • Functional components only with hooks
  • CSS Modules for styling (Component.module.css) or Tailwind CSS
  • File naming: PascalCase for components, camelCase for hooks/utils/services
  • Props destructured in function signature
  • Every async operation: loading state + error state + success state
  • Forms: controlled components with useForm hook
  • API calls only through services/api.js -- never raw axios/fetch in components
  • Token stored in localStorage (simple) -- HttpOnly cookie for production security
  • Lazy load pages with React.lazy + Suspense for bundle splitting
  • All user-facing text should be easy to extract for i18n later

Knowledge Strategy

  • Patterns to capture: Component implementations that worked well, hook patterns, form handling approaches
  • Examples to collect: Complete page implementations, auth flow code, API integration patterns
  • Update permission: Agents may freely add/update files in references/. Changes to SKILL.md or scripts/ require user approval.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.