Awesome Cursor Rules Collection

Showing 865-876 of 1033 matches

JavaScript
# Workspace AI Rules for Hebert Thomas Law Project

## Whats been done:

- Added in the User Management and Role Management
- Added in the Permission Management
- Added in the Blog Management

## Project Structure
1. All React components must be `.jsx` files (not `.tsx`)
2. Components should be organized in subdirectories based on pages they belong to
3. Directory structure for components:
   ```
   resources/js/
   ├── Components/
   │   ├── Common/           # Shared components
   │   ├── Home/            # Home page components
   │   ├── About/           # About page components
   │   └── [PageName]/      # Other page-specific components
   ├── images/              # All images must be stored locally
   └── Layouts/             # Layout components
   ```

## Styling and Design
1. Colors:
   - Primary Dark: `cod-gray` (#141414)
   - Primary Light: `gallery` (#F0F0F0)
   - Accent: `pippin` (#FFE8E5)
   - Use color variants defined in tailwind.config.js

2. Typography:
   - Headings: Heebo font (`font-heading`)
     - Weights: 400, 500, 600, 700
   - Body: Poppins font (`font-sans`)
     - Weights: 300, 400, 500, 600, 700

3. Components:
   - Use @relume_io/relume-ui components
   - Convert all Relume components to .jsx format
   - Follow Delto.com design patterns for layout and spacing

## UI/UX Guidelines
1. Icons:
   - Use Lucide icons exclusively (https://lucide.dev/)
   - Import icons individually to minimize bundle size
   ```jsx
   import { IconName } from 'lucide-react'
   ```

2. Animations:
   - Use Motion.dev for all animations
   - Keep animations subtle and professional
   - Ensure animations enhance UX without being distracting

3. Component Library:
   - Primary: @relume_io/relume-ui
   - Styling: @relume_io/relume-tailwind
   - Convert all template code to JSX format


## Filament
- Installed Filament
- Remember to not change the styles of the filament components unless I ask that includes sidebar, navbar, etc.
- Please use Filament built in feature before trying anything else.
- Please use use JSONB instead of JSON for PostgreSQL compatibility

## Best Practices
1. Image Handling:
   - All images must be stored in resources/js/images/
   - Use appropriate image formats (WebP preferred)
   - Implement lazy loading for images
   - Optimize images for web use

2. Component Structure:
   ```jsx
   import React from 'react'
   import { IconName } from 'lucide-react'
   import { motion } from 'framer-motion'
   
   export default function ComponentName({ props }) {
     return (
       <motion.div
         initial={{ opacity: 0 }}
         animate={{ opacity: 1 }}
         className="font-sans"
       >
         {/* Component content */}
       </motion.div>
     )
   }
   ```

3. Responsive Design:
   - Mobile-first approach
   - Use Tailwind breakpoints consistently
   - Test on multiple device sizes

## Development Rules
1. File Naming:
   - Use PascalCase for component files
   - Use kebab-case for image files
   - Use camelCase for utility files

2. Code Organization:
   - Group related components in page-specific folders
   - Keep components small and focused
   - Extract reusable logic into custom hooks

3. Performance:
   - Implement code splitting where appropriate
   - Optimize bundle size
   - Use React.lazy() for route-based code splitting

## Brand Guidelines
1. Visual Style:
   - Clean, modern, and professional
   - Consistent with Delto.com aesthetic
   - Emphasis on whitespace and typography
   - Subtle animations for interactions

2. Content:
   - Professional legal tone
   - Clear hierarchy of information
   - Accessible language
   - Strong calls-to-action

## Fixing Errors
- If you see an error, please fix it.
- If you see a warning, please fix it.
- If you see a suggestion, please fix it.
- If you see a suggestion, please fix it.
- Please do not cghange something that is already working when I ask you to fix it.
blade
bun
css
javascript
less
php
postgresql
react
+1 more

First seen in:

rthomas98/htl-marcom

Used in 1 repository

TypeScript
You are an expert in TypeScript, Node.js, Next.js App Router, React, Shadcn UI, Radix UI and Tailwind.

Code Style and Structure

- Write concise, technical TypeScript code with accurate examples.
- Use functional and declarative programming patterns; avoid classes.
- Prefer iteration and modularization over code duplication.
- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
- Structure files: exported component, subcomponents, helpers, static content, types.
- Use the ./src directory for all source code.

Naming Conventions

- Use lowercase with dashes for directories (e.g., components/auth-wizard).
- Favor named exports for components.

TypeScript Usage

- Use TypeScript for all code; prefer interfaces over types.
- Avoid enums; use maps instead.
- Use functional components with TypeScript interfaces.

Syntax and Formatting

- Use the "function" keyword for pure functions.
- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.
- Use declarative JSX.

UI and Styling

- Use Shadcn UI, Radix, and Tailwind for components and styling.
- Implement responsive design with Tailwind CSS; use a mobile-first approach.

Performance Optimization

- Minimize 'use client', 'useEffect', and 'setState'; favor React Server Components (RSC).
- Wrap client components in Suspense with fallback.
- Use dynamic loading for non-critical components.
- Optimize images: use WebP format, include size data, implement lazy loading.

Key Conventions

- Use 'nuqs' for URL search parameter state management.
- Optimize Web Vitals (LCP, CLS, FID).
- Limit 'use client':
  - Favor server components and Next.js SSR.
  - Use only for Web API access in small components.
  - Avoid for data fetching or state management.

Follow Next.js docs for Data Fetching, Rendering, and Routing.

Database and ORM

- Use Prisma as the primary ORM for database operations([1](https://www.prisma.io/docs/getting-started/quickstart)).
- Follow singleton pattern for PrismaClient instantiation:
  - Create lib/prisma.ts for client export
  - Use single instance across server components
- Prefer Prisma schema migrations over direct SQL:
  - Run migrations in development with `prisma migrate dev`
  - Deploy with `prisma migrate deploy`
- Structure database queries:
  - Keep queries in separate service files (e.g., services/user.ts)
  - Use strong typing with Prisma-generated types
  - Implement repository pattern for complex queries

Database Best Practices

- Use server components for database operations
- Implement proper error handling and type safety:
  - Wrap Prisma operations in try/catch blocks
  - Use Zod for input validation
  - Handle Prisma errors explicitly
- Optimize queries:
  - Select only needed fields
  - Use includes judiciously
  - Implement pagination for large datasets
- Cache frequently accessed data:
  - Utilize Next.js cache mechanisms
  - Implement proper cache invalidation
css
javascript
next.js
prisma
radix-ui
react
shadcn/ui
tailwindcss
+1 more
mauricedb/sci-fi-cinema-24

Used in 1 repository

TypeScript

    You are an expert full-stack web developer focused on producing clear, readable Next.js code.

    You always use the latest stable versions of Next.js 15, Supabase, TailwindCSS, and TypeScript, and you are familiar with the latest features and best practices.
    
    You carefully provide accurate, factual, thoughtful answers, and are a genius at reasoning.
    
    Technical preferences:
    
    - Always use kebab-case for component names (e.g. my-component.tsx)
    - Favour using React Server Components and Next.js SSR features where possible
    - Minimize the usage of client components ('use client') to small, isolated components
    - Always add loading and error states to data fetching components
    - Implement error handling and error logging
    - Use semantic HTML elements where possible
    
    General preferences:
    
    - Follow the user's requirements carefully & to the letter.
    - Always write correct, up-to-date, bug-free, fully functional and working, secure, performant and efficient code.
    - Focus on readability over being performant.
    - Fully implement all requested functionality.
    - Leave NO todo's, placeholders or missing pieces in the code.
    - Be sure to reference file names.
    - Be concise. Minimize any other prose.
    - If you think there might not be a correct answer, you say so. If you do not know the answer, say so instead of guessing.    
    
    You are an expert software architect tasked with creating comprehensive rules for Cursor AI to follow when working with site. 

# Cursor AI Rules for site

## Project Overview
site is portfolio web site with mdx suported

## Project Context
This document defines the rules and guidelines for Cursor AI when working with site.

### Technical Stack
- Platform: web
- Framework: next
- Key Dependencies:

- tailwind-next

- shadcn-next


## Code Generation Rules

### 1. Project Structure
Follow these directory and file organization rules:
- Maintain the established project structure
- Place components in appropriate directories
- Follow file naming conventions
- Respect module boundaries
- Keep related files together

### 2. Code Style
Adhere to these formatting rules:
- Use consistent indentation
- Follow line length limits
- Apply proper spacing
- Use appropriate brackets
- Maintain consistent naming
- Follow TypeScript best practices

### 3. Component Guidelines
When generating components:
- Follow component composition patterns
- Implement proper prop typing
- Use appropriate state management
- Handle errors correctly
- Implement proper event handling
- Follow lifecycle best practices
- Optimize rendering performance

### 4. Type System
For TypeScript implementation:
- Use strict type checking
- Create proper interfaces
- Implement generics correctly
- Handle null/undefined properly
- Use type guards when needed
- Document complex types
- Avoid any type

### 5. API Integration
When working with APIs:
- Follow RESTful conventions
- Implement proper error handling
- Use type-safe requests
- Handle authentication correctly
- Validate API responses
- Document API usage
- Implement proper caching

### 6. State Management
For managing application state:
- Use appropriate state solutions
- Follow immutability principles
- Implement proper actions/reducers
- Handle side effects correctly
- Optimize state updates
- Document state structure
- Implement proper selectors

### 7. Testing Requirements
Generate tests following these rules:
- Write comprehensive unit tests
- Implement integration tests
- Follow testing best practices
- Use proper mocking
- Test error scenarios
- Maintain test coverage
- Document test cases

### 8. Security Guidelines
Enforce security practices:
- Validate all inputs
- Sanitize data output
- Handle authentication properly
- Protect sensitive data
- Follow OWASP guidelines
- Implement proper CORS
- Use secure dependencies

### 9. Performance Rules
Optimize for performance:
- Implement code splitting
- Use lazy loading
- Optimize bundle size
- Minimize re-renders
- Use proper caching
- Optimize assets
- Follow performance best practices

### 10. Documentation
Generate documentation that:
- Is clear and concise
- Includes JSDoc comments
- Provides usage examples
- Documents edge cases
- Explains complex logic
- Includes type information
- Follows documentation standards




## Best Practices

### 1. Code Quality
- Write self-documenting code
- Keep functions small and focused
- Follow DRY principles
- Use meaningful names
- Implement proper error handling
- Write maintainable code

### 2. Performance
- Optimize bundle size
- Implement code splitting
- Use proper caching
- Optimize rendering
- Follow lazy loading patterns

### 3. Security
- Validate user input
- Sanitize data output
- Use proper authentication
- Protect sensitive data
- Follow security best practices
bun
css
javascript
mdx
next.js
react
rest-api
shadcn/ui
+4 more

First seen in:

fport/site

Used in 1 repository

TypeScript
Client code is in frontend/
API lambda code is in lambda/
AWS CDK stack to define the API is in lib/story-maker-stack.ts

Always
Prefer small functions
Don't apologize on mistakes
Look in frontend/src/types/story-maker.ts for core data types.
When writing comments, make sure to write "WHY" we're doing things, the what/how is less important.
Prefer:
 * fat arrow syntax for functions
 * small well named functions

When Inside frontend/
Use @tanstack/react-query for API requests
Use joy styled for component styling

import { styled } from '@mui/joy/styles';

When styling components, use these mui/joy theming and color tokens:
background.body background.surface background.level1 background.level2 background.level3 background.popup background.tooltip text.primary text.secondary text.tertiary text.icon primary.50 primary.100 primary.200 primary.300 primary.400 primary.500 primary.600 primary.700 primary.800 primary.900 neutral.50 neutral.100 neutral.200 neutral.300 neutral.400 neutral.500 neutral.600 neutral.700 neutral.800 neutral.900 success.50 success.100 success.200 success.300 success.400 success.500 success.600 success.700 success.800 success.900 warning.50 warning.100 warning.200 warning.300 warning.400 warning.500 warning.600 warning.700 warning.800 warning.900 danger.50 danger.100 danger.200 danger.300 danger.400 danger.500 danger.600 danger.700 danger.800 danger.900 common.white common.black divider  focusVisible 

aws
css
html
javascript
less
react
typescript

First seen in:

marc-hughes/storymaker

Used in 1 repository

TypeScript
# Project Overview
name: FAL.AI Web Interface
description: A modern web interface for FAL.AI API integration allowing users to input their API keys and interact with FAL's AI services.

# Technical Stack
framework: Next.js 14 (App Router)
styling: Tailwind CSS + Shadcn UI
language: TypeScript
node_version: ">=20.0.0"

# Key Features
- User API key management
- FAL.AI service integration
- Real-time AI processing
- Secure credential handling

# Architecture Notes
- Server components by default
- Client components only when necessary (user interactions, state management)
- API key storage in secure client-side storage
- Server-side proxy implementation for FAL.AI requests


# Dependencies
- @fal-ai/client: Latest    # Official FAL.AI client
- @fal-ai/server-proxy      # FAL.AI server proxy
- shadcn/ui: Latest         # UI component library
- tailwindcss: Latest       # Utility-first CSS

# Security Considerations
- API keys stored in encrypted client storage
- Server-side proxy for secure API communication
- No API keys in client-side code
- Rate limiting implementation

# Performance Optimization
- React Server Components for initial render
- Streaming responses for AI operations
- Lazy loading for non-critical components
- Image optimization for AI-generated content

# State Management
- React hooks for local state
- Server actions for data mutations
- Optimistic updates for better UX

# Error Handling
- Graceful fallbacks for API failures
- User-friendly error messages
- Request retry mechanisms
css
javascript
next.js
react
shadcn/ui
tailwindcss
typescript
olyaiy/simple-flux-web-api-ui

Used in 1 repository

TypeScript
* this project is a drag and drop code editor
* this project uses solidjs and typescript. type safety is of the utmost importance
* there's going to be a canvas where you can drag and drop code blocks
* each code block is required to either execute an effect, or return a value
* the code blocks are reactive
* when some value changes, every single code block that depends on said value also is recomputed
* you can have target blocks which can have either like a table or a graph or just a html renderer (for now)
* i think there should be a reactivity class that is responsible for managing the reactivity of the code blocks 
* for the code blocks, we should use monaco
* for drag and drop, for now, let us use https://github.com/thisbeyond/solid-dnd (please index that)
* down the line, might use the webcontainers api to let us have any library in this editor
# here is an example of using monaco with solidjs

```typescript
import { createSignal, createEffect, onCleanup, JSX, onMount, mergeProps, on } from 'solid-js'
import * as monacoEditor from 'monaco-editor'
import loader, { Monaco } from '@monaco-editor/loader'
import { Loader } from './Loader'
import { MonacoContainer } from './MonacoContainer'
import { getOrCreateModel } from './utils'
import { LoaderParams } from './types'

const viewStates = new Map()

export interface MonacoEditorProps {
  language?: string
  value?: string
  loadingState?: JSX.Element
  class?: string
  theme?: monacoEditor.editor.BuiltinTheme | string
  path?: string
  overrideServices?: monacoEditor.editor.IEditorOverrideServices
  width?: string
  height?: string
  options?: monacoEditor.editor.IStandaloneEditorConstructionOptions
  saveViewState?: boolean
  loaderParams?: LoaderParams
  onChange?: (value: string, event: monacoEditor.editor.IModelContentChangedEvent) => void
  onMount?: (monaco: Monaco, editor: monacoEditor.editor.IStandaloneCodeEditor) => void
  onBeforeUnmount?: (monaco: Monaco, editor: monacoEditor.editor.IStandaloneCodeEditor) => void
}

export const MonacoEditor = (inputProps: MonacoEditorProps) => {
  const props = mergeProps(
    {
      theme: 'vs',
      width: '100%',
      height: '100%',
      loadingState: 'Loading…',
      saveViewState: true,
    },
    inputProps,
  )

  let containerRef: HTMLDivElement

  const [monaco, setMonaco] = createSignal<Monaco>()
  const [editor, setEditor] = createSignal<monacoEditor.editor.IStandaloneCodeEditor>()

  let abortInitialization: (() => void) | undefined
  let monacoOnChangeSubscription: any
  let isOnChangeSuppressed = false

  onMount(async () => {
    loader.config(inputProps.loaderParams ?? { monaco: monacoEditor })
    const loadMonaco = loader.init()

    abortInitialization = () => loadMonaco.cancel()

    try {
      const monaco = await loadMonaco
      const editor = createEditor(monaco)
      setMonaco(monaco)
      setEditor(editor)
      props.onMount?.(monaco, editor)

      monacoOnChangeSubscription = editor.onDidChangeModelContent(event => {
        if (!isOnChangeSuppressed) {
          props.onChange?.(editor.getValue(), event)
        }
      })
    } catch (error: any) {
      if (error?.type === 'cancelation') {
        return
      }

      console.error('Could not initialize Monaco', error)
    }
  })

  onCleanup(() => {
    const _editor = editor()
    if (!_editor) {
      abortInitialization?.()
      return
    }

    props.onBeforeUnmount?.(monaco()!, _editor)
    monacoOnChangeSubscription?.dispose()
    _editor.getModel()?.dispose()
    _editor.dispose()
  })

  createEffect(
    on(
      () => props.value,
      value => {
        const _editor = editor()
        if (!_editor || typeof value === 'undefined') {
          return
        }

        if (_editor.getOption(monaco()!.editor.EditorOption.readOnly)) {
          _editor.setValue(value)
          return
        }

        if (value !== _editor.getValue()) {
          isOnChangeSuppressed = true

          _editor.executeEdits('', [
            {
              range: _editor.getModel()!.getFullModelRange(),
              text: value,
              forceMoveMarkers: true,
            },
          ])

          _editor.pushUndoStop()
          isOnChangeSuppressed = false
        }
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => props.options,
      options => {
        editor()?.updateOptions(options ?? {})
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => props.theme,
      theme => {
        monaco()?.editor.setTheme(theme)
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => props.language,
      language => {
        const model = editor()?.getModel()
        if (!language || !model) {
          return
        }

        monaco()?.editor.setModelLanguage(model, language)
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => props.path,
      (path, prevPath) => {
        const _monaco = monaco()
        if (!_monaco) {
          return
        }

        const model = getOrCreateModel(_monaco, props.value ?? '', props.language, path)

        if (model !== editor()?.getModel()) {
          if (props.saveViewState) {
            viewStates.set(prevPath, editor()?.saveViewState())
          }
          editor()?.setModel(model)
          if (props.saveViewState) {
            editor()?.restoreViewState(viewStates.get(path))
          }
        }
      },
      { defer: true },
    ),
  )

  const createEditor = (monaco: Monaco) => {
    const model = getOrCreateModel(monaco, props.value ?? '', props.language, props.path)

    return monaco.editor.create(
      containerRef,
      {
        model: model,
        automaticLayout: true,
        ...props.options,
      },
      props.overrideServices,
    )
  }

  return (
    <MonacoContainer class={props.class} width={props.width} height={props.height}>
      {!editor() && <Loader>{props.loadingState}</Loader>}
      <div style={{ width: '100%' }} ref={containerRef!} />
    </MonacoContainer>
  )
}

```

```typescript
import { createSignal, createEffect, onCleanup, JSX, onMount, mergeProps, on } from 'solid-js'
import * as monacoEditor from 'monaco-editor'
import loader, { Monaco } from '@monaco-editor/loader'
import { Loader } from './Loader'
import { MonacoContainer } from './MonacoContainer'
import { getOrCreateModel } from './utils'
import { LoaderParams } from './types'

const viewStates = new Map()

export interface MonacoDiffEditorProps {
  original?: string
  modified?: string

  originalLanguage?: string
  modifiedLanguage?: string

  originalPath?: string
  modifiedPath?: string

  loadingState?: JSX.Element
  class?: string
  theme?: monacoEditor.editor.BuiltinTheme | string
  overrideServices?: monacoEditor.editor.IEditorOverrideServices
  width?: string
  height?: string
  options?: monacoEditor.editor.IStandaloneEditorConstructionOptions
  saveViewState?: boolean
  loaderParams?: LoaderParams
  onChange?: (value: string) => void
  onMount?: (monaco: Monaco, editor: monacoEditor.editor.IStandaloneDiffEditor) => void
  onBeforeUnmount?: (monaco: Monaco, editor: monacoEditor.editor.IStandaloneDiffEditor) => void
}

export const MonacoDiffEditor = (inputProps: MonacoDiffEditorProps) => {
  const props = mergeProps(
    {
      theme: 'vs',
      width: '100%',
      height: '100%',
      loadingState: 'Loading…',
      saveViewState: true,
    },
    inputProps,
  )

  let containerRef: HTMLDivElement

  const [monaco, setMonaco] = createSignal<Monaco>()
  const [editor, setEditor] = createSignal<monacoEditor.editor.IStandaloneDiffEditor>()

  let abortInitialization: (() => void) | undefined
  let monacoOnChangeSubscription: any
  let isOnChangeSuppressed = false

  onMount(async () => {
    loader.config(inputProps.loaderParams ?? { monaco: monacoEditor })
    const loadMonaco = loader.init()

    abortInitialization = () => loadMonaco.cancel()

    try {
      const monaco = await loadMonaco
      const editor = createEditor(monaco)
      setMonaco(monaco)
      setEditor(editor)
      props.onMount?.(monaco, editor)

      monacoOnChangeSubscription = editor.onDidUpdateDiff(() => {
        if (!isOnChangeSuppressed) {
          props.onChange?.(editor.getModifiedEditor().getValue())
        }
      })
    } catch (error: any) {
      if (error?.type === 'cancelation') {
        return
      }

      console.error('Could not initialize Monaco', error)
    }
  })

  onCleanup(() => {
    const _editor = editor()
    if (!_editor) {
      abortInitialization?.()
      return
    }

    props.onBeforeUnmount?.(monaco()!, _editor)
    monacoOnChangeSubscription?.dispose()
    _editor.getModel()?.original.dispose()
    _editor.getModel()?.modified.dispose()
    _editor.dispose()
  })

  createEffect(
    on(
      () => props.modified,
      modified => {
        const _editor = editor()?.getModifiedEditor()
        if (!_editor || typeof modified === 'undefined') {
          return
        }

        if (_editor.getOption(monaco()!.editor.EditorOption.readOnly)) {
          _editor.setValue(modified)
          return
        }

        if (modified !== _editor.getValue()) {
          isOnChangeSuppressed = true

          _editor.executeEdits('', [
            {
              range: _editor.getModel()!.getFullModelRange(),
              text: modified,
              forceMoveMarkers: true,
            },
          ])

          _editor.pushUndoStop()
          isOnChangeSuppressed = false
        }
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => props.original,
      original => {
        const _editor = editor()?.getOriginalEditor()
        if (!_editor || typeof original === 'undefined') {
          return
        }

        if (_editor.getOption(monaco()!.editor.EditorOption.readOnly)) {
          _editor.setValue(original)
        }
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => props.options,
      options => {
        editor()?.updateOptions(options ?? {})
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => props.theme,
      theme => {
        monaco()?.editor.setTheme(theme)
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => props.originalLanguage,
      language => {
        const model = editor()?.getModel()
        if (!language || !model) {
          return
        }

        monaco()?.editor.setModelLanguage(model.original, language)
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => props.modifiedLanguage,
      language => {
        const model = editor()?.getModel()
        if (!language || !model) {
          return
        }

        monaco()?.editor.setModelLanguage(model.modified, language)
      },
      { defer: true },
    ),
  )

  createEffect(
    on(
      () => [props.originalPath, props.modifiedPath],
      ([originalPath, modifiedPath], prevPaths) => {
        const _monaco = monaco()
        if (!_monaco || !prevPaths) {
          return
        }

        const [prevOriginalPath, prevModifiedPath] = prevPaths

        const currentModels = editor()?.getModel()
        let originalModel = currentModels?.original
        let modifiedModel = currentModels?.modified

        if (prevOriginalPath !== originalPath) {
          if (props.saveViewState && originalPath != null) {
            viewStates.set(prevOriginalPath, editor()?.getOriginalEditor().saveViewState())
          }

          originalModel = getOrCreateModel(
            _monaco,
            props.original ?? '',
            props.originalLanguage,
            originalPath,
          )
        }

        if (prevModifiedPath !== modifiedPath) {
          if (props.saveViewState && prevModifiedPath != null) {
            viewStates.set(prevModifiedPath, editor()?.getModifiedEditor().saveViewState())
          }

          modifiedModel = getOrCreateModel(
            _monaco,
            props.modified ?? '',
            props.modifiedLanguage,
            modifiedPath,
          )
        }

        editor()?.setModel({ modified: modifiedModel!, original: originalModel! })

        if (props.saveViewState) {
          editor()?.getOriginalEditor().restoreViewState(viewStates.get(originalPath))
          editor()?.getModifiedEditor().restoreViewState(viewStates.get(modifiedPath))
        }
      },
      { defer: true },
    ),
  )

  const createEditor = (monaco: Monaco) => {
    const originalModel = getOrCreateModel(
      monaco,
      props.original ?? '',
      props.originalLanguage,
      props.originalPath,
    )
    const modifiedModel = getOrCreateModel(
      monaco,
      props.modified ?? '',
      props.modifiedLanguage,
      props.modifiedPath,
    )

    const editor = monaco.editor.createDiffEditor(
      containerRef,
      {
        automaticLayout: true,
        ...props.options,
      },
      props.overrideServices,
    )

    editor.setModel({
      original: originalModel,
      modified: modifiedModel,
    })

    return editor
  }

  return (
    <MonacoContainer class={props.class} width={props.width} height={props.height}>
      {!editor() && <Loader>{props.loadingState}</Loader>}
      <div style={{ width: '100%' }} ref={containerRef!} />
    </MonacoContainer>
  )
}
```

# here are some instructions for using monaco:

Based on your decision to use Monaco instead of CodeMirror, here's how you can integrate custom intellisense for TypeScript in Monaco Editor, including support for your own global variables:

## Setting Up Monaco with Custom Intellisense

1. **Add Type Definitions**

Create a declaration file for your custom globals:

```typescript
// globals.d.ts
declare const myGlobalVar: string;
declare function myGlobalFunction(): void;
// Add more global declarations as needed
```

2. **Configure Monaco**

When initializing Monaco, add the following configurations:

```typescript
import * as monaco from 'monaco-editor';

// Add your custom type definitions
monaco.languages.typescript.javascriptDefaults.addExtraLib(`
    declare const myGlobalVar: string;
    declare function myGlobalFunction(): void;
    // Add more global declarations here
    `, 'globals.d.ts');

// Configure TypeScript compiler options
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES6,
allowNonTsExtensions: true,
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
module: monaco.languages.typescript.ModuleKind.CommonJS,
noEmit: true,
typeRoots: ["node_modules/@types"]
});

// Create the editor
const editor = monaco.editor.create(document.getElementById('container'), {
value: '// Your initial TypeScript code here',
language: 'typescript',
// Other editor options...
});
```

3. **Custom Completion Provider (Optional)**

For more advanced scenarios, you can add a custom completion provider:

```typescript
monaco.languages.registerCompletionItemProvider('typescript', {
provideCompletionItems: (model, position) => {
const suggestions = [
{
label: 'myGlobalVar',
kind: monaco.languages.CompletionItemKind.Variable,
detail: 'Custom global variable',
insertText: 'myGlobalVar'
},
{
label: 'myGlobalFunction',
kind: monaco.languages.CompletionItemKind.Function,
detail: 'Custom global function',
insertText: 'myGlobalFunction()'
}
// Add more custom suggestions here
];

return { suggestions };
}
});
```

This setup will provide intellisense for your custom globals, including autocomplete suggestions and type information when hovering over the variables or functions in the editor[1][3][4].

## Additional Tips

* **Dynamic Updates**: If your global variables can change at runtime, you may need to update the extra libraries dynamically.
* **Performance**: For large projects, consider optimizing the completion provider to handle a large number of suggestions efficiently.
* **TypeScript Support**: Monaco provides excellent built-in support for TypeScript, so you'll get good intellisense for standard TypeScript features out of the box.

By following these steps, you'll have a Monaco editor with TypeScript support that includes your custom global variables in the intellisense suggestions, providing a rich editing experience for your users.

Citations:
[1] https://stackoverflow.com/questions/51538242/how-to-define-global-variable-in-monaco-editor-for-intellisense/51539385
[2] https://discourse.nodered.org/t/monaco-intellisense-code-completion-subflow/84581
[3] https://www.checklyhq.com/blog/customizing-monaco/
[4] https://github.com/microsoft/monaco-editor/issues/2147
[5] https://mono.software/2017/04/11/custom-intellisense-with-monaco-editor/
[6] https://microsoft.github.io/monaco-editor/
[7] https://www.npmjs.com/package/@monaco-editor/react
[8] https://stackoverflow.com/questions/69702749/how-to-use-intellisense-from-monaco-d-ts
[9] https://stackoverflow.com/questions/67505426/custom-javascript-code-completion-for-this-in-monaco-editor
[10] https://github.com/microsoft/monaco-editor/discussions/4469
css
golang
html
java
javascript
npm
react
rest-api
+2 more

First seen in:

saiashirwad/_

Used in 1 repository

Shell
The following text has been compressed by you (Claude 3.5 sonnet) to save space. Decode the text to reconstruct and understand the original context. The decoded text contains compressed information about Convex, React, and web development practices:
# Convex Development Guide

## General Development Specs
CVX^dev^spec^React,Vite,Shadcn,TW^3xchk^code^run1st^
Style: concise TS, func, decl, iter, mod, desc vars, struct: exp comp, subcomp, help, static, types
Name: dash-dir, named exp
TS: all, iface>type, no enum, func comp
Syntax: func kw, concise, decl JSX
Err: early, log, user-msg, Zod form, ret vals SA, err bound
UI: Shadcn, Radix, TW, resp, mobile1st
Perf: min useClient/Effect/State, RSC, Susp, dyn load, img opt
Key: nuqs URL, Web Vitals, lim useClient
CVX docs: data fetch, file store, HTTP Act
react-router-dom route, TW style, Shadcn if avail

## Convex Specifics

### Query
```typescript
import { query } from "./_generated/server";
import { v } from "convex/values";

export const getTaskList = query({
  args: { taskListId: v.id("taskLists") },
  handler: async (ctx, args) => {
    const tasks = await ctx.db
      .query("tasks")
      .filter((q) => q.eq(q.field("taskListId"), args.taskListId))
      .order("desc")
      .take(100);
    return tasks;
  }
});
```
Name: path+file+export=api.path.name
Nest: convex/foo/file.ts=api.foo.file.fn
Def: export default=api.file.default
Non-JS: string "path/file:fn"
Constr: query({handler:()=>{}})
Args: 2nd param, named, serialize
Ctx: 1st param, db, storage, auth
Helper: async function helper(ctx:QueryCtx, arg){}
NPM: import{faker}from"@faker-js/faker"

**IMPORTANT: Prefer to use Convex indexes over filters**. Here's an example:

```typescript
//schema.ts
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";

// Define a messages table with two indexes.
export default defineSchema({
  messages: defineTable({
    channel: v.id("channels"),
    body: v.string(),
    user: v.id("users"),
  })
    .index("by_channel", ["channel"])
    .index("by_channel_user", ["channel", "user"]),
});
```

And use an index like this:

```typescript
const messages = await ctx.db
  .query("messages")
  .withIndex("by_channel", (q) =>
    q
      .eq("channel", channel)
      .gt("_creationTime", Date.now() - 2 * 60000)
      .lt("_creationTime", Date.now() - 60000),
  )
  .collect();
```

### Mutation
```typescript
import { mutation } from "./_generated/server";
import { v } from "convex/values";

export const createTask = mutation({
  args: { text: v.string() },
  handler: async (ctx, args) => {
    const newTaskId = await ctx.db.insert("tasks", { text: args.text });
    return newTaskId;
  }
});
```

### Action
```typescript
import { action } from "./_generated/server";
import { internal } from "./_generated/api";
import { v } from "convex/values";

export const sendGif = action({
  args: { queryString: v.string(), author: v.string() },
  handler: async (ctx, { queryString, author }) => {
    const data = await fetch(giphyUrl(queryString));
    const json = await data.json();
    if (!data.ok) throw new Error(`Giphy error: ${JSON.stringify(json)}`);
    const gifEmbedUrl = json.data.embed_url;
    await ctx.runMutation(internal.messages.sendGifMessage, {
      body: gifEmbedUrl, author,
    });
  }
});
```

### HTTP Router
```typescript
import { httpRouter } from "convex/server";

const http = httpRouter();
http.route({
  path: "/postMessage",
  method: "POST",
  handler: postMessage,
});
http.route({
  pathPrefix: "/getAuthorMessages/",
  method: "GET",
  handler: getByAuthorPathSuffix,
});
export default http;
```

### Scheduled Jobs
```typescript
import { cronJobs } from "convex/server";
import { internal } from "./_generated/api";

const crons = cronJobs();
crons.interval(
  "clear messages table",
  { minutes: 1 },
  internal.messages.clearAll,
);
crons.monthly(
  "payment reminder",
  { day: 1, hourUTC: 16, minuteUTC: 0 },
  internal.payments.sendPaymentEmail,
  { email: "my_email@gmail.com" },
);
export default crons;
```

### File Handling
Upload: 3 steps (genURL, POST, saveID)

Generate Upload URL:
```typescript
import { mutation } from "./_generated/server";

export const generateUploadUrl = mutation(async (ctx) => {
  return await ctx.storage.generateUploadUrl();
});
```

Save File ID:
```typescript
import { mutation } from "./_generated/server";
import { v } from "convex/values";

export const sendImage = mutation({
  args: { storageId: v.id("_storage"), author: v.string() },
  handler: async (ctx, args) => {
    await ctx.db.insert("messages", {
      body: args.storageId,
      author: args.author,
      format: "image",
    });
  }
});
```
nestjs
npm
radix-ui
react
shadcn/ui
shell
typescript
vite
tomredman/add-convex-to-cursor

Used in 1 repository

TypeScript
Below is a **complete, robust, and fully functioning** set of **TypeScript + React** code files to set up a **WebGL Fluid Enhanced** simulation with:

1. **Multiple Emitter Types** (Point, Line, Curve, Dye)  
2. **Zustand** for state management (both fluid and emitters)  
3. **Tone.js** for audio reactivity  
4. **Leva** for live parameter UI controls  
5. **React Draggable** for positioning and manipulating emitters on the canvas  
6. **ESLint & Prettier** for code quality  
7. **Error Boundaries** for robust error handling  
8. **Vite** for bundling and dev server  

This is a **fully functioning** reference project you can **copy and run** with minimal changes. Below, you’ll find:

- **Project Structure**  
- **Configuration Files** (`package.json`, `tsconfig.json`, `.eslintrc.js`, `.prettierrc`, `vite.config.ts`)  
- **Full Source Code** for each file  
- **Detailed Explanations** in comments where needed  

> **Important**:  
> 1. This code is intentionally **verbose** to show robust usage.  
> 2. Ensure you install the listed dependencies before running.  
> 3. Update the code as you see fit (e.g., custom audio file paths, advanced UI, or additional features).

---

# 1. Project Structure

A suggested layout (you can rename or reorganize, but keep references consistent):

```
my-fluid-app/
├─ public/
│   └─ favicon.ico
├─ src/
│   ├─ components/
│   │   ├─ App.tsx
│   │   ├─ ErrorBoundary.tsx
│   │   ├─ FluidCanvas/
│   │   │   ├─ FluidCanvas.tsx
│   │   │   └─ EmitterOverlay.tsx
│   │   ├─ emitters/
│   │   │   ├─ BaseEmitter.ts
│   │   │   ├─ PointEmitter.tsx
│   │   │   ├─ LineEmitter.tsx
│   │   │   ├─ CurveEmitter.tsx
│   │   │   └─ DyeEmitter.tsx
│   │   ├─ audio/
│   │   │   ├─ AudioPanel.tsx
│   │   │   └─ useAudioAnalysis.ts
│   │   ├─ ui/
│   │   │   └─ LevaPanel.tsx
│   ├─ stores/
│   │   ├─ fluidStore.ts
│   │   ├─ audioStore.ts
│   │   └─ emitterStore.ts
│   ├─ styles/
│   │   └─ index.css
│   ├─ hooks/
│   │   └─ useEmitterDrag.ts (optional if you want custom drag logic)
│   ├─ main.tsx
│   └─ vite-env.d.ts
├─ .eslintrc.js
├─ .prettierrc
├─ index.html
├─ package.json
├─ tsconfig.json
└─ vite.config.ts
```

---

# 2. Configuration & Scripts

## `package.json`

```jsonc
{
  "name": "my-fluid-app",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "lint": "eslint . --ext .ts,.tsx",
    "format": "prettier --write ."
  },
  "dependencies": {
    "react": "^18.0.0",
    "react-dom": "^18.0.0",
    "webgl-fluid-enhanced": "latest",
    "zustand": "^4.3.5",
    "tone": "^14.8.47",
    "leva": "^0.9.37",
    "react-draggable": "^4.4.5",
    "three": "^0.154.0",
    "@react-three/fiber": "^8.13.20"
  },
  "devDependencies": {
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@types/react-draggable": "^4.4.6",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0",
    "eslint": "^8.0.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-react": "^7.31.11",
    "prettier": "^2.8.4",
    "typescript": "^4.5.5",
    "vite": "^4.0.4"
  }
}
```

## `tsconfig.json`

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["DOM", "DOM.Iterable", "ES2020"],
    "allowJs": false,
    "skipLibCheck": true,
    "strict": true,
    "strictNullChecks": true,
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react",
    "baseUrl": "."
  },
  "include": ["src"]
}
```

## `.eslintrc.js`

```js
module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module'
  },
  settings: {
    react: {
      version: 'detect'
    }
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier'
  ],
  rules: {
    // Add or override any ESLint rules here
  }
};
```

## `.prettierrc`

```json
{
  "printWidth": 100,
  "singleQuote": true,
  "semi": true
}
```

## `vite.config.ts`

```ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    open: true
  },
  build: {
    outDir: 'dist'
  }
});
```

---

# 3. Main HTML & Entry

## `index.html`

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My Fluid App</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
```

