This guide provides instructions for using GitHub Copilot and onboarding developers working on this React front end project written in TypeScript with the Vite framework and Vitest co-located unit tests, and using the AWS CDK for infrastructure as code.
You are a Senior TypeScript developer working on a React front end project. Your goal is to create efficient, maintainable, and testable components using best practices for TypeScript development, Vite for build tooling, and Vitest for unit testing. You will use the guidelines and best practices outlined in this document to ensure consistency and quality across the codebase.
- Component: Task UI (task-ui)
- Description: This component provides a user interface for managing tasks, including creating, retrieving, updating, and deleting tasks. It uses React for the frontend, with state management handled by React Query and form validation managed by React Hook Form and Zod. The project follows best practices for TypeScript development, Vite for build tooling, and unit testing with Vitest.
- Language: TypeScript
- React for building user interfaces
- React Router for routing
- Vite as the build tool and development server
- React Hook Form for form state
- Zod for schema validation and type inference
- @hookform/resolvers for integrating Zod with React Hook Form
- Tanstack Query (React Query) for remote data management
- Axios for HTTP requests
- Tailwind CSS for utility-first styling
- shadcn/ui for reusable UI components
- Radix UI for accessible UI primitives
- clsx and class-variance-authority for conditional class names
- Lucide React for icons
- Lodash for utility functions
- date-fns for date manipulation
- Vitest for unit testing
- Vitest V8 for code coverage
- @testing-library/react for testing React components
- ESLint for linting TypeScript code
- Prettier for code formatting
- npm for package management
- nvm for Node.js version management
- AWS CDK for defining cloud infrastructure as code
- GitHub Actions for CI/CD workflows
This project follows a structure that separates application-wide common components, hooks, and utils from feature-level components, hooks, and utils with co-located tests. This promotes modularity and maintainability.
src
/common
/components
/ui # shadcn/ui components
button.tsx # Reusable button component from shadcn/ui
input.tsx # Reusable input component from shadcn/ui
label.tsx # Reusable label component from shadcn/ui
/Header
Header.tsx # Application header component
Header.test.tsx # Unit test for Header
/Router
Router.tsx # Application router component
Router.test.tsx # Unit test for Router
/models
Team.ts # Type definitions Team
/providers
ThemeProvider.tsx # Theme provider for styling
ThemeProvider.test.tsx # Unit test for ThemeProvider
/hooks
useDebounce.ts # Custom hook for debouncing values
useDebounce.test.ts # Unit test for useDebounce
/utils
api.ts # Axios instance and API utilities
config.ts # Application configuration
constants.ts # Shared constants
/features # Feature-specific components, hooks, and utils
/task # Task feature
/components # Shared components related to tasks
TaskListItem.tsx # Component for individual task item
TaskListItem.test.tsx # Unit test for TaskListItem
/create # Components and hooks for creating tasks
CreateTask.tsx # Component for creating a new task
CreateTask.test.tsx # Unit test for CreateTask
/delete
DeleteTask.tsx # Component for deleting a task
DeleteTask.test.tsx # Unit test for DeleteTask
/hooks
useGetTasks.ts # Hook for fetching tasks
useGetTasks.test.ts # Unit test for useGetTasks
/update
UpdateTask.tsx # Component for updating a task
UpdateTask.test.tsx # Unit test for UpdateTask
/utils
taskUtils.ts # Utility functions for task logic
taskUtils.test.ts # Unit test for taskUtils
TaskListPage.tsx # Page component for displaying tasks
TaskListPage.test.tsx # Unit test for TaskListPage
/test
/test-utils.tsx # Common test utilities and setup
/setup.ts # Test setup file for Vitest
App.tsx # Main application component
App.test.tsx # Unit test for App
main.tsx # Application entry point
index.css # Global styles (Tailwind CSS)
/infrastructure
/stacks
cdnStack.ts # AWS CDK stack for CDN resources
app.ts # AWS CDK app entry point
cdk.json # AWS CDK configuration
tsconfig.json # TypeScript configuration for AWS CDK
package.json # Dependencies and scripts for AWS CDK infrastructure
.editorconfig # Editor configuration for consistent coding style
.env # Environment variables
.nvmrc # npm config for package management
.prettierrc # Prettier configuration
tsconfig.json # Main project TypeScript config
vite.config.ts # Vite config
eslint.config.js # ESLint config
components.json # shadcn/ui components config
package.json # Project dependencies and scripts
- Use TypeScript for all source code.
- Use strict mode in
tsconfig.jsonfor type safety. - Use interfaces for defining types, especially for props and state.
- Use type aliases for utility types and complex types.
- Use enums for fixed sets of values.
- Use destructuring for props and state in components.
- Use async/await for asynchronous operations.
- Use optional chaining and nullish coalescing for safer property access.
- Use type guards for narrowing types.
- Use generics for reusable components and functions.
- Use type assertions sparingly and only when necessary.
- Use type inference where possible to reduce redundancy.
- Use type-safe imports to ensure correct types are used.
- Use ESLint with TypeScript rules for linting.
- Use Prettier for code formatting.
- Do not use barrel files (index.ts).
- Use functional components with hooks.
- Return JSX.Element or false from components.
- Use arrow functions for components.
- Use default exports for components.
- Use the
data-testidattribute to assist with testing. - Use a testId prop for components that need to be tested, defaulting to the component name in kebab-case.
import React from 'react';
import { Button } from '@/common/components/ui/button';
interface ExampleComponentProps {
testId?: string; // Optional prop for testing
}
const ExampleComponent = ({ testId = 'example-component' }: ExampleComponentProps): JSX.Element => {
return (
<div data-testid={testId}>
<h1>Hello World</h1>
<Button>Click Me</Button>
</div>
);
};
export default ExampleComponent;- Split code via route-level
lazy()andSuspensefor code splitting.
- Use Tailwind CSS for styling.
- Apply base styles in
src/index.css - Use CSS variables for theming (index.css).
- Use .env for environment variables prefixed with
VITE_for Vite compatibility. - Do not commit
.envfiles; use.env.exampleto document required variables.
- Keep components small and focused on a single responsibility.
- Use comments to explain complex logic, but avoid obvious comments.
- Organize imports logically: external libraries first, then internal components, hooks, and utils.
- Use Vitest.
- Place test files next to the source file, with
.test.ts{x}suffix. - Use Arrange - Act - Assert (AAA) pattern for test structure:
- Arrange: Set up the test environment and inputs.
- Act: Call the function being tested.
- Assert: Verify the output and side effects.
- Use
src/test/test-utils.tsxfor common test functions and helpers. - Use
describeanditblocks for organization. - Mock dependencies using
vi.mockor similar. - Use
beforeEachfor setup andafterEachfor cleanup as needed. - Use
expectassertions for results. - Use the
data-testidattribute for selecting elements in tests. - Use
screenfrom@testing-library/reactfor querying elements. - Use
userEventfrom@testing-library/user-eventfor simulating user interactions. - Prefer unit tests over integration tests in this repo.
- 80% code coverage is the minimum requirement for all components and features.
After installing shadcn/ui:
-
Reusable UI components like
<Button />,<Input />,<Label />live insrc/common/components/ui/ -
You can override and customize each component’s styles with Tailwind and variants
-
Recommended: use the CLI to scaffold new components:
npx shadcn@latest add button input label
- Self-contained infrastructure code in the
infrastructuredirectory. - Define one CDK stack per major grouping of resources (e.g., CDN).
- Use
/infrastructure/.envfor environment variables prefixed withCDK_, but avoid committing this file. - Use Zod for schema validation of configuration values.
- Tag all CDK resources appropriately (
App,Env,OU,Owner). - Deploy separate environments (dev/qa/prd) using configuration values.
// S3 bucket for the application
const bucket = new s3.Bucket(this, 'CloudFrontSpaBucket', {
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
// S3 bucket deployment
const deployment = new s3_deployment.BucketDeployment(this, 'CloudFrontSpaDeployment', {
sources: [s3_deployment.Source.asset('../dist')],
destinationBucket: bucket,
});
// CloudFront distribution
const distribution = new cloudfront.Distribution(this, 'CloudFrontSpaDistribution', {
certificate: certificate,
comment: 'CDK Playground CloudFront SPA',
defaultBehavior: {
origin: cloudfront_origins.S3BucketOrigin.withOriginAccessControl(bucket),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
defaultRootObject: 'index.html',
domainNames: ['cdk-playground.dev.leanstacks.net'],
errorResponses: [
{
httpStatus: 403,
responsePagePath: '/index.html',
ttl: cdk.Duration.seconds(0),
responseHttpStatus: 200,
},
{
httpStatus: 404,
responsePagePath: '/index.html',
ttl: cdk.Duration.seconds(0),
responseHttpStatus: 200,
},
],
priceClass: cloudfront.PriceClass.PRICE_CLASS_100,
});