Crafting Excellence With AI A Deep Dive Into Copilot-instructions.md For NestJS Multitenancy Projects
This document serves as a comprehensive guide to creating and maintaining a robust copilot-instructions.md
file for NestJS multitenancy projects. The primary objective is to ensure that this file provides clear, objective guidelines for AI tools like Copilot or ChatGPT, enabling them to generate and review code that aligns perfectly with the project's architecture and standards. By meticulously crafting this guide, we aim to streamline development processes, maintain code consistency, and leverage the power of AI to enhance our coding practices.
Objective
The core objective is to ensure our repository includes a complete .github/copilot-instructions.md
file. This file acts as a blueprint, offering precise guidelines for AI tools such as Copilot or ChatGPT. These guidelines are crucial for generating and reviewing code that not only meets our project's architectural requirements but also adheres to our established coding standards. A well-structured copilot-instructions.md
ensures consistency, reduces errors, and accelerates the development lifecycle.
✅ Tasks to Perform
The tasks involved in achieving this objective are multifaceted, requiring a blend of meticulous review and insightful additions. Here’s a breakdown of the steps we’ll undertake:
1. Locate or Create the File
The first step is to identify whether the .github/copilot-instructions.md
file already exists within the repository. If it doesn't, we will create it from scratch. If the file is present, as it is in this repository, we will use it as a foundation, augmenting it with any missing sections to ensure comprehensive coverage of our project guidelines.
2. Review and Complete the Following Sections
Each section of the copilot-instructions.md
file must be carefully reviewed and completed. The content should be articulated in English, maintaining the tone and clarity expected of technical documentation. This ensures that the instructions are easily understood and consistently applied by both human developers and AI tools.
3. Keep and Improve the Project Overview
The project overview section is pivotal. It provides a high-level summary of the project's technology stack, including NestJS, TypeORM, and PostgreSQL. It should also detail the architectural approach, such as multitenancy with a single database, and explain how local development is structured. This overview is crucial for anyone, especially AI, to grasp the project's scope and technical underpinnings.
A well-crafted project overview is the cornerstone of effective collaboration, both among human developers and with AI tools. This section should clearly articulate the project's technology stack, architectural patterns, and development workflows. For instance, explicitly mentioning that the project leverages NestJS for its backend framework, TypeORM for database interactions, and PostgreSQL as the database system provides immediate context. Furthermore, detailing the multitenancy approach, such as using a single database with tenant-specific schemas, is critical for understanding data isolation and management strategies. Finally, outlining the steps for setting up and running the project locally ensures that new contributors and AI assistants can quickly become productive. The goal is to create a concise yet comprehensive summary that serves as a central reference point for the entire project.
For example, consider the following enhanced overview:
Project Overview
This project is built using a robust technology stack comprising NestJS, TypeORM, and PostgreSQL. It employs a multitenancy architecture, utilizing a single database with tenant-specific schemas to ensure data isolation and efficient resource management. Local development is facilitated through Docker Compose, allowing developers to quickly spin up the necessary services. The application follows a modular structure, with distinct modules for core functionalities, tenant-specific features, and shared utilities. This architecture promotes scalability, maintainability, and a clear separation of concerns.
To run the project locally, follow these steps:
- Install Docker and Docker Compose.
- Clone the repository.
- Run
docker-compose up --build
in the project root directory. - Access the application at
http://localhost:3000
.
This detailed overview not only introduces the technology stack and architecture but also provides practical instructions for setting up the development environment, making it easier for both human developers and AI tools to contribute effectively.
4. Expand on the Project Folder Structure
Describing the project's folder structure is essential. Key directories such as admin
, tenant-aware
, shared
, and modules
should be explained in detail. The guidance should specify how code is organized within these folders, ensuring that both developers and AI can place new code in the correct location, maintaining project consistency.
Elaborating on the project's folder structure is crucial for maintaining a clean, organized, and easily navigable codebase. This section of the copilot-instructions.md
should provide a detailed map of the project's directories, explaining the purpose and conventions for each. For instance, the admin
directory might house modules and components related to administrative functionalities, while tenant-aware
would contain code specifically designed for the multitenancy aspect of the application. The shared
directory typically holds reusable components, services, and utilities that are common across multiple modules. Finally, the modules
directory is where the main features of the application reside, each encapsulated in its own module.
To enhance this section, consider providing specific examples and guidelines for code placement. For example:
- admin: This directory contains modules and components related to administrative functionalities, such as user management, system configuration, and monitoring dashboards. Code placed here should adhere to the naming conventions outlined below and should be thoroughly tested.
- tenant-aware: This directory houses code that is specifically designed for the multitenancy architecture of the application. It includes services, repositories, and middleware that handle tenant context, data isolation, and tenant-specific configurations. All classes and files in this directory should include the
Tenant
prefix or suffix to clearly indicate their purpose. - shared: This directory contains reusable components, services, and utilities that are common across multiple modules. Examples include custom exceptions, validation pipes, and utility functions. Code placed here should be generic and should not have dependencies on specific modules or tenants.
- modules: This directory is the main container for the application's features. Each feature should be encapsulated in its own module, with its own controllers, services, entities, and DTOs. Modules should be self-contained and should have clear boundaries and responsibilities.
By providing this level of detail, you ensure that both human developers and AI tools can easily understand the project's structure and contribute code that fits seamlessly within the existing architecture. This reduces the risk of misplaced files, circular dependencies, and other common issues that can arise in large projects.
5. Add or Improve Naming Conventions
Establishing clear naming conventions is vital for code readability and maintainability. The copilot-instructions.md
should include rules for naming files, entities, DTOs, and services. It should also clarify how suffixes like Service
, Dto
, and Repository
are used, promoting consistency across the codebase.
Defining and enforcing consistent naming conventions is a cornerstone of maintainable and scalable software development. In the copilot-instructions.md
file, this section should meticulously outline the rules for naming various code artifacts, including files, entities, DTOs, services, and repositories. Consistency in naming facilitates code comprehension, reduces cognitive load, and minimizes the risk of errors. For example, specifying that all service classes should end with the Service
suffix, such as UserService
, immediately conveys the class's role within the application.
Consider the following detailed guidelines for naming conventions:
- Files: File names should be descriptive and should reflect the primary class or module they contain. Use kebab-case (e.g.,
user-service.ts
,create-user.dto.ts
). - Entities: Entity names should correspond to the database table they represent and should be singular nouns. Use PascalCase (e.g.,
User
,Product
). - DTOs (Data Transfer Objects): DTO names should indicate the purpose of the data transfer, such as
CreateUserDto
,UpdateProductDto
, orUserResponseDto
. Use PascalCase and include theDto
suffix. - Services: Service names should describe the business logic they encapsulate. Use PascalCase and include the
Service
suffix (e.g.,UserService
,ProductService
). - Repositories: Repository names should follow the pattern
<EntityName>Repository
(e.g.,UserRepository
,ProductRepository
). Use PascalCase and include theRepository
suffix. - Controllers: Controller names should follow the pattern
<Resource>Controller
(e.g.,UserController
,ProductController
). Use PascalCase and include theController
suffix. - Modules: Module names should correspond to the feature or domain they represent (e.g.,
UserModule
,ProductModule
). Use PascalCase and include theModule
suffix. - Variables and Constants: Use camelCase for variables and UPPER_SNAKE_CASE for constants (e.g.,
userName
,API_KEY
).
In addition to these general guidelines, it's beneficial to provide specific examples to illustrate how these conventions should be applied in practice. For instance, a service for managing users might be named UserService
, with its corresponding repository named UserRepository
, and a DTO for creating users named CreateUserDto
. By providing these concrete examples, you ensure that developers and AI tools alike can adhere to the naming conventions consistently.
6. Add Examples of IA Prompts or Code Comments
This section is crucial for guiding AI tools. Include examples of effective prompts or code comments that can generate helpful results. For instance, prompts like // Generate a NestJS service using TenantBaseService with CRUD methods
or // Generate a controller with tenant-jwt auth guard and Swagger decorators
can steer AI towards generating the desired code structure and functionality.
Providing examples of effective AI prompts and code comments is a powerful way to leverage AI tools like Copilot and ChatGPT. This section of the copilot-instructions.md
should offer concrete examples that demonstrate how to instruct the AI to generate specific code structures and functionalities. By crafting clear and precise prompts, you can significantly improve the quality and relevance of the AI-generated code. The goal is to empower developers to use AI as a collaborative partner, rather than just a code completion tool.
Consider the following examples of AI prompts and code comments:
// Generate a NestJS service using TenantBaseService with CRUD methods for the Product entity
- This prompt instructs the AI to create a NestJS service that inherits from a
TenantBaseService
(which likely provides common tenant-aware functionalities) and includes CRUD (Create, Read, Update, Delete) methods for theProduct
entity. This is a highly specific prompt that should yield a well-structured service class. // Generate a controller with tenant-jwt auth guard and Swagger decorators for the Product entity
- This prompt asks the AI to generate a NestJS controller that incorporates a tenant-JWT (JSON Web Token) authentication guard, ensuring that only authenticated users with the appropriate tenant context can access the controller's endpoints. Additionally, it requests the inclusion of Swagger decorators, which automatically generate API documentation. This prompt results in a secure and well-documented controller.
- `/**
- @description Generates a DTO for creating a new user.
- @property {string} firstName - The first name of the user.
- @property {string} lastName - The last name of the user.
- @property {string} email - The email address of the user.
- @property {string} password - The password of the user. */ // Generate a CreateUserDto class with the above properties and validation decorators`
- This example combines a detailed JSDoc-style comment with a prompt. The comment clearly describes the purpose and properties of the DTO, while the prompt instructs the AI to generate the
CreateUserDto
class with the specified properties and validation decorators. This approach ensures that the generated DTO is both well-defined and validated. // Generate a TypeORM entity for the Product model with fields: id (UUID, primary), name (string), description (string), price (number), tenantId (UUID, foreign key to Tenant entity)
- This prompt provides a comprehensive description of the entity's structure, including field names, data types, and relationships. The AI should be able to generate a TypeORM entity class that accurately reflects this schema.
By including these types of examples in the copilot-instructions.md
file, you provide a clear roadmap for how to interact with AI tools effectively. This not only improves the quality of the generated code but also reduces the amount of manual effort required to refine the AI's output.
7. Include a Code Review Checklist
A comprehensive code review checklist is essential for maintaining code quality. This checklist should include items such as: ensuring adherence to naming conventions, verifying test coverage for new features, confirming that Swagger documentation is updated, and ensuring that business logic is kept out of controllers. This checklist provides a structured approach to code reviews, helping to catch potential issues early in the development process.
A well-defined code review checklist is a critical component of a healthy software development process. It ensures that code changes are thoroughly vetted for quality, consistency, and adherence to project standards. This section of the copilot-instructions.md
file should provide a comprehensive checklist that reviewers can use to evaluate pull requests. The checklist should cover various aspects of the code, from naming conventions and test coverage to API documentation and architectural principles. By following a structured checklist, reviewers can identify potential issues early in the development cycle, reducing the risk of bugs and technical debt.
Consider the following detailed code review checklist:
-
Naming Conventions: Verify that the code adheres to the naming conventions outlined in the
copilot-instructions.md
file. This includes file names, class names, method names, variable names, and any other identifiers. -
Test Coverage: Ensure that new features and bug fixes are accompanied by adequate unit and integration tests. Aim for a high level of test coverage to minimize the risk of regressions.
-
Swagger Documentation: Confirm that the Swagger documentation is up-to-date and accurately reflects any changes to the API. This includes new endpoints, request/response schemas, and authentication requirements.
-
Business Logic in Controllers: Ensure that controllers are lean and do not contain business logic. Controllers should primarily handle request routing, parameter validation, and response formatting. Business logic should be encapsulated in services.
-
Error Handling: Verify that the code includes proper error handling mechanisms, such as try-catch blocks, exception filters, and global error handlers. Ensure that errors are logged appropriately and that user-friendly error messages are returned to the client.
-
Security: Review the code for potential security vulnerabilities, such as SQL injection, cross-site scripting (XSS), and authentication/authorization issues. Ensure that sensitive data is properly protected and that security best practices are followed.
-
Performance: Evaluate the code for potential performance bottlenecks, such as inefficient database queries, excessive memory usage, and slow algorithms. Identify and address any performance issues before they impact the application's responsiveness.
-
Code Clarity: Assess the code for readability and maintainability. Ensure that the code is well-structured, properly commented, and easy to understand. Use meaningful variable and function names, and avoid overly complex logic.
-
Dependencies: Review the project's dependencies and ensure that they are up-to-date and secure. Identify and remove any unnecessary dependencies.
-
Multitenancy: For multitenant applications, verify that the code properly handles tenant context and data isolation. Ensure that tenant-specific data is not exposed to other tenants.
By incorporating this comprehensive checklist into the copilot-instructions.md
file, you provide reviewers with a clear framework for evaluating code quality. This helps to ensure that code changes are thoroughly vetted and that the codebase remains maintainable and robust.
8. Retain and Review Multitenancy and Authentication Instructions
The existing multitenancy and authentication instructions are well-written and should be retained. However, they should be reviewed periodically to ensure they remain current and aligned with any changes in the project's architecture or security requirements. Update as needed to reflect the latest best practices.
Maintaining robust multitenancy and authentication mechanisms is paramount in modern web applications, especially those designed to serve multiple tenants or organizations. The existing instructions within the copilot-instructions.md
file likely provide a solid foundation for these critical aspects of the project. However, it's imperative to regularly review and update these instructions to ensure they remain aligned with the project's evolving architecture, security landscape, and industry best practices. This section should emphasize the importance of these reviews and provide guidelines for identifying and addressing potential gaps or areas for improvement.
Consider the following aspects when reviewing multitenancy and authentication instructions:
-
Multitenancy Strategy: Revisit the chosen multitenancy strategy (e.g., separate databases, shared database with tenant IDs, schema-based multitenancy) and ensure it still meets the project's requirements. Evaluate its scalability, performance, and data isolation capabilities. If necessary, update the instructions to reflect any changes to the strategy.
-
Tenant Context Management: Review how the application manages tenant context throughout the request lifecycle. Ensure that the tenant ID is correctly propagated and used to filter data access. Look for any potential vulnerabilities, such as tenant ID spoofing or unauthorized access to other tenants' data.
-
Authentication Mechanisms: Evaluate the authentication mechanisms in use (e.g., JWT, OAuth 2.0, SAML) and ensure they are secure and up-to-date. Verify that access tokens are properly validated and that user credentials are securely stored and managed.
-
Authorization Policies: Review the authorization policies that govern access to resources and functionalities. Ensure that users only have access to the resources they are authorized to use. Implement role-based access control (RBAC) or attribute-based access control (ABAC) as appropriate.
-
Security Best Practices: Ensure that the instructions incorporate the latest security best practices, such as using strong passwords, implementing multi-factor authentication (MFA), and protecting against common web vulnerabilities like SQL injection and cross-site scripting (XSS).
-
Compliance Requirements: If the application is subject to any regulatory compliance requirements (e.g., GDPR, HIPAA), ensure that the instructions address these requirements and that the authentication and multitenancy mechanisms are compliant.
-
Documentation: Verify that the instructions are clear, concise, and easy to follow. Include examples and diagrams to illustrate key concepts and workflows. Ensure that the documentation is kept up-to-date as the project evolves.
By conducting regular reviews and updates of the multitenancy and authentication instructions, you can ensure that these critical aspects of the application remain robust and secure. This proactive approach helps to mitigate risks and maintain the integrity of the system.
9. Add Links to Related Documentation or Reference Repos
Providing links to related documentation or reference repositories enhances the copilot-instructions.md
file's value. For example, linking to the siga-nestjs
repository can provide additional context and guidance. These links serve as valuable resources for developers and AI tools alike, offering deeper insights into the project's design and implementation.
Adding links to related documentation and reference repositories is a simple yet powerful way to enhance the utility of the copilot-instructions.md
file. These links serve as valuable resources for both human developers and AI tools, providing additional context, guidance, and examples. By curating a collection of relevant links, you can create a comprehensive knowledge hub that supports the project's development and maintenance efforts. This section should emphasize the importance of these links and provide guidelines for selecting and organizing them.
Consider the following types of links to include:
-
Reference Repositories: Link to other repositories that exemplify best practices, architectural patterns, or specific functionalities used in the project. For example, linking to the
siga-nestjs
repository, as mentioned in the original instructions, can provide insights into multitenancy implementations in NestJS. Other potential reference repositories might include open-source libraries, frameworks, or example projects that align with the project's technology stack and architecture. -
Official Documentation: Link to the official documentation for the technologies used in the project, such as NestJS, TypeORM, PostgreSQL, and any other relevant libraries or frameworks. These links provide developers with access to the most up-to-date information on APIs, configurations, and best practices.
-
Design Documents: Link to any design documents, architectural diagrams, or technical specifications that describe the project's overall structure, components, and interactions. These documents provide a high-level overview of the system and can help developers understand the rationale behind design decisions.
-
Coding Standards and Style Guides: Link to the project's coding standards, style guides, and linting configurations. These resources ensure that code is written consistently and adheres to established best practices.
-
API Documentation: Link to the project's API documentation, such as Swagger/OpenAPI specifications. This allows developers to easily explore the available endpoints, request/response schemas, and authentication requirements.
-
Tutorials and Articles: Link to relevant tutorials, articles, and blog posts that provide guidance on specific topics or technologies used in the project. These resources can help developers learn new concepts and techniques.
-
Community Forums and Discussion Boards: Link to community forums, discussion boards, and Stack Overflow threads where developers can ask questions and share knowledge about the project and its underlying technologies.
When adding links, be sure to provide a brief description of each link's purpose and content. This helps developers quickly identify the resources that are most relevant to their needs. Organize the links into logical categories to make them easier to navigate. Regularly review the links to ensure they are still valid and up-to-date.
By curating a comprehensive collection of links, you can create a valuable resource that supports the project's development and maintenance efforts. This not only improves the productivity of developers but also enhances the project's overall knowledge sharing and collaboration.
10. Keep or Update the Future Goals Section
The future goals section provides a roadmap for the project's evolution. Clarify which goals are pending and which are already in progress. This ensures that the project's direction is transparent and that developers and AI tools are aligned with its long-term objectives.
The Future Goals section of the copilot-instructions.md
file serves as a strategic roadmap, outlining the project's planned enhancements, features, and long-term objectives. This section is crucial for maintaining alignment among developers, stakeholders, and AI tools, ensuring everyone is working towards the same vision. Regularly reviewing and updating this section is essential to reflect the project's progress, changing priorities, and emerging opportunities. This section should provide clear guidelines for defining, prioritizing, and communicating future goals.
When reviewing the Future Goals section, consider the following aspects:
-
Clarity and Specificity: Ensure that each goal is clearly defined and specific, leaving no room for ambiguity. Use concrete language and measurable outcomes whenever possible. For example, instead of stating "Improve performance," specify "Reduce API response time by 20%" or "Optimize database queries to handle 10,000 concurrent users."
-
Prioritization: Prioritize the goals based on their impact, urgency, and feasibility. Use a framework like the Eisenhower Matrix (Urgent/Important) or a simple High/Medium/Low prioritization scheme. Clearly indicate the priority of each goal in the
copilot-instructions.md
file. -
Status Tracking: Track the status of each goal, indicating whether it is pending, in progress, completed, or abandoned. This provides a clear view of the project's progress and helps identify any roadblocks or delays. Use a consistent status nomenclature, such as "Pending," "In Progress," "Completed," "Blocked," or "Deferred."
-
Roadmap Integration: Integrate the future goals into a broader project roadmap, which may include timelines, milestones, and dependencies. This provides a visual representation of the project's trajectory and helps stakeholders understand the overall plan.
-
AI Alignment: Ensure that the future goals are aligned with the capabilities and limitations of AI tools. Identify areas where AI can assist in achieving the goals, such as code generation, testing, or documentation. Provide specific instructions or prompts that AI tools can use to contribute to these goals.
-
Stakeholder Input: Solicit input from stakeholders, including developers, product owners, and users, when defining and prioritizing future goals. This ensures that the goals are aligned with the needs and expectations of all parties involved.
-
Regular Review: Schedule regular reviews of the Future Goals section to assess progress, adjust priorities, and incorporate new ideas. This ensures that the project remains agile and responsive to changing circumstances.
By maintaining a clear and up-to-date Future Goals section, you provide a valuable guide for the project's evolution. This not only helps to keep the project on track but also empowers developers and AI tools to contribute effectively to its long-term success.
11. Commit the Updated File
Finally, commit the updated `copilot-instructions.md` file using the following commit message: `docs: update copilot-instructions with project conventions and best practices`. This commit message clearly communicates the purpose of the changes, making it easier to track the evolution of the project's guidelines.
🤖 Execution
This issue is primarily assigned to GitHub Copilot or a team member. If the AI cannot fully complete the task, it should clearly mark any remaining tasks with <!-- TODO -->
tags. This ensures that manual input can be easily identified and addressed, maintaining a smooth workflow.
By diligently performing these tasks, we can create a copilot-instructions.md
file that significantly enhances our project's development process, ensuring code quality, consistency, and efficient collaboration with AI tools.