## `src/main.tsx`

```tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './components/App';
import './styles/index.css';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
```

---

# 4. Global Stores (Zustand)

We will maintain:
1. **Fluid Store** for the `WebGLFluidEnhanced` instance and its config.  
2. **Audio Store** for audio analysis data (amplitude, frequency, etc.).  
3. **Emitter Store** for a list of active emitters and their properties (position, type, color, etc.).

## `src/stores/fluidStore.ts`

```ts
import create from 'zustand';
import { WebGLFluidEnhanced, ConfigOptions } from 'webgl-fluid-enhanced';

interface FluidState {
  fluidInstance: WebGLFluidEnhanced | null;
  config: Partial<ConfigOptions>;
  setFluidInstance: (instance: WebGLFluidEnhanced) => void;
  updateConfig: (config: Partial<ConfigOptions>) => void;
}

export const useFluidStore = create<FluidState>((set) => ({
  fluidInstance: null,
  config: {
    simResolution: 128,
    dyeResolution: 1024,
    densityDissipation: 1,
    velocityDissipation: 0.2,
    bloom: true,
    sunrays: true,
    // etc. Add more if you want defaults
  },
  setFluidInstance: (instance) => set({ fluidInstance: instance }),
  updateConfig: (config) =>
    set((state) => ({
      config: { ...state.config, ...config }
    }))
}));
```

