Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ba3b42e
Claude context
kyle-ssg Oct 14, 2025
9746d13
Claude context
kyle-ssg Oct 14, 2025
5955f25
Claude context
kyle-ssg Oct 14, 2025
efedbdc
Add api-sync / optmimise contexts
kyle-ssg Oct 21, 2025
cae73d7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 21, 2025
23a6495
Add api-sync / optimise contexts
kyle-ssg Oct 21, 2025
af5bfda
Merge remote-tracking branch 'origin/chore/claude-context' into chore…
kyle-ssg Oct 21, 2025
ac641db
Update contexts
kyle-ssg Nov 4, 2025
0c03b8f
Update contexts
kyle-ssg Nov 4, 2025
fb2df65
Update contexts
kyle-ssg Nov 4, 2025
b064e81
Update contexts
kyle-ssg Nov 4, 2025
27019de
Update contexts
kyle-ssg Nov 4, 2025
96c81d6
Update contexts
kyle-ssg Nov 4, 2025
4a3bafa
Update contexts
kyle-ssg Nov 4, 2025
4b846d9
Update contexts
kyle-ssg Nov 4, 2025
6cbde85
Merge branch 'main' into chore/claude-context
kyle-ssg Nov 4, 2025
dd7b743
Update contexts
kyle-ssg Nov 10, 2025
df85873
Update claude contexts
kyle-ssg Nov 11, 2025
d4809c4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 11, 2025
885cfe0
Simplify contexts
kyle-ssg Nov 11, 2025
91b542e
Merge remote-tracking branch 'origin/chore/claude-context' into chore…
kyle-ssg Nov 11, 2025
7edc926
Merge branch 'main' into chore/claude-context
kyle-ssg Nov 11, 2025
5b64f88
Revert makefile changes
kyle-ssg Nov 11, 2025
d9132b3
- Add AGENTS.md
khvn26 Dec 31, 2025
3d7a4aa
rename api/README.md
khvn26 Dec 31, 2025
6df6fc0
fix typo
khvn26 Dec 31, 2025
31e3c5e
fix path separators
khvn26 Dec 31, 2025
fb75a62
fix typo
khvn26 Dec 31, 2025
30a7158
clarify migrations squashing recommendation
khvn26 Dec 31, 2025
5feac3c
fix grammar
khvn26 Dec 31, 2025
453b867
update pull request template to include additional checklist items
khvn26 Jan 2, 2026
1fcdb88
Merge branch 'chore/claude-context' of github.com:Flagsmith/flagsmith…
Zaimwa9 Jan 7, 2026
9c4a74b
docs: split-heavy-context-and-created-agents
Zaimwa9 Jan 7, 2026
6c2fcaf
docs: basic-readme-for-frontend
Zaimwa9 Jan 7, 2026
ce3e9d4
docs: fixed-broken-link
Zaimwa9 Jan 7, 2026
845ad75
Remove mobile draft
kyle-ssg Jan 20, 2026
750a2ad
feat: rebased
Zaimwa9 Jan 20, 2026
4213b50
Merge branch 'main' of github.com:Flagsmith/flagsmith into docs/backe…
Zaimwa9 Jan 21, 2026
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
12 changes: 12 additions & 0 deletions frontend/.claude/commands/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
description: Generate a new RTK Query API service
---

<!-- TODO: Update /api-types-sync once OpenAPI schema is ready -->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worth waiting and having it complete


Generate a new API service. Follow these steps:

1. Go through the process mentioned in `.claude/context/api-integration.md`
2. If I haven't specified, attempt to find where I'd want to create this component in the frontend

Context file: `.claude/context/api-integration.md`
14 changes: 14 additions & 0 deletions frontend/.claude/commands/backend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
description: Search the backend codebase for endpoint details
---

Search the `../api` codebase for the requested endpoint.

Look for:
1. Route definitions (URL path)
2. HTTP method (GET, POST, PUT, DELETE)
3. Request validation schema (request body/params types)
4. Response structure (what data is returned)
5. Authentication/authorization requirements

If the endpoint isn't found, check swagger docs: https://staging.flagsmith.com/api/v1/docs/
8 changes: 8 additions & 0 deletions frontend/.claude/commands/check-staged.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
description: Run type checking and linting on staged files
---

Run TypeScript checking and linting on all currently staged files, similar to pre-commit hooks. Steps:
1. Run `npm run check:staged` to typecheck and lint only staged files
2. Report any type errors or linting issues found
3. If errors exist, offer to fix them
9 changes: 9 additions & 0 deletions frontend/.claude/commands/check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
description: Run type checking and linting
---

Run the following checks on the codebase:

1. `npx lint-staged --allow-empty` - Fix linting issues on staged files only (same as git hook)

Report any errors found and offer to fix them.
12 changes: 12 additions & 0 deletions frontend/.claude/commands/context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
description: Load detailed context files for specific topics
---

Available context files in `.claude/context/`:

