Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
7c5d8f7
Sidebar improvement (#227)
sumansaurabh May 31, 2025
058c8fc
fix: upgrade mixpanel-browser from 2.55.1 to 2.64.0 (#226)
sumansaurabh May 31, 2025
cd41037
fix(ConnectMoreVendors): uncomment Popover component and adjust termi…
sumansaurabh Jun 1, 2025
c4f176c
feat(ReadmeAnalysis): add LLMReadmeAnalysisResponse type and update R…
sumansaurabh Jun 4, 2025
b3358a3
feat(ReadmeAnalysisModal): refactor modal layout and enhance styling …
sumansaurabh Jun 4, 2025
90c54b8
feat(ReadmeAnalysisModal): update LLMReadmeAnalysisResponse structure…
sumansaurabh Jun 4, 2025
a250216
fix(ReadmeAnalysisModal): adjust padding and positioning for improved…
sumansaurabh Jun 4, 2025
2acda68
feat(RepoMetricsCards): update outdated documentation calculation to …
sumansaurabh Jun 24, 2025
5f3ebc3
refactor(JobsPage): comment out unused translation import and function
sumansaurabh Jun 27, 2025
be39f88
feat(PaymentPricing): implement plan selection logic and enhance card…
sumansaurabh Jun 28, 2025
61b5604
refactor(RepoNav): uncomment navigation items for improved readabilit…
sumansaurabh Jun 28, 2025
b3a75f1
feat(CLAUDE): add comprehensive documentation for development setup a…
sumansaurabh Dec 13, 2025
e4943eb
feat: implement decodeGitOrgName utility and update components to use…
sumansaurabh Dec 13, 2025
c487fa9
refactor(ListAllRepos): remove unused imports and form state for clea…
sumansaurabh Dec 14, 2025
f6aa330
refactor: clean up unused props and improve documentation analysis logic
sumansaurabh Dec 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
294 changes: 294 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Development Commands

### Setup
```bash
yarn # Install dependencies (requires Node.js >=20.x)
```

### Development
```bash
yarn start # Start dev server on localhost:3000
yarn build # Production build to ./build directory
yarn lint # Run ESLint
yarn lint:styles # Run stylelint on styled-components
```

### Notes
- This project uses **Yarn 4.5.1** as the package manager
- Development server runs on port 3000 (configured in vite.config.ts)
- Build output is in `./build` directory (not `dist`)
- No test suite is currently configured

## High-Level Architecture

### Tech Stack
- **React 18** with TypeScript (strict mode)
- **Vite** for build tooling
- **Redux Toolkit** for state management
- **React Router v6** for routing
- **Ant Design v5** + styled-components for UI
- **Axios** for HTTP with interceptors

### Application Purpose
Penify (Snorkell) Dashboard is a SaaS platform for automated code documentation generation and analysis. It integrates with multiple Git platforms (GitHub, GitLab, Bitbucket, Azure DevOps) to provide:
- Function-level documentation coverage analysis
- AI-powered documentation generation
- Code quality metrics (complexity, maintainability)
- README quality analysis
- Security vulnerability scanning

### Core Architectural Patterns

#### 1. Multi-Vendor Git Platform Integration
The app is vendor-agnostic and supports 4 Git platforms through a unified abstraction:

```typescript
// Routes follow pattern: /repositories/{vendor}/{orgName}/{repoName}
// vendor = GITHUB | GITLAB | BITBUCKET | AZURE
```

**Integration mechanisms**:
- **GitHub**: OAuth flow via redirect to GitHub Apps
- **GitLab/Bitbucket/Azure**: Custom Server-Sent Events (SSE) installation flow with real-time progress streaming

Key files:
- `src/api/git.api.ts` - Git repository operations (vendor-agnostic)
- `src/api/azure.api.ts` - Azure-specific PAT authentication
- `src/utils/EventSourceWithAuth.ts` - Custom SSE client with Bearer token support

#### 2. Long-Running Operations (LRO) Pattern
Documentation generation is asynchronous and may take minutes. The app uses a job-based system:

```typescript
// Workflow:
// 1. POST /v1/git/job/{genType}/start → returns lroJobId
// 2. Poll GET /v1/git/lro/jobs/{jobId} → check LroJobState
// 3. Stream progress via GET /v1/git/lro/jobs/{jobId}/logs (SSE)
// 4. On COMPLETE → fetch generated results
```

States: `START | VALIDATING | QUEUED | RUNNING | COMPLETE | FAILED | CANCELLED | TIMEOUT`

Key files:
- `src/api/lro.api.ts` - Job status polling
- `src/api/docgen.api.ts` - Documentation generation triggers
- `src/components/dashboard/DashboardTerminal/` - Real-time progress UI

#### 3. Layered Architecture
The codebase follows strict separation of concerns:

```
┌─────────────────────────────────────┐
│ Components & Pages (UI Layer) │
│ - React components │
│ - styled-components │
│ - Ant Design integration │
└─────────────┬───────────────────────┘
┌─────────────────────────────────────┐
│ Redux Store (State Layer) │
│ - userSlice, authSlice, themeSlice │
│ - Async thunks for API calls │
│ - localStorage persistence │
└─────────────┬───────────────────────┘
┌─────────────────────────────────────┐
│ API Layer (Data Layer) │
│ - src/api/*.api.ts files │
│ - All HTTP communication │
│ - Request/response transformation │
└─────────────────────────────────────┘
```

**Critical rule**: Components NEVER import API modules directly. All data fetching flows through Redux thunks or React hooks that encapsulate API calls.

#### 4. Authentication & Request Flow

```typescript
// All HTTP requests flow through src/api/http.api.ts
const httpApi = axios.create({ baseURL: VITE_BASE_URL })

// Request interceptor: Adds Authorization header from localStorage
httpApi.interceptors.request.use(config => {
const token = readToken()
if (token) config.headers.Authorization = `Bearer ${token}`
return config
})

// Response interceptor: Handles 511 (auth required) → auto-logout
httpApi.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 511) {
// Logout user, clear token, redirect to /
}
throw error
}
)
```

Token persistence: `src/services/localStorage.service.ts` handles sync between Redux and localStorage.

#### 5. Multi-Language Documentation Support
The platform supports language-specific documentation styles:

```typescript
// Python: GOOGLE | EPYDOC | NUMPYDOC | REST
// JavaScript/TypeScript: JSDoc
// Java: JavaDoc
// C#: XML
// Kotlin: KDoc
// C/C++: Doxygen | JavaDoc-Style
```

Fetched via `getLanguage(orgName, repoName, vendor)` in `src/api/docgen.api.ts`, then passed to generation API.

#### 6. Routing & Code Splitting
Routes defined in `src/components/router/AppRouter.tsx`:

**Protected routes** (requires auth token):
- `/repositories` - Repository list dashboard
- `/repositories/{vendor}/{orgName}/{repoName}` - Repository detail
- `/repositories/{vendor}/{orgName}/{repoName}/analyze` - Analysis view
- `/repositories/{vendor}/{orgName}/{repoName}/docufy` - Documentation generation
- `/repositories/{vendor}/{orgName}/{repoName}/security` - Security scan
- `/jobs` - Job history
- `/penify-api-keys` - API key management
- `/profile/*` - User settings

**Public routes**:
- `/auth/login`, `/auth/sign-up` - Authentication
- `/oauth/github`, `/oauth/google` - OAuth callbacks

**Code splitting**: Most pages are lazy-loaded via `React.lazy()` + `withLoading()` HOC (except auth pages to prevent flickering).

#### 7. Analytics Integration
Dual tracking system:

```typescript
// Mixpanel: Custom event tracking with user context
trackEvent(eventName, properties)
trackPageView(pathname, user)
trackClicks() // Global click listener

// Google Analytics 4: Basic page view tracking
trackGAPageView(pathname)
```

Initialized in `src/App.tsx`, configured in `src/config/mixpanel.ts` and `src/config/ga.ts`.

All events include user metadata: `distinct_id`, `user_email`, `github_id`, `google_id`, etc.

#### 8. Theme System
Dual theme support (light/dark) with system preference detection:

```typescript
// src/styles/themes/themeVariables.ts defines color palettes
// useThemeWatcher() hook detects OS dark mode preference
// themeSlice stores user's explicit theme choice
// styled-components ThemeProvider propagates theme to all components
```

Theme toggle available in user profile settings.

### Key Directory Purposes

**`src/api/`** - All backend HTTP communication
Each file maps to a backend service domain (auth, git, docgen, payment, etc.). All functions return typed Promises.

**`src/store/`** - Redux Toolkit configuration
- `store.ts` - Store setup with error logging middleware
- `slices/` - Feature-based reducers with async thunks

**`src/components/`** - Feature-based React components
Organized by domain (dashboard, auth, profile, common). Each complex component has its own directory with `.styles.ts` file.

**`src/pages/`** - Route-level page components
Top-level components that map to router paths. These orchestrate smaller components.

**`src/domain/`** - Data models
TypeScript interfaces representing backend entities (UserModel, etc.).

**`src/hooks/`** - Custom React hooks
`reduxHooks.ts` provides typed `useAppSelector`/`useAppDispatch`. Other hooks encapsulate common logic (language switching, responsive breakpoints).

**`src/utils/`** - Utility functions
`EventSourceWithAuth.ts` is critical - custom EventSource class that supports Authorization headers for SSE streaming.

**`src/constants/`** - Enums and static config
Plan types, Git vendors, language codes, etc.

**`src/styles/`** - Global styles and theme definitions
`GlobalStyle.tsx` applies CSS reset + base styles. `themeVariables.ts` defines color system.

**`src/locales/`** - i18n translation files
Currently supports English (en) and German (de).

### Important Implementation Notes

1. **Backend uses snake_case, frontend uses camelCase**
API transformation happens in Redux thunks or API layer. Example in `src/api/auth.api.ts`.

2. **Environment variables required**:
```bash
VITE_BASE_URL=<backend-api-url>
VITE_ASSETS_BUCKET=<s3-bucket-for-assets>
```

3. **Path alias**: `@app/*` resolves to `src/*` (configured in tsconfig + vite)

4. **SVG imports**: SVGs can be imported as React components via vite-plugin-svgr

5. **Vendor colors**: Each Git platform has a brand color (GitHub: purple, GitLab: orange, etc.) defined in theme variables

6. **Modal/Notification controllers**: Centralized UI feedback in `src/controllers/`
```typescript
import { notificationController } from '@app/controllers/notificationController'
notificationController.success({ message: 'Success!' })
```

7. **Subscription tiers**: FREE, PREMIUM, PRO (impacts feature availability)
User plan stored in `user.subscription_info.planType`

8. **Security**: Never commit `.env` files. API keys/tokens only in environment variables.

### Common Workflows

**Adding a new API endpoint**:
1. Define TypeScript interface for request/response in `src/@types/` or inline
2. Add function to appropriate `src/api/*.api.ts` file
3. Create async thunk in Redux slice if state management needed
4. Use in component via `useAppDispatch()`

**Adding a new protected route**:
1. Create page component in `src/pages/DashboardPages/`
2. Lazy load with `withLoading()` HOC
3. Add route in `src/components/router/AppRouter.tsx` inside `<RequireAuth>`
4. Add navigation link in `src/components/layouts/main/MainSider/`

**Adding analytics tracking**:
```typescript
import { trackEvent } from '@app/config/mixpanel'

// In component:
trackEvent('Button Clicked', { buttonName: 'Generate Docs', repoName })
```

**Styling new components**:
```typescript
// ComponentName.tsx
import * as S from './ComponentName.styles'

export const ComponentName = () => <S.Container>...</S.Container>

// ComponentName.styles.ts
import styled from 'styled-components'

export const Container = styled.div`
color: ${props => props.theme.colors.main.primary};
`
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"framer-motion": "^12.5.0",
"html-react-parser": "^5.2.3",
"i18next": "^23.15.1",
"mixpanel-browser": "^2.55.1",
"mixpanel-browser": "^2.64.0",
"prismjs": "^1.29.0",
"qs": "^6.13.0",
"react": "^18.3.1",
Expand Down
11 changes: 5 additions & 6 deletions src/api/docgen.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const triggerDocGen = (
archDocConfig?: ArchDocConfig,
): Promise<DocGenInitialResponse> => {
const data = buildDocGenData(orgName, repoName, vendor);
const url = `/v1/git/generate/${genType}/doc`;
const url = `/v1/git/job/${genType}/start`;
return httpApi.post<DocGenInitialResponse>(url, { ...data, style_guide: styleGuide, arch_doc_config: archDocConfig }).then(({ data }) => data);
};

Expand All @@ -119,15 +119,14 @@ export const getDocGenStatus = (
genType: string,
lroJobId: string,
): Promise<DocGenStatusReponse> => {
const data = buildDocGenData(orgName, repoName, vendor);
const url = `/v1/git/generate/${genType}/doc/status?jobId=${lroJobId}`;
return httpApi.post<DocGenStatusReponse>(url, { ...data }).then(({ data }) => data);
const url = `/v1/git/job/${lroJobId}/status`;
return httpApi.get<DocGenStatusReponse>(url).then(({ data }) => data);
};

export const terminateJob = (
lroJobId: string,
): Promise<Record<string, string>> => {
const url = `/v1/git/lro/${lroJobId}/terminate`;
const url = `/v1/git/job/${lroJobId}/terminate`;
return httpApi.post<Record<string, string>>(url).then(({ data }) => data);
};

Expand Down Expand Up @@ -165,7 +164,7 @@ export const getAdvancedRepoAnalysisDetails = (
analysisType: string,
): Promise<FunctionDetail[] | Record<string, string>> => {
const data = buildDocGenData(orgName, repoName, vendor);
const url = `/v1/git/analyze/repo/${analysisType}/details`;
const url = `/v1/git/job/${analysisType}/details`;

return httpApi.post<FunctionDetail[] | Record<string, string>>(url, { ...data }).then(({ data }) => data); // Extract the message
};
Expand Down
Loading