# Neexo AI Hub > Curated AI-assisted development resources by Neexo — https://awesome.neexo.dk > Give this file to any LLM to bootstrap a project with Neexo conventions. ## Agents ### Neexo Code Reviewer > A focused reviewer agent for Neexo projects that prioritizes bugs, security issues, tenant isolation, production risk, and missing validation over style feedback. > Source: https://github.com/NeexoCore/awesome-neexo > Tags: code-review, security, neexo ## Overview Use this agent when a change needs a high-signal review before merge. It should inspect only the diff or explicitly scoped files, then report issues that matter in production. ## Review Focus - Logic bugs and edge cases - Security and privacy risks - Tenant or organization isolation - Data loss and migration risk - Missing validation or tests - Deployment and runtime failures ## Cost Discipline For routine reviews, use scoped diffs or selected files. Avoid broad repository scans unless the task is explicitly a repository-wide audit. --- ### Neexo Consensus Review > A multi-perspective review pattern for high-risk changes where architecture, security, performance, and UX concerns need separate review passes. > Source: https://github.com/NeexoCore/awesome-neexo > Tags: code-review, architecture, high-risk ## Overview Use consensus review sparingly for high-risk changes such as auth, billing, database schema, tenant isolation, production deployment, or large cross-domain refactors. ## When to Use - Auth or billing logic changes - Database schema migrations affecting production data - Tenant isolation boundary changes - Large refactors spanning 5+ files across domains - Security-sensitive changes (CORS, CSP, secrets handling) ## Cost Warning Multi-perspective review can be expensive under AI Credit billing. Prefer a single reviewer for normal PRs. Use consensus review only when the risk justifies the cost. ## Review Perspectives Each pass focuses on one concern: | Pass | Focus | Key Questions | |------|-------|---------------| | **Architecture** | Structure, boundaries, coupling | Does this change respect module boundaries? Will it cause cascading changes? | | **Security** | Auth, secrets, injection, OWASP | Are role checks preserved? Is user input validated? | | **Performance** | Queries, caching, bundle size | Are there N+1 queries? Does this affect page load? | | **UX** | User flow, error states, accessibility | Does the happy path work? Are error states handled? | ## How to Invoke ```markdown Review this PR from four perspectives: architecture, security, performance, and UX. For each perspective, list findings with severity (critical/high/medium/low), the affected file, and a specific recommendation. Dismiss style-only findings. ``` ## Output Each reviewer should provide concrete findings with: - **Severity**: critical / high / medium / low - **Evidence**: specific code reference or line - **Affected file**: path to the file - **Recommendation**: specific fix, not vague advice Dismiss style-only or subjective findings that do not affect correctness, security, or performance. --- ### Neexo Studio Editor Agent > A specialized agent pattern for 3D configurator studio work, including editor flows, machine configuration, asset metadata, and viewer handoff. > Source: https://github.com/NeexoCore/awesome-neexo > Tags: configurator, 3d, studio ## Overview Use this agent pattern for studio-facing configurator work where UI state, 3D metadata, asset references, and publishing workflows meet. ## Guardrails - Read schemas and shared types before changing editor behavior - Prefer asset metadata over loading binary files - Keep studio write paths separate from published viewer read paths - Validate changes with focused type checks and browser smoke tests --- ### Neexo Worker Agent > A background-job agent pattern for queue processing, render jobs, asset pipelines, and other asynchronous workflows in Neexo projects. > Source: https://github.com/NeexoCore/awesome-neexo > Tags: worker, jobs, automation ## Overview Use this agent pattern for changes to background jobs, workers, queue handlers, render pipelines, or other asynchronous task processors. ## When to Use - Editing queue consumer/producer code - Adding or modifying scheduled jobs (cron, intervals) - Changing render pipeline steps or asset post-processing - Reviewing retry logic, dead-letter queues, or failure recovery ## Guardrails - **Idempotency** — verify that reprocessing the same job produces the same result without side effects - **Retry behavior** — check retry limits, exponential backoff, and dead-letter handling - **Failure paths** — ensure failed jobs log actionable context (job ID, attempt count, error) without leaking secrets or customer data - **Payload schemas** — keep job payloads versioned and narrow; avoid passing entire database rows - **Timeouts** — set explicit timeouts on job execution to prevent zombie workers ## Validation - Run the smallest available worker or queue test before broader integration tests - For render jobs, validate with a single lightweight asset before triggering full batch renders - Check that failed jobs appear in monitoring/alerting and are not silently dropped ## Example Agent Instruction ```markdown You are a worker-agent. Before modifying any job handler: 1. Read the job schema and check recent processing logs 2. Verify idempotency — would rerunning this job cause duplicate side effects? 3. Confirm retry/failure behavior is tested 4. Keep the change scoped — do not refactor unrelated worker code ``` --- ## Instructions ### Cost-Aware AI Instructions > Always-on guidance for keeping AI context small, avoiding expensive agent sessions, and classifying tasks before broad edits. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/* > Tags: cost, ai-credits, guardrails ## Overview These instructions are the baseline for AI-assisted work in Neexo repositories. They help agents keep context small, avoid broad scans, and treat high-risk changes as planning tasks before implementation. ## Core Rule Never combine an expensive model, large repository context, and a vague task. That pattern is the fastest route to unnecessary AI Credit usage. ## Task Classes - LOW: 1-3 files, clear local change - MEDIUM: 3-7 files or uncertain scope - HIGH: auth, security, billing, database schema, tenant isolation, deployment, AI/model usage, or broad architecture changes LOW tasks can be edited directly. MEDIUM tasks should start with a short plan. HIGH tasks should stop after analysis unless explicitly approved. ## Tooling Rule Prefer local CLI tools over MCP servers when a suitable CLI exists. CLIs are often cheaper for context because the agent can ask for `--help`, inspect only the relevant command, and receive compact output. Use MCP when the task needs interactive remote capabilities, richer API context, or cross-system access that the CLI does not provide. If an approved Neexo Windows AI toolbelt CLI is missing and the task benefits from it, install it with `winget`, verify it with `--version`, and continue. Ask before installing other tools or modifying PowerShell profile files. Example: prefer GitHub CLI (`gh`) for routine issue, PR, repo, and workflow queries. Use GitHub MCP when the work benefits from persistent API tooling or agent-managed GitHub operations. --- ### Clerk Authentication > Authentication patterns for Next.js apps using Clerk, including middleware setup, role-based access, organization scoping, and dev-mode fallbacks. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*.{ts,tsx}, **/proxy.ts, **/middleware.ts > Tags: auth, clerk, nextjs ## Overview Clerk provides authentication, user management, and organization-based RBAC for Next.js apps. In Neexo projects, Clerk handles sign-in, sign-up, organization switching, and role enforcement. ## Next.js 16 Middleware Next.js 16 uses `proxy.ts` (named `proxy` export) instead of `middleware.ts`: ```tsx // src/proxy.ts import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server"; const isPublicRoute = createRouteMatcher(["/", "/sign-in(.*)", "/sign-up(.*)", "/api/public(.*)"]); export const proxy = clerkMiddleware(async (auth, request) => { if (!isPublicRoute(request)) { await auth.protect(); } }); export const config = { matcher: ["/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)"], }; ``` ## Auth Context Helper ```tsx import { auth } from "@clerk/nextjs/server"; export async function getAuthContext() { const { userId, orgId, orgRole } = await auth(); if (!userId || !orgId) { throw new Error("Unauthorized"); } return { userId, orgId, orgRole }; } ``` ## Role-Based Access ```tsx const STUDIO_ROLES = new Set(["org:admin", "org:editor"]); export function hasStudioAccess(orgRole: string | undefined) { return orgRole ? STUDIO_ROLES.has(orgRole) : false; } // In an API route or server action: const { orgRole } = await getAuthContext(); if (!hasStudioAccess(orgRole)) { return new Response("Forbidden", { status: 403 }); } ``` ## Organization Scoping Every database query must filter by organization: ```tsx // ✅ Correct — always scope by orgId const items = await db.select().from(machines).where(eq(machines.orgId, orgId)); // ❌ Wrong — returns data across all organizations const items = await db.select().from(machines); ``` ## Dev Mode Fallback For local development without Clerk keys: ```tsx const DEV_USER_ID = "dev-user"; const DEV_ORG_ID = "dev-org"; const DEV_ORG_ROLE = "org:admin"; export async function getAuthContext() { if (process.env.NODE_ENV === "development" && !process.env.CLERK_SECRET_KEY) { return { userId: DEV_USER_ID, orgId: DEV_ORG_ID, orgRole: DEV_ORG_ROLE }; } // ... real auth } ``` ## Common Pitfalls - Do not call `auth()` in client components — it's server-only - Use `useUser()` and `useOrganization()` for client-side auth state - Wrap Clerk components (UserButton, OrganizationSwitcher) in safe client wrappers - Never expose `CLERK_SECRET_KEY` to the client — only `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` --- ### CLI-First Tooling Instructions > Guidance for preferring compact local CLI tools over MCP servers when they provide the same capability with less context and lower AI cost. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*.{ps1,sh,bash,zsh,fish,bat,cmd,json,yml,yaml,md} > Tags: cli, mcp, cost ## Overview Agents should prefer local CLI tools when they are available and suitable for the task. A CLI can usually explain itself through `--help`, expose focused subcommands, and return compact output. ## Rule Use a CLI first when: - the task is narrow and command-based - the CLI is already installed - `--help` or `help ` gives enough guidance - the output can be filtered or scoped Use MCP when: - the task needs richer remote API access - the agent benefits from structured tool calls - the task spans several resources or systems - the CLI is missing important capabilities ## Installation If an approved Neexo Windows AI toolbelt CLI is missing, install it with `winget`, verify it with `--version`, and continue. Ask before installing other tools or modifying PowerShell profile files. Example: use GitHub CLI (`gh`) for routine issue, PR, repository, and workflow operations. Use GitHub MCP when persistent GitHub API tooling or richer agent-managed operations are needed. --- ### Figma HMI Design Standards > Design-to-code standards for Figma-based HMI (Human-Machine Interface) projects — Figma plugin architecture, monorepo conventions, OPC-UA integration, and runtime rendering patterns. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*.ts, **/*.tsx > Tags: figma, hmi, monorepo, typescript ## Monorepo Structure HMI compiler projects use a pnpm monorepo with `@figma-hmi/*` aliases: | Package | Purpose | |---|---| | `schema` | Domain types + Zod validation (base dependency) | | `design` | Design document structure + CSS rendering | | `protocol` | WebSocket message schemas | | `runtime-core` | Pure business logic — no React | | `runtime-web` | React UI + connectors (mock, WebSocket) | | `compiler` | CLI to package into deployable artifact | | `figma-plugin` | Figma plugin UI | | `opcua-gateway` | OPC-UA server bridge | Cross-package imports use `@figma-hmi/*` aliases. Internal deps use `workspace:*` protocol. ## TypeScript Rules - Target ES2022, strict mode, ESM (`"type": "module"`) - Explicit `type` imports: `import type { Foo } from '...'` - `node:` prefix for Node.js built-ins: `import { resolve } from 'node:path'` - Define explicit return types on functions - Discriminated unions + Zod schemas for domain types; infer via `z.infer` ## React (Runtime Web) - React 19, functional components only - Wrap presentational components in `memo()` with callback props - State: local `useState` only — no global state manager - Async effects with cancellation: `let cancelled = false` + cleanup return - Inline styles via `CSSProperties` — no Tailwind, no CSS modules - Props: explicit interface (`interface FooProps { ... }`) ## Figma Plugin Architecture The Figma plugin bridges the design tool with the HMI compiler: 1. **Read**: Extract component hierarchy, styles, variables, and interactive states from Figma 2. **Transform**: Convert to the `@figma-hmi/schema` format (Zod-validated) 3. **Bundle**: `_generated-project-bundle.ts` is auto-generated from the Figma design 4. **Deploy**: Compiler packages into Docker container with OPC-UA gateway Rebuild runtime-web before regenerating the bundle: ```bash corepack pnpm build node apps/figma-plugin/scripts/build.mjs ``` ## OPC-UA Integration - The `opcua-gateway` bridges HMI runtime to industrial OPC-UA servers - WebSocket protocol defined in `@figma-hmi/protocol` with Zod schemas - All message types are discriminated unions for type safety - Gateway runs as Docker container alongside the compiled HMI frontend ## Testing - Vitest with `describe`/`it` syntax - Test files in `test/` folder per package, named `*.test.ts` - React tests: `createRoot` + `act()`, DOM queries via `querySelector` - Run per-package: `corepack pnpm --filter test` ## Code Style - PascalCase: components, types, schemas - camelCase: functions, variables, properties - `as const` arrays for enum-like values - Section headers: `// ─── Section Name ───────────────` - Pure functions, immutable patterns — return new objects, don't mutate --- ### Neexo Blender Python Instructions > Guidance for Blender Python scripts, add-ons, subprocess rendering, generated assets, and 3D pipeline automation. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*.py > Tags: blender, python, 3d ## Overview Use these instructions for Blender add-ons, render-studio automation, and configurator asset pipelines. ## API and Scripting Rules - Use `bpy.data`, `bpy.context`, and `bpy.ops` through the stable API — avoid internal/undocumented modules - Register operators and panels with proper `bl_idname`, `bl_label`, and `bl_options` - Always provide `poll()` methods on operators to prevent invalid context execution - Use `bpy.app.handlers` for persistent callbacks; clean up handlers on add-on unregister ## Asset Pipeline Rules - Treat large GLB, EXR, HDR, and render files as assets, not chat context — summarize metadata instead - Prefer metadata summaries and small config files before reading generated output - Use relative paths in `.blend` files for portability across machines ## Subprocess and Rendering - Keep subprocess execution deterministic and logged without exposing secrets - Use `--background` and `--python` flags for headless Blender rendering: ```bash blender --background scene.blend --python render_script.py -- --output /tmp/render ``` - Parse arguments after `--` using `sys.argv[sys.argv.index("--") + 1:]` - Validate with focused scripts or tests before broad render runs ## Common Pitfalls - Do not call `bpy.ops` outside the correct context — use context overrides or `temp_override()` - Do not block the UI thread with long operations — use modal operators or background threads for heavy work - Always check `bpy.app.version` when targeting multiple Blender versions --- ### Neexo Drizzle Database Instructions > Database and migration guidance for Drizzle ORM, Drizzle Kit, Neon, tenant-scoped queries, atomic schema changes, and production-safe data access. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*{schema,migration,db,sql,drizzle,neon}* > Tags: database, drizzle, neon ## Overview Database work is high-risk in Neexo projects because schema changes often combine tenant scoping, production data, and generated migrations. ## Schema and Migration Rules - Inspect the relevant schema, migration, query, or action before changing database logic - Keep schema changes, generated SQL, and dependent code in the **same commit** — never split across commits - Avoid destructive migrations by default — prefer additive changes (new columns, new tables) - Use `drizzle-kit generate` to create migration SQL after schema edits - Use `drizzle-kit push` for local development against throwaway databases - Use `drizzle-kit migrate` for production deployments with migration tracking ## Drizzle Kit Workflow ```bash # 1. Edit schema file (e.g. src/db/schema.ts) # 2. Push to local dev database npx drizzle-kit push # 3. Generate migration SQL for production npx drizzle-kit generate # 4. Commit schema + migration + code together git add -A && git commit -m "feat(db): add user preferences table" ``` ## Query Patterns - Preserve organization, customer, and tenant filters on every query — never return unscoped data - Use Drizzle's type-safe query builder; avoid raw SQL unless performance requires it - Use `drizzle-kit studio` to inspect data during development — never query production directly - Prefer soft delete (`deletedAt` timestamp) for financial, audit, and compliance data ## Common Pitfalls - Do not run `drizzle-kit push` against production — it applies changes without migration tracking - Do not rename columns in production without a two-step migration (add new → migrate data → drop old) - Do not use `drizzle-kit drop` without explicit team approval --- ### Neexo Next.js Conventions > Shared App Router, React 19, TypeScript, UI, and validation conventions for Neexo's Next.js 16 projects. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*.{ts,tsx}, **/app/**/*.tsx > Tags: nextjs, react, typescript ## Overview Neexo projects default to Next.js 16 App Router patterns, server components, narrow TypeScript boundaries, and existing local UI conventions. ## Server vs Client Components - Prefer server components unless hooks, browser APIs, or event handlers require client components - Keep server/client boundaries explicit — mark client components with `"use client"` at the top - Use server actions for mutations; do not create API routes for simple form submissions ## Next.js 16 Specifics - `params` and `searchParams` are now async in route components — always `await` them: ```tsx export default async function Page({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params } ``` - `cookies()` and `headers()` from `next/headers` are async — `await` before reading - Turbopack is the default bundler in development — do not add Webpack-specific config unless required for production - Use the `use` hook from React 19 to unwrap promises in client components - Use `"use cache"` for fine-grained caching instead of relying solely on route segment config ## TypeScript and Code Style - Avoid `any` unless justified at an integration boundary - Reuse existing components, hooks, utilities, and design tokens - Add dependencies only when the existing stack cannot reasonably solve the problem - Prefer `satisfies` for type narrowing of config objects ## Patterns to Avoid - Do not use `getServerSideProps` or `getStaticProps` — these are Pages Router patterns - Do not wrap server components in unnecessary client wrappers - Do not use `useEffect` for data fetching — fetch in server components or use server actions --- ### Neexo Playwright Testing Instructions > Focused E2E testing guidance for Playwright specs, browser smoke tests, selectors, screenshots, and validation commands. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*{test,spec,e2e,playwright}*.{ts,tsx,js,jsx} > Tags: testing, playwright, e2e ## Overview Use these instructions when adding or reviewing browser tests. Prefer focused tests over full-suite runs for local logic. ## Locator Strategy Use stable, user-visible locators in priority order: 1. `getByRole('button', { name: 'Submit' })` — best for accessibility 2. `getByText('Welcome')` — for visible text content 3. `getByTestId('checkout-form')` — when role/text is ambiguous 4. `locator('[data-testid="..."]')` — fallback for complex selectors Avoid fragile selectors: `nth-child`, deep CSS paths, auto-generated class names. ## Test Structure - One assertion per logical check — avoid mega-tests that assert 10 things - Use `test.describe` to group related scenarios - Use `test.beforeEach` for shared navigation, not repeated `goto()` calls - Name tests by user behavior: `"user can add item to cart"`, not `"test button click"` ## Reliability Rules - Never use `page.waitForTimeout()` — use `expect(locator).toBeVisible()` or `waitForResponse()` - Check console errors for UI changes: `page.on('console', ...)` - Use `expect(page).toHaveURL()` instead of checking raw URL strings - Run the smallest relevant test first — `npx playwright test path/to/file.spec.ts` ## Screenshots and Visual Testing - Use `await expect(page).toHaveScreenshot()` for visual regression - Avoid `whileInView` animations and lazy-loaded images in screenshot tests — they produce flaky baselines - Use `page.setViewportSize()` for consistent screenshot dimensions ## Patterns to Avoid - Timing-based waits (`setTimeout`, `waitForTimeout`) - Selectors coupled to CSS framework class names (`.css-1a2b3c`) - Tests that depend on external API state without mocking - Full test suite runs for single-file logic changes --- ### Neexo Security and OWASP Instructions > Security review guidance covering OWASP Top 10 risks, auth boundaries, secrets handling, tenant isolation, and production-safe configuration. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*.{ts,tsx,js,jsx,json,yml,yaml,env,md} > Tags: security, owasp, privacy ## Overview Use these instructions when editing code or configuration that can affect authentication, authorization, tenant boundaries, storage permissions, secrets, billing, or production deployment. ## OWASP Top 10 Awareness Watch for these categories in every code change: 1. **Broken Access Control** — verify role checks and tenant scoping on every endpoint and server action 2. **Cryptographic Failures** — never hardcode secrets, use environment variables and proper key management 3. **Injection** — parameterize all database queries; never interpolate user input into SQL, shell commands, or templates 4. **Insecure Design** — validate business logic constraints server-side, not only in the UI 5. **Security Misconfiguration** — review CORS, CSP, exposed headers, verbose error messages, and default credentials 6. **Vulnerable Components** — audit dependencies regularly; keep frameworks and libraries updated 7. **Authentication Failures** — enforce strong session management, rate limiting, and MFA where available 8. **Data Integrity Failures** — verify signatures, checksums, and pipeline integrity for CI/CD and software updates 9. **Logging and Monitoring Gaps** — log security events but never log secrets, tokens, or PII 10. **Server-Side Request Forgery (SSRF)** — validate and restrict outbound URLs; do not allow user input to control fetch targets ## Required Checks - Do not expose secrets, tokens, keys, signed URLs, or private customer data - Preserve role checks and organization/customer scoping on every mutation - Keep server-side validation in place — never rely solely on client-side checks - Avoid logging sensitive values (tokens, passwords, PII) - Call out any weakening of security controls explicitly in PR descriptions ## Patterns to Reject - `dangerouslySetInnerHTML` with unsanitized user input - String concatenation in SQL queries instead of parameterized statements - Disabled CSRF protection without documented justification - Broad CORS origins (`*`) in production - Secrets committed to version control, even in "test" files --- ### next-intl Internationalization > Conventions for multi-language Next.js apps using next-intl, including translation patterns, locale detection, and common pitfalls. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*.{ts,tsx}, **/messages/** > Tags: i18n, nextjs, next-intl ## Overview next-intl provides type-safe internationalization for Next.js App Router apps. Neexo projects typically use Danish as the primary language with English and optionally German as secondaries. ## Setup Translation files live in `messages/` as JSON: ``` messages/ da.json # Danish (primary source) en.json # English de.json # German (optional) ``` ## Translation Pattern ```tsx "use client"; import { useTranslations } from "next-intl"; export default function HeroSection() { const t = useTranslations("hero"); return (