1. **api-integration.md** - API integration workflow, Redux setup, cross-platform patterns
2. **architecture.md** - Environment config, tech stack, additional rules
3. **feature-flags/** - Flagsmith feature flags (usage + MCP workflows)
4. **patterns/** - Code patterns (API, mobile)

Which context would you like to explore?
5 changes: 5 additions & 0 deletions frontend/.claude/commands/feature-flag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Create a feature flag
---

1. Create a feature flag using the context defined in `.claude/context/feature-flags/`
15 changes: 15 additions & 0 deletions frontend/.claude/commands/form.md.draft
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
description: Create a new form using Yup + Formik pattern
---

Create a form following the standard pattern:

1. Use `useFormik` hook with `validationSchema` from Yup
2. Always include `validateOnMount: true`
3. Use `validateForm` utility from `project/utils/forms/validateForm` in submit handler
4. Use `InputGroup` component with `touched` and `error` props
5. For special inputs (date, phone, select), use `component` prop on InputGroup

Reference: `/examples/forms/ComprehensiveFormExample.tsx`

Context file: `.claude/context/forms.md`
47 changes: 47 additions & 0 deletions frontend/.claude/commands/ui-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# UI Patterns & Best Practices

## Confirmation Dialogs

**NEVER use `window.confirm`** - Always use the `openConfirm` function from `components/base/Modal`.

### Correct Usage

```typescript
import { openConfirm } from 'components/base/Modal'

// Signature: openConfirm(title, body, onYes, onNo?, challenge?)
openConfirm(
'Delete Partner',
'Are you sure you want to delete this partner?',
async (closeModal) => {
const res = await deleteAction()
if (!res.error) {
toast(null, 'Partner deleted successfully')
closeModal() // Always call closeModal to dismiss the dialog
}
},
)
```

### Parameters
- `title: string` - Dialog title
- `body: ReactNode` - Dialog content (can be JSX)
- `onYes: (closeModal: () => void) => void` - Callback when user confirms
- `onNo?: () => void` - Optional callback when user cancels
- `challenge?: string` - Optional challenge text user must type to confirm

### Key Points
- The `onYes` callback receives a `closeModal` function
- Always call `closeModal()` when the action completes successfully
- Can be async - use `async (closeModal) => { ... }`

## Backend Integration

### Always Run API Types Sync Before API Work

When using `/api` to generate new API services, the command automatically runs `/api-types-sync` first to:
1. Pull latest backend changes (`git pull` in `../api`)
2. Sync frontend types with backend serializers
3. Ensure types are up-to-date before generating new services

This prevents type mismatches and ensures consistency.
220 changes: 220 additions & 0 deletions frontend/.claude/context/api-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
# API Integration Guide

## Overview

This project uses **RTK Query** (Redux Toolkit Query) for all API calls. The workflow is optimized for type safety and automatic sync with backend Django serializers.

**Finding Backend Endpoints**: See `.claude/context/backend-integration.md` for strategies to locate and understand backend API endpoints.

## Quick Start: Adding a New Endpoint (Complete Example)

This example shows how to add a new endpoint for fetching company invoices (a real implementation from the codebase).

### Step 1: Find Backend Endpoint

Use strategies from `backend-integration.md` to locate the endpoint.

**Backend endpoint found:** `GET /organisations/{organisation_id}/invoices`

### Step 2: Add Request Type

**File:** `common/types/requests.ts`

```typescript
export type Req = {
// ... existing types
getCompanyInvoices: {
organisation_id: string
}
}
```

### Step 3: Add RTK Query Endpoint

**File:** `common/services/useInvoice.ts`

```typescript
export const invoiceService = service
.enhanceEndpoints({ addTagTypes: ['Invoice'] })
.injectEndpoints({
endpoints: (builder) => ({
// Add new endpoint
getCompanyInvoices: builder.query<
Res['invoices'],
Req['getCompanyInvoices']
>({
providesTags: [{ id: 'LIST', type: 'Invoice' }],
query: (req) => ({
url: `organisations/${organisation_id}/invoices`,
}),
transformResponse(res: InvoiceSummary[]) {
return res?.map((v) => ({ ...v, date: v.date * 1000 }))
},
}),
}),
})

export const {
useGetCompanyInvoicesQuery, // Export new hook
// END OF EXPORTS
} = invoiceService
```

### Step 4: Use in Component

```typescript
import { useGetCompanyInvoicesQuery } from 'common/services/useInvoice'

const MyComponent = () => {
const { subscriptionDetail } = useDefaultSubscription()
const companyId = subscriptionDetail?.company_id

const { data: invoices, error, isLoading } = useGetCompanyInvoicesQuery(
{ organisation_id: `${companyId}` },
{ skip: !organisation_id } // Skip if no company ID
)

if (isLoading) return <Loader />
if (error) return <ErrorMessage>{error}</ErrorMessage>

return (
<div>
{invoices?.map(inv => <div key={inv.id}>{inv.id}</div>)}
</div>
)
}
```

### Step 5: Run Linter

```bash
npx eslint --fix common/types/requests.ts common/services/useInvoice.ts
```

**Done!** The endpoint is now integrated and ready to use.

## Manual Service Creation (Rare Cases)

If you need to manually create a service (follow template in `.claude/commands/api.md`):

1. **Identify backend endpoint**
- Use `/backend <search-term>` to search backend codebase
- Check `../api/apps/*/serializers.py`, `../api/apps/*/views.py`, `apps/*/urls.py`
- Or swagger docs: https://api.flagsmith.com/api/v1/docs/

2. **Define types** in `common/types/`
- Response: `export type EntityName = { field: type }` in `responses.ts`
- Add to `Res` type: `entityName: EntityName`
- Request: `getEntityName: { param: type }` in `requests.ts`

3. **Create service** `common/services/use{Entity}.ts`
- Use `builder.query` for GET, `builder.mutation` for POST/PUT/DELETE
- Configure cache tags: `providesTags`, `invalidatesTags`
- Export hooks: `useGetEntityQuery`, `useCreateEntityMutation`

4. **Register in type map** `.claude/api-type-map.json`
- Add to `response_types` or `request_types` with full metadata
- Increment `_metadata.totalTypes`

5. **Run linter**
```bash
npx eslint --fix common/services/use*.ts common/types/*.ts
```

### Backend → Frontend Type Mapping

| Django Type | TypeScript |
|------------|------------|
| `CharField` | `string` |
| `IntegerField` | `number` |
| `BooleanField` | `boolean` |
| `DateTimeField` | `string` (ISO) |
| `required=False` | `field?: type` |
| `many=True` | `Type[]` |
| Enum/Choices | `'A' \| 'B'` |

### Example Service Structure

```typescript
import { service } from 'common/service'
import { Req } from 'common/types/requests'
import { Res } from 'common/types/responses'

export const entityService = service
.enhanceEndpoints({ addTagTypes: ['Entity'] })
.injectEndpoints({
endpoints: (builder) => ({
getEntity: builder.query<Res['entity'], Req['getEntity']>({
providesTags: (res) => [{ id: res?.id, type: 'Entity' }],
query: (query) => ({
url: `entities/${query.id}`,
}),
}),
updateEntity: builder.mutation<Res['entity'], Req['updateEntity']>({
invalidatesTags: (res) => [
{ id: 'LIST', type: 'Entity' },
{ id: res?.id, type: 'Entity' },
],
query: (query) => ({
body: query,
method: 'PUT',
url: `entities/${query.id}`,
}),
}),
// END OF ENDPOINTS
}),
})

export const {
useGetEntityQuery,
useUpdateEntityMutation,
// END OF EXPORTS
} = entityService
```

See `common/services/useAuditLog.ts` for a complete example.

## State Management

- **Redux Toolkit + RTK Query** for all API calls
- Store: `common/store.ts` with redux-persist
- Base service: `common/service.ts`
The `npx ssg` CLI requires interactive input that cannot be automated. Instead, **manually create RTK Query services** following the patterns in existing service files.
- **IMPORTANT**: When implementing API logic, prefer implementing it in the RTK Query service layer (using `transformResponse`, `transformErrorResponse`, etc.) rather than in components. This makes the logic reusable across the application.

## Error Handling Patterns

### RTK Query Mutations

```typescript
const [createMail, { isLoading, error }] = useCreateMailMutation()

const handleSubmit = async () => {
try {
const result = await createThing(data).unwrap()
toast('Success!')
} catch (err) {
if ('status' in err) {
// FetchBaseQueryError - has status, data, error
const errMsg = 'error' in err ? err.error : JSON.stringify(err.data)
toast.error(errMsg)
} else {
// SerializedError - has message, code, name
toast(err.message || 'An error occurred', 'danger')
toast(err.message || 'An error occurred')
}
}
}
```

### RTK Query Queries

```typescript
const { data, error, isLoading, refetch } = useThing({ id: '123' })

// Display error in UI, it won't render if error is undefined
return <ErrorMessage>{error}</ErrorMessage>

// Retry on error
const handleRetry = () => refetch()
```
28 changes: 28 additions & 0 deletions frontend/.claude/context/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Architecture & Configuration

## Environment Configuration

- Config files: `env/project_<ENV>.js`
- Available environments: `dev`, `prod`, `staging`, `local`, `selfhosted`, `e2e`
- Project config: `common/project.js` (imports from env files)
- Override: `ENV=local npm run dev` or `ENV=staging npm run dev`

## Key Technologies

- React 16.14 + TypeScript + Bootstrap 5.2.2
- Redux Toolkit + RTK Query (API state management)
- Flux stores (legacy state management)
- Webpack 5 + Express dev server
- Sentry (error tracking)
- Flagsmith (feature flags - this project IS Flagsmith, dogfooding its own platform)

## Additional Rules

- **TypeScript/ESLint**: Build may ignore some errors, but always run linting on modified files
- **Web-specific code**: Goes in `/web/` directory (not `/common`)
- **Redux Persist**: Whitelist in `common/store.ts`
- **Imports**: Always use path aliases (`common/*`, `components/*`, `project/*`) - NO relative imports

## Documentation

Check the main repository README and docs for additional information
Loading
Loading