EN
JavaScript Project Guidelines
Git workflow, dependencies, testing, API design and security practices for JavaScript projects, after Elsewhen's Project Guidelines. Source: envico801, after Project Guidelines by Elsewhen, https://github.com/envico801/project-guidelines (MIT), converted for RepeatMe.
Что внутри
- What is the best practice for JSON property names in request and response bodies?
- Use camelCase for JSON property names in request and response bodies to maintain consistency, especially as JavaScript is typically used for JSON parsing and generation.
- When are verbs appropriate in API URLs?
-
Use verbs in non-resource URLs when the endpoint doesn’t return a resource but performs an action, delivering the result. These are not CRUD operations. Example:
/translate?text=Hallo
For CRUD operations, use HTTP methods on resource or collection URLs. Verbs in this context generally refer to Controllers, and typically only a few are needed.
References:
API Guidelines: Controller Usage - In API design, it’s recommended to exclude […] from resource URLs to avoid an excess of URLs and inconsistent patterns.
- verbs
- In API design, it’s recommended to exclude verbs from […] to avoid an excess of URLs and inconsistent patterns.
- resource URLs
- In API design, it’s recommended to exclude verbs from resource URLs to avoid […] and inconsistent patterns.
- an excess of URLs
- In API design, it’s recommended to exclude verbs from resource URLs to avoid an excess of URLs and […].
- inconsistent patterns
- What is the recommended URL format for identifying specific resources?
-
Use a singular resource that begins with a collection and ends with an identifier, for example:
/students/245743
/airports/kjfk
Avoid formats like:
GET /blogs/:blogId/posts/:postId/summary
This structure targets a *property* rather than a resource. Instead, include the property as a parameter to simplify responses. - How should plural nouns be used in variables and properties within source code?
- In source code, represent plural collections with variables or properties by adding a List suffix. Plural naming in URLs is clearer, though in code, it can lead to subtle errors.
- Why should plural nouns be used for collection URLs in APIs?
-
Plural nouns (e.g., /users) in collection URLs enhance readability and provide a consistent URL structure.
References:
RESTful API Design: Plural Nouns and Concrete Names
Web Archive (it will take some time to load) - What is the recommended case for query string parameters and resource fields?
-
Use camelCase for parameters in query strings or resource fields.
Examples:
Query string parameters:
https://api.example.com/users?firstName=John&lastName=Doe&sortBy=createdDate
JSON resource fields:
{
"firstName": "John",
"lastName": "Doe",
"createdDate": "2023-11-21",
"contactInfo": {
"phoneNumber": "123-456-7890",
"emailAddress": "john.doe@example.com"
}
} - Which naming convention should be used for URLs and resource names in API design?
- Use kebab-case for URLs and plural kebab-case for resource names within URLs.
- What advantages does resource-oriented design offer for API development?
-
Resource-oriented design benefits API development by:
Being familiar to developers, who are the primary API users.
Improving readability and ease of use.
Supporting generic libraries and connectors without requiring detailed API structure knowledge. - What are the core components of resource-oriented API design?
-
The three main components in resource-oriented API design are:
Resources: Have data, may be nested, and have methods for operation.
Collections: Groups of resources.
URLs: Identify the online location of resources or collections. - Name two widely used tools for API documentation: […] and Swagger.
- API Blueprint
- Name two widely used tools for API documentation: API Blueprint and […].
- Swagger
- Why is documenting all potential error responses crucial for API usability?
- Documenting all possible error responses helps avoid assumptions by API users and sets clear expectations for handling potential failures.
- How should API documentation detail potential error responses?
-
Document Error Responses by including:
Possible failure scenarios for each endpoint (e.g., unauthorized access, incorrect parameters)
Error code, message, and description for each type of error
For example:
{
"code": 401,
"message": "Authentication failed",
"description": "Invalid username or password"
} - What should be outlined in the Success Response section of API documentation?
-
The Success Response section should include:
The expected status code
Any return data expected
For example:
Code: 200
Content: { id : 12 } - For POST requests in API documentation, provide […] and categorize parameters into Optional and Required sections.
- working examples
- For POST requests in API documentation, provide working examples and categorize parameters into […] and Required sections.
- Optional
- For POST requests in API documentation, provide working examples and categorize parameters into Optional and […] sections.
- Required
- How should API documentation address URL parameters?
-
Document URL parameters by:
Specifying whether they are required or optional
Naming each parameter and indicating its data type
For example:
Required: id=[integer]
Optional: photo_id=[alphanumeric] - What structure information should be included when explaining an API's URL format?
- When explaining the URL structure of an API, include the path (excluding the root URL) and specify the HTTP request method for each endpoint.
- How should API authentication methods be represented in documentation?
- API authentication methods should be documented with a code sample to demonstrate proper usage clearly.
- What essential details belong in the API Reference section of README.md?
-
The API Reference section in README.md should provide a comprehensive overview of the API, covering authentication methods, URL structure, request types, and endpoint information.
References:
README.md Template - Where is a reliable checklist for API security practices available?
-
The API Security Checklist Project offers a detailed list of best practices for securing APIs effectively.
References:
Comprehensive API Security Checklist on GitHub - How can APIs ensure robust data validation?
- APIs should validate all data exchanged—including both incoming requests and outgoing responses—to ensure data integrity, accuracy, and security.
- How can HTTP headers enhance API security?
-
Setting HTTP headers appropriately can help secure your API by restricting shared information. The Helmet project provides middleware for Express apps that configures headers to bolster security.
References:
Helmet Middleware for HTTP Header Security - When validating the content-type in API requests, prioritize accepting […]. Allowing other MIME types like application/x-www-form-urlencoded can enable attackers to create a form and trigger a POST request.
- application/*json
- When validating the content-type in API requests, prioritize accepting application/*json. Allowing other MIME types like […] can enable attackers to create a form and trigger a POST request.
- application/x-www-form-urlencoded
- When validating the content-type in API requests, prioritize accepting application/*json. Allowing other MIME types like application/x-www-form-urlencoded can enable attackers to […].
- create a form and trigger a POST request
- Why is JSON serialization a security necessity for API responses?
- JSON serialization prevents potential JavaScript remote code execution in both browsers and Node.js environments. A proper serializer ensures user-supplied data is encoded accurately, blocking unintended execution of such data on the client side.
- What steps should an API take to handle incoming data securely?
- An API should normalize received data or reject it if it doesn't meet standards. When errors occur due to bad or missing data, the API should respond with a 400 Bad Request and include relevant error details.
- Why is Rate Limiting a key element for API security?
- Rate Limiting protects your API from bot attacks and excessive requests. By setting rate limits early in API development, you help prevent abuse and conserve resources effectively.
- To maximize API security, […] should be short-lived, and all non-TLS requests should be rejected with a 403 Forbidden response.
- Authorization Code
- To maximize API security, Authorization Code should be […], and all non-TLS requests should be rejected with a 403 Forbidden response.
- short-lived
- To maximize API security, Authorization Code should be short-lived, and all […] should be rejected with a 403 Forbidden response.
- non-TLS requests
- To maximize API security, Authorization Code should be short-lived, and all non-TLS requests should be rejected with a […] response.
- 403 Forbidden
- What is the best way to include authentication tokens in API requests?
- Include authentication tokens in each request using the Authorization header (e.g., Authorization: Bearer xxxxxx, Extra yyyyy). Avoid placing tokens in the URL to minimize security risks.
- Why is it unsafe to use basic authentication without HTTPS?
-
Avoid basic authentication over unsecured connections, as it transmits the user ID and password in plain text (encoded in base64, which is easily reversible). Without HTTPS, this information can be intercepted, posing a significant security risk.
References:
Importance of HTTPS for Basic Authentication - How should security exceptions be represented in API response messages?
- Use generic messages for security exceptions to avoid disclosing sensitive information. For instance, instead of saying "incorrect password", use a message like "invalid username or password" to prevent revealing that the username is correct.
- Why is it essential to use common HTTP status codes in API responses?
-
Using common HTTP status codes is important because most developers don't memorize all HTTP status codes. Relying on a familiar subset prevents developers from needing to look up each code's meaning, making workflows more efficient. This practice also aligns with the limited subset used by most API providers for consistency.
References:
Why Use Standard HTTP Status Codes
Web Archive (it will take some time to load) - In API design, it’s recommended to provide […] in your response and to accept limit and offset parameters for pagination.
- total numbers of resources
- In API design, it’s recommended to provide total numbers of resources in your response and to accept […] and offset parameters for pagination.
- limit
- In API design, it’s recommended to provide total numbers of resources in your response and to accept limit and […] parameters for pagination.
- offset
- In API design, it’s recommended to provide total numbers of resources in your response and to accept limit and offset parameters for […].
- pagination
- How can API responses limit the data they return?
-
Use a fields query parameter to specify a comma-separated list of fields to include in the response. For example:
GET /students?fields=id,name,age,class
This limits the data returned, improving performance and minimizing data transfer. - What key HTTP status codes should be used in API responses, and what do they indicate?
-
Key HTTP status codes include:
200 OK: Successful GET, PUT, or POST requests.
201 Created: New resource successfully created (used with POST).
204 No Content: Success with no content to return (common for DELETE success).
304 Not Modified: Indicates a cached version can be used, reducing data transfer.
400 Bad Request: The request could not be understood or was incorrect.
401 Unauthorized: Request is missing valid credentials; re-authentication needed.
403 Forbidden: Server understood the request but refuses authorization.
404 Not Found: The requested resource does not exist.
500 Internal Server Error: A valid request could not be processed due to server error. - An effective error message response in an API should include a […], a message, and a description. For validation errors, it should also include an errors array with detailed information on each error.
- code
- An effective error message response in an API should include a code, a […], and a description. For validation errors, it should also include an errors array with detailed information on each error.
- message
- An effective error message response in an API should include a code, a message, and a […]. For validation errors, it should also include an errors array with detailed information on each error.
- description
- An effective error message response in an API should include a code, a message, and a description. For validation errors, it should also include an […] array with detailed information on each error.
- errors
- How should API versioning be implemented in URLs?
-
Use an ordinal number with a "v" prefix (e.g., v1, v2) for versioning and place it at the beginning of the URL to give it higher scope. For example:
http://api.domain.com/v1/schools/3/students
Versioning is helpful for public APIs as it allows changes without breaking existing implementations that third-party services rely on.
References:
RESTful API Design Tips: Versioning
Web Archive (it will take some time to load) - What is the best way to structure URLs for nested resources?
-
For nested resources, use URLs that represent the relationship between them. Examples:
GET /schools/2/students retrieves all students from school with ID 2.
GET /schools/2/students/31 retrieves details of student 31 from school 2.
DELETE /schools/2/students/31 removes student 31 from school 2.
PUT /schools/2/students/31 updates information for student 31. Only use PUT on resource URLs, not on collections.
POST /schools creates a new school and returns details of the newly created school. Use POST on collection URLs. - How should HTTP methods represent CRUD operations in API design?
-
Represent CRUD operations with HTTP methods as follows:
GET: Retrieve a resource's representation.
POST: Create new resources or sub-resources.
PUT: Update existing resources.
PATCH: Partially update existing resources with specified fields.
DELETE: Remove existing resources. - Why should table and column names be avoided as resource names and properties in APIs?
- Avoid using table_name for resource names and column_name for resource properties because an API should expose resources rather than the underlying database schema. This abstraction helps keep the API design separate from database structure.
- What are the advantages of using logging libraries in production?
- Logging libraries improve the troubleshooting experience by offering features like colorization, timestamps, file-based logging alongside console logging, and even daily log rotation. Read more on logging best practices.
- What is the recommended method for logging in production environments?
- Use logging libraries like winston or node-bunyan for production logging. These tools enhance readability and manage logs more effectively than console logs.
- Why is it important to avoid client-side console logs in production?
- While the build process should remove them, it's essential to have code style checks that flag any leftover console logs, preventing unintentional logging in production.
- What is the benefit of using Prettier with a precommit hook?
- Using Prettier with a precommit hook, along with lint-staged and husky, streamlines the process of code formatting. This setup saves time, as Prettier runs automatically before each commit, ensuring code consistency across the project. More on lint-staged and on husky.
- Why consider using Git hooks in your workflow?
- Git hooks improve productivity by automating certain checks before code commits, reducing the chance of breaking builds in staging or production environments. Learn more about Git hooks.
- How can editors be set up to flag code style errors?
- Use eslint-plugin-prettier and eslint-config-prettier with ESLint to integrate Prettier and receive notifications for code style issues within the editor. Read more.
- What is the purpose of a .editorconfig file?
- A .editorconfig file helps maintain consistent coding styles across different editors and IDEs within a project. It defines coding styles and integrates well with version control systems, making it easy for developers to adhere to set conventions.
- How should functions be organized within a file?
-
Organize functions in a file according to the step-down rule, placing higher-level functions at the top and lower-level functions below for readability and logical flow.
// Higher-level function at the top
function processUserData(userData) {
const validatedData = validateUserInput(userData);
const normalizedData = normalizeUserData(validatedData);
return saveToDatabase(normalizedData);
}
// Mid-level supporting functions
function validateUserInput(userData) {
validateEmail(userData.email);
validateAge(userData.age);
return userData;
}
function normalizeUserData(userData) {
return {
email: userData.email.toLowerCase(),
age: Number(userData.age),
lastUpdated: new Date(),
};
}
// Lower-level utility functions at the bottom
function validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
throw new Error('Invalid email format');
}
}
function validateAge(age) {
if (age < 0 || age > 120) {
throw new Error('Invalid age');
}
}
function saveToDatabase(data) {
// Database saving logic here
return data;
}
This example shows how to organize functions with:
The main high-level function processUserData at the top, which describes the overall business logic
Supporting functions validateUserInput and normalizeUserData in the middle
Utility functions like validateEmail, validateAge, and saveToDatabase at the bottom - What naming convention is recommended for functions?
-
Use long, descriptive names for functions. A function name should be a verb or verb phrase that clearly communicates its intention and functionality.
References:
Function names should say what they do
Anki deck created from this repository - Why should irrelevant or humorous comments, logs, or names be avoided?
- Avoid irrelevant or humorous comments, logs, or naming. While these may be removed during the build process, source code might be handed to a different company or client, who may not appreciate this style.
- Comments should be […] as code changes, and commented blocks of code should be removed.
- kept relevant
- Comments should be kept relevant as code changes, and […] should be removed.
- commented blocks of code
- Comments should be kept relevant as code changes, and commented blocks of code should be […].
- removed
- How should small tasks be marked in the code?
- Use //TODO: comments for small tasks. For larger tasks, use //TODO(#3456), where the number corresponds to an open ticket for tracking.
- What should be done with eslint disable comments before submitting a Pull Request?
- Remove all eslint disable comments before submitting a Pull Request to maintain code quality and style standards.
- What is the purpose of the .eslintignore file?
- Use the .eslintignore file to exclude specific files or folders from code style checks, avoiding the need for eslint-disable comments within the code.
- Which JavaScript Style Guide is recommended?
-
The Airbnb JavaScript Style Guide is recommended for consistency and best practices.
Additional Resources:
More on Airbnb’s guide - Why is ESLint preferred for enforcing code style?
- ESLint offers extensive support for rules, customization options, and custom rule additions, making it highly flexible for enforcing code style.
- What tool is recommended to enforce JavaScript code style?
- Use ESLint - Pluggable JavaScript linter to enforce code style in JavaScript projects.
- Code style checks should be included in your […].
- build process
- Why should stage-2 and higher JavaScript syntax be used?
- Stage-2 syntax is more stable and likely to become part of the official JavaScript specification, often with minor changes. Transpilers allow projects to leverage these features even before full browser support.
- What JavaScript syntax is recommended for new projects?
- Use stage-2 or higher (modern) JavaScript syntax for new projects. For older projects, remain consistent with the existing syntax unless you intend to modernize the project.
- How Should Build Output Be Managed in Version Control?
-
Build output should follow these conventions:
project/
├── build/ # Contains generated files
│ ├── dist/ # Distribution-ready files
│ ├── temp/ # Temporary build artifacts
│ └── reports/ # Build reports and stats
├── src/ # Source code
└── .gitignore # Git configuration
Example .gitignore entry:
# Ignore all build output
/build
# Exceptions (if any)
!/build/.gitkeep
Reasons for not committing build output:
Reproducibility: Build files can be regenerated by any team member using the source code and build scripts
Version Control Efficiency:
Prevents repository bloat
Avoids unnecessary merge conflicts
Keeps commit history focused on actual code changes
Build Environment Consistency:
Ensures everyone uses the same build process
Prevents issues from environment-specific builds
CI/CD Best Practices:
Builds should be performed in CI/CD pipelines
Each deployment should use freshly built files
Exceptions where you might commit build output:
GitHub Pages requiring built static files
Documentation sites that need pre-built assets
Libraries that provide pre-built distributions for convenience
In these cases, document the exception in the repository README and consider using git submodules or dedicated branches for built files. - How Should Project Scripts Be Organized and Why?
-
Place all project scripts (bash, node, etc.) in a dedicated ./scripts folder for better organization. This practice offers several benefits:
project/
├── scripts/
│ ├── build/
│ │ ├── production.js
│ │ └── development.js
│ ├── db/
│ │ ├── migrate.sh
│ │ ├── seed.js
│ │ └── sync.sh
│ ├── deploy/
│ │ ├── staging.sh
│ │ └── production.sh
│ └── tests/
│ ├── e2e.js
│ └── setup-test-db.sh
├── src/
└── package.json
Common script categories include:
Build scripts (production, development, staging)
Database management (migrations, seeding, backups)
Deployment automation
Test setup and execution
Development environment setup
Code generation tools
CI/CD helpers
This organization:
Makes scripts easily discoverable
Prevents cluttering the root directory
Allows for logical grouping of related scripts
Simplifies script management in package.json:
{
"scripts": {
"build:prod": "node scripts/build/production.js",
"build:dev": "node scripts/build/development.js",
"db:migrate": "bash scripts/db/migrate.sh",
"db:seed": "node scripts/db/seed.js",
"deploy:staging": "bash scripts/deploy/staging.sh"
}
} - How should values for configuration files be supplied?
-
Use environment variables to provide values for config files, keeping configuration flexible and secure.
References:
Read more on configuration management - Config files should be placed in a […] folder, and you should not make different config files for different environments.
- ./config
- Config files should be placed in a ./config folder, and you should […] for different environments.
- not make different config files
- Config files should be placed in a ./config folder, and you should not make different config files for […].
- different environments
- In a well-organized project structure, you should create […] that encapsulate one responsibility including its test.
- small modules
- In a well-organized project structure, you should create small modules that […] including its test.
- encapsulate one responsibility
- In a well-organized project structure, you should create small modules that encapsulate one responsibility including its […].
- test
- How should project files be organized?
-
Organize files around product features, pages, or components, rather than by role. Place test files next to the code they test.
Bad
.
├── controllers
| ├── product.js
| └── user.js
├── models
| ├── product.js
| └── user.js
Good
.
├── product
| ├── index.js
| ├── product.js
| └── product.test.js
├── user
| ├── index.js
| ├── user.js
| └── user.test.js - Why is test documentation important?
- Documenting tests provides clarity and context, making it easier for other developers, DevOps, QA, and future contributors to understand and run tests effectively.
- When and why should you run tests during the development workflow?
-
Run tests:
Locally before creating pull requests to the develop branch
After performing a rebase
Before pushing code to a remote repository
Benefits:
Ensures code changes are stable
Reduces potential integration issues
Prevents build failures on production-ready branches
Catches errors early in the development process
Maintains the quality of the shared codebase
This approach helps catch and resolve potential problems before they impact other team members or CI/CD pipelines. - What is the benefit of using a static type checker in testing?
-
A static type checker enhances reliability by catching type-related errors before runtime, contributing to more robust code.
References:
FreeCodeCamp article on static types - Why is it beneficial to use pure functions for testable code?
-
Pure functions make your code more reliable by allowing you to:
Test business logic independently as isolated units.
Minimize the impact of randomness and external conditions, which could reduce test reliability.
References:
Read more on test-driven development - A […] is a function that always returns the same output for the same input and has no side effects.
- pure function
- A pure function is a function that always returns the […] for the same input and has no side effects.
- same output
- A pure function is a function that always returns the same output for the […] and has no side effects.
- same input
- What are the key characteristics of testable code?
-
Testable code should:
Avoid side effects.
Extract side effects to isolated functions.
Make use of pure functions for predictable results. - Why is the __test__ folder name widely adopted?
- The __test__ folder name is considered a standard convention and is automatically recognized by many JavaScript testing frameworks.
- Where should additional test files that don’t relate to specific files be stored?
- Store additional test files in a separate folder, usually named __test__, to keep them distinct from specific implementation files and reduce confusion.
- Test files should be placed […] using the naming convention *.test.js or *.spec.js.
- next to the tested modules
- Test files should be placed next to the tested modules using the naming convention […] or *.spec.js.
- *.test.js
- Test files should be placed next to the tested modules using the naming convention *.test.js or […].
- *.spec.js
- Why is a separate test mode environment often necessary?
-
A separate test mode environment can help avoid issues such as:
Preventing test data from affecting production analytics or dashboards.
Avoiding production API rate limits, which might block test calls if exceeded. - When updating dependencies, it's important to always check their […] when updates show up to be aware of potential breaking changes.
- release notes
- When updating dependencies, it's important to always check their release notes when updates show up to be aware of potential […].
- breaking changes
- How can you check for security vulnerabilities in npm packages?
- Use tools like Snyk to scan for known security vulnerabilities in npm packages.
- What tool can simplify the process of updating npm packages?
- The npm-check-updates tool can help manage npm package updates more efficiently.
- Why is it beneficial to update dependencies one at a time?
- Updating dependencies one by one simplifies troubleshooting, making it easier to identify and resolve issues if something goes wrong.
- To ensure your app works with the latest version of its dependencies without breaking, use the command […].
- npm outdated
- What should you do before using a lesser-known dependency?
- Discuss using any lesser-known dependencies with the team to ensure alignment and evaluate potential risks or alternatives.
- Why is maintainer activity crucial when selecting a dependency?
- Active maintainers are essential for quickly merging fixes and patches, ensuring your project can receive timely updates and improvements.
- What should you evaluate before adding a new npm dependency?
-
Before using a dependency, evaluate its release frequency, number of maintainers, and download statistics to determine if it is widely used and actively maintained. This helps ensure community support, ongoing updates, and timely bug fixes.
References:
npm view command documentation
npm-stat usage statistics - Why is it important to remove unused dependencies?
- Removing unused dependencies helps reduce the production bundle size, which improves optimization and load times.
- What tool helps identify unused or irrelevant packages in a project?
-
Use the depcheck tool to check for packages that have become unused or irrelevant in your project.
References:
Depcheck npm package - How can you list currently available npm packages in your project?
-
You can use the command npm ls --depth=0 to list currently available packages in your project.
References:
npm ls command documentation - How can you ensure consistent dependencies when using older versions of npm?
-
For older versions of npm, use --save --save-exact when installing a new dependency and create an npm-shrinkwrap.json file before publishing. This will lock dependencies to specific versions, similar to package-lock.json in newer npm versions.
References:
npm documentation on package locks - To ensure consistent dependencies across a team, use […] on npm@5 or higher, or alternatively use Yarn.
- package-lock.json
- To ensure consistent dependencies across a team, use package-lock.json on […] or higher, or alternatively use Yarn.
- npm@5
- To ensure consistent dependencies across a team, use package-lock.json on npm@5 or higher, or alternatively use […].
- Yarn
- Why is it preferable to use local modules instead of globally installed ones?
- Local modules ensure that tooling is shared among team members, avoiding the need for each person to install global dependencies on their own systems.
- What are the benefits of using Docker in a project?
-
Docker provides a consistent environment across development, testing, and production, minimizing dependency and configuration issues.
References:
Guide to Dockerizing a Node.js application - Why should a preinstall script be added to a project?
- A preinstall script that checks node and npm versions helps avoid dependency issues, which can arise if dependencies are installed with incompatible npm versions.
- What is the purpose of using nvm and a .nvmrc file in a project?
-
A .nvmrc file and nvm allow users to switch to the correct node version with nvm use, ensuring a consistent environment.
Note: nvm allows you to quickly install and use different versions of node via the command line.
References:
nvm repository - To specify the node version for a project, set it in the […] field of package.json.
- engines
- To specify the node version for a project, set it in the engines field of […].
- package.json
- Why is it advised to validate environment variables before the app starts?
-
Validating environment variables can prevent long troubleshooting sessions by catching errors early. Libraries like joi can be helpful for validating these values.
References:
Sample configuration with validation - How should environment variables be handled in a project?
-
Store environment variables in .env files and exclude them from version control using .gitignore. Commit a .env.example file as a guide for developers, and set environment variables through standard means for production.
References:
Guide to managing environment variables in Node.js - Why should deployment-specific configurations be loaded from […] instead of added as constants in the codebase?
- environment variables
- Why is it essential to define separate environments in a project?
-
Different environments often require distinct configurations, such as data sources, tokens, APIs, and ports. For example, development mode might use a fake API for testing, while production may have Google Analytics enabled.
References:
Learn more about environment-specific configs - What are the three main environments commonly defined in a project?
- The three main environments typically defined are development, test, and production.
- How should comments be maintained as code evolves?
- Update or remove comments as your code changes to keep them relevant and accurate. Outdated comments can be misleading, so they should evolve alongside the code they describe.
- Comments should not be used as an […]. Instead, you should keep your code clean.
- excuse for bad code
- Comments should not be used as an excuse for bad code. Instead, you should […].
- keep your code clean
- When should you include links to external discussions in your code comments?
- Include links to open discussions (e.g., on GitHub or StackOverflow) within comments when they provide helpful context or detail for the approach you're using.
- How Should Code Comments Be Used to Enhance Code Quality?
-
Comments and clean code work together to create maintainable software. While code should be as readable as possible, comments serve specific purposes:
Explain the intent and reasoning:
// BAD - Comment states the obvious
function calculateTotal(items) {
// Loop through items and add prices
return items.reduce((sum, item) => sum + item.price, 0);
}
// GOOD - Comment explains the business logic
function calculateTotal(items) {
// Include bulk discount when order contains more than 10 items
// This matches our Q4 2024 pricing strategy
return items.reduce(
(sum, item) => sum + item.getDiscountedPrice(items.length),
0,
);
}
Clarify complex or non-obvious logic:
// BAD - Comment just restates the code
function calculateDateDifference(startDate, endDate) {
// Subtract dates and convert to days
return Math.floor((endDate - startDate) / (1000 60 60 24));
}
// GOOD - Explains domain-specific logic and edge cases
function calculateDateDifference(startDate, endDate) {
// For billing purposes, partial days are counted as full days
// following financial regulation §34.2.1
// e.g., 1.5 days = 2 days, 2.1 days = 3 days
// This ensures compliance with contract terms requiring
// minimum one-day billing even for same-day services
return Math.ceil((endDate - startDate) / (1000 60 60 24));
}
Document why certain decisions were made:
// BAD - Comment explains implementation without context
function sanitizeUserInput(input) {
// Replace special characters and trim spaces
return input.replace(/[<>]/g, '').trim();
}
// GOOD - Documents security decisions and their rationale
function sanitizeUserInput(input) {
/*
Custom sanitization implementation because:
1. DOMPurify is too heavyweight for our use case
(adds 45KB to bundle size)
2. We only need to handle basic text inputs
3. Full HTML sanitization happens server-side
SECURITY NOTICE: This method is NOT sufficient for
sanitizing HTML content or preventing XSS in HTML contexts.
Review security policy SP-2024-03 before modifying.
Reference: https://docs.aws.amazon.com/transfer/latest/userguide/security-policies-connectors.html
/
return input.replace(/[<>]/g, '').trim();
}
Remember:
Clean code reduces the need for obvious comments
Comments should explain the "why" rather than the "what"
Keep comments up-to-date with code changes
Use comments to provide context that can't be expressed in code alone
JSDoc comments for function documentation are still valuable even with clean code
// GOOD - JSDoc provides clear documentation while code remains clean
/*
Processes customer refund requests according to company policy
@param {Object} transaction - Transaction details
@param {string} transaction.id - Transaction ID
@param {number} transaction.amount - Original transaction amount
@param {Date} transaction.date - Transaction date
@param {string} reason - Refund reason code
@returns {Object} Refund details including approved amount
@throws {PolicyViolationError} If refund violates company policy
/
function processRefundRequest(transaction, reason) {
// Implementation...
} - How should the […] file be maintained as the project progresses?
- README.md
- How should documentation be organized for projects with multiple repositories?
- For multi-repository projects, include links to other repositories in each respective README.md file.
- What template should be used for a README.md file?
- Use this README.md template as a starting point. Add additional sections if needed.
- What potential legal issues should be considered when using images and videos in a project?
-
When using visual content in your project, consider these key points:
Copyright infringement: Using copyrighted images and videos without proper permission may cause legal problems
Attribution requirements: Some licenses require proper credit to the original creator
Usage restrictions: Some licenses may limit how you can use or modify the content
Commercial vs. non-commercial use: Different licenses may apply depending on your project's nature - When using resources in your project, it's important to ensure you have the […] them. For libraries, look for licenses such as MIT, Apache, or BSD.
- rights to use
- When using resources in your project, it's important to ensure you have the rights to use them. For libraries, look for licenses such as […].
- MIT, Apache, or BSD
- Where can I find comprehensive accessibility guidelines?
-
You can explore detailed accessibility guidelines at:
Deque University’s axe rules
W3C Web Content Accessibility Guidelines (WCAG)
WebAIM’s Accessibility Principles
These resources offer a broad range of best practices, standards, and rules to improve digital accessibility. - Why should images include alternative text?
- Screen readers can’t interpret images, so providing short, descriptive alt text enables visually impaired users to understand an image's content and intent, including images that are purely text.
- Why is sufficient contrast important for text accessibility?
- Sufficient contrast between text and background helps people with low vision by making outlines, borders, edges, and details clearer, improving readability.
- How does a semantic heading hierarchy enhance web accessibility?
-
Heading Structure Benefits:
Creates clear content hierarchy
Enables screen reader navigation
Helps users understand document structure
Best Practices:
Start with <h1> for primary page title
Use <h2>, <h3> hierarchically
Avoid skipping heading levels
Example:
<h1>Website Title</h1>
<h2>Main Section</h2>
<h3>Subsection Details</h3>
References:
WCAG Heading Guidelines
WebAIM Semantic Structure - How should lists be structured to support accessibility?
- For lists to be accessible, include both parent and child elements. Screen readers announce lists and item counts, so structuring them properly improves accessibility for users navigating with assistive devices.
- Why is accessible naming important for links?
- Poorly named or inaccessible link elements hinder usability. Adding aria-labels to describe links enhances accessibility for users who rely on assistive technologies.
- What are prominent design systems with strong accessibility considerations?
-
Accessibility-Focused Design Systems:
[Adobe React Spectrum](https://react-spectrum.adobe.com/react-spectrum/)
Fully WCAG 2.1 compliant
Built-in keyboard navigation
Screen reader support
Dynamic color contrast management
Comprehensive internationalization support
[Google Material Design](https://material.io/design)
Extensive accessibility guidelines
Semantic HTML components
High color contrast ratios
Adaptive typography
Robust keyboard interaction patterns
[Carbon Design System (IBM)](https://carbondesignsystem.com/)
Developed with accessibility at its core
Supports multiple frameworks (React, Angular, Vue)
Rigorous WCAG 2.1 compliance
Detailed accessibility documentation
References:
Web Content Accessibility Guidelines (WCAG)
W3C Accessibility Guidelines - How does a linter improve a project’s accessibility?
- An accessibility linter helps ensure that your project consistently meets baseline accessibility standards. It’s easy to set up and integrates well into most development workflows, providing ongoing accessibility feedback.
- Which accessibility linters are recommended for popular frameworks?
-
Recommended accessibility linters include:
React: eslint-plugin-jsx-a11y
Angular: Angular Codelyzer
Vue: eslint-plugin-vuejs-accessibility - What accessibility checks require manual verification?
-
Certain accessibility checks, like logical tab order and user interaction testing, require manual verification. Accessibility tools like Lighthouse and axe list these as manual/guided tests for additional inspection.
References:
Lighthouse accessibility score
Web Archive (it will take some time to load) - What tools and techniques are essential for comprehensive web accessibility testing?
-
Automated Testing Tools:
[Lighthouse](https://chromewebstore.google.com/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk) (Chrome DevTools)
Provides overall accessibility score
Generates detailed audit reports
Integrated directly in browser development tools
[axe DevTools](https://chromewebstore.google.com/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd) (Browser Extension)
Detailed accessibility violation detection
Provides specific remediation guidance
Supports WCAG 2.1 Level A & AA standards
For those using Storybook, consider implementing [accessibility testing with Storybook](https://storybook.js.org/blog/accessibility-testing-with-storybook/) to catch any changes impacting accessibility and audit scores.
Manual Testing Techniques:
Keyboard Navigation Testing
Verify all interactive elements are keyboard-accessible
Check focus states and tab order
Ensure no keyboard traps exist
Screen Reader Compatibility
Test with NVDA (Windows)
Test with VoiceOver (Mac)
Verify meaningful content hierarchy
Color Contrast Verification
Use tools like WebAIM Color Contrast Checker
Ensure minimum contrast ratios (4.5:1 for normal text)
Advanced Validation:
WAVE Web Accessibility Evaluation Tool
Pa11y for automated accessibility testing
Browser extensions for quick accessibility insights
Key References:
Web Accessibility Initiative (WAI)
axe Core Rule Descriptions
WCAG 2.1 Guidelines - Why should accessibility be prioritized from the start of a web project?
-
Web content is accessible by default, but complex features can reduce accessibility. Starting with accessibility in mind makes it easier to maintain rather than having to rework features later to comply with accessibility standards.
References:
Accessible HTML Guide on MDN - How can develop and master branches be protected from accidental changes?
-
Enable branch protection for develop and master to prevent unexpected and irreversible changes.
References:
GitHub - About protected branches
Bitbucket - Using branch permissions
GitLab - Protected branches - Why is a customized .gitignore file recommended?
- Use this .gitignore file as it excludes system files, editor settings, and common dependency folders that shouldn't be in a remote repository.
- Before making a Pull Request, ensure your feature branch […] and passes all tests, including code style checks.
- builds successfully
- Before making a Pull Request, ensure your feature branch builds successfully and […], including code style checks.
- passes all tests
- Before making a Pull Request, ensure your feature branch builds successfully and passes all tests, including […].
- code style checks
- What Cleanup Steps Should Be Taken After Merging Feature Branches?
-
After your feature branch has been merged (either through a Pull Request or direct merge), you should perform these cleanup steps:
Delete your local feature branch:
git branch -d <branchname>
Delete the remote feature branch to avoid repository clutter:
git push origin --delete <branchname>
Clean up any local branches that are no longer on the remote:
git fetch -p && for branch in `git branch -vv --no-color | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
These steps ensure that:
Your repository stays clean and organized
You avoid accidentally reusing old feature branches
Each feature branch is only merged once
Your local repository accurately reflects the remote state - When is it best to handle conflicts in Git?
- Resolve potential conflicts during rebasing and before submitting a Pull Request.
- What preparations are necessary before pushing a feature and making a Pull Request?
-
Update your local develop branch and perform an interactive rebase. This rebases the requested branch (master or develop) and applies your local commits at the top of the history without creating a merge commit, ensuring a clean history.
References:
Merging vs Rebasing by Atlassian - When working with Git, you should never push into […] or master branch. Instead, you should make a Pull Request.
- develop
- When working with Git, you should never push into develop or […] branch. Instead, you should make a Pull Request.
- master
- When working with Git, you should never push into develop or master branch. Instead, you should make a […].
- Pull Request
- What Should the Commit Message Body Focus on Explaining?
-
The body of a commit message should explain what and why changes are made, rather than focusing on how they were implemented.
Example of a poor commit message (focuses on how):
feat: Add user authentication
Created a new AuthService class
Added login() method with bcrypt
Modified UserController to use AuthService
Added password hashing function
Example of a good commit message (focuses on what and why):
feat: Add user authentication
Implement secure user authentication to protect sensitive user data
and meet compliance requirements for our banking features.
This change:
- Prevents unauthorized access to user accounts
- Adds industry-standard password security
- Addresses security audit finding #45
- Sets foundation for upcoming 2FA feature
Another good example:
fix: Update database connection timeout
Increase connection timeout from 5s to 30s to handle peak traffic
periods. Our monitoring shows connection failures during high load
times (>1000 concurrent users), causing customer complaints.
Related to incident #123
The body should provide context that future maintainers would need to understand why this change was necessary, not just what files were modified or how the code works. - Why is it important to use imperative mood in commit message subject lines?
-
The imperative mood frames the commit message as an instruction for what will happen after it’s applied, rather than a record of what was done.
References:
Why use imperative mood in commit messages - What are the best practices for formatting commit message subject lines?
-
Traditional Commit Message Rules:
Capitalize the first word.
Avoid ending with a period.
Use the imperative mood.
Example: Add user authentication
Conventional Commits Format ([Official Specification](https://www.conventionalcommits.org/)):
Structure: <type>[optional scope]: <description>
Common types include:
feat: for new features
fix: for bug fixes
docs: for documentation changes
style: for formatting
refactor: for code restructuring
test: for test-related changes
chore: for maintenance tasks
Example: feat(auth): add user login functionality
References:
conventional-commits-cheatsheet.md - When writing a commit message, limit the subject line to […] and wrap the body at 72 characters.
- 50 characters
- When writing a commit message, limit the subject line to 50 characters and wrap the body at […].
- 72 characters
- Which branch should be used as a starting point for feature branches?
- You should branch out from develop. This ensures that code in master will generally build without issues and can often be used directly for releases (though this may be overkill for smaller projects).
- How should you structure the subject and body of Git Commit messages??
-
Separate the subject from the body with a newline. Git will interpret the first line as the summary. You can use git shortlog to display only commit summaries.
References:
Guidelines for writing clear Git commit messages - What is a safer alternative to git push -f if others are working on the branch?
-
Use --force-with-lease instead of -f when others may also be working on the branch. It prevents overwriting changes someone else may have pushed.
References:
Explanation of --force-with-lease
Web Archive (it will take some time to load) - Why is the -f flag needed when pushing after a rebase?
-
After a rebase, Git rejects a normal git push due to changed history. Use the -f or --force flag to push:
git push -f - If you encounter conflicts during rebasing, you should […] and then continue the rebase using git rebase --continue.
- resolve them
- If you encounter conflicts during rebasing, you should resolve them and then continue the rebase using […].
- git rebase --continue
- What is the purpose of interactive rebasing in Git?
-
Interactive rebasing is a powerful feature in Git that allows you to edit, combine, or reorder commits in your branch history before applying them to another branch. It is commonly used to clean up commit history, fix mistakes, or squash multiple commits into a single one to make the history more concise and easier to understand.
Interactive rebasing is often used to update a feature branch with the latest changes from a target branch (e.g., develop). For example, you can use the following commands:
git checkout <branchname>
git rebase -i --autosquash develop
What does the -i flag do?
The -i flag stands for interactive mode. When used, it opens an editor where you can see a list of commits and choose actions to perform on each commit, such as:
Reword: Change the commit message.
Pick: Keep the commit as is.
Squash: Combine this commit with the previous one.
Drop: Remove the commit entirely.
Edit: Pause the rebase to make changes to the commit.
Without the -i flag, Git performs a non-interactive rebase, meaning it automatically replays all commits from your branch onto the target branch (develop in this case) without giving you the opportunity to modify, reorder, or squash commits. This can be faster if no changes to the commit history are needed, but it lacks the flexibility to clean up or reorganize commits.
What does the --autosquash option do?
The --autosquash option works in conjunction with interactive rebasing. It automatically groups and combines fixup commits (commits prefixed with fixup!) with their respective base commits during the rebase process. This ensures that the branch history is cleaner, with fewer intermediate commits, and helps maintain a more organized and professional commit log on the target branch.
Use Case:
By combining all related commits into a single, polished commit, interactive rebasing with -i and --autosquash keeps the develop branch cleaner and avoids clutter from multiple commits for a single feature.
References:
Interactive rebasing with --autosquash
References:
Interactive rebasing with autosquash - How do you sync your branch with the remote repository to get the latest changes?
-
To sync with the remote repository:
git checkout develop
git pull
This allows you to handle conflicts on your machine before rebasing or creating a Pull Request with conflicts. - What Git command allows you to review each change before committing?
- Use git add -p to review each change individually and decide if it should be included in the commit.
- In your Git workflow, stage specific files with […], then record those changes with a commit.
- git add <file1> <file2> ...
- In your Git workflow, stage specific files with git add <file1> <file2> ..., then […] with a commit.
- record those changes
- How do you create and manage a new feature or bug-fix branch in Git?
-
Create a new branch:
git checkout -b <branch-name>
Branch Naming Conventions:
Features: feature/add-login
Bugs: bugfix/auth-error
Push to remote:
git push -u origin <branch-name>
Best Practices:
Create from updated main/develop
Keep branches focused
Use pull requests for review
Delete after merging - How should you initialize a new project with Git?
-
In the project directory, initialize a git repository with these commands:
cd <project directory>
git init
Note: Skip this step for subsequent features or changes. - What is the best branch strategy for developing new features?
-
You should perform work in a feature branch. This way, all work is done in isolation on a dedicated branch rather than the main branch, allowing you to submit multiple pull requests without confusion. You can iterate without polluting the master branch with potentially unstable, unfinished code.
References:
Feature branch workflow by Atlassian