mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-21 21:18:50 -05:00
docs: coding standards (#4770)
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> Co-authored-by: Johannes <johannes@formbricks.com> Co-authored-by: Matti Nannt <mail@matthiasnannt.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
d082e7c44d
commit
ee2573d128
+23
-17
@@ -1,32 +1,38 @@
|
||||
# Mintlify Starter Kit
|
||||
# Formbricks Documentation
|
||||
|
||||
Click on `Use this template` to copy the Mintlify starter kit. The starter kit contains examples including
|
||||
This documentation is built using Mintlify. Here's how to run it locally and contribute.
|
||||
|
||||
- Guide pages
|
||||
- Navigation
|
||||
- Customizations
|
||||
- API Reference pages
|
||||
- Use of popular components
|
||||
## Local Development
|
||||
|
||||
### Development
|
||||
1. Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify):
|
||||
|
||||
Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the documentation changes locally. To install, use the following command
|
||||
|
||||
```
|
||||
```bash
|
||||
npm i -g mintlify
|
||||
```
|
||||
|
||||
Run the following command at the root of your documentation (where mint.json is)
|
||||
2. Clone the Formbricks repository and navigate to the docs folder:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/formbricks/formbricks.git
|
||||
cd formbricks/docs
|
||||
```
|
||||
|
||||
3. Run the documentation locally:
|
||||
|
||||
```bash
|
||||
mintlify dev
|
||||
```
|
||||
|
||||
### Publishing Changes
|
||||
The documentation will be available at `http://localhost:3000`.
|
||||
|
||||
Install our Github App to auto propagate changes from your repo to your deployment. Changes will be deployed to production automatically after pushing to the default branch. Find the link to install on your dashboard.
|
||||
### Contributing
|
||||
|
||||
#### Troubleshooting
|
||||
1. Create a new branch for your changes
|
||||
2. Make your documentation updates
|
||||
3. Submit a pull request to the main repository
|
||||
|
||||
- Mintlify dev isn't running - Run `mintlify install` it'll re-install dependencies.
|
||||
- Page loads as a 404 - Make sure you are running in a folder with `mint.json`
|
||||
### Troubleshooting
|
||||
|
||||
- If Mintlify dev isn't running, try `mintlify install` to reinstall dependencies
|
||||
- If a page loads as a 404, ensure you're in the `docs` folder with the `mint.json` file
|
||||
- For other issues, please check our [Contributing Guidelines](./CONTRIBUTING.md)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Contributing to Formbricks 🤗"
|
||||
title: "Contribute to Formbricks"
|
||||
description: "How to contribute to Formbricks"
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Development
|
||||
description: Learn how to setup formbricks locally and develop on it
|
||||
title: Overview
|
||||
description: Learn how to setup formbricks locally and build custom integrations and services.
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
---
|
||||
title: File and Directory Org.
|
||||
description: This document outlines the structure and organization of files and directories in the Formbricks codebase, providing guidelines for maintaining consistency and clarity across the project.
|
||||
icon: folder-tree
|
||||
---
|
||||
|
||||
## Project Structure Overview
|
||||
|
||||
The Formbricks codebase follows a monorepo structure using pnpm workspaces, with two main directories:
|
||||
|
||||
* `apps/` - Contains full applications
|
||||
|
||||
* `packages/` - Contains shared libraries and utilities
|
||||
|
||||
## Apps Directory
|
||||
|
||||
The `apps/` directory contains complete applications:
|
||||
|
||||
### apps/web/
|
||||
|
||||
* Main Formbricks web application (Next.js)
|
||||
|
||||
* Primary application with full feature set
|
||||
|
||||
* Uses App Router architecture
|
||||
|
||||
* Contains environment-specific settings and configurations
|
||||
|
||||
### apps/demo/
|
||||
|
||||
* Demo application (Next.js)
|
||||
|
||||
* Showcases Formbricks in-product surveying functionality
|
||||
|
||||
* Used for testing and demonstration purposes
|
||||
|
||||
### apps/demo-react-native/
|
||||
|
||||
* React Native demo app (React Native)
|
||||
|
||||
* Demonstrates mobile integration capabilities
|
||||
|
||||
* Example implementation for React Native
|
||||
|
||||
### apps/storybook/
|
||||
|
||||
* Component documentation
|
||||
|
||||
* Visual documentation of UI components
|
||||
|
||||
* Testing environment for isolated components
|
||||
|
||||
## Packages Directory
|
||||
|
||||
The `packages/` directory contains shared libraries and utilities:
|
||||
|
||||
### packages/js-core/
|
||||
|
||||
* Contains core functionality for in-product surveys
|
||||
|
||||
* Shared logic between different SDK implementations
|
||||
|
||||
* Base classes and utilities
|
||||
|
||||
### packages/js/
|
||||
|
||||
* JavaScript SDK for browser-based applications
|
||||
|
||||
* Used for running surveys on websites and web apps (browser)
|
||||
|
||||
* Public NPM package
|
||||
|
||||
### packages/react-native/
|
||||
|
||||
* React Native SDK
|
||||
|
||||
* Used to run surveys in mobile apps built with React Native / Expo
|
||||
|
||||
* Includes native platform adaptations
|
||||
|
||||
### packages/lib/
|
||||
|
||||
* Shared business logic
|
||||
|
||||
* Shared utilities and helpers
|
||||
|
||||
### packages/types/
|
||||
|
||||
* TypeScript type definitions
|
||||
|
||||
* Zod schemas for validation
|
||||
|
||||
### packages/database/
|
||||
|
||||
* Database schemas and migrations
|
||||
|
||||
* Prisma schema definitions
|
||||
|
||||
* Migration management
|
||||
|
||||
### packages/surveys/
|
||||
|
||||
* Survey-specific functionality
|
||||
|
||||
* Survey rendering logic and UI components
|
||||
|
||||
* Survey state management
|
||||
|
||||
## Module Organization
|
||||
|
||||
### Core Module Structure
|
||||
|
||||
Each feature module follows a consistent structure:
|
||||
|
||||
```
|
||||
modules/
|
||||
└── ee/
|
||||
├── insights/
|
||||
│ ├── components/
|
||||
│ ├── experience/
|
||||
│ └── types/
|
||||
└── contacts/
|
||||
├── segments/
|
||||
└── components/
|
||||
```
|
||||
|
||||
## Adding New Code
|
||||
|
||||
### New Features
|
||||
|
||||
When adding new features, follow these guidelines:
|
||||
|
||||
1. **Determine Scope**:
|
||||
|
||||
* Complete application → `apps/`
|
||||
|
||||
* Shared library → `packages/`
|
||||
|
||||
* Feature for existing app → appropriate module in `apps/web/modules/`
|
||||
|
||||
2. **Module Creation**:
|
||||
Create a new module with the standard structure:
|
||||
|
||||
```
|
||||
modules/
|
||||
└── your-feature/
|
||||
├── components/ # React components
|
||||
├── lib/ # Business logic
|
||||
├── types/ # TypeScript types
|
||||
├── actions.ts # Server actions
|
||||
└── route.ts # API routes
|
||||
```
|
||||
|
||||
3. **Component Organization**:
|
||||
|
||||
* Base UI components → `modules/ui/components/`
|
||||
|
||||
* Feature-specific components → `modules/[feature]/components/`
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Code Organization
|
||||
|
||||
* Keep modules focused and single-purpose
|
||||
|
||||
* Maintain clear separation between UI and business logic
|
||||
|
||||
* Use proper TypeScript interfaces and types
|
||||
|
||||
### File Structure
|
||||
|
||||
* Group related files in descriptive directories
|
||||
|
||||
* Use consistent naming patterns
|
||||
|
||||
* Keep files focused and modular
|
||||
|
||||
### Module Independence
|
||||
|
||||
* Minimize dependencies between modules
|
||||
|
||||
* Share common utilities through appropriate packages
|
||||
|
||||
* Maintain clear module boundaries
|
||||
|
||||
### Documentation
|
||||
|
||||
* Document complex logic and APIs as laid out in the [Documentation](/development/standards/practices/documentation) section
|
||||
|
||||
* Keep documentation current with code changes
|
||||
|
||||
## Testing Organization
|
||||
|
||||
### Test File Location
|
||||
|
||||
* Test files should be located alongside the code they test
|
||||
|
||||
* Use `.test.ts` or `.spec.ts` suffix for test files
|
||||
|
||||
* Example: `user-service.test.ts` for `user-service.ts`
|
||||
|
||||
### Test Directory Structure
|
||||
|
||||
```
|
||||
feature/
|
||||
├── tests/ # Test directory (if grouping tests)
|
||||
├── components/ # Feature components
|
||||
└── lib/ # Business logic
|
||||
```
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### Root Level Configuration
|
||||
|
||||
* `.eslintrc.js` - ESLint configuration
|
||||
|
||||
* `tsconfig.json` - TypeScript configuration
|
||||
|
||||
* `package.json` - Package metadata and scripts
|
||||
|
||||
* `.env` - Environment variables
|
||||
|
||||
### Package Level Configuration
|
||||
|
||||
Each package maintains its own configuration files:
|
||||
|
||||
* `package.json` - Package-specific dependencies and scripts
|
||||
|
||||
* `tsconfig.json` - Package-specific TypeScript settings
|
||||
|
||||
* `.eslintrc.js` - Package-specific linting rules
|
||||
|
||||
## Version Control
|
||||
|
||||
### Git Organization
|
||||
|
||||
* `.gitignore` - Specifies ignored files and directories
|
||||
|
||||
* `.github/` - GitHub specific configurations and workflows
|
||||
|
||||
* `CHANGELOG.md` - Documents version changes
|
||||
|
||||
* `LICENSE` - License information
|
||||
|
||||
## Conclusion
|
||||
|
||||
Following these organizational patterns ensures:
|
||||
|
||||
* Consistent code structure across the project
|
||||
|
||||
* Easy navigation and maintenance
|
||||
|
||||
* Clear separation of concerns
|
||||
|
||||
* Scalable architecture for future growth
|
||||
|
||||
Remember to maintain these patterns when adding new code to keep the codebase organized and maintainable.
|
||||
@@ -0,0 +1,102 @@
|
||||
---
|
||||
title: Modules & Components
|
||||
description: In this document we outline the best practices for organizing modules and components across the codebase. Clear separation of concerns between modules (which encompass business logic and domain-specific functionality) and components (reusable UI elements and building blocks) promotes clarity, scalability, and maintainability.
|
||||
icon: boxes-stacked
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Our codebase follows a modular architecture with two primary organizational units:
|
||||
|
||||
1. **UI Components**: Reusable components in the `modules/ui/components` directory
|
||||
2. **Feature Modules**: Domain-specific functionality organized by feature in the `modules` directory
|
||||
|
||||
## Module Organization
|
||||
|
||||
### Core Module Structure
|
||||
|
||||
Modules are organized by feature and can be found in the `modules` directory. Each module typically includes:
|
||||
|
||||
```
|
||||
modules/
|
||||
└── feature-name/
|
||||
├── components/ # Feature-specific components
|
||||
├── lib/ # Business logic and utilities
|
||||
├── types/ # TypeScript types
|
||||
├── actions.ts # Server actions
|
||||
└── route.ts # API routes (if needed)
|
||||
```
|
||||
|
||||
### Enterprise Edition (EE) Modules
|
||||
|
||||
Enterprise features are organized in a dedicated `modules/ee` directory:
|
||||
|
||||
```
|
||||
modules/
|
||||
└── ee/
|
||||
├── insights/
|
||||
│ ├── components/
|
||||
│ ├── experience/
|
||||
│ └── types/
|
||||
└── contacts/
|
||||
├── segments/
|
||||
└── components/
|
||||
```
|
||||
|
||||
## Component Organization
|
||||
|
||||
### UI Component Structure
|
||||
|
||||
UI components are centralized in `modules/ui/components` and follow a consistent structure:
|
||||
|
||||
```
|
||||
modules/ui/components/
|
||||
└── component-name/
|
||||
├── index.tsx # Main component implementation
|
||||
├── stories.tsx # Storybook stories
|
||||
└── components/ # Sub-components (if needed)
|
||||
```
|
||||
|
||||
### Component Types
|
||||
|
||||
1. **Base Components**: Fundamental UI elements like Button, Input, Modal
|
||||
|
||||
2. **Composite Components**: More complex components that combine base components
|
||||
|
||||
3. **Feature-Specific Components**: Components tied to specific features
|
||||
|
||||
|
||||
### Feature Module Example
|
||||
|
||||
A feature module with its components and business logic:
|
||||
|
||||
```
|
||||
modules/survey/
|
||||
├── components/
|
||||
│ ├── question-form-input/
|
||||
│ └── template-list/
|
||||
├── editor/
|
||||
│ └── components/
|
||||
├── lib/
|
||||
│ └── utils.ts
|
||||
└── types/
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Component Organization**
|
||||
- Keep components focused and single-purpose
|
||||
- Use proper TypeScript interfaces for props
|
||||
- Implement Storybook stories for UI components
|
||||
|
||||
2. **Module Structure**
|
||||
- Organize by feature domain
|
||||
- Separate business logic from UI components
|
||||
- Use proper type definitions
|
||||
|
||||
3. **Code Sharing**
|
||||
- Share common utilities through the ui/lib directory
|
||||
- Maintain clear boundaries between modules
|
||||
- Use proper imports with aliases (@/modules/...)
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: Naming Conventions
|
||||
description: This section outlines the guidelines for naming conventions across the codebase, ensuring consistency and clarity in the project.
|
||||
icon: input-text
|
||||
---
|
||||
|
||||
## Files and Directories
|
||||
|
||||
### General Files
|
||||
- Use lowercase and hyphen-separated names (kebab-case) for files and directories
|
||||
- ✅ `user-profile.ts`
|
||||
- ❌ `UserProfile.ts`
|
||||
- Group related files in directories with descriptive plural names
|
||||
- ✅ `components`, `services`, `utils`
|
||||
- ❌ `component`, `util`
|
||||
|
||||
### Special Files
|
||||
- Configuration files should follow framework conventions
|
||||
- ✅ `next.config.mjs`, `tailwind.config.js`
|
||||
- Test files should mirror source files with `.test` or `.spec` suffix
|
||||
- ✅ `user-service.test.ts` for `user-service.ts`
|
||||
- Database migration files should include timestamp and description
|
||||
- ✅ `20241017124431_add_documents_and_insights.sql`
|
||||
|
||||
## Code Symbols
|
||||
|
||||
### Variables and Functions
|
||||
- Use camelCase for variables and function names
|
||||
- ✅ `fetchUserData`, `isLoading`, `handleSubmit`
|
||||
- ❌ `FetchUserData`, `is_loading`
|
||||
- Boolean variables should use is/has/should prefix
|
||||
- ✅ `isVerifyEmailEnabled`, `hasPermission`, `shouldDisplay`
|
||||
- Async functions should use verb prefixes suggesting async
|
||||
- ✅ `fetchData`, `createUser`, `updateProfile`
|
||||
|
||||
### Classes and Types
|
||||
- Use PascalCase for:
|
||||
- Classes: `Config`, `Client`, `ResponseAPI`
|
||||
- Interfaces: `TSurveySummaryResponse`, `ApiConfig`
|
||||
- Type aliases: `TResponseData`, `TJsTrackProperties`
|
||||
- Prefix types with T and interfaces with I (when helpful)
|
||||
- ✅ `TStats`, `TResponseData`, `IApiConfig`
|
||||
- Enum names should be PascalCase, values in UPPER_SNAKE_CASE
|
||||
```typescript
|
||||
enum ProjectFeatureKeys {
|
||||
FREE = "free",
|
||||
STARTUP = "startup",
|
||||
SCALE = "scale"
|
||||
}
|
||||
```
|
||||
|
||||
### Constants
|
||||
- Use UPPER_SNAKE_CASE for constant values
|
||||
- ✅ `API_TIMEOUT`, `MAX_RETRIES`, `CONTAINER_ID`
|
||||
- Use PascalCase for constant references/objects
|
||||
- ✅ `ErrorCodes`, `Config`
|
||||
|
||||
### Database Models
|
||||
- Use PascalCase singular form for model names
|
||||
- ✅ `Survey`, `Response`, `Document`
|
||||
- Use camelCase for field names
|
||||
- ✅ `createdAt`, `environmentId`, `isSpam`
|
||||
- Use snake_case for database column names
|
||||
- ✅ `created_at`, `updated_at`
|
||||
|
||||
### Components
|
||||
- Use PascalCase for React components and their files
|
||||
- ✅ `SurveyCard.tsx`, `UserProfile.tsx`
|
||||
- Component-specific types should be prefixed with component name
|
||||
- ✅ `SurveyCardProps`, `UserProfileData`
|
||||
|
||||
### API and Endpoints
|
||||
- Use kebab-case for API endpoints
|
||||
- ✅ `/api/user-profile`, `/api/survey-responses`
|
||||
- Use camelCase for query parameters
|
||||
- ✅ `/api/surveys?pageSize=10&sortOrder=desc`
|
||||
|
||||
## Schema and Validation
|
||||
- Prefix Zod schemas with Z
|
||||
- ✅ `ZSurvey`, `ZDocument`, `ZInsight`
|
||||
- Use descriptive names for validation schemas
|
||||
- ✅ `ZUpdateDocumentAction`, `ZGenerateDocumentObjectSchema`
|
||||
|
||||
## Error Handling
|
||||
- Suffix error classes with "Error"
|
||||
- ✅ `ValidationError`, `DatabaseError`, `AuthenticationError`
|
||||
- Use descriptive names for error types
|
||||
- ✅ `SURVEY_NOT_FOUND`, `INVALID_RESPONSE`
|
||||
|
||||
## Best Practices
|
||||
- Keep names descriptive but concise
|
||||
- Be consistent within each context
|
||||
- Follow existing patterns in the codebase
|
||||
- Use full words instead of abbreviations unless widely accepted
|
||||
- ✅ `configuration` vs ❌ `config` (except in standard terms)
|
||||
- ✅ `id`, `url` (standard abbreviations are acceptable)
|
||||
|
||||
By following these conventions, we maintain consistency and clarity across the codebase, making it more maintainable and easier to understand for all team members.
|
||||
@@ -0,0 +1,184 @@
|
||||
---
|
||||
title: "Code Formatting"
|
||||
description: "Standards for consistent code formatting across the Formbricks project"
|
||||
icon: code
|
||||
---
|
||||
|
||||
|
||||
## Core Configuration
|
||||
|
||||
### Prettier Config
|
||||
Formbricks uses a standardized Prettier configuration defined in `@formbricks/config-prettier`:
|
||||
```javascript
|
||||
module.exports = {
|
||||
bracketSpacing: true,
|
||||
bracketSameLine: true,
|
||||
singleQuote: false,
|
||||
jsxSingleQuote: false,
|
||||
trailingComma: "es5",
|
||||
semi: true,
|
||||
printWidth: 110,
|
||||
arrowParens: "always",
|
||||
importOrder: [
|
||||
// Mocks must be at the top as they contain vi.mock calls
|
||||
"(.*)/__mocks__/(.*)",
|
||||
"server-only",
|
||||
"<THIRD_PARTY_MODULES>",
|
||||
"^@formbricks/(.*)$",
|
||||
"^~/(.*)$",
|
||||
"^[./]",
|
||||
],
|
||||
importOrderSeparation: false,
|
||||
importOrderSortSpecifiers: true,
|
||||
};
|
||||
```
|
||||
|
||||
Key configurations:
|
||||
- 110 characters line width
|
||||
- Double quotes for strings
|
||||
- ES5 trailing commas
|
||||
- Always use parentheses for arrow functions
|
||||
- Strict import ordering
|
||||
|
||||
### Import Order
|
||||
All imports follow a strict ordering:
|
||||
1. Mocks (for testing)
|
||||
2. Server-only imports
|
||||
3. Third-party modules
|
||||
4. Internal `@formbricks/*` modules
|
||||
5. Local aliases (`~/*)
|
||||
6. Relative imports
|
||||
|
||||
### TypeScript Config
|
||||
- Strict TypeScript checking enabled
|
||||
- Consistent use of `tsconfig.json` extending from `@formbricks/config-typescript`
|
||||
- Example configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"resolveJsonModule": true,
|
||||
"strict": true
|
||||
},
|
||||
"extends": "@formbricks/config-typescript/js-library.json",
|
||||
"include": ["src", "package.json"]
|
||||
}
|
||||
```
|
||||
|
||||
### JSDoc Comments
|
||||
Required for public APIs and complex functions:
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Creates a new user
|
||||
* @param {string} name - User's name
|
||||
* @returns {Promise<User>} The created user object
|
||||
*/
|
||||
function createUser(name: string): Promise<User> {
|
||||
// implementation
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
Standardized error handling using the ErrorHandler class:
|
||||
|
||||
```typescript
|
||||
export class ErrorHandler {
|
||||
private static instance: ErrorHandler | null;
|
||||
private handleError: (error: unknown) => void;
|
||||
public customized = false;
|
||||
public static initialized = false;
|
||||
|
||||
private constructor(errorHandler?: (error: unknown) => void) {
|
||||
if (errorHandler) {
|
||||
this.handleError = errorHandler;
|
||||
this.customized = true;
|
||||
} else {
|
||||
this.handleError = (error) => {
|
||||
Logger.getInstance().error(JSON.stringify(error));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ... additional methods
|
||||
}
|
||||
```
|
||||
|
||||
## Enforcement Tools
|
||||
|
||||
### Pre-commit Hooks
|
||||
Using Husky and lint-staged for automated checks:
|
||||
|
||||
```json
|
||||
{
|
||||
"lint-staged": {
|
||||
"(apps|packages)/**/*.{js,ts,jsx,tsx}": [
|
||||
"prettier --write",
|
||||
"eslint --fix"
|
||||
],
|
||||
"*.json": [
|
||||
"prettier --write"
|
||||
],
|
||||
"packages/database/schema.prisma": [
|
||||
"prisma format"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ESLint Configuration
|
||||
Each package extends from `@formbricks/eslint-config` with specific presets:
|
||||
- `library.js` for packages
|
||||
- `next.js` for Next.js applications
|
||||
- `react.js` for React applications
|
||||
|
||||
### Continuous Integration
|
||||
- Automated formatting checks in CI/CD pipeline
|
||||
- SonarCloud integration for code quality analysis
|
||||
- Coverage requirements for tests
|
||||
|
||||
## VS Code Integration
|
||||
|
||||
### Required Extensions
|
||||
- `esbenp.prettier-vscode` - Prettier formatting
|
||||
- `dbaeumer.vscode-eslint` - ESLint integration
|
||||
- `bradlc.vscode-tailwindcss` - Tailwind CSS support
|
||||
|
||||
### Recommended Settings
|
||||
```json
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Consistent Formatting**
|
||||
- Always run `pnpm format` before committing
|
||||
- Use VS Code's format on save feature
|
||||
- Follow the established import order
|
||||
|
||||
2. **Type Safety**
|
||||
- Enable strict TypeScript checks
|
||||
- Use explicit type annotations when necessary
|
||||
- Avoid using `any` type
|
||||
|
||||
3. **Code Organization**
|
||||
- Keep files focused and modular
|
||||
- Group related functionality
|
||||
- Use clear, descriptive names
|
||||
|
||||
4. **Documentation**
|
||||
- Document complex logic
|
||||
- Use JSDoc for public APIs
|
||||
- Keep comments current with code changes
|
||||
|
||||
These standards ensure consistency across the Formbricks codebase while maintaining high code quality and developer productivity.
|
||||
@@ -0,0 +1,133 @@
|
||||
---
|
||||
title: "Documentation"
|
||||
description: "Standards for documenting code and features in the Formbricks codebase"
|
||||
icon: "book"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
At Formbricks, we maintain strict documentation standards to ensure code clarity, maintainability, and ease of use for both internal developers and external contributors.
|
||||
|
||||
### Contribute to Documentation
|
||||
|
||||
We use Mintlify to maintain our documentation. You can find more information about how to contribute to the documentation in the [README](https://github.com/formbricks/formbricks/blob/main/docs/README.md) file.
|
||||
|
||||
## Code Documentation
|
||||
|
||||
### Function Documentation
|
||||
|
||||
1. **Complex Logic Documentation**
|
||||
- All functions with complex logic must include JSDoc comments
|
||||
- Document parameters, return types, and potential side effects
|
||||
- Example:
|
||||
|
||||
|
||||
```typescript
|
||||
/**
|
||||
Creates a new user and initializes their preferences
|
||||
@param {string} name - User's full name
|
||||
@param {UserOptions} options - Configuration options for user creation
|
||||
@returns {Promise<User>} The created user object
|
||||
@throws {ValidationError} If name is invalid
|
||||
*/
|
||||
async function createUser(name: string, options: UserOptions): Promise<User> {
|
||||
// implementation
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
2. **TypeScript Ignore Comments**
|
||||
- When using `@ts-ignore` or `@ts-expect-error`, always include a comment explaining why
|
||||
- Example:
|
||||
|
||||
|
||||
```typescript
|
||||
// @ts-expect-error -- Required for dynamic function calls
|
||||
void window.formbricks.init(...args);
|
||||
```
|
||||
|
||||
|
||||
### API Documentation
|
||||
|
||||
1. **API Endpoints**
|
||||
- All new API endpoints must be documented in the OpenAPI specification
|
||||
- Include request/response schemas, authentication requirements, and examples
|
||||
- Document both Client API and Management API endpoints
|
||||
- Place API documentation in the `docs/api-reference` directory
|
||||
|
||||
2. **Authentication**
|
||||
- Clearly specify authentication requirements
|
||||
- Document API key usage and permissions
|
||||
- Include error scenarios and handling
|
||||
|
||||
### Feature Documentation
|
||||
|
||||
- All new features must include a feature documentation file
|
||||
- Document the feature's purpose, usage, and implementation details
|
||||
- Include code examples and best practices
|
||||
|
||||
## Working with Mintlify
|
||||
We use Mintlify to write our documentation.
|
||||
|
||||
### File Structure
|
||||
|
||||
1. **MDX Files**
|
||||
- All documentation files must use the `.mdx` extension
|
||||
- Include frontmatter with required metadata:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: "Document Title"
|
||||
description: "Brief description of the content"
|
||||
icon: "appropriate-icon"
|
||||
---
|
||||
```
|
||||
|
||||
|
||||
2. **Navigation**
|
||||
- Add new pages to the appropriate section in `docs/mint.json`
|
||||
- Follow the existing navigation structure
|
||||
- Include proper redirects if URLs change
|
||||
|
||||
### Content Guidelines
|
||||
|
||||
1. **Writing Style**
|
||||
- Use clear, concise language
|
||||
- Break content into logical sections with proper headings
|
||||
- Include practical examples and code snippets
|
||||
- Use Mintlify components for notes, warnings, and callouts:
|
||||
|
||||
```markdown
|
||||
<Note>
|
||||
Important information goes here
|
||||
</Note>
|
||||
```
|
||||
|
||||
|
||||
2. **Media and Assets**
|
||||
- Store images in the appropriate `/images` subdirectory
|
||||
- Use descriptive alt text for all images
|
||||
- Optimize images for web delivery
|
||||
- Use relative paths for internal links
|
||||
|
||||
3. **Code Examples**
|
||||
- Specify the language for all code blocks
|
||||
- Include comments for complex code snippets
|
||||
- Use proper indentation and formatting
|
||||
|
||||
## Validation
|
||||
|
||||
1. **Local Testing**
|
||||
- Test documentation locally using Mintlify CLI:
|
||||
|
||||
```bash
|
||||
mintlify dev
|
||||
```
|
||||
|
||||
2. **Review Process**
|
||||
- Documentation changes require peer review
|
||||
- Verify all links and references work
|
||||
- Ensure proper formatting and rendering
|
||||
|
||||
These documentation requirements ensure that our codebase remains maintainable, accessible, and well-documented for both current and future developers.
|
||||
@@ -0,0 +1,137 @@
|
||||
---
|
||||
title: "Error Handling"
|
||||
description: "Standards for handling errors across the Formbricks codebase"
|
||||
icon: "triangle-exclamation"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
At Formbricks, we follow consistent error handling patterns to ensure reliability, debuggability, and maintainability across our codebase. This document outlines our standard approaches to error handling.
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Type Safety**: Use typed errors and results
|
||||
2. **Meaningful Messages**: Provide clear, actionable error messages
|
||||
3. **Proper Propagation**: Handle or propagate errors appropriately
|
||||
4. **Logging**: Ensure errors are properly logged for debugging
|
||||
5. **Recovery**: Implement graceful fallbacks where possible
|
||||
|
||||
|
||||
|
||||
## Standard Error Types
|
||||
|
||||
We maintain a set of standardized error types for different scenarios:
|
||||
|
||||
```typescript
|
||||
export interface ApiErrorResponse {
|
||||
code:
|
||||
| "not_found"
|
||||
| "gone"
|
||||
| "bad_request"
|
||||
| "internal_server_error"
|
||||
| "unauthorized"
|
||||
| "method_not_allowed"
|
||||
| "not_authenticated"
|
||||
| "forbidden"
|
||||
| "network_error";
|
||||
message: string;
|
||||
status: number;
|
||||
url: URL;
|
||||
details?: Record<string, string | string[] | number | number[] | boolean | boolean[]>;
|
||||
responseMessage?: string;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Error Handling Patterns
|
||||
|
||||
### API Error Handling
|
||||
|
||||
For API endpoints:
|
||||
|
||||
```typescript
|
||||
export const GET = async (request: Request) => {
|
||||
try {
|
||||
const authentication = await authenticateRequest(request);
|
||||
if (!authentication) return responses.notAuthenticatedResponse();
|
||||
const data = await fetchData(authentication.environmentId!);
|
||||
return responses.successResponse(data);
|
||||
} catch (error) {
|
||||
if (error instanceof DatabaseError) {
|
||||
return responses.badRequestResponse(error.message);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
### Client-Side Error Handling
|
||||
|
||||
For client-side operations:
|
||||
|
||||
```typescript
|
||||
const handleOperation = async () => {
|
||||
const result = await performAction();
|
||||
if (!result.ok) {
|
||||
logger.error(`Operation failed: ${result.error.message}`);
|
||||
toast.error("Operation failed. Please try again.");
|
||||
return;
|
||||
}
|
||||
// Process successful result
|
||||
processResult(result.data);
|
||||
};
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Never Swallow Errors**
|
||||
- Always handle or propagate errors
|
||||
- Log errors appropriately for debugging
|
||||
- Use error boundaries in React components
|
||||
|
||||
2. **Type Safety**
|
||||
- Use typed error responses
|
||||
- Leverage TypeScript for compile-time error checking
|
||||
- Define clear error interfaces
|
||||
|
||||
3. **Error Messages**
|
||||
- Include relevant context in error messages
|
||||
- Make messages actionable for developers
|
||||
- Use consistent error formatting
|
||||
|
||||
4. **Error Recovery**
|
||||
- Implement fallback behaviors where appropriate
|
||||
- Gracefully degrade functionality when possible
|
||||
- Provide user feedback for recoverable errors
|
||||
|
||||
5. **Documentation**
|
||||
- Document expected errors in function JSDoc
|
||||
- Include error handling in code examples
|
||||
- Keep error handling documentation up to date
|
||||
|
||||
## Testing Error Scenarios
|
||||
|
||||
Always include error case testing:
|
||||
|
||||
```typescript
|
||||
describe("fetchEnvironmentState()", () => {
|
||||
test("returns err(...) on network error", async () => {
|
||||
const mockNetworkError = {
|
||||
code: "network_error",
|
||||
message: "Timeout",
|
||||
responseMessage: "Network fail",
|
||||
};
|
||||
const result = await fetchEnvironmentState();
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error.code).toBe(mockNetworkError.code);
|
||||
expect(result.error.message).toBe(mockNetworkError.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
|
||||
These standards ensure consistent, reliable error handling across the Formbricks codebase while maintaining good developer experience and system reliability.
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
title: Code Reviews
|
||||
description: This document outlines our comprehensive code review process at Formbricks. We maintain high quality, consistency, and best practices within our codebase through this structured approach.
|
||||
icon: eyes
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Initial Checks via GitHub Workflows
|
||||
|
||||
When a Pull Request (PR) is opened, our automated GitHub workflows perform several critical checks:
|
||||
|
||||
> **Note:** At Formbricks, all feature changes must be submitted through Pull Requests - direct pushes to protected branches are not allowed.
|
||||
|
||||
- **PR Title Validation**: Ensures clear, descriptive titles following our conventions
|
||||
- **Build Verification**: Confirms that the build process completes successfully
|
||||
- **Test Suite**: Runs all automated tests to catch potential regressions
|
||||
- **Translation Check**: Identifies any missing translation keys
|
||||
- **Linting**: Enforces our coding standards and style guidelines
|
||||
|
||||
These checks must pass before proceeding to manual review.
|
||||
|
||||
## Reviewer Assignment
|
||||
|
||||
Once all automated checks pass successfully:
|
||||
|
||||
- A team member with relevant expertise is assigned as the reviewer
|
||||
- The reviewer is notified automatically through GitHub
|
||||
- Priority is given based on PR urgency and complexity
|
||||
|
||||
## Functional Testing and UI Review
|
||||
|
||||
The assigned reviewer performs thorough testing:
|
||||
|
||||
### Functionality Testing
|
||||
|
||||
- Verifies that new features work as specified
|
||||
- Tests edge cases and error scenarios
|
||||
- Ensures proper error handling
|
||||
- Checks integration with existing features
|
||||
|
||||
### UI Review (if applicable)
|
||||
|
||||
- Validates visual consistency
|
||||
- Checks responsive behavior
|
||||
- Ensures accessibility standards
|
||||
- Reviews user interaction flows
|
||||
|
||||
## Feedback Process
|
||||
|
||||
If improvements are needed:
|
||||
|
||||
- Reviewers add inline comments on GitHub
|
||||
- Feedback is specific and actionable
|
||||
- Code suggestions are provided when helpful
|
||||
- Comments follow our constructive feedback guidelines
|
||||
|
||||
## In-depth Code Review
|
||||
|
||||
Our code review process utilizes both human expertise and AI assistance:
|
||||
|
||||
### Manual Review
|
||||
|
||||
- Code structure and organization
|
||||
- Design patterns and best practices
|
||||
- Performance considerations
|
||||
- Security implications
|
||||
- Documentation completeness
|
||||
|
||||
### AI-Assisted Review
|
||||
|
||||
We leverage advanced AI tools for additional insights:
|
||||
|
||||
- **Code Rabbit**: Automated code analysis and suggestions
|
||||
- **Sonarqube**: Code quality metrics and potential issues
|
||||
|
||||
## Resolution and Merge
|
||||
|
||||
Final steps before merging:
|
||||
|
||||
- All review comments must be addressed
|
||||
- Required changes are implemented
|
||||
- At least one reviewer approval is required
|
||||
- All conversations must be resolved
|
||||
- CI/CD pipeline passes again
|
||||
- PR is merged into the target branch
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Keep PRs focused and reasonably sized
|
||||
- Respond to review comments promptly
|
||||
- Use the "Request Changes" feature when necessary
|
||||
- Mark conversations as resolved when addressed
|
||||
- Use approve/request changes workflow appropriately
|
||||
|
||||
## Conclusion
|
||||
|
||||
Our code review process combines automated checks, manual review, and AI assistance to ensure high-quality code contributions. This multi-layered approach helps maintain code quality while promoting knowledge sharing within the team.
|
||||
|
||||
Remember: Code reviews are not just about finding issues—they're opportunities for learning and improving our codebase together.
|
||||
@@ -0,0 +1,127 @@
|
||||
---
|
||||
title: Testing Methodology
|
||||
icon: magnifying-glass
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
At Formbricks, we maintain a rigorous testing strategy to ensure high-quality code and reliable functionality. Our testing approach is standardized and integrated into our development workflow.
|
||||
|
||||
## Testing Structure
|
||||
|
||||
### Unit Testing with Vitest
|
||||
|
||||
We use Vitest as our primary testing framework. All unit tests follow these conventions:
|
||||
|
||||
1. **File Location and Naming**
|
||||
|
||||
- Test files are co-located with the source files they test
|
||||
- Test files use the `.test.ts` extension (e.g., `utils.test.ts` tests `utils.ts`)
|
||||
|
||||
2. **Test Organization**
|
||||
|
||||
```typescript
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
describe("ComponentName or FeatureName", () => {
|
||||
describe("functionName or scenario", () => {
|
||||
it("should describe expected behavior", () => {
|
||||
// test implementation
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
3. **Coverage Requirements**
|
||||
- Minimum 85% code coverage requirement (WIP 👷♂️)
|
||||
- Coverage is tracked using V8 provider
|
||||
- Coverage reports include:
|
||||
- Text summaries
|
||||
- HTML reports
|
||||
- LCOV reports
|
||||
|
||||
### End-to-End Testing with Playwright
|
||||
|
||||
E2E tests are located in `apps/web/playwright/` and focus on critical user workflows.
|
||||
|
||||
## Testing Setup
|
||||
|
||||
### Configuration
|
||||
|
||||
Our Vitest configuration (`vite.config.ts`) includes:
|
||||
|
||||
```typescript
|
||||
test: {
|
||||
exclude: ['playwright/', 'node_modules/'],
|
||||
setupFiles: ['../../packages/lib/vitestSetup.ts'],
|
||||
coverage: {
|
||||
provider: 'v8',
|
||||
reporter: ['text', 'html', 'lcov'],
|
||||
reportsDirectory: './coverage',
|
||||
},
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Test Utilities
|
||||
|
||||
Common test utilities are available in `vitestSetup.ts`:
|
||||
|
||||
- Mock implementations for commonly used functions
|
||||
- Test lifecycle hooks (beforeEach, afterEach)
|
||||
- Validation test helpers
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Test Independence**
|
||||
|
||||
```typescript
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
```
|
||||
|
||||
2. **Mocking**
|
||||
|
||||
- Use Vitest's built-in mocking utilities
|
||||
- Mock external dependencies and services
|
||||
- Example:
|
||||
|
||||
```typescript
|
||||
vi.mock("@formbricks/database", () => ({
|
||||
prisma: {
|
||||
user: {
|
||||
create: vi.fn(),
|
||||
findUnique: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
```
|
||||
|
||||
3. **Assertions**
|
||||
- Write clear, specific assertions
|
||||
- Test both success and error cases
|
||||
- Example:
|
||||
```typescript
|
||||
expect(result.ok).toBe(true);
|
||||
expect(result.data).toEqual(expectedData);
|
||||
expect(async () => await invalidCall()).rejects.toThrow(ValidationError);
|
||||
```
|
||||
|
||||
## Quality Assurance Process
|
||||
|
||||
1. **Continuous Integration**
|
||||
|
||||
- Automated test suite execution on pull requests
|
||||
- Coverage reports generation
|
||||
- Test results reporting
|
||||
|
||||
2. **New Features**
|
||||
- Must include corresponding unit tests
|
||||
- Must maintain or improve coverage metrics
|
||||
- Must include relevant E2E tests for user-facing features
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Framework Usage
|
||||
icon: book
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
This document outlines the framework usage guidelines for Formbricks, which is built primarily on Next.js (with heavy use of Server-Side Rendering through the App Router), Tailwind CSS, and Prisma ORM.
|
||||
|
||||
## Next.js
|
||||
|
||||
### App Router and Server Components
|
||||
|
||||
- Use the Next.js App Router with the /app directory for building the application.
|
||||
- Leverage React Server Components, which are the default in the App Router.
|
||||
- Perform server-side data fetching directly within page.tsx files using async function components.
|
||||
|
||||
### Data Fetching in page.tsx
|
||||
|
||||
- Implement data fetching logic directly in your page.tsx components. This allows for server-side rendering without needing separate data fetching methods like getServerSideProps.
|
||||
- Utilize React Suspense and streaming features if using advanced asynchronous patterns.
|
||||
|
||||
### Server Actions for Mutations
|
||||
|
||||
- Define Server Actions in dedicated action.ts files.
|
||||
- Server actions serve as entry points for mutations and delegate to service layers that perform Prisma operations and other business logic.
|
||||
- This approach promotes separation of concerns and maintainability by keeping form actions and mutations decoupled from UI components.
|
||||
|
||||
### Error Handling and Performance
|
||||
|
||||
- Integrate error boundaries and loading states appropriately within your App Router structure.
|
||||
- Optimize performance with Next.js built-in features such as dynamic imports, the Image component, and code splitting.
|
||||
|
||||
## Tailwind CSS
|
||||
We follow the Tailwind framework as intended. Please have a look at the [Tailwind CSS Guidelines](https://tailwindcss.com/docs/styling-with-utility-classes) for more information.
|
||||
|
||||
## Prisma ORM
|
||||
We're working with Prisma as our ORM. Please have a look at the [Prisma ORM Documentation](https://www.prisma.io/docs/orm) for more information.
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
title: Language-Specific
|
||||
description: This document outlines the language-specific conventions for the Formbricks codebase, providing guidelines for writing code in TypeScript/JavaScript.
|
||||
icon: code
|
||||
---
|
||||
|
||||
## TypeScript
|
||||
|
||||
Our codebase follows the Vercel Engineering Style Guide conventions.
|
||||
|
||||
### ESLint Configuration
|
||||
|
||||
We maintain three primary ESLint configurations for different project types:
|
||||
|
||||
1. **Library Configuration** (for packages):
|
||||
|
||||
```javascript
|
||||
extends: [
|
||||
"@vercel/style-guide/eslint/node",
|
||||
"@vercel/style-guide/eslint/typescript"
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
2. **React Configuration** (for React applications):
|
||||
|
||||
```javascript
|
||||
extends: [
|
||||
"@vercel/style-guide/eslint/node",
|
||||
"@vercel/style-guide/eslint/typescript",
|
||||
"@vercel/style-guide/eslint/browser",
|
||||
"@vercel/style-guide/eslint/react",
|
||||
"@vercel/style-guide/eslint/next"
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
3. **Next.js Configuration** (for Next.js applications):
|
||||
|
||||
```javascript
|
||||
extends: [
|
||||
"@vercel/style-guide/eslint/node",
|
||||
"@vercel/style-guide/eslint/typescript",
|
||||
"@vercel/style-guide/eslint/browser",
|
||||
"@vercel/style-guide/eslint/react",
|
||||
"@vercel/style-guide/eslint/next"
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
### Key Conventions
|
||||
|
||||
1. **TypeScript Usage**
|
||||
- Strict TypeScript checking enabled
|
||||
- Explicit type annotations when necessary
|
||||
- Proper interface and type naming (prefix with T for types, I for interfaces when helpful)
|
||||
- No use of `any` type unless absolutely necessary
|
||||
|
||||
2. **Imports/Exports**
|
||||
- Follow strict import ordering:
|
||||
1. Mocks (for testing)
|
||||
2. Server-only imports
|
||||
3. Third-party modules
|
||||
4. Internal `@formbricks/*` modules
|
||||
5. Local aliases (`~/*)
|
||||
6. Relative imports
|
||||
|
||||
3. **Error Handling**
|
||||
- Use typed error responses
|
||||
- Proper error propagation
|
||||
- Consistent error message formatting
|
||||
- Implement error boundaries in React components
|
||||
|
||||
4. **Async/Await**
|
||||
- Prefer async/await over raw promises
|
||||
- Proper error handling in async functions
|
||||
- Use Promise.all for parallel operations
|
||||
|
||||
5. **React Specific**
|
||||
- Functional components with TypeScript
|
||||
- Proper use of hooks
|
||||
- Consistent prop typing
|
||||
- Server Components by default in Next.js App Router
|
||||
|
||||
### Code Formatting
|
||||
|
||||
We use Prettier with specific configurations:
|
||||
|
||||
```javascript
|
||||
{
|
||||
bracketSpacing: true,
|
||||
bracketSameLine: true,
|
||||
singleQuote: false,
|
||||
jsxSingleQuote: false,
|
||||
trailingComma: "es5",
|
||||
semi: true,
|
||||
printWidth: 110,
|
||||
arrowParens: "always"
|
||||
}
|
||||
```
|
||||
|
||||
## Swift
|
||||
Will be added upon release of the native iOS SDK.
|
||||
|
||||
## Kotlin
|
||||
Will be added upon release of the native Android SDK.
|
||||
|
||||
+37
-1
@@ -182,7 +182,43 @@
|
||||
"pages": ["development/technical-handbook/overview", "development/technical-handbook/database-model"]
|
||||
},
|
||||
{
|
||||
"group": "Contribution",
|
||||
"group": "Standards",
|
||||
"pages": [
|
||||
{
|
||||
"group": "Code Organization",
|
||||
"icon": "code",
|
||||
"pages": [
|
||||
"development/standards/organization/file-and-directory-organization",
|
||||
"development/standards/organization/naming-conventions",
|
||||
"development/standards/organization/module-component-structure"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Development Practices",
|
||||
"icon": "laptop",
|
||||
"pages": [
|
||||
"development/standards/practices/code-formatting",
|
||||
"development/standards/practices/documentation",
|
||||
"development/standards/practices/error-handling"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Technical Standards",
|
||||
"icon": "gear",
|
||||
"pages": [
|
||||
"development/standards/technical/language-specific-conventions",
|
||||
"development/standards/technical/framework-usage"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Quality Assurance",
|
||||
"icon": "shield",
|
||||
"pages": ["development/standards/qa/code-reviews", "development/standards/qa/testing-methodology"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Contributions",
|
||||
"pages": ["development/contribution/contribution"]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -8,17 +8,11 @@ Experience Management is the practice of measuring and managing how a stakeholde
|
||||
|
||||
Historically, Experience Management has three steps:
|
||||
|
||||
1. **Gather**
|
||||
1. **Gather data**
|
||||
|
||||
data
|
||||
2. **Analyze and report on the data**
|
||||
|
||||
2. **Analyze**
|
||||
|
||||
and report on the data
|
||||
|
||||
3. **Integrate**
|
||||
|
||||
and automate to measure experiences at scale
|
||||
3. **Integrate and automate to measure experiences at scale**
|
||||
|
||||
## Gather data
|
||||
|
||||
|
||||
Reference in New Issue
Block a user