@ngxtm/devkit 3.4.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/rules/README.md +141 -0
- package/rules/dart/best-practices/SKILL.md +23 -0
- package/rules/dart/language/SKILL.md +52 -0
- package/rules/dart/tooling/SKILL.md +43 -0
- package/rules/dotnet/aspnet-core/SKILL.md +92 -0
- package/rules/dotnet/aspnet-core/references/REFERENCE.md +335 -0
- package/rules/dotnet/best-practices/SKILL.md +101 -0
- package/rules/dotnet/best-practices/references/REFERENCE.md +256 -0
- package/rules/dotnet/blazor/SKILL.md +146 -0
- package/rules/dotnet/blazor/references/REFERENCE.md +392 -0
- package/rules/dotnet/language/SKILL.md +82 -0
- package/rules/dotnet/language/references/REFERENCE.md +222 -0
- package/rules/dotnet/patterns.rule.md +388 -0
- package/rules/dotnet/razor-pages/SKILL.md +124 -0
- package/rules/dotnet/razor-pages/references/REFERENCE.md +321 -0
- package/rules/dotnet/security/SKILL.md +89 -0
- package/rules/dotnet/security/references/REFERENCE.md +295 -0
- package/rules/dotnet/tooling/SKILL.md +92 -0
- package/rules/dotnet/tooling/references/REFERENCE.md +300 -0
- package/rules/flutter/auto-route-navigation/SKILL.md +43 -0
- package/rules/flutter/auto-route-navigation/references/REFERENCE.md +19 -0
- package/rules/flutter/auto-route-navigation/references/router-config.md +62 -0
- package/rules/flutter/bloc-state-management/SKILL.md +64 -0
- package/rules/flutter/bloc-state-management/references/REFERENCE.md +20 -0
- package/rules/flutter/bloc-state-management/references/auth-bloc-example.md +52 -0
- package/rules/flutter/bloc-state-management/references/equatable-usage.md +56 -0
- package/rules/flutter/bloc-state-management/references/property-based-state.md +68 -0
- package/rules/flutter/bloc.rule.md +76 -0
- package/rules/flutter/cicd/SKILL.md +48 -0
- package/rules/flutter/cicd/references/advanced-workflow.md +66 -0
- package/rules/flutter/cicd/references/fastlane.md +139 -0
- package/rules/flutter/cicd/references/github-actions.md +59 -0
- package/rules/flutter/dependency-injection/SKILL.md +42 -0
- package/rules/flutter/dependency-injection/references/REFERENCE.md +15 -0
- package/rules/flutter/dependency-injection/references/modules.md +37 -0
- package/rules/flutter/error-handling/SKILL.md +32 -0
- package/rules/flutter/error-handling/references/REFERENCE.md +19 -0
- package/rules/flutter/error-handling/references/error-mapping.md +31 -0
- package/rules/flutter/feature-based-clean-architecture/SKILL.md +46 -0
- package/rules/flutter/feature-based-clean-architecture/references/REFERENCE.md +14 -0
- package/rules/flutter/feature-based-clean-architecture/references/folder-structure.md +36 -0
- package/rules/flutter/getx-navigation/SKILL.md +70 -0
- package/rules/flutter/getx-navigation/references/app-pages.md +40 -0
- package/rules/flutter/getx-navigation/references/middleware-example.md +29 -0
- package/rules/flutter/getx-state-management/SKILL.md +76 -0
- package/rules/flutter/getx-state-management/references/binding-example.md +32 -0
- package/rules/flutter/getx-state-management/references/reactive-vs-simple.md +39 -0
- package/rules/flutter/go-router-navigation/SKILL.md +57 -0
- package/rules/flutter/idiomatic-flutter/SKILL.md +20 -0
- package/rules/flutter/layer-based-clean-architecture/SKILL.md +50 -0
- package/rules/flutter/layer-based-clean-architecture/references/REFERENCE.md +60 -0
- package/rules/flutter/layer-based-clean-architecture/references/repository-mapping.md +50 -0
- package/rules/flutter/localization/SKILL.md +50 -0
- package/rules/flutter/localization/references/REFERENCE.md +48 -0
- package/rules/flutter/localization/references/sheet-loader.md +33 -0
- package/rules/flutter/navigator-v1-navigation/SKILL.md +71 -0
- package/rules/flutter/navigator-v1-navigation/references/on-generate-route.md +48 -0
- package/rules/flutter/performance/SKILL.md +24 -0
- package/rules/flutter/retrofit-networking/SKILL.md +51 -0
- package/rules/flutter/retrofit-networking/references/REFERENCE.md +19 -0
- package/rules/flutter/retrofit-networking/references/token-refresh.md +40 -0
- package/rules/flutter/riverpod-state-management/SKILL.md +53 -0
- package/rules/flutter/riverpod-state-management/references/architecture.md +124 -0
- package/rules/flutter/riverpod-state-management/references/best-practices.md +89 -0
- package/rules/flutter/riverpod-state-management/references/testing.md +73 -0
- package/rules/flutter/riverpod.rule.md +78 -0
- package/rules/flutter/security/SKILL.md +33 -0
- package/rules/flutter/security/references/REFERENCE.md +15 -0
- package/rules/flutter/security/references/network-security.md +28 -0
- package/rules/flutter/testing/SKILL.md +44 -0
- package/rules/flutter/testing/references/REFERENCE.md +21 -0
- package/rules/flutter/testing/references/bloc-testing.md +38 -0
- package/rules/flutter/testing/references/integration-testing.md +128 -0
- package/rules/flutter/testing/references/robot-pattern.md +82 -0
- package/rules/flutter/testing/references/unit-testing.md +130 -0
- package/rules/flutter/testing/references/widget-testing.md +120 -0
- package/rules/flutter/widgets/SKILL.md +37 -0
- package/rules/golang/chi-router/SKILL.md +219 -0
- package/rules/golang/chi-router/references/REFERENCE.md +13 -0
- package/rules/golang/chi-router/references/routing-patterns.md +205 -0
- package/rules/golang/cobra-cli/SKILL.md +227 -0
- package/rules/golang/cobra-cli/references/REFERENCE.md +13 -0
- package/rules/golang/cobra-cli/references/command-patterns.md +224 -0
- package/rules/golang/core/SKILL.md +210 -0
- package/rules/golang/core/references/REFERENCE.md +14 -0
- package/rules/golang/core/references/concurrency-patterns.md +114 -0
- package/rules/golang/core/references/error-handling.md +87 -0
- package/rules/golang/echo-framework/SKILL.md +215 -0
- package/rules/golang/echo-framework/references/REFERENCE.md +14 -0
- package/rules/golang/echo-framework/references/middleware-patterns.md +141 -0
- package/rules/golang/echo-framework/references/routing-patterns.md +140 -0
- package/rules/golang/ent-orm/SKILL.md +239 -0
- package/rules/golang/ent-orm/references/REFERENCE.md +13 -0
- package/rules/golang/ent-orm/references/schema-patterns.md +255 -0
- package/rules/golang/fiber-framework/SKILL.md +196 -0
- package/rules/golang/fiber-framework/references/REFERENCE.md +13 -0
- package/rules/golang/fiber-framework/references/routing-patterns.md +191 -0
- package/rules/golang/gin-framework/SKILL.md +205 -0
- package/rules/golang/gin-framework/references/REFERENCE.md +14 -0
- package/rules/golang/gin-framework/references/middleware-patterns.md +119 -0
- package/rules/golang/gorm-orm/SKILL.md +196 -0
- package/rules/golang/gorm-orm/references/REFERENCE.md +14 -0
- package/rules/golang/gorm-orm/references/model-definitions.md +167 -0
- package/rules/golang/gorm-orm/references/query-patterns.md +161 -0
- package/rules/golang/grpc/SKILL.md +231 -0
- package/rules/golang/grpc/references/REFERENCE.md +13 -0
- package/rules/golang/grpc/references/service-patterns.md +276 -0
- package/rules/golang/testify/SKILL.md +239 -0
- package/rules/golang/testify/references/REFERENCE.md +13 -0
- package/rules/golang/testify/references/assert-patterns.md +170 -0
- package/rules/golang/validator/SKILL.md +234 -0
- package/rules/golang/validator/references/REFERENCE.md +13 -0
- package/rules/golang/validator/references/validation-tags.md +211 -0
- package/rules/golang/viper-config/SKILL.md +244 -0
- package/rules/golang/viper-config/references/REFERENCE.md +13 -0
- package/rules/golang/viper-config/references/config-loading.md +181 -0
- package/rules/golang/wire-di/SKILL.md +243 -0
- package/rules/golang/wire-di/references/REFERENCE.md +13 -0
- package/rules/golang/wire-di/references/provider-patterns.md +193 -0
- package/rules/golang/zap-logging/SKILL.md +203 -0
- package/rules/golang/zap-logging/references/REFERENCE.md +13 -0
- package/rules/golang/zap-logging/references/logger-config.md +165 -0
- package/rules/java/build-gradle/SKILL.md +92 -0
- package/rules/java/build-gradle/references/REFERENCE.md +14 -0
- package/rules/java/build-gradle/references/kotlin-dsl.md +118 -0
- package/rules/java/build-gradle/references/task-configuration.md +132 -0
- package/rules/java/build-maven/SKILL.md +86 -0
- package/rules/java/build-maven/references/REFERENCE.md +14 -0
- package/rules/java/build-maven/references/dependency-management.md +111 -0
- package/rules/java/build-maven/references/lifecycle-phases.md +114 -0
- package/rules/java/graalvm-native/SKILL.md +105 -0
- package/rules/java/graalvm-native/references/REFERENCE.md +12 -0
- package/rules/java/java-collections-streams/SKILL.md +148 -0
- package/rules/java/java-collections-streams/references/REFERENCE.md +15 -0
- package/rules/java/java-collections-streams/references/collectors-patterns.md +178 -0
- package/rules/java/java-collections-streams/references/stream-pipelines.md +165 -0
- package/rules/java/java-concurrency/SKILL.md +187 -0
- package/rules/java/java-concurrency/references/REFERENCE.md +17 -0
- package/rules/java/java-concurrency/references/completable-future.md +165 -0
- package/rules/java/java-concurrency/references/executor-patterns.md +176 -0
- package/rules/java/java-concurrency/references/virtual-threads.md +190 -0
- package/rules/java/java-core-language/SKILL.md +121 -0
- package/rules/java/java-core-language/references/REFERENCE.md +15 -0
- package/rules/java/java-core-language/references/jvm-memory-model.md +160 -0
- package/rules/java/java-core-language/references/modern-java-features.md +168 -0
- package/rules/java/java-project-structure/SKILL.md +195 -0
- package/rules/java/java-project-structure/references/REFERENCE.md +15 -0
- package/rules/java/java-project-structure/references/maven-project-layout.md +199 -0
- package/rules/java/java-project-structure/references/module-system.md +159 -0
- package/rules/java/micronaut-core/SKILL.md +99 -0
- package/rules/java/micronaut-core/references/REFERENCE.md +12 -0
- package/rules/java/micronaut-reactive/SKILL.md +68 -0
- package/rules/java/micronaut-reactive/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-core/SKILL.md +85 -0
- package/rules/java/quarkus-core/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-reactive/SKILL.md +67 -0
- package/rules/java/quarkus-reactive/references/REFERENCE.md +12 -0
- package/rules/java/spring-batch/SKILL.md +102 -0
- package/rules/java/spring-batch/references/REFERENCE.md +12 -0
- package/rules/java/spring-boot-architecture/SKILL.md +206 -0
- package/rules/java/spring-boot-architecture/references/REFERENCE.md +15 -0
- package/rules/java/spring-boot-architecture/references/auto-configuration.md +158 -0
- package/rules/java/spring-boot-architecture/references/configuration-properties.md +202 -0
- package/rules/java/spring-boot-web/SKILL.md +217 -0
- package/rules/java/spring-boot-web/references/REFERENCE.md +17 -0
- package/rules/java/spring-cloud/SKILL.md +109 -0
- package/rules/java/spring-cloud/references/REFERENCE.md +13 -0
- package/rules/java/spring-data-jpa/SKILL.md +241 -0
- package/rules/java/spring-data-jpa/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/SKILL.md +161 -0
- package/rules/java/spring-security/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/references/jwt-auth-flow.md +213 -0
- package/rules/java/testing-junit-mockito/SKILL.md +135 -0
- package/rules/java/testing-junit-mockito/references/REFERENCE.md +15 -0
- package/rules/java/testing-junit-mockito/references/junit5-patterns.md +159 -0
- package/rules/java/testing-junit-mockito/references/mockito-patterns.md +148 -0
- package/rules/java/testing-junit-mockito/references/spring-boot-testing.md +152 -0
- package/rules/javascript/best-practices/SKILL.md +64 -0
- package/rules/javascript/best-practices/references/REFERENCE.md +91 -0
- package/rules/javascript/language/SKILL.md +71 -0
- package/rules/javascript/language/references/REFERENCE.md +106 -0
- package/rules/javascript/tooling/SKILL.md +60 -0
- package/rules/javascript/tooling/references/REFERENCE.md +107 -0
- package/rules/metadata.json +54 -0
- package/rules/nestjs/api-standards/SKILL.md +47 -0
- package/rules/nestjs/api-standards/references/pagination-wrapper.md +87 -0
- package/rules/nestjs/architecture/SKILL.md +68 -0
- package/rules/nestjs/architecture/references/dynamic-module.md +53 -0
- package/rules/nestjs/caching/SKILL.md +51 -0
- package/rules/nestjs/caching/references/REFERENCE.md +13 -0
- package/rules/nestjs/caching/references/cache-patterns.md +183 -0
- package/rules/nestjs/configuration/SKILL.md +41 -0
- package/rules/nestjs/configuration/references/REFERENCE.md +13 -0
- package/rules/nestjs/configuration/references/config-patterns.md +184 -0
- package/rules/nestjs/controllers-services/SKILL.md +63 -0
- package/rules/nestjs/controllers-services/references/REFERENCE.md +14 -0
- package/rules/nestjs/controllers-services/references/controller-patterns.md +119 -0
- package/rules/nestjs/controllers-services/references/service-patterns.md +129 -0
- package/rules/nestjs/database/SKILL.md +102 -0
- package/rules/nestjs/database/references/REFERENCE.md +14 -0
- package/rules/nestjs/database/references/typeorm-patterns.md +156 -0
- package/rules/nestjs/deployment/SKILL.md +36 -0
- package/rules/nestjs/deployment/references/REFERENCE.md +13 -0
- package/rules/nestjs/deployment/references/deployment-patterns.md +140 -0
- package/rules/nestjs/documentation/SKILL.md +64 -0
- package/rules/nestjs/documentation/references/REFERENCE.md +13 -0
- package/rules/nestjs/documentation/references/swagger-patterns.md +139 -0
- package/rules/nestjs/error-handling/SKILL.md +55 -0
- package/rules/nestjs/error-handling/references/REFERENCE.md +13 -0
- package/rules/nestjs/error-handling/references/exception-filters.md +152 -0
- package/rules/nestjs/file-uploads/SKILL.md +35 -0
- package/rules/nestjs/file-uploads/references/REFERENCE.md +13 -0
- package/rules/nestjs/file-uploads/references/upload-patterns.md +125 -0
- package/rules/nestjs/observability/SKILL.md +39 -0
- package/rules/nestjs/observability/references/REFERENCE.md +13 -0
- package/rules/nestjs/observability/references/logging-metrics.md +175 -0
- package/rules/nestjs/performance/SKILL.md +60 -0
- package/rules/nestjs/performance/references/REFERENCE.md +13 -0
- package/rules/nestjs/performance/references/performance-patterns.md +107 -0
- package/rules/nestjs/real-time/SKILL.md +45 -0
- package/rules/nestjs/real-time/references/REFERENCE.md +13 -0
- package/rules/nestjs/real-time/references/websocket-patterns.md +121 -0
- package/rules/nestjs/scheduling/SKILL.md +39 -0
- package/rules/nestjs/scheduling/references/REFERENCE.md +13 -0
- package/rules/nestjs/scheduling/references/scheduling-patterns.md +137 -0
- package/rules/nestjs/search/SKILL.md +41 -0
- package/rules/nestjs/search/references/REFERENCE.md +13 -0
- package/rules/nestjs/search/references/search-patterns.md +137 -0
- package/rules/nestjs/security/SKILL.md +87 -0
- package/rules/nestjs/security/references/REFERENCE.md +14 -0
- package/rules/nestjs/security/references/authentication.md +151 -0
- package/rules/nestjs/testing/SKILL.md +40 -0
- package/rules/nestjs/testing/references/REFERENCE.md +14 -0
- package/rules/nestjs/testing/references/unit-testing.md +179 -0
- package/rules/nestjs/transport/SKILL.md +45 -0
- package/rules/nestjs/transport/references/REFERENCE.md +13 -0
- package/rules/nestjs/transport/references/microservices-patterns.md +170 -0
- package/rules/nextjs/app-router/SKILL.md +46 -0
- package/rules/nextjs/app-router/references/REFERENCE.md +14 -0
- package/rules/nextjs/app-router/references/routing-patterns.md +182 -0
- package/rules/nextjs/architecture/SKILL.md +44 -0
- package/rules/nextjs/architecture/references/fsd-structure.md +77 -0
- package/rules/nextjs/authentication/SKILL.md +29 -0
- package/rules/nextjs/authentication/references/auth-implementation.md +73 -0
- package/rules/nextjs/caching/SKILL.md +66 -0
- package/rules/nextjs/caching/references/REFERENCE.md +13 -0
- package/rules/nextjs/caching/references/cache-strategies.md +168 -0
- package/rules/nextjs/data-access-layer/SKILL.md +33 -0
- package/rules/nextjs/data-access-layer/references/patterns.md +66 -0
- package/rules/nextjs/data-fetching/SKILL.md +59 -0
- package/rules/nextjs/data-fetching/references/REFERENCE.md +13 -0
- package/rules/nextjs/data-fetching/references/fetch-patterns.md +160 -0
- package/rules/nextjs/internationalization/SKILL.md +105 -0
- package/rules/nextjs/internationalization/references/REFERENCE.md +13 -0
- package/rules/nextjs/internationalization/references/i18n-patterns.md +180 -0
- package/rules/nextjs/optimization/SKILL.md +64 -0
- package/rules/nextjs/optimization/references/REFERENCE.md +13 -0
- package/rules/nextjs/optimization/references/optimization-patterns.md +190 -0
- package/rules/nextjs/rendering/SKILL.md +91 -0
- package/rules/nextjs/rendering/references/REFERENCE.md +13 -0
- package/rules/nextjs/rendering/references/rendering-modes.md +163 -0
- package/rules/nextjs/server-actions/SKILL.md +46 -0
- package/rules/nextjs/server-actions/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-actions/references/action-patterns.md +188 -0
- package/rules/nextjs/server-components/SKILL.md +52 -0
- package/rules/nextjs/server-components/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-components/references/component-patterns.md +175 -0
- package/rules/nextjs/state-management/SKILL.md +73 -0
- package/rules/nextjs/state-management/references/REFERENCE.md +13 -0
- package/rules/nextjs/state-management/references/state-patterns.md +218 -0
- package/rules/nextjs/styling/SKILL.md +31 -0
- package/rules/nextjs/styling/references/implementation.md +56 -0
- package/rules/react/component-patterns/SKILL.md +66 -0
- package/rules/react/component-patterns/references/REFERENCE.md +126 -0
- package/rules/react/hooks/SKILL.md +60 -0
- package/rules/react/hooks/references/REFERENCE.md +132 -0
- package/rules/react/hooks.rule.md +79 -0
- package/rules/react/performance/SKILL.md +69 -0
- package/rules/react/performance/references/REFERENCE.md +143 -0
- package/rules/react/security/SKILL.md +46 -0
- package/rules/react/security/references/REFERENCE.md +170 -0
- package/rules/react/state-management/SKILL.md +56 -0
- package/rules/react/state-management/references/REFERENCE.md +137 -0
- package/rules/react/testing/SKILL.md +45 -0
- package/rules/react/testing/references/REFERENCE.md +149 -0
- package/rules/react/tooling/SKILL.md +39 -0
- package/rules/react/typescript/SKILL.md +53 -0
- package/rules/rust/actix-web/SKILL.md +160 -0
- package/rules/rust/actix-web/references/REFERENCE.md +13 -0
- package/rules/rust/actix-web/references/handler-patterns.md +198 -0
- package/rules/rust/async-graphql/SKILL.md +228 -0
- package/rules/rust/async-graphql/references/REFERENCE.md +13 -0
- package/rules/rust/async-graphql/references/schema-patterns.md +215 -0
- package/rules/rust/axum/SKILL.md +161 -0
- package/rules/rust/axum/references/REFERENCE.md +14 -0
- package/rules/rust/axum/references/handler-patterns.md +97 -0
- package/rules/rust/bevy/SKILL.md +206 -0
- package/rules/rust/bevy/references/REFERENCE.md +13 -0
- package/rules/rust/bevy/references/ecs-patterns.md +226 -0
- package/rules/rust/clap/SKILL.md +217 -0
- package/rules/rust/clap/references/REFERENCE.md +13 -0
- package/rules/rust/clap/references/derive-patterns.md +205 -0
- package/rules/rust/core/SKILL.md +154 -0
- package/rules/rust/core/references/REFERENCE.md +14 -0
- package/rules/rust/core/references/error-handling.md +92 -0
- package/rules/rust/diesel-orm/SKILL.md +176 -0
- package/rules/rust/diesel-orm/references/REFERENCE.md +13 -0
- package/rules/rust/diesel-orm/references/schema-patterns.md +206 -0
- package/rules/rust/rocket/SKILL.md +182 -0
- package/rules/rust/rocket/references/REFERENCE.md +13 -0
- package/rules/rust/rocket/references/handler-patterns.md +209 -0
- package/rules/rust/sea-orm/SKILL.md +230 -0
- package/rules/rust/sea-orm/references/REFERENCE.md +13 -0
- package/rules/rust/sea-orm/references/entity-patterns.md +221 -0
- package/rules/rust/serde-serialization/SKILL.md +150 -0
- package/rules/rust/serde-serialization/references/REFERENCE.md +13 -0
- package/rules/rust/serde-serialization/references/serialization-patterns.md +199 -0
- package/rules/rust/sqlx-database/SKILL.md +140 -0
- package/rules/rust/sqlx-database/references/REFERENCE.md +13 -0
- package/rules/rust/sqlx-database/references/query-patterns.md +210 -0
- package/rules/rust/tauri/SKILL.md +180 -0
- package/rules/rust/tauri/references/REFERENCE.md +13 -0
- package/rules/rust/tauri/references/command-patterns.md +209 -0
- package/rules/rust/tokio-runtime/SKILL.md +167 -0
- package/rules/rust/tokio-runtime/references/REFERENCE.md +14 -0
- package/rules/rust/tokio-runtime/references/async-patterns.md +137 -0
- package/rules/rust/tokio-runtime/references/synchronization.md +152 -0
- package/rules/rust/tonic/SKILL.md +231 -0
- package/rules/rust/tonic/references/REFERENCE.md +13 -0
- package/rules/rust/tonic/references/service-patterns.md +213 -0
- package/rules/rust/tracing/SKILL.md +214 -0
- package/rules/rust/tracing/references/REFERENCE.md +13 -0
- package/rules/rust/tracing/references/instrumentation.md +187 -0
- package/rules/typescript/best-practices/SKILL.md +108 -0
- package/rules/typescript/best-practices/references/REFERENCE.md +68 -0
- package/rules/typescript/language/SKILL.md +72 -0
- package/rules/typescript/language/references/REFERENCE.md +67 -0
- package/rules/typescript/patterns.rule.md +85 -0
- package/rules/typescript/security/SKILL.md +59 -0
- package/rules/typescript/security/references/REFERENCE.md +113 -0
- package/rules/typescript/tooling/SKILL.md +52 -0
- package/rules/typescript/tooling/references/REFERENCE.md +110 -0
- package/skills/learn/SKILL.md +476 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Next.js Server Components
|
|
3
|
+
description: RSC usage, "use client" directive, and Component Purity.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [nextjs, rsc, components]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.tsx', '**/*.jsx']
|
|
8
|
+
keywords: [use client, Server Component, Client Component, hydration]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Server & Client Components
|
|
12
|
+
|
|
13
|
+
## **Priority: P0 (CRITICAL)**
|
|
14
|
+
|
|
15
|
+
Next.js (App Router) uses React Server Components (RSC) by default.
|
|
16
|
+
|
|
17
|
+
## Server Components (Default)
|
|
18
|
+
|
|
19
|
+
- **Behavior**: Rendered on server, sent as HTML/Payload to client. Zero bundle size for included libs.
|
|
20
|
+
- **Capabilities**: Async/Await, Direct DB access, Secrets usage.
|
|
21
|
+
- **Restrictions**: No `useState`, `useEffect`, or Browser APIs (`window`, `localstorage`).
|
|
22
|
+
|
|
23
|
+
## Client Components
|
|
24
|
+
|
|
25
|
+
- **Directive**: Add `'use client'` at the VERY TOP of the file.
|
|
26
|
+
- **Usage**: Interactivity (`onClick`), State (`useState`), Lifecycle effects, Browser APIs.
|
|
27
|
+
- **Strategy**: Move Client Components to the leaves of the tree.
|
|
28
|
+
- _Bad_: Making the root layout a Client Component.
|
|
29
|
+
- _Good_: Wrapping a `<Button />` in a Client Component.
|
|
30
|
+
|
|
31
|
+
## Composition Patterns
|
|
32
|
+
|
|
33
|
+
- **Server-in-Client**: You cannot import a Server Component directly into a Client Component.
|
|
34
|
+
- _Fix_: Pass Server Component as `children` prop to the Client Component.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
// ClientWrapper.tsx
|
|
38
|
+
'use client';
|
|
39
|
+
export default function ClientWrapper({ children }) {
|
|
40
|
+
return <div>{children}</div>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Page.tsx (Server)
|
|
44
|
+
<ClientWrapper>
|
|
45
|
+
<ServerComponent />
|
|
46
|
+
</ClientWrapper>;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Anti-Patterns
|
|
50
|
+
|
|
51
|
+
- **Poisoning**: Importing server-only secrets into Client Components (Use `server-only` package to prevent).
|
|
52
|
+
- **Over-fetching**: Passing large data props to Client Components (Serialization cost). Only pass IDs if possible.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Next.js Server Components References
|
|
2
|
+
|
|
3
|
+
## References
|
|
4
|
+
|
|
5
|
+
- [**Component Patterns**](component-patterns.md) - RSC, client boundaries, data
|
|
6
|
+
|
|
7
|
+
## Quick Checks
|
|
8
|
+
|
|
9
|
+
- [ ] Default to Server Components
|
|
10
|
+
- [ ] 'use client' only when needed
|
|
11
|
+
- [ ] Fetch data in Server Components
|
|
12
|
+
- [ ] Composition pattern for interactivity
|
|
13
|
+
- [ ] Stream with Suspense
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Next.js Server Component Patterns
|
|
2
|
+
|
|
3
|
+
## Server vs Client Components
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
// Server Component (default) - runs on server only
|
|
7
|
+
async function UserList() {
|
|
8
|
+
const users = await db.users.findMany(); // Direct DB access
|
|
9
|
+
return (
|
|
10
|
+
<ul>
|
|
11
|
+
{users.map(user => <li key={user.id}>{user.name}</li>)}
|
|
12
|
+
</ul>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Client Component - runs on client
|
|
17
|
+
'use client';
|
|
18
|
+
|
|
19
|
+
import { useState } from 'react';
|
|
20
|
+
|
|
21
|
+
function Counter() {
|
|
22
|
+
const [count, setCount] = useState(0);
|
|
23
|
+
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## When to Use Client Components
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
'use client';
|
|
31
|
+
|
|
32
|
+
// Use 'use client' when you need:
|
|
33
|
+
// - useState, useEffect, useReducer
|
|
34
|
+
// - Event listeners (onClick, onChange)
|
|
35
|
+
// - Browser APIs (window, document)
|
|
36
|
+
// - Custom hooks with state
|
|
37
|
+
// - Class components
|
|
38
|
+
|
|
39
|
+
function InteractiveForm() {
|
|
40
|
+
const [value, setValue] = useState('');
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<input
|
|
44
|
+
value={value}
|
|
45
|
+
onChange={(e) => setValue(e.target.value)}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Composition Pattern
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
// Server Component with Client Component children
|
|
55
|
+
async function Dashboard() {
|
|
56
|
+
const data = await fetchDashboardData();
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div>
|
|
60
|
+
<h1>Dashboard</h1>
|
|
61
|
+
{/* Server-rendered data passed to client component */}
|
|
62
|
+
<InteractiveChart data={data.chartData} />
|
|
63
|
+
{/* Server Component */}
|
|
64
|
+
<StaticStats stats={data.stats} />
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Client Component receives serializable props
|
|
70
|
+
'use client';
|
|
71
|
+
|
|
72
|
+
function InteractiveChart({ data }: { data: ChartData[] }) {
|
|
73
|
+
const [selected, setSelected] = useState<string | null>(null);
|
|
74
|
+
return <Chart data={data} onSelect={setSelected} />;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Streaming with Suspense
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { Suspense } from 'react';
|
|
82
|
+
|
|
83
|
+
async function Page() {
|
|
84
|
+
return (
|
|
85
|
+
<div>
|
|
86
|
+
<h1>Dashboard</h1>
|
|
87
|
+
|
|
88
|
+
{/* Streams independently */}
|
|
89
|
+
<Suspense fallback={<StatsSkeleton />}>
|
|
90
|
+
<Stats />
|
|
91
|
+
</Suspense>
|
|
92
|
+
|
|
93
|
+
<Suspense fallback={<ChartSkeleton />}>
|
|
94
|
+
<Chart />
|
|
95
|
+
</Suspense>
|
|
96
|
+
|
|
97
|
+
<Suspense fallback={<TableSkeleton />}>
|
|
98
|
+
<DataTable />
|
|
99
|
+
</Suspense>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Each component fetches its own data
|
|
105
|
+
async function Stats() {
|
|
106
|
+
const stats = await getStats(); // Slow query
|
|
107
|
+
return <StatsDisplay stats={stats} />;
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Passing Server Data to Client
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
// Server Component fetches, Client Component interacts
|
|
115
|
+
async function ProductPage({ id }: { id: string }) {
|
|
116
|
+
const product = await getProduct(id);
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div>
|
|
120
|
+
<h1>{product.name}</h1>
|
|
121
|
+
<p>{product.description}</p>
|
|
122
|
+
{/* Pass serializable data to client */}
|
|
123
|
+
<AddToCartButton productId={product.id} price={product.price} />
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
'use client';
|
|
129
|
+
|
|
130
|
+
function AddToCartButton({ productId, price }: { productId: string; price: number }) {
|
|
131
|
+
const [adding, setAdding] = useState(false);
|
|
132
|
+
|
|
133
|
+
async function handleClick() {
|
|
134
|
+
setAdding(true);
|
|
135
|
+
await addToCart(productId);
|
|
136
|
+
setAdding(false);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<button onClick={handleClick} disabled={adding}>
|
|
141
|
+
Add to Cart - ${price}
|
|
142
|
+
</button>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Avoid Client Component Wrappers
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
// ❌ Bad - makes everything client
|
|
151
|
+
'use client';
|
|
152
|
+
export default function Layout({ children }) {
|
|
153
|
+
const [theme, setTheme] = useState('light');
|
|
154
|
+
return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ✅ Good - minimal client boundary
|
|
158
|
+
// ThemeProvider.tsx
|
|
159
|
+
'use client';
|
|
160
|
+
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|
161
|
+
const [theme, setTheme] = useState('light');
|
|
162
|
+
return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// layout.tsx (Server Component)
|
|
166
|
+
export default function Layout({ children }) {
|
|
167
|
+
return (
|
|
168
|
+
<html>
|
|
169
|
+
<body>
|
|
170
|
+
<ThemeProvider>{children}</ThemeProvider>
|
|
171
|
+
</body>
|
|
172
|
+
</html>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Next.js State Management
|
|
3
|
+
description: Best practices for managing state (Server URL vs Client Hooks).
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [nextjs, state, zustand, context]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/hooks/*.ts', '**/store.ts', '**/components/*.tsx']
|
|
8
|
+
keywords: [useState, useContext, zustand, redux]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# State Management
|
|
12
|
+
|
|
13
|
+
## **Priority: P2 (MEDIUM)**
|
|
14
|
+
|
|
15
|
+
Prefer Server State (URL) and Local State over Global Stores.
|
|
16
|
+
|
|
17
|
+
## Principles
|
|
18
|
+
|
|
19
|
+
1. **URL as Source of Truth**: For any state that should be shareable or persistent (Search queries, Filters, Pagination, Tabs), use the URL Search Params.
|
|
20
|
+
- _Why_: Keeps state syncable across refreshes and shareable links.
|
|
21
|
+
- _Tool_: `useSearchParams` hook.
|
|
22
|
+
2. **Colocation**: Keep state as close to the component as possible. **Do not lift state** unless necessary to share between siblings.
|
|
23
|
+
- _Bad_: `App` component holding `searchTerm` for a `SearchBar` nested 5 levels deep.
|
|
24
|
+
- _Good_: `SearchBar` has internal state, or `MainContent` holds it if it needs to pass to siblings.
|
|
25
|
+
3. **No Global Store Default**: Avoid Redux/Zustand for simple apps. Be skeptical of adding a library.
|
|
26
|
+
- _Use Cases for Global Store_: Complex interactors like a Music Player (persists across navigation), Shopping Cart (shared everywhere).
|
|
27
|
+
|
|
28
|
+
## Patterns
|
|
29
|
+
|
|
30
|
+
### 1. Granular State (Best Practice)
|
|
31
|
+
|
|
32
|
+
Don't store large objects. Subscribe only to what you need to prevent unnecessary re-renders.
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
// BAD: Re-renders on any change to 'user'
|
|
36
|
+
const [user, setUser] = useState({ name: '', stats: {}, friends: [] });
|
|
37
|
+
|
|
38
|
+
// GOOD: Independent states
|
|
39
|
+
const [name, setName] = useState('');
|
|
40
|
+
const [stats, setStats] = useState({});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. URL-Driven State (Search/Filter)
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
// Client Component
|
|
47
|
+
'use client';
|
|
48
|
+
import { useSearchParams, useRouter, usePathname } from 'next/navigation';
|
|
49
|
+
|
|
50
|
+
export function Search() {
|
|
51
|
+
const searchParams = useSearchParams();
|
|
52
|
+
const { replace } = useRouter();
|
|
53
|
+
const pathname = usePathname();
|
|
54
|
+
|
|
55
|
+
function handleSearch(term: string) {
|
|
56
|
+
const params = new URLSearchParams(searchParams);
|
|
57
|
+
if (term) params.set('q', term);
|
|
58
|
+
else params.delete('q');
|
|
59
|
+
|
|
60
|
+
// Updates URL -> Server Component re-renders with new params
|
|
61
|
+
replace(`${pathname}?${params.toString()}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 3. Server State (TanStack Query / SWR)
|
|
67
|
+
|
|
68
|
+
If you need "Live" data on the client (e.g., polling stock prices, chat), do not implement `useEffect` fetch manually. Use a library.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
// Automated caching, deduplication, and revalidation
|
|
72
|
+
const { data, error } = useSWR('/api/user', fetcher);
|
|
73
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Next.js State Management References
|
|
2
|
+
|
|
3
|
+
## References
|
|
4
|
+
|
|
5
|
+
- [**State Patterns**](state-patterns.md) - React Context, Zustand, server state
|
|
6
|
+
|
|
7
|
+
## Quick Checks
|
|
8
|
+
|
|
9
|
+
- [ ] Use React Context for simple global state
|
|
10
|
+
- [ ] Use Zustand/Jotai for complex client state
|
|
11
|
+
- [ ] Use React Query/SWR for server state
|
|
12
|
+
- [ ] Minimize client-side state with RSC
|
|
13
|
+
- [ ] Consider URL state for shareable state
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Next.js State Management Patterns
|
|
2
|
+
|
|
3
|
+
## React Context (Simple Global State)
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
// contexts/theme-context.tsx
|
|
7
|
+
'use client';
|
|
8
|
+
|
|
9
|
+
import { createContext, useContext, useState } from 'react';
|
|
10
|
+
|
|
11
|
+
type Theme = 'light' | 'dark';
|
|
12
|
+
|
|
13
|
+
const ThemeContext = createContext<{
|
|
14
|
+
theme: Theme;
|
|
15
|
+
setTheme: (theme: Theme) => void;
|
|
16
|
+
} | null>(null);
|
|
17
|
+
|
|
18
|
+
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|
19
|
+
const [theme, setTheme] = useState<Theme>('light');
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<ThemeContext.Provider value={{ theme, setTheme }}>
|
|
23
|
+
{children}
|
|
24
|
+
</ThemeContext.Provider>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function useTheme() {
|
|
29
|
+
const context = useContext(ThemeContext);
|
|
30
|
+
if (!context) throw new Error('useTheme must be used within ThemeProvider');
|
|
31
|
+
return context;
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Zustand (Complex Client State)
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// stores/cart-store.ts
|
|
39
|
+
import { create } from 'zustand';
|
|
40
|
+
import { persist } from 'zustand/middleware';
|
|
41
|
+
|
|
42
|
+
interface CartItem {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
quantity: number;
|
|
46
|
+
price: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface CartStore {
|
|
50
|
+
items: CartItem[];
|
|
51
|
+
addItem: (item: CartItem) => void;
|
|
52
|
+
removeItem: (id: string) => void;
|
|
53
|
+
clearCart: () => void;
|
|
54
|
+
total: () => number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const useCartStore = create<CartStore>()(
|
|
58
|
+
persist(
|
|
59
|
+
(set, get) => ({
|
|
60
|
+
items: [],
|
|
61
|
+
addItem: (item) =>
|
|
62
|
+
set((state) => {
|
|
63
|
+
const existing = state.items.find((i) => i.id === item.id);
|
|
64
|
+
if (existing) {
|
|
65
|
+
return {
|
|
66
|
+
items: state.items.map((i) =>
|
|
67
|
+
i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i
|
|
68
|
+
),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return { items: [...state.items, item] };
|
|
72
|
+
}),
|
|
73
|
+
removeItem: (id) =>
|
|
74
|
+
set((state) => ({ items: state.items.filter((i) => i.id !== id) })),
|
|
75
|
+
clearCart: () => set({ items: [] }),
|
|
76
|
+
total: () => get().items.reduce((acc, i) => acc + i.price * i.quantity, 0),
|
|
77
|
+
}),
|
|
78
|
+
{ name: 'cart-storage' }
|
|
79
|
+
)
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Usage in component
|
|
83
|
+
'use client';
|
|
84
|
+
|
|
85
|
+
export function Cart() {
|
|
86
|
+
const { items, removeItem, total } = useCartStore();
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<div>
|
|
90
|
+
{items.map((item) => (
|
|
91
|
+
<div key={item.id}>
|
|
92
|
+
{item.name} x{item.quantity}
|
|
93
|
+
<button onClick={() => removeItem(item.id)}>Remove</button>
|
|
94
|
+
</div>
|
|
95
|
+
))}
|
|
96
|
+
<p>Total: ${total()}</p>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## React Query (Server State)
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// providers/query-provider.tsx
|
|
106
|
+
'use client';
|
|
107
|
+
|
|
108
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
109
|
+
import { useState } from 'react';
|
|
110
|
+
|
|
111
|
+
export function QueryProvider({ children }: { children: React.ReactNode }) {
|
|
112
|
+
const [queryClient] = useState(() => new QueryClient({
|
|
113
|
+
defaultOptions: {
|
|
114
|
+
queries: {
|
|
115
|
+
staleTime: 60 * 1000,
|
|
116
|
+
gcTime: 5 * 60 * 1000,
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
}));
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<QueryClientProvider client={queryClient}>
|
|
123
|
+
{children}
|
|
124
|
+
</QueryClientProvider>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// hooks/use-products.ts
|
|
129
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
130
|
+
|
|
131
|
+
export function useProducts() {
|
|
132
|
+
return useQuery({
|
|
133
|
+
queryKey: ['products'],
|
|
134
|
+
queryFn: () => fetch('/api/products').then((res) => res.json()),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function useCreateProduct() {
|
|
139
|
+
const queryClient = useQueryClient();
|
|
140
|
+
|
|
141
|
+
return useMutation({
|
|
142
|
+
mutationFn: (data: CreateProductDto) =>
|
|
143
|
+
fetch('/api/products', {
|
|
144
|
+
method: 'POST',
|
|
145
|
+
body: JSON.stringify(data),
|
|
146
|
+
}).then((res) => res.json()),
|
|
147
|
+
onSuccess: () => {
|
|
148
|
+
queryClient.invalidateQueries({ queryKey: ['products'] });
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## URL State (Shareable)
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
'use client';
|
|
158
|
+
|
|
159
|
+
import { useSearchParams, useRouter, usePathname } from 'next/navigation';
|
|
160
|
+
import { useCallback } from 'react';
|
|
161
|
+
|
|
162
|
+
export function useQueryState(key: string) {
|
|
163
|
+
const searchParams = useSearchParams();
|
|
164
|
+
const router = useRouter();
|
|
165
|
+
const pathname = usePathname();
|
|
166
|
+
|
|
167
|
+
const value = searchParams.get(key);
|
|
168
|
+
|
|
169
|
+
const setValue = useCallback(
|
|
170
|
+
(newValue: string | null) => {
|
|
171
|
+
const params = new URLSearchParams(searchParams);
|
|
172
|
+
if (newValue === null) {
|
|
173
|
+
params.delete(key);
|
|
174
|
+
} else {
|
|
175
|
+
params.set(key, newValue);
|
|
176
|
+
}
|
|
177
|
+
router.push(`${pathname}?${params.toString()}`);
|
|
178
|
+
},
|
|
179
|
+
[key, pathname, router, searchParams]
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
return [value, setValue] as const;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Usage
|
|
186
|
+
function ProductFilters() {
|
|
187
|
+
const [category, setCategory] = useQueryState('category');
|
|
188
|
+
const [sort, setSort] = useQueryState('sort');
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<div>
|
|
192
|
+
<select value={category || ''} onChange={(e) => setCategory(e.target.value)}>
|
|
193
|
+
<option value="">All</option>
|
|
194
|
+
<option value="electronics">Electronics</option>
|
|
195
|
+
</select>
|
|
196
|
+
</div>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Server State with RSC
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// Prefer server components for data that doesn't need client interactivity
|
|
205
|
+
// app/products/page.tsx
|
|
206
|
+
async function ProductsPage() {
|
|
207
|
+
const products = await getProducts(); // Server fetch
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
<div>
|
|
211
|
+
{products.map((product) => (
|
|
212
|
+
<ProductCard key={product.id} product={product} />
|
|
213
|
+
))}
|
|
214
|
+
<AddToCartButton /> {/* Client component for interaction */}
|
|
215
|
+
</div>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Next.js Styling & UI Performance
|
|
3
|
+
description: Zero-runtime CSS strategies (Tailwind) and RSC compatibility.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [nextjs, styling, tailwind, css]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.css', 'tailwind.config.ts', '**/components/ui/*.tsx']
|
|
8
|
+
keywords: [tailwind, css modules, styled-components, clsx, cn]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Styling & UI Performance
|
|
12
|
+
|
|
13
|
+
## **Priority: P1 (HIGH)**
|
|
14
|
+
|
|
15
|
+
Prioritize **Zero-Runtime** CSS for Server Components.
|
|
16
|
+
|
|
17
|
+
## Library Selection
|
|
18
|
+
|
|
19
|
+
| Library | Verdict | Reason |
|
|
20
|
+
| :------------------------- | :----------------- | :------------------------------------------------- |
|
|
21
|
+
| **Tailwind / shadcn** | **Preferred (P1)** | Zero-runtime, RSC compatible. Best for App Router. |
|
|
22
|
+
| **CSS Modules** | **Recommended** | Scoped, zero-runtime. |
|
|
23
|
+
| **MUI / Chakra (Runtime)** | **Avoid** | Forces `use client` widely. Degrades performance. |
|
|
24
|
+
|
|
25
|
+
## Patterns
|
|
26
|
+
|
|
27
|
+
1. **Dynamic Classes**: Use `clsx` + `tailwind-merge` (`cn` utility).
|
|
28
|
+
- _Reference_: [Dynamic Classes & Button Example](references/implementation.md)
|
|
29
|
+
2. **Font Optimization**: Use `next/font` to prevent Cumulative Layout Shift (CLS).
|
|
30
|
+
- _Reference_: [Font Setup](references/implementation.md)
|
|
31
|
+
3. **CLS Prevention**: Always specify `width`/`height` on images.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Styling Implementation
|
|
2
|
+
|
|
3
|
+
## Dynamic Classes Utility
|
|
4
|
+
|
|
5
|
+
Standard `cn` helper for shadcn/ui and Tailwind.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// lib/utils.ts
|
|
9
|
+
import { type ClassValue, clsx } from 'clsx';
|
|
10
|
+
import { twMerge } from 'tailwind-merge';
|
|
11
|
+
|
|
12
|
+
export function cn(...inputs: ClassValue[]) {
|
|
13
|
+
return twMerge(clsx(inputs));
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Component Usage Example
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// components/ui/button.tsx
|
|
21
|
+
export function Button({ className, variant, ...props }) {
|
|
22
|
+
return (
|
|
23
|
+
<button
|
|
24
|
+
className={cn(
|
|
25
|
+
// Base styles
|
|
26
|
+
"px-4 py-2 rounded font-medium transition-colors",
|
|
27
|
+
// Conditional variants
|
|
28
|
+
variant === 'primary' && "bg-blue-500 text-white",
|
|
29
|
+
// External overrides
|
|
30
|
+
className
|
|
31
|
+
)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Font Optimization
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// app/layout.tsx
|
|
42
|
+
import { Inter } from 'next/font/google';
|
|
43
|
+
|
|
44
|
+
const inter = Inter({
|
|
45
|
+
subsets: ['latin'],
|
|
46
|
+
display: 'swap', // Prevents FOIT
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export default function RootLayout({ children }) {
|
|
50
|
+
return (
|
|
51
|
+
<html lang="en" className={inter.className}>
|
|
52
|
+
<body>{children}</body>
|
|
53
|
+
</html>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: React Component Patterns
|
|
3
|
+
description: Modern React component architecture and composition patterns.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [react, components, composition, patterns]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.jsx', '**/*.tsx']
|
|
8
|
+
keywords: [component, props, children, composition, hoc, render-props]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# React Component Patterns
|
|
12
|
+
|
|
13
|
+
## **Priority: P0 (CRITICAL)**
|
|
14
|
+
|
|
15
|
+
Standards for building scalable, maintainable React components.
|
|
16
|
+
|
|
17
|
+
## Implementation Guidelines
|
|
18
|
+
|
|
19
|
+
- **Function Components**: Only hooks. No classes.
|
|
20
|
+
- **Composition**: Use `children` prop. Avoid inheritance.
|
|
21
|
+
- **Props**: Explicit TS interfaces. Destructure in params.
|
|
22
|
+
- **Boolean Props**: Shorthand `<Cmp isVisible />` vs `isVisible={true}`.
|
|
23
|
+
- **Imports**: Group: `Built-in` -> `External` -> `Internal` -> `Styles`.
|
|
24
|
+
- **Error Boundaries**: Wrap app/features with `react-error-boundary`.
|
|
25
|
+
- **Size**: Small (< 250 lines). One component per file.
|
|
26
|
+
- **Naming**: `PascalCase` components. `use*` hooks.
|
|
27
|
+
- **Exports**: Named exports only.
|
|
28
|
+
- **Conditionals**: Ternary (`Cond ? <A/> : <B/>`) over `&&` for rendering consistency.
|
|
29
|
+
- **Hoisting**: Extract static JSX/Objects outside component to prevent recreation.
|
|
30
|
+
|
|
31
|
+
## Anti-Patterns
|
|
32
|
+
|
|
33
|
+
- **No Classes**: Use hooks.
|
|
34
|
+
- **No Prop Drilling**: Use Context/Zustand.
|
|
35
|
+
- **No Nested Definitions**: Define components at top level.
|
|
36
|
+
- **No Index Keys**: Use stable IDs.
|
|
37
|
+
- **No Inline Handlers**: Define before return.
|
|
38
|
+
|
|
39
|
+
## Code
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
// Composition
|
|
43
|
+
export function Layout({ children, aside }: LayoutProps) {
|
|
44
|
+
return (
|
|
45
|
+
<div className='grid'>
|
|
46
|
+
<aside>{aside}</aside>
|
|
47
|
+
<main>{children}</main>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Compound Component
|
|
53
|
+
export function Select({ children }: { children: ReactNode }) {
|
|
54
|
+
return <select>{children}</select>;
|
|
55
|
+
}
|
|
56
|
+
Select.Option = ({ val, children }) => <option value={val}>{children}</option>;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Reference & Examples
|
|
60
|
+
|
|
61
|
+
For advanced patterns (HOCs, Render Props, Compound Components):
|
|
62
|
+
See [references/REFERENCE.md](references/REFERENCE.md).
|
|
63
|
+
|
|
64
|
+
## Related Topics
|
|
65
|
+
|
|
66
|
+
hooks | state-management | performance
|