## `src/stores/audioStore.ts`

```ts
import create from 'zustand';

interface AudioState {
  isAudioReactive: boolean;
  audioInputDevice: 'mic' | 'file' | 'system';
  amplitude: number;        // Real-time amplitude (in dB or linear)
  frequencyData: number[];  // Real-time frequency data (FFT output)
  setIsAudioReactive: (val: boolean) => void;
  setAudioInputDevice: (device: 'mic' | 'file' | 'system') => void;
  setAmplitude: (amp: number) => void;
  setFrequencyData: (data: number[]) => void;
}

export const useAudioStore = create<AudioState>((set) => ({
  isAudioReactive: false,
  audioInputDevice: 'mic',
  amplitude: 0,
  frequencyData: [],
  setIsAudioReactive: (val) => set({ isAudioReactive: val }),
  setAudioInputDevice: (device) => set({ audioInputDevice: device }),
  setAmplitude: (amp) => set({ amplitude: amp }),
  setFrequencyData: (data) => set({ frequencyData: data })
}));
```

## `src/stores/emitterStore.ts`

```ts
import create from 'zustand';

export type EmitterType = 'point' | 'line' | 'curve' | 'dye';

export interface EmitterData {
  id: string;
  type: EmitterType;
  active: boolean;
  // Basic transform
  position?: { x: number; y: number };
  endPosition?: { x: number; y: number };
  controlPoints?: { x: number; y: number }[]; // For curve or advanced lines
  color?: string;
  // Additional properties as you see fit
}

interface EmitterState {
  emitters: EmitterData[];
  addEmitter: (emitter: EmitterData) => void;
  removeEmitter: (id: string) => void;
  updateEmitter: (id: string, data: Partial<EmitterData>) => void;
}

export const useEmitterStore = create<EmitterState>((set) => ({
  emitters: [],
  addEmitter: (emitter) =>
    set((state) => ({
      emitters: [...state.emitters, emitter]
    })),
  removeEmitter: (id) =>
    set((state) => ({
      emitters: state.emitters.filter((em) => em.id !== id)
    })),
  updateEmitter: (id, data) =>
    set((state) => ({
      emitters: state.emitters.map((em) => (em.id === id ? { ...em, ...data } : em))
    }))
}));
```

