223 lines
8.0 KiB
Markdown
223 lines
8.0 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Development Commands
|
|
|
|
- **Development server**: `npm run dev` - Starts Next.js development server on http://localhost:3000
|
|
- **Build**: `npm run build` - Creates production build
|
|
- **Production server**: `npm run start` - Starts production server (requires build first)
|
|
- **Lint**: `npm run lint` - Runs Next.js ESLint checks
|
|
|
|
**Note**: No test framework is currently configured in this project.
|
|
|
|
## High-Level Architecture
|
|
|
|
This is a Next.js 15 application built with React 19 that creates an interactive map visualization with a custom WebGL timeline component.
|
|
|
|
### Core Architecture Components
|
|
|
|
**Map System**:
|
|
- Uses MapLibre GL JS for interactive mapping
|
|
- `app/map-context.tsx` provides global map state management via React Context
|
|
- `components/map-component.tsx` handles map rendering and initialization
|
|
- Default map center: Singapore (103.851959, 1.290270) at zoom level 11
|
|
- Custom map style from MapTiler API
|
|
|
|
**Timeline Visualization**:
|
|
- `app/timeline.tsx` is a complex WebGL-powered timeline component using custom shaders
|
|
- Uses vesica piscis (lens-shaped) geometry rendered via WebGL2
|
|
- Custom GLSL shaders in `app/glsl/timeline/` for vertex and fragment processing
|
|
- Supports interactive features: dragging, zooming, panning, custom time markers
|
|
- Dual-canvas architecture: WebGL canvas for vesica shapes, 2D canvas overlay for UI elements
|
|
|
|
**UI Framework**:
|
|
- Tailwind CSS with Radix UI components
|
|
- Theme system with dark/light mode support via `components/theme-provider.tsx`
|
|
- shadcn/ui component library in `components/ui/`
|
|
- Sidebar layout using `components/ui/sidebar.tsx`
|
|
|
|
**Admin System**:
|
|
- Comprehensive admin interface in `app/admin/` with dashboard, analytics, user management, and content editor
|
|
- Admin pages include dynamic configuration system and navigation components
|
|
- Uses both Apollo Client and GraphQL Request for data fetching
|
|
|
|
**Data Layer**:
|
|
- GraphQL API integration using Apollo Client and GraphQL Request
|
|
- Backend communication via `/api/bff` endpoint (configured in `lib/gr-client.ts`)
|
|
- Page-based content management with block-based architecture
|
|
- Authentication support with JWT tokens
|
|
|
|
### Key Technical Details
|
|
|
|
**WebGL Timeline**:
|
|
- Renders vesica piscis shapes as timeline markers
|
|
- Supports high-DPI displays with proper pixel ratio handling
|
|
- Interactive controls for zoom (mouse wheel), pan (drag), and custom time selection
|
|
- Real-time shader uniform updates for responsive interactions
|
|
|
|
**State Management**:
|
|
- Map state centralized in `MapProvider` context
|
|
- Timeline uses internal React state with refs for performance-critical interactions
|
|
- Custom hooks in `hooks/` for map location, zoom, timeline, and mobile detection
|
|
|
|
**Styling**:
|
|
- Tailwind CSS v4 with PostCSS
|
|
- Custom animations via `tw-animate-css`
|
|
- Component styling via `class-variance-authority` and `clsx`
|
|
|
|
**Build Configuration**:
|
|
- Next.js 15 with App Router
|
|
- Custom webpack config for GLSL file loading via `raw-loader` (see `next.config.ts`)
|
|
- TypeScript with strict mode enabled
|
|
- Absolute imports using `@/*` path mapping
|
|
|
|
**GraphQL Integration**:
|
|
- Uses both Apollo Client (`@apollo/client`) and GraphQL Request (`graphql-request`) for different use cases
|
|
- Page content fetching via `lib/fetchers.ts` with support for authentication
|
|
- Block-based content architecture supporting TextBlock, ChartBlock, SettingsBlock, and HeroBlock types
|
|
- Environment variables: `GRAPHQL_BACKEND_URL` and `NEXTAUTH_URL`
|
|
|
|
### File Structure Notes
|
|
|
|
- `app/` - Next.js App Router pages and components
|
|
- `app/admin/` - Complete admin interface with dashboard, analytics, users, and content editor
|
|
- `app/glsl/timeline/` - Custom GLSL shaders for WebGL timeline rendering
|
|
- `components/` - Reusable React components
|
|
- `components/ui/` - shadcn/ui component library
|
|
- `hooks/` - Custom React hooks for map, timeline, and mobile detection
|
|
- `lib/` - Utility functions including GraphQL clients and data fetchers
|
|
- `types/` - TypeScript type definitions
|
|
- `public/` - Static assets
|
|
|
|
The application combines modern web mapping with custom WebGL visualization to create an interactive timeline-driven map interface, complemented by a full-featured admin system for content management.
|
|
|
|
|
|
These examples should be used as guidance when configuring Sentry functionality within a project.
|
|
|
|
# Exception Catching
|
|
|
|
Use `Sentry.captureException(error)` to capture an exception and log the error in Sentry.
|
|
Use this in try catch blocks or areas where exceptions are expected
|
|
|
|
# Tracing Examples
|
|
|
|
Spans should be created for meaningful actions within an applications like button clicks, API calls, and function calls
|
|
Use the `Sentry.startSpan` function to create a span
|
|
Child spans can exist within a parent span
|
|
|
|
## Custom Span instrumentation in component actions
|
|
|
|
The `name` and `op` properties should be meaninful for the activities in the call.
|
|
Attach attributes based on relevant information and metrics from the request
|
|
|
|
```javascript
|
|
function TestComponent() {
|
|
const handleTestButtonClick = () => {
|
|
// Create a transaction/span to measure performance
|
|
Sentry.startSpan(
|
|
{
|
|
op: "ui.click",
|
|
name: "Test Button Click",
|
|
},
|
|
(span) => {
|
|
const value = "some config";
|
|
const metric = "some metric";
|
|
|
|
// Metrics can be added to the span
|
|
span.setAttribute("config", value);
|
|
span.setAttribute("metric", metric);
|
|
|
|
doSomething();
|
|
},
|
|
);
|
|
};
|
|
|
|
return (
|
|
<button type="button" onClick={handleTestButtonClick}>
|
|
Test Sentry
|
|
</button>
|
|
);
|
|
}
|
|
```
|
|
|
|
## Custom span instrumentation in API calls
|
|
|
|
The `name` and `op` properties should be meaninful for the activities in the call.
|
|
Attach attributes based on relevant information and metrics from the request
|
|
|
|
```javascript
|
|
async function fetchUserData(userId) {
|
|
return Sentry.startSpan(
|
|
{
|
|
op: "http.client",
|
|
name: `GET /api/users/${userId}`,
|
|
},
|
|
async () => {
|
|
const response = await fetch(`/api/users/${userId}`);
|
|
const data = await response.json();
|
|
return data;
|
|
},
|
|
);
|
|
}
|
|
```
|
|
|
|
# Logs
|
|
|
|
Where logs are used, ensure Sentry is imported using `import * as Sentry from "@sentry/nextjs"`
|
|
Enable logging in Sentry using `Sentry.init({ _experiments: { enableLogs: true } })`
|
|
Reference the logger using `const { logger } = Sentry`
|
|
Sentry offers a consoleLoggingIntegration that can be used to log specific console error types automatically without instrumenting the individual logger calls
|
|
|
|
## Configuration
|
|
|
|
In NextJS the client side Sentry initialization is in `instrumentation-client.ts`, the server initialization is in `sentry.edge.config.ts` and the edge initialization is in `sentry.server.config.ts`
|
|
Initialization does not need to be repeated in other files, it only needs to happen the files mentioned above. You should use `import * as Sentry from "@sentry/nextjs"` to reference Sentry functionality
|
|
|
|
### Baseline
|
|
|
|
```javascript
|
|
import * as Sentry from "@sentry/nextjs";
|
|
|
|
Sentry.init({
|
|
dsn: "https://109bcfcc2d1cdd643e0af61409016900@o4505647824109568.ingest.us.sentry.io/4509868655181824",
|
|
|
|
_experiments: {
|
|
enableLogs: true,
|
|
},
|
|
});
|
|
```
|
|
|
|
### Logger Integration
|
|
|
|
```javascript
|
|
Sentry.init({
|
|
dsn: "https://109bcfcc2d1cdd643e0af61409016900@o4505647824109568.ingest.us.sentry.io/4509868655181824",
|
|
integrations: [
|
|
// send console.log, console.warn, and console.error calls as logs to Sentry
|
|
Sentry.consoleLoggingIntegration({ levels: ["log", "warn", "error"] }),
|
|
],
|
|
});
|
|
```
|
|
|
|
## Logger Examples
|
|
|
|
`logger.fmt` is a template literal function that should be used to bring variables into the structured logs.
|
|
|
|
```javascript
|
|
logger.trace("Starting database connection", { database: "users" });
|
|
logger.debug(logger.fmt`Cache miss for user: ${userId}`);
|
|
logger.info("Updated profile", { profileId: 345 });
|
|
logger.warn("Rate limit reached for endpoint", {
|
|
endpoint: "/api/results/",
|
|
isEnterprise: false,
|
|
});
|
|
logger.error("Failed to process payment", {
|
|
orderId: "order_123",
|
|
amount: 99.99,
|
|
});
|
|
logger.fatal("Database connection pool exhausted", {
|
|
database: "users",
|
|
activeConnections: 100,
|
|
});
|
|
``` |