code-reviewer
Comprehensive code review for Ishkul's React Native/TypeScript frontend and Go backend. Checks for quality, security, performance, and adherence to project conventions. Use after implementing features or during PR review.
$ 安裝
git clone https://github.com/mesbahtanvir/ishkul /tmp/ishkul && cp -r /tmp/ishkul/.claude/skills/code-reviewer ~/.claude/skills/ishkul// tip: Run this command in your terminal to install the skill
SKILL.md
name: code-reviewer description: Comprehensive code review for Ishkul's React Native/TypeScript frontend and Go backend. Checks for quality, security, performance, and adherence to project conventions. Use after implementing features or during PR review.
Code Reviewer
Comprehensive code review skill for the Ishkul codebase (React Native/Expo + Go).
Tech Stack Context
- Frontend: React Native/Expo, TypeScript 5.9, Zustand, React Navigation 7
- Backend: Go 1.24, Cloud Run, Firestore
- Auth: Firebase + Custom JWT
- Testing: Jest + React Testing Library (frontend), Go testing + testify (backend)
Review Checklist
Frontend (TypeScript/React Native)
Critical Issues
- React Rules of Hooks - All hooks at top, before conditionals (see hooks-validator skill)
- No
anytypes - Useunknownor proper types - No hardcoded secrets - Use environment variables
- Proper error handling - Try-catch with typed ApiError
TypeScript Quality
- Interfaces for public APIs (props, return types)
- Types for internal structures
- No type assertions without validation (
askeyword) - Proper null/undefined handling with optional chaining
Component Patterns
// GOOD - Follows Ishkul patterns
interface ComponentProps {
title: string;
onPress: () => void;
variant?: 'primary' | 'secondary';
}
export const Component: React.FC<ComponentProps> = ({
title,
onPress,
variant = 'primary',
}) => {
const { colors } = useTheme(); // Theme hook
// ...
};
// BAD
export const Component = (props: any) => { // No type
const { colors } = useTheme();
if (loading) return null; // Hook after this could crash
const [state] = useState(); // BAD!
};
State Management (Zustand)
- Store actions properly typed
- Selectors for derived state
- No state mutations (use set())
- Clear separation of concerns
// GOOD - Follows lessonStore.ts pattern
interface LessonState {
currentLesson: Lesson | null;
lessonLoading: boolean;
error: string | null;
// Actions
fetchLesson: (courseId: string, lessonId: string) => Promise<Lesson | null>;
clearError: () => void;
}
export const useLessonStore = create<LessonState>((set, get) => ({
currentLesson: null,
lessonLoading: false,
error: null,
fetchLesson: async (courseId, lessonId) => {
set({ lessonLoading: true, error: null });
try {
const lesson = await lessonsApi.getLesson(courseId, lessonId);
set({ currentLesson: lesson, lessonLoading: false });
return lesson;
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
set({ error: message, lessonLoading: false });
return null;
}
},
}));
API Client Usage
- Use ApiClient from
services/api/client.ts - Proper error handling with ApiError
- No raw fetch() calls for authenticated endpoints
// GOOD
try {
const data = await apiClient.get<ResponseType>('/endpoint');
} catch (error) {
if (error instanceof ApiError) {
if (error.status === 401) { /* handle auth */ }
console.error(error.code, error.message);
}
}
// BAD
const response = await fetch('/endpoint'); // Missing auth, error handling
Backend (Go)
Critical Issues
- Input validation - Validate all request bodies
- Error codes - Use defined error codes (ErrCodeInvalidRequest, etc.)
- Context usage - Pass context through for cancellation
- No panics in handlers - Always return proper errors
Handler Patterns
// GOOD - Follows Ishkul handler pattern
func HandleResource(w http.ResponseWriter, r *http.Request) {
// Method check first
if !RequireMethod(w, r, http.MethodPost) {
return
}
// Parse request
var req RequestType
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
sendErrorResponse(w, http.StatusBadRequest, ErrCodeInvalidRequest, "Invalid request format")
return
}
// Validate
if req.Field == "" {
sendErrorResponse(w, http.StatusBadRequest, ErrCodeInvalidRequest, "Field is required")
return
}
// Get user from context (set by auth middleware)
userID := middleware.GetUserID(r.Context())
if userID == "" {
sendErrorResponse(w, http.StatusUnauthorized, ErrCodeUnauthorized, "User not authenticated")
return
}
// Business logic
result, err := processRequest(r.Context(), req)
if err != nil {
sendErrorResponse(w, http.StatusInternalServerError, ErrCodeInternalError, "Processing failed")
return
}
JSONSuccess(w, result)
}
// BAD
func HandleResource(w http.ResponseWriter, r *http.Request) {
var req RequestType
json.NewDecoder(r.Body).Decode(&req) // Error ignored!
result := process(req) // No validation, no error handling
json.NewEncoder(w).Encode(result) // No content-type
}
Error Response Pattern
// Use defined error codes
const (
ErrCodeInvalidRequest = "INVALID_REQUEST"
ErrCodeUnauthorized = "UNAUTHORIZED"
ErrCodeNotFound = "NOT_FOUND"
ErrCodeInternalError = "INTERNAL_ERROR"
)
// Send structured error
sendErrorResponse(w, http.StatusBadRequest, ErrCodeInvalidRequest, "Human-readable message")
Logging Pattern
// Use structured logging
appLogger.Info("action_completed",
slog.String("user_id", userID),
slog.String("resource_id", resourceID),
slog.Int("count", len(items)),
)
appLogger.Error("action_failed",
slog.String("error", err.Error()),
slog.String("user_id", userID),
)
Security Review
Frontend Security
- No secrets in code (use config files)
- Proper token storage (tokenStorage service)
- No sensitive data in logs
- Input sanitization for user-generated content
Backend Security
- All
/api/*routes use Auth middleware - Firebase Admin SDK for server-side auth
- No SQL injection (Firestore is NoSQL, but validate inputs)
- Rate limiting on auth endpoints
- CORS properly configured
Firebase Security Rules
- Users can only read/write own documents
- No wildcard write permissions
- Validation rules on document structure
Performance Review
Frontend Performance
- No N+1 patterns in data fetching
- Memoization where needed (useMemo, useCallback)
- Proper list virtualization for long lists
- Images use proper sizing
Backend Performance
- Firestore queries use proper indexes
- No unbounded queries (always limit)
- Batch operations for multiple writes
- Connection pooling for external services
Testing Requirements
Frontend Tests
- Test file exists for new screens/components
- Loading, error, success states tested
- State transition tests (critical for hooks safety)
- User interactions tested
Backend Tests
- Test file exists for new handlers
- Success and error cases covered
- Edge cases handled
Output Format
## Code Review Summary
**Files Reviewed**: 5
**Issues Found**: 3 Critical, 2 Medium, 5 Low
### Critical Issues
#### Issue #1: React Hooks Violation
- **File**: `src/screens/NewScreen.tsx:45`
- **Issue**: `useCallback` called after conditional return
- **Impact**: Will crash on state transitions
- **Fix**:
```typescript
// Move before conditional return
const handleSubmit = useCallback(() => {...}, [deps]);
if (loading) return <Spinner />;
Issue #2: Missing Input Validation
- File:
internal/handlers/users.go:67 - Issue: Request body parsed without validation
- Impact: Could crash or allow invalid data
- Fix:
if req.Email == "" { sendErrorResponse(w, http.StatusBadRequest, ErrCodeInvalidRequest, "Email required") return }
Medium Issues
...
Low Issues
...
Positive Notes
- Good separation of concerns in store
- Proper TypeScript types throughout
- Comprehensive error handling
## When to Use
- After implementing a new feature
- Before creating a PR
- During PR code review
- After major refactoring
Repository

mesbahtanvir
Author
mesbahtanvir/ishkul/.claude/skills/code-reviewer
1
Stars
0
Forks
Updated3d ago
Added1w ago