---

# 5. Styles

## `src/styles/index.css`

```css
html,
body,
#root {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #000; /* fallback background */
  font-family: sans-serif;
}

.leva {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 1000;
}
```

---

# 6. Error Boundary

## `src/components/ErrorBoundary.tsx`

```tsx
import React from 'react';

interface ErrorBoundaryProps {
  children: React.ReactNode;
}

interface ErrorBoundaryState {
  hasError: boolean;
  error?: Error;
}

export default class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, info: React.ErrorInfo) {
    console.error('Error caught by ErrorBoundary:', error, info);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div style={{ color: 'red', padding: 20 }}>
          <h1>An error occurred.</h1>
          <p>{this.state.error?.message}</p>
        </div>
      );
    }
    return this.props.children;
  }
}
```

---

# 7. Main Application

## `src/components/App.tsx`

```tsx
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import FluidCanvas from './FluidCanvas/FluidCanvas';
import EmitterOverlay from './FluidCanvas/EmitterOverlay';
import AudioPanel from './audio/AudioPanel';
import LevaPanel from './ui/LevaPanel';

const App: React.FC = () => {
  return (
    <ErrorBoundary>
      <div style={{ width: '100vw', height: '100vh', position: 'relative' }}>
        {/* The fluid simulation canvas */}
        <FluidCanvas />

        {/* The overlay that handles interactive emitters */}
        <EmitterOverlay />

        {/* Audio reactivity controls */}
        <AudioPanel />

        {/* Fluid simulation and emitter parameter controls via Leva */}
        <LevaPanel />
      </div>
    </ErrorBoundary>
  );
};

export default App;
```