{t("title")}

{t("description")}

); } ``` ## Rules - **Danish is the source language** — always write Danish text first, then translate to other languages - Use `useTranslations()` hook in client components — never inline text strings - Namespace translations by feature/page: `hero.title`, `contact.submit`, `nav.home` - Keep translation keys in kebab-case or camelCase — be consistent within the project ## Message File Structure ```json { "nav": { "home": "Forside", "about": "Om os", "contact": "Kontakt" }, "hero": { "title": "Industriel 3D-visualisering", "description": "Vi omdanner tekniske CAD-data til visuelle oplevelser" } } ``` ## Language Switching For apps without locale in the URL (single-domain approach): ```tsx "use client"; import { useLocale } from "next-intl"; function LanguageSwitcher() { const locale = useLocale(); // Switch by updating cookie or context } ``` ## Danish Text Rules - Use proper Danish characters: æ, ø, å — never ae, oe, aa - Do not use em-dashes (—) in translations — rephrase with commas or "herunder" - Avoid AI/corporate buzzwords: "transformér", "unik", "robust", "gnidningsfrit" - Write naturally as a Dane would speak ## Common Pitfalls - Do not use `useTranslations()` in Server Components — use `getTranslations()` instead - Keep `defaultLocale` set to `"da"` in the i18n config - Ensure all three language files have the same keys — missing keys cause runtime fallback warnings - Do not create inline translation objects — always use the message files --- ### React Three Fiber 3D > Conventions for React Three Fiber (R3F) components including dynamic imports, SSR avoidance, camera patterns, and postprocessing in Next.js apps. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*{canvas,scene,viewer,3d,three,r3f}*.{ts,tsx} > Tags: react-three-fiber, threejs, 3d, nextjs ## Overview React Three Fiber (R3F) renders Three.js scenes as React components. In Next.js, all 3D code must be client-only to avoid SSR hydration errors. ## Critical: No SSR for 3D Three.js requires browser APIs (WebGL, canvas). Always use dynamic import with `ssr: false`: ```tsx // In a Server Component or page import dynamic from "next/dynamic"; const Scene3D = dynamic(() => import("./Scene3D"), { ssr: false }); export default function Page() { return ; } ``` The Scene3D component itself must have `"use client"` at the top. ## Canvas Setup Pattern ```tsx "use client"; import { Canvas } from "@react-three/fiber"; import { Environment, OrbitControls } from "@react-three/drei"; export default function Scene3D() { return ( {/* Your 3D content */} ); } ``` ## GLB Model Loading ```tsx import { useGLTF } from "@react-three/drei"; function MachineModel({ url }: { url: string }) { const { scene } = useGLTF(url); return ; } // Preload for instant display useGLTF.preload("/models/machine.glb"); ``` ## Module Visibility Toggle For configurators where modules can be toggled on/off: ```tsx import { useEffect, useRef } from "react"; import { useGLTF } from "@react-three/drei"; import * as THREE from "three"; function ConfigurableModel({ url, visibleModules }: { url: string; visibleModules: Set }) { const { scene } = useGLTF(url); useEffect(() => { scene.traverse((node: THREE.Object3D) => { if (node.name && visibleModules !== undefined) { node.visible = visibleModules.has(node.name); } }); }, [scene, visibleModules]); return ; } ``` ## Postprocessing ```tsx import { EffectComposer, N8AO, Bloom, ToneMapping } from "@react-three/postprocessing"; ``` ## Common Pitfalls - **Never** import Three.js at the top level of a Server Component — use dynamic imports - **Never** use `useEffect` for animations — use R3F's `useFrame` hook instead - Avoid creating new `THREE.Vector3()` or `THREE.Color()` inside render — allocate once and reuse - Use `` around heavy models for loading states - Set `reactStrictMode: false` in `next.config.ts` — R3F is not compatible with strict mode double-rendering - For WebGPU detection, check `navigator.gpu` before attempting WebGPU renderer --- ### shadcn/ui v4 (Base UI) > Instructions for shadcn/ui v4 which uses Base UI primitives — use the render prop for composition, not Radix asChild. > Source: https://github.com/NeexoCore/awesome-neexo > Apply to: **/*.{ts,tsx}, **/components/** > Tags: shadcn, ui, base-ui, react ## Overview shadcn/ui v4 switched from Radix UI to Base UI (`@base-ui/react`) under the hood. The most important change is how composition works. ## Critical: render Prop, Not asChild ```tsx // ✅ Correct — shadcn/ui v4 (Base UI) // ❌ Wrong — this is Radix UI / shadcn v3 syntax ``` This is the most common mistake when moving to shadcn/ui v4. `asChild` does not exist in Base UI components. ## Component Installation ```bash npx shadcn@latest add button dialog select ``` Components are installed to `components/ui/`. Do not barrel-export them — import directly: ```tsx import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"; ``` ## Styling Conventions - Use `cn()` from `@/lib/utils` for conditional classes: ```tsx import { cn } from "@/lib/utils";
``` - Use Tailwind utility classes — do not create custom CSS for component styling - Respect existing design tokens in `globals.css` - Generated `components/ui/` files are exempt from file-size limits ## Patterns ### Dialog with Form ```tsx }>Open
{/* form fields */}
``` ### Select with Controlled Value ```tsx ``` ## Do Not - Use `asChild` — it does not exist in Base UI - Create new button styles — use `variant` prop on `