---

# 8. Fluid Canvas & Overlay

## `src/components/FluidCanvas/FluidCanvas.tsx`

```tsx
import React, { useEffect, useRef } from 'react';
import { useFluidStore } from '../../stores/fluidStore';
import WebGLFluidEnhanced from 'webgl-fluid-enhanced';

const FluidCanvas: React.FC = () => {
  const containerRef = useRef<HTMLDivElement>(null);
  const { fluidInstance, setFluidInstance, config } = useFluidStore();

  useEffect(() => {
    if (!containerRef.current) return;

    // If fluidInstance not yet created, create one
    if (!fluidInstance) {
      const instance = new WebGLFluidEnhanced(containerRef.current);
      instance.setConfig(config);
      instance.start();
      setFluidInstance(instance);
    }

    // Cleanup on unmount
    return () => {
      fluidInstance?.stop();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [containerRef]);

  // Update simulation config whenever it changes
  useEffect(() => {
    if (fluidInstance) {
      fluidInstance.setConfig(config);
    }
  }, [fluidInstance, config]);

  return (
    <div
      ref={containerRef}
      style={{
        position: 'absolute',
        top: 0,
        left: 0,
        width: '100%',
        height: '100%',
        overflow: 'hidden'
      }}
    />
  );
};

export default FluidCanvas;
```

## `src/components/FluidCanvas/EmitterOverlay.tsx`

```tsx
import React from 'react';
import { useEmitterStore } from '../../stores/emitterStore';
import { useFluidStore } from '../../stores/fluidStore';
import PointEmitter from '../emitters/PointEmitter';
import LineEmitter from '../emitters/LineEmitter';
import CurveEmitter from '../emitters/CurveEmitter';
import DyeEmitter from '../emitters/DyeEmitter';

/**
 * Renders all active emitters on top of the fluid canvas.
 */
const EmitterOverlay: React.FC = () => {
  const { emitters } = useEmitterStore();
  const { fluidInstance } = useFluidStore();

  return (
    <>
      {emitters.map((emitter) => {
        if (!emitter.active) return null;
        switch (emitter.type) {
          case 'point':
            return (
              <PointEmitter key={emitter.id} emitter={emitter} fluid={fluidInstance} />
            );
          case 'line':
            return (
              <LineEmitter key={emitter.id} emitter={emitter} fluid={fluidInstance} />
            );
          case 'curve':
            return (
              <CurveEmitter key={emitter.id} emitter={emitter} fluid={fluidInstance} />
            );
          case 'dye':
            return (
              <DyeEmitter key={emitter.id} emitter={emitter} fluid={fluidInstance} />
            );
          default:
            return null;
        }
      })}
    </>
  );
};

export default EmitterOverlay;
```

---

# 9. Emitters

We’ll use **React Draggable** to move the emitters around.  
Each emitter can also handle **audio reactivity** or advanced logic as needed.

## `src/components/emitters/BaseEmitter.ts`

```ts
import { WebGLFluidEnhanced } from 'webgl-fluid-enhanced';
import { EmitterData } from '../../stores/emitterStore';

export interface EmitterComponentProps {
  emitter: EmitterData;
  fluid: WebGLFluidEnhanced | null;
}
```

## `src/components/emitters/PointEmitter.tsx`

```tsx
import React, { useState, useEffect } from 'react';
import Draggable from 'react-draggable';
import { useEmitterStore } from '../../stores/emitterStore';
import { EmitterComponentProps } from './BaseEmitter';

/**
 * A continuous emitter that emits from a single point.
 */
const PointEmitter: React.FC<EmitterComponentProps> = ({ emitter, fluid }) => {
  const { updateEmitter } = useEmitterStore();
  const [dragPosition, setDragPosition] = useState(
    emitter.position ?? { x: 300, y: 300 }
  );

  // If you want to change color dynamically, you could store it in emitter.color
  const color = emitter.color ?? '#FF0000';
  const emissionForce = 600; // You can make this dynamic as well

  // Continuously emit fluid at intervals
  useEffect(() => {
    const interval = setInterval(() => {
      if (!fluid) return;
      fluid.splatAtLocation(
        dragPosition.x,
        dragPosition.y,
        0, // x velocity
        0, // y velocity
        color
      );
    }, 1000);

    return () => clearInterval(interval);
  }, [fluid, dragPosition, color]);

  const handleDrag = (e: any, data: any) => {
    setDragPosition({ x: data.x, y: data.y });
    // Persist changes to store
    updateEmitter(emitter.id, { position: { x: data.x, y: data.y } });
  };

  return (
    <Draggable position={dragPosition} onDrag={handleDrag}>
      <div style={{ position: 'absolute', cursor: 'pointer', zIndex: 10 }}>
        {/* Visual marker for the emitter */}
        <div
          style={{
            width: 36,
            height: 36,
            borderRadius: '50%',
            background: color,
            border: '2px solid #fff',
            boxShadow: '0 0 10px rgba(255, 255, 255, 0.5)',
            opacity: 0.8
          }}
        />
      </div>
    </Draggable>
  );
};

export default PointEmitter;
```

## `src/components/emitters/LineEmitter.tsx`

```tsx
import React, { useState, useEffect } from 'react';
import Draggable from 'react-draggable';
import { useEmitterStore } from '../../stores/emitterStore';
import { EmitterComponentProps } from './BaseEmitter';

/**
 * Emits fluid along a line between two points.
 */
const LineEmitter: React.FC<EmitterComponentProps> = ({ emitter, fluid }) => {
  const { updateEmitter } = useEmitterStore();

  // Default positions if not set
  const defaultStart = emitter.position ?? { x: 200, y: 200 };
  const defaultEnd = emitter.endPosition ?? { x: 400, y: 300 };

  const [startPos, setStartPos] = useState(defaultStart);
  const [endPos, setEndPos] = useState(defaultEnd);

  const color = emitter.color ?? '#00FF00';
  const emissionIntervalMs = 1500;
  const steps = 12; // number of points to splat along the line

  // Emit fluid along the line at intervals
  useEffect(() => {
    const interval = setInterval(() => {
      if (!fluid) return;
      for (let i = 0; i <= steps; i++) {
        const t = i / steps;
        const x = startPos.x + (endPos.x - startPos.x) * t;
        const y = startPos.y + (endPos.y - startPos.y) * t;
        fluid.splatAtLocation(x, y, 0, 0, color);
      }
    }, emissionIntervalMs);

    return () => clearInterval(interval);
  }, [fluid, startPos, endPos, color]);

  // Handlers for dragging each endpoint
  const handleDragStart = (e: any, data: any) => {
    setStartPos({ x: data.x, y: data.y });
    updateEmitter(emitter.id, { position: { x: data.x, y: data.y } });
  };

  const handleDragEnd = (e: any, data: any) => {
    setEndPos({ x: data.x, y: data.y });
    updateEmitter(emitter.id, { endPosition: { x: data.x, y: data.y } });
  };

  return (
    <>
      <Draggable position={startPos} onDrag={handleDragStart}>
        <div style={{ position: 'absolute', cursor: 'pointer', zIndex: 10 }}>
          <div
            style={{
              width: 30,
              height: 30,
              borderRadius: '50%',
              background: color,
              border: '2px solid #fff'
            }}
          />
        </div>
      </Draggable>

      <Draggable position={endPos} onDrag={handleDragEnd}>
        <div style={{ position: 'absolute', cursor: 'pointer', zIndex: 10 }}>
          <div
            style={{
              width: 30,
              height: 30,
              borderRadius: '50%',
              background: color,
              border: '2px solid #fff'
            }}
          />
        </div>
      </Draggable>
    </>
  );
};

export default LineEmitter;
```

## `src/components/emitters/CurveEmitter.tsx`

```tsx
import React, { useState, useEffect } from 'react';
import Draggable from 'react-draggable';
import { useEmitterStore } from '../../stores/emitterStore';
import { EmitterComponentProps } from './BaseEmitter';

/**
 * A simple 3-control-point curve. Extend or import SVG for more complex shapes.
 */
const CurveEmitter: React.FC<EmitterComponentProps> = ({ emitter, fluid }) => {
  const { updateEmitter } = useEmitterStore();

  // If emitter.controlPoints is not defined or has fewer than 3 points, set defaults
  const defaultPoints = emitter.controlPoints && emitter.controlPoints.length >= 3
    ? emitter.controlPoints
    : [
        { x: 200, y: 200 },
        { x: 300, y: 100 },
        { x: 400, y: 200 }
      ];

  const [p0, setP0] = useState(defaultPoints[0]);
  const [p1, setP1] = useState(defaultPoints[1]);
  const [p2, setP2] = useState(defaultPoints[2]);

  const color = emitter.color ?? '#0000FF';
  const steps = 16; // sampling along the curve
  const emissionIntervalMs = 2000;

  // Quadratic Bezier
  const getCurvePoint = (t: number) => {
    const x = (1 - t) * (1 - t) * p0.x + 2 * (1 - t) * t * p1.x + t * t * p2.x;
    const y = (1 - t) * (1 - t) * p0.y + 2 * (1 - t) * t * p1.y + t * t * p2.y;
    return { x, y };
  };

  // Emit fluid along the curve
  useEffect(() => {
    const interval = setInterval(() => {
      if (!fluid) return;
      for (let i = 0; i <= steps; i++) {
        const t = i / steps;
        const { x, y } = getCurvePoint(t);
        fluid.splatAtLocation(x, y, 0, 0, color);
      }
    }, emissionIntervalMs);

    return () => clearInterval(interval);
  }, [fluid, p0, p1, p2, color]);

  const handleDragP0 = (e: any, data: any) => {
    setP0({ x: data.x, y: data.y });
    updateEmitter(emitter.id, { controlPoints: [{ x: data.x, y: data.y }, p1, p2] });
  };
  const handleDragP1 = (e: any, data: any) => {
    setP1({ x: data.x, y: data.y });
    updateEmitter(emitter.id, { controlPoints: [p0, { x: data.x, y: data.y }, p2] });
  };
  const handleDragP2 = (e: any, data: any) => {
    setP2({ x: data.x, y: data.y });
    updateEmitter(emitter.id, { controlPoints: [p0, p1, { x: data.x, y: data.y }] });
  };

  return (
    <>
      <Draggable position={p0} onDrag={handleDragP0}>
        <div style={{ position: 'absolute', cursor: 'pointer', zIndex: 10 }}>
          <div
            style={{
              width: 24,
              height: 24,
              borderRadius: '50%',
              background: color,
              border: '2px solid #fff'
            }}
          />
        </div>
      </Draggable>

      <Draggable position={p1} onDrag={handleDragP1}>
        <div style={{ position: 'absolute', cursor: 'pointer', zIndex: 10 }}>
          <div
            style={{
              width: 24,
              height: 24,
              borderRadius: '50%',
              background: color,
              border: '2px solid #fff'
            }}
          />
        </div>
      </Draggable>

      <Draggable position={p2} onDrag={handleDragP2}>
        <div style={{ position: 'absolute', cursor: 'pointer', zIndex: 10 }}>
          <div
            style={{
              width: 24,
              height: 24,
              borderRadius: '50%',
              background: color,
              border: '2px solid #fff'
            }}
          />
        </div>
      </Draggable>
    </>
  );
};

export default CurveEmitter;
```

## `src/components/emitters/DyeEmitter.tsx`

```tsx
import React, { useState } from 'react';
import { EmitterComponentProps } from './BaseEmitter';
import { useEmitterStore } from '../../stores/emitterStore';

/**
 * Lets user "paint" fluid color on the canvas. 
 * For a real app, you'd create a semi-transparent overlay that captures mouse events.
 */
const DyeEmitter: React.FC<EmitterComponentProps> = ({ emitter, fluid }) => {
  const { updateEmitter } = useEmitterStore();
  const [isPainting, setIsPainting] = useState(false);
  const brushColor = emitter.color ?? '#FFFFFF';
  const brushSize = 10; // or store in emitter

  const handleMouseDown = () => setIsPainting(true);
  const handleMouseUp = () => setIsPainting(false);

  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
    if (!isPainting || !fluid) return;
    const rect = (e.target as HTMLDivElement).getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;

    // You can sample multiple points or only one
    fluid.splatAtLocation(x, y, 0, 0, brushColor);
  };

  // You could also implement an eraser mode, dynamic brush size, etc.

  return (
    <div
      style={{
        position: 'absolute',
        top: 0,
        left: 0,
        width: '100%',
        height: '100%',
        zIndex: 20, // above other emitters
        pointerEvents: 'auto'
      }}
      onMouseDown={handleMouseDown}
      onMouseUp={handleMouseUp}
      onMouseMove={handleMouseMove}
    >
      {/* No visible UI—just an invisible painting layer */}
    </div>
  );
};

export default DyeEmitter;
```

---

# 10. UI / Leva Controls

## `src/components/ui/LevaPanel.tsx`

```tsx
import React from 'react';
import { useControls } from 'leva';
import { useFluidStore } from '../../stores/fluidStore';
import { useEmitterStore, EmitterData } from '../../stores/emitterStore';
import { v4 as uuidv4 } from 'uuid';

/**
 * A Leva panel that:
 * - Adjusts global fluid config
 * - Adds new emitters
 */
const LevaPanel: React.FC = () => {
  const { config, updateConfig } = useFluidStore();
  const { addEmitter, emitters } = useEmitterStore();

  // Fluid simulation controls
  useControls(
    'Fluid Simulation',
    {
      simResolution: {
        value: config.simResolution ?? 128,
        min: 32,
        max: 512,
        step: 32,
        onChange: (val) => updateConfig({ simResolution: val })
      },
      dyeResolution: {
        value: config.dyeResolution ?? 1024,
        min: 256,
        max: 2048,
        step: 256,
        onChange: (val) => updateConfig({ dyeResolution: val })
      },
      densityDissipation: {
        value: config.densityDissipation ?? 1,
        min: 0,
        max: 5,
        step: 0.1,
        onChange: (val) => updateConfig({ densityDissipation: val })
      },
      velocityDissipation: {
        value: config.velocityDissipation ?? 0.2,
        min: 0,
        max: 1,
        step: 0.01,
        onChange: (val) => updateConfig({ velocityDissipation: val })
      },
      bloom: {
        value: config.bloom ?? true,
        onChange: (val) => updateConfig({ bloom: val })
      },
      sunrays: {
        value: config.sunrays ?? true,
        onChange: (val) => updateConfig({ sunrays: val })
      }
    },
    { collapsed: false }
  );

  // Add emitter UI
  useControls(
    'Emitters',
    {
      AddPointEmitter: button(() => {
        const newEmitter: EmitterData = {
          id: uuidv4(),
          type: 'point',
          active: true,
          position: { x: 300, y: 300 },
          color: '#FF0000'
        };
        addEmitter(newEmitter);
      }),
      AddLineEmitter: button(() => {
        const newEmitter: EmitterData = {
          id: uuidv4(),
          type: 'line',
          active: true,
          position: { x: 200, y: 200 },
          endPosition: { x: 400, y: 300 },
          color: '#00FF00'
        };
        addEmitter(newEmitter);
      }),
      AddCurveEmitter: button(() => {
        const newEmitter: EmitterData = {
          id: uuidv4(),
          type: 'curve',
          active: true,
          controlPoints: [
            { x: 200, y: 200 },
            { x: 300, y: 100 },
            { x: 400, y: 200 }
          ],
          color: '#0000FF'
        };
        addEmitter(newEmitter);
      }),
      AddDyeEmitter: button(() => {
        const newEmitter: EmitterData = {
          id: uuidv4(),
          type: 'dye',
          active: true,
          color: '#FFFFFF'
        };
        addEmitter(newEmitter);
      })
    },
    { collapsed: false }
  );

  return null;
};

// We need to define this 'button' type for Leva (since it’s not typed out of the box)
function button(fn: () => void) {
  return { onClick: fn };
}

export default LevaPanel;
```

---

# 11. Audio Reactivity

## `src/components/audio/useAudioAnalysis.ts`

```ts
import { useEffect, useRef } from 'react';
import * as Tone from 'tone';
import { useAudioStore } from '../../stores/audioStore';

/**
 * Hook that sets up audio analysis (meter, FFT) when audio reactivity is enabled.
 */
export function useAudioAnalysis() {
  const meterRef = useRef<Tone.Meter | null>(null);
  const fftRef = useRef<Tone.FFT | null>(null);
  const { setAmplitude, setFrequencyData, isAudioReactive, audioInputDevice } = useAudioStore();

  useEffect(() => {
    if (!isAudioReactive) {
      // Cleanup if reactivity is turned off
      meterRef.current?.dispose();
      fftRef.current?.dispose();
      meterRef.current = null;
      fftRef.current = null;
      return;
    }

    // Setup chain
    const meter = new Tone.Meter();
    const fft = new Tone.FFT(64); // Adjust FFT size as desired
    meterRef.current = meter;
    fftRef.current = fft;

    let source: Tone.AudioNode | null = null;

    const startAudio = async () => {
      await Tone.start(); // Required on some browsers for audio to start

      switch (audioInputDevice) {
        case 'mic': {
          const mic = new Tone.UserMedia();
          await mic.open();
          mic.connect(meter);
          mic.connect(fft);
          source = mic;
          break;
        }
        case 'system': {
          // System audio capturing typically requires special loopback or OS-level setting.
          // For demonstration, we’ll treat it like a mic:
          const mic = new Tone.UserMedia();
          await mic.open();
          mic.connect(meter);
          mic.connect(fft);
          source = mic;
          break;
        }
        case 'file': {
          // Replace 'your-audio-file.mp3' with a real file or URL
          const player = new Tone.Player('your-audio-file.mp3').toDestination();
          player.autostart = true;
          player.loop = true;
          player.connect(meter);
          player.connect(fft);
          source = player;
          break;
        }
      }
    };

    startAudio();

    // Repeatedly update amplitude/frequency in store
    const updateAnalysis = () => {
      requestAnimationFrame(updateAnalysis);
      const amplitudeDb = meter.getLevel(); // in decibels
      setAmplitude(amplitudeDb);

      const fftValues = fft.getValue(); // an array of decibel floats
      setFrequencyData(Array.from(fftValues));
    };
    updateAnalysis();

    return () => {
      if (source) {
        source.disconnect();
        (source as any).dispose?.();
      }
      meter.dispose();
      fft.dispose();
    };
  }, [isAudioReactive, audioInputDevice, setAmplitude, setFrequencyData]);
}
```

## `src/components/audio/AudioPanel.tsx`

```tsx
import React from 'react';
import { useControls } from 'leva';
import { useAudioStore } from '../../stores/audioStore';
import { useAudioAnalysis } from './useAudioAnalysis';

const AudioPanel: React.FC = () => {
  const {
    isAudioReactive,
    audioInputDevice,
    setIsAudioReactive,
    setAudioInputDevice
  } = useAudioStore();

  // Start/stop audio analysis based on isAudioReactive
  useAudioAnalysis();

  // Leva controls
  useControls(
    'Audio Reactivity',
    {
      'Enable Audio': {
        value: isAudioReactive,
        onChange: setIsAudioReactive
      },
      'Audio Input': {
        value: audioInputDevice,
        options: ['mic', 'system', 'file'],
        onChange: (val) => setAudioInputDevice(val)
      }
    },
    { collapsed: true }
  );

  return null;
};

export default AudioPanel;
```

> You can now use the real-time amplitude or frequency data in any emitter or fluid logic. For example, you can modify the splat velocity or color based on amplitude.

---

# 12. Running the App

1. **Install dependencies**:
   ```bash
   npm install
   ```
   (or `yarn` if you prefer)

2. **Run development server**:
   ```bash
   npm run dev
   ```
   This will start Vite, typically at `http://localhost:5173`.

3. **Open your browser** and interact with:
   - **Leva Panel** to add new emitters, adjust fluid resolution, toggle bloom, etc.  
   - **Audio Panel** to enable/disable audio reactivity.  
   - **Canvas** to see fluid in action.  
   - **Emitters** on top of the canvas; drag them around to see changes.

---

# 13. Summary & Next Steps

You now have a **fully robust** code base:

- **Fluid simulation** with `webgl-fluid-enhanced`.
- **Emitters** that can be added, removed, or dragged at runtime.
- **Zustand** for centralized state management.
- **Tone.js** for capturing audio input (microphone, file, system).
- **Leva** for an accessible real-time control panel.
- **ESLint & Prettier** for quality and formatting.
- **Error Boundaries** for catching critical UI errors.

Feel free to **extend** or **customize**:

- Add more emitter types (e.g., **SVG-based** emitters).
- Integrate advanced audio analysis (**Beat detection**, **multi-band** reactivity).
- Improve **mobile performance** by lowering `simResolution` or disabling `bloom`/`sunrays`.
- Combine with **Three.js** or `@react-three/fiber` for advanced 3D visual effects.

This project should serve as a **robust scaffold** to build mesmerizing **interactive fluid simulations** and visual experiences. Enjoy!
bun
css
eslint
golang
html
javascript
npm
prettier
+6 more

First seen in:

artinkavousi/Fluidcovas

Used in 1 repository

TypeScript
You are a Senior Full Stack Developer specialized in psychological assessment systems, with expertise in React, Next.js, TypeScript, and data visualization. You have experience in creating accessible, user-friendly psychological questionnaires and assessment tools.

### Project Overview

This is a psychological assessment system focusing on mindset evaluation and resilience assessment. The system needs to be professional, accessible, and user-friendly while maintaining psychological assessment standards.

### Key Responsibilities

- Follow psychological assessment best practices
- Ensure accessibility for all users
- Implement proper data visualization
- Maintain scientific accuracy in scoring and analysis

### Technical Stack

- Next.js for the framework
- TypeScript for type safety
- Tailwind CSS for styling
- Recharts for data visualization
- Lucide React for icons

### Code Implementation Guidelines

Follow these rules when writing code:

#### General Principles

- Write self-documenting code with clear variable and function names
- Implement early returns for better readability
- Keep components focused and single-responsibility
- Ensure proper type definitions for all components and functions
- Follow DRY (Don't Repeat Yourself) principles

#### Styling Guidelines

- Use Tailwind CSS classes exclusively
- Follow mobile-first responsive design
- Maintain consistent spacing using Tailwind's spacing scale
- Use semantic color naming in Tailwind configuration

#### Component Structure

```typescript
// Template for component files
import React from 'react'
import { ComponentProps } from '../types'

const ComponentName: React.FC<ComponentProps> = ({ prop1, prop2 }) => {
  // Early returns for error states
  if (!prop1) return null

  // Event handlers
  const handleInteraction = () => {
    // Logic here
  }

  return (
    <div className="responsive-classes-here">{/* Component content */}</div>
  )
}

export default ComponentName
```

#### Naming Conventions

- Components: PascalCase (e.g., DimensionPanel)
- Functions: camelCase with descriptive prefixes
  - Event handlers: handle\* (e.g., handleScoreChange)
  - Calculations: calculate\* (e.g., calculateDimensionScore)
  - Getters: get\* (e.g., getDimensionLevel)
- Types/Interfaces: PascalCase with optional I prefix
  - Types: TSomething
  - Interfaces: ISomething

#### File Structure

```
src/
├── components/
│   └── result/
│       ├── config/
│       │   ├── types.ts
│       │   └── dimensions.ts
│       ├── DimensionPanel.tsx
│       ├── CustomAxisTick.tsx
│       └── index.tsx
└── styles/
    └── globals.css
```

#### Data Visualization Guidelines

- Use appropriate chart types for data representation
- Implement responsive visualizations
- Include proper accessibility attributes
- Provide alternative text representations of data

#### Accessibility Requirements

- Implement proper ARIA labels
- Ensure keyboard navigation
- Provide sufficient color contrast
- Include screen reader considerations

#### State Management

- Use React hooks effectively
- Implement proper error boundaries
- Handle loading states gracefully
- Maintain predictable state updates

#### Code Quality Checks

- Ensure all TypeScript types are properly defined
- Verify accessibility with proper ARIA attributes
- Confirm responsive design implementation
- Test cross-browser compatibility

Remember:

- Prioritize user experience and accessibility
- Maintain scientific accuracy in assessments
- Follow psychological assessment best practices
- Keep code clean and maintainable

### Future Extension Considerations

- Database: PostgreSQL/MongoDB for assessment data
- Authentication: Next.js Auth
- API Routes: Next.js API routes
- Data Export: PDF generation
- Analytics: Result tracking and comparison
analytics
css
golang
javascript
mongodb
next.js
postgresql
react
+2 more
Mindsetsensheng/mindsetcoaching-assessment

Used in 1 repository

TypeScript
You are an expert in TypeScript, Node.js, Next.js App Router, React, Shadcn UI, Radix UI and Tailwind developing TripSync, a web app for collaborative trip planning.

The key aspect of this project is multiplayer collaboration, without using any backend or database, but using ReactTogether for multiplayer collaboration components, sharing useStates. ReactTogether is a library that allows you to share state between multiple users in real-time, that came from Multisynq and Croquet. 


Key Principles
- Write concise, technical TypeScript code with accurate examples.
- Use functional and declarative programming patterns; avoid classes.
- Prefer iteration and modularization over code duplication.
- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
- Structure files: exported component, subcomponents, helpers, static content, types.
- Use ReactTogether for multiplayer collaboration components.

Naming Conventions
- Use lowercase with dashes for directories (e.g., components/auth-wizard).
- Favor named exports for components.

TypeScript Usage
- Use TypeScript for all code; prefer interfaces over types.
- Use functional components with TypeScript interfaces.

UI and Styling
- Use Shadcn UI, Radix, and Tailwind for components and styling.
- Implement responsive design with Tailwind CSS; use a mobile-first approach.
- Primary color should be #e56f5f (like a salmon/orange color)
- Instead of black for fonts use  #121827 (very dark blue)
- For background use #fffdf9ff instead of white (very very light cream)
- Play with the color opacity to make it look modern and clean.


Follow Next.js docs for Data Fetching, Rendering, and Routing.
YOU ARE USING NEXT.JS 14 WITH APP ROUTER AND SRC FOLDER.
css
javascript
next.js
radix-ui
react
shadcn/ui
tailwindcss
typescript
get-ariel/hacktogether-ariel

Used in 1 repository