Skip to content

Development Guide

Mahid Ahmad edited this page Feb 23, 2025 · 4 revisions

Bluewave Datahall Development Guide πŸš€

The goal of this guide is to keep our workflow efficient, our codebase clean, and our communication clear. Though not everything may be straightforward at first.

Please keep these points in mind:

  • βœ… Follow the guide as closely as possible. It’s designed to prevent confusion and improve collaboration.
  • ❓ If something is unclear or you’re unsure how to proceed please let me (@mahid797) know.
  • πŸ“ Got suggestions? If you think part of this guide can be improved, bring it upβ€”I’m open to feedback!

1. Coding Standards πŸ’»

Coding consistency and clarity are critical for collaboration, maintainability, and scalability.This section covers the essential practices every developer should follow when writing code for Datahall.


1.1 General Practices πŸ› οΈ

  1. Use Prettier for Formatting

    • A .prettierrc file is provided in the repository.
    • All code must be formatted with Prettier before committing.
    • This ensures consistency in tabs, semicolons, quotes, and other stylistic choices.
  2. Meaningful Naming

    • Choose clear, descriptive names for variables, functions, and components.
    • Avoid abbreviations or overly short identifiers (e.g., fn or tmp) unless they are standard (e.g., id).
  3. Small, Focused Files

    • Aim to keep files under ~200 lines. If a file grows beyond that, consider splitting it into smaller, logical parts.
    • This keeps the code easier to navigate, read, and maintain.
  4. Avoid Reinventing the Wheel

    • Before writing a new hook, component, or utility, check existing ones in the codebase.
    • Small modifications to existing code are preferable to duplicating logic.
    • As the saying goes, β€œDon’t reinvent the wheel.”
  5. Commenting and Documentation

    • Add concise inline comments for complex logic.
    • For public-facing or reusable functions, include brief JSDoc/TSDoc annotations to clarify parameter types and return values.
  6. TypeScript Usage

    • Use TypeScript interfaces and types for function parameters, return values, component props, and hooks.
    • Keep shared models/types in the shared/models/ or shared/types/ folders.
    • While we don’t enforce specific TS compiler flags beyond the defaults, strict typing is encouraged to catch errors early.

πŸ’‘ Pro Tip: Take short breaks when your brain feels fried. A quick stretch or β˜• can save you from tunnel vision!


1.2 Frontend / Client-Side πŸ–±οΈ

  1. All API Calls in Hooks

    • No direct API calls in componentsβ€”create or use existing hooks in src/hooks/.
    • Organize hooks by domain (e.g., hooks/documents/, hooks/auth/) rather than lumping everything together.
  2. Preferred Libraries

    • TanStack Query (or React Query) for data fetching, caching, and mutations.
    • This ensures consistent handling of loading states, error states, and caching strategies.
    • TanStack Query Usage Tips
      • Domain-Specific Keys: When creating queries, use descriptive keys (e.g., ['documents', docId]) so that your caching and invalidation remain accurate.
      • Invalidate on Mutations: Always invalidate relevant queries (queryClient.invalidateQueries(['documents'])) after successful mutations to keep data fresh.
      • No Direct axios or fetch in Components: All network calls should live in hooks; components should just consume hook data.
  3. Component Guidelines

    • Reusable UI Components go under src/components/, grouped by category (common/, input/, loaders/, etc.).
    • Feature-Specific Components can live inside their respective feature folders (e.g., app/documents/[documentId]/components/).
  4. Styling

    • Use Material UI (MUI) components and sx props for one-off styling or small modifications.
    • Larger or repeated style patterns can go into global or theme-based styles (theme/ folder).
    • Avoid adding multiple styling libraries to keep the bundle lean and the styles consistent.
  5. Error Handling

    • In most cases, rely on try/catch in hooks or fetch logic to handle errors gracefully.
    • Display user-friendly error messages (e.g., using a toast) whenever an API request fails.
    • If needed, React’s error boundaries can be used for critical failures.

πŸ’‘ Pro Tip: If you spot a component that might be useful in other parts of the app, refactor it to be reusable and share the love! ❀️


1.3 Backend / Server-Side πŸ—„οΈ

  1. Services for Business Logic

    • All database operations and critical logic must be placed in src/app/api/_services/.
    • API route handlers (route.ts) should remain thin and delegate work to their corresponding service functions.
  2. No Direct Prisma in Routes

    • Import the relevant service in route.ts and call it.
    • This pattern keeps your routes readable and encourages reusability/testing of the service layer.
  3. Error Handling

    • Use try/catch blocks in service functions if your logic can throw.
    • Return standardized error responses to the client so they can handle them consistently.
  4. File & Folder Size

    • As with frontend, keep files under ~200 lines where possible.
    • Break large services into smaller domain-specific files if they become too large or cluttered.

πŸ’‘ Pro Tip: A well-organized backend means fewer late-night debugging sessions. Sleep is precious! 😴


1.4 Additional Best Practices πŸ’‘

  1. Environment Files

    • Never commit .env or .env.local files to the repository.
    • Keep secrets (API keys, database credentials) in environment variables.
    • If new environment variables are introduced, document them in the project’s README or .env.example.
  2. Reusability & Modularity

    • Look for existing utilities, hooks, or components before creating new ones.
    • Maintain a logical hierarchy: if code is used in multiple places, move it to a more generic folder (utils/, components/, or a relevant domain folder).
  3. Consistency Over Individual Preference

    • Adhere to established patterns (naming, file structure, code style) even if you prefer a different style.
    • Consistency greatly reduces confusion in a growing team and codebase.

πŸ’‘ Pro Tip: Great code is a team effort! Don’t hesitate to ask for help or review.


2. Project Structure & Organization πŸ“‚

A well-defined structure makes it easier for everyone to navigate, contribute, and scale the codebase. Below are guidelines on how to organize your files and folders for both frontend and backend in Bluewave Datahall. Consistency is keyβ€”if in doubt, ask the team or check existing patterns before creating a new folder or file structure.


2.1 Frontend 🎨

A typical Next.js App Router layout means feature-related routes and pages go under src/app/. We group things by feature (e.g., documents, links, profile) to keep them logical and discoverable.

  1. Next.js App Router

    • Organize pages/routes under src/app/<feature>/. Each feature folder might have subfolders like [documentId], [linkId], etc.
    • Keep route definitions (page.tsx, layout.tsx) straightforward; heavy business logic or specialized UI goes in subfolders or separate components.
  2. Components

    • Reusable UI components go under src/components/, grouped by domain (e.g., common/, input/, loaders/, fileHandling/, etc.).
    • If a component is only relevant to one feature, you may keep it in that feature’s folder (e.g., app/documents/[documentId]/components/).
    • Strive to keep them small, focused, and easy to reuse.
  3. Hooks

    • Place all custom hooks in src/hooks/ (or subfolders like src/hooks/documents/, src/hooks/auth/, etc.) to keep them discoverable.
    • Create one file per hook: Each hook (e.g., useDocuments.ts, useAddDocument.ts) should live in its own file rather than bundling multiple hooks together.
    • Domain-Based Organization: For example, if you have multiple document-related hooks (useDocuments.ts, useDeleteDocument.ts, useAddDocument.ts), store them under src/hooks/documents/.
    • TanStack Query Integration: Hooks should encapsulate all query, mutation, and caching logic, ensuring components don’t call axios or fetch directly.
  4. Shared & Theming

    • Common helpers, data models, and utilities now reside in src/shared/. For instance:
      • src/shared/models/
      • src/shared/types/
      • src/shared/utils/
    • MUI theming files are in src/theme/ (e.g., globalTheme.ts, mainTheme.ts).
    • Keep frequently reused style objects or CSS snippets accessible in a shared location to maintain consistency.
  5. Example Frontend Structure

    src/
    β”œβ”€β”€ app/
    β”‚   β”œβ”€β”€ documents/
    β”‚   β”‚   β”œβ”€β”€ [documentId]/
    β”‚   β”‚   β”‚   β”œβ”€β”€ components/
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ DocumentView.tsx
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ FilterToggle.tsx
    β”‚   β”‚   β”‚   β”‚   └── InfoTable.tsx
    β”‚   β”‚   β”‚   β”œβ”€β”€ loading.tsx
    β”‚   β”‚   β”‚   └── page.tsx
    β”‚   β”‚   β”œβ”€β”€ components/
    β”‚   β”‚   β”‚   β”œβ”€β”€ DocumentsTable.tsx
    β”‚   β”‚   β”‚   β”œβ”€β”€ DragAndDropBox.tsx
    β”‚   β”‚   β”‚   └── ...
    β”‚   β”‚   └── page.tsx
    β”‚   β”œβ”€β”€ links/
    β”‚   β”‚   β”œβ”€β”€ [linkId]/
    β”‚   β”‚   β”‚   β”œβ”€β”€ components/
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ FileAccessContainer.tsx
    β”‚   β”‚   β”‚   β”‚   └── FileDisplay.tsx
    β”‚   β”‚   β”‚   β”œβ”€β”€ layout.tsx
    β”‚   β”‚   β”‚   β”œβ”€β”€ loading.tsx
    β”‚   β”‚   β”‚   └── page.tsx
    β”‚   β”œβ”€β”€ profile/
    β”‚   β”‚   β”œβ”€β”€ components/
    β”‚   β”‚   └── page.tsx
    β”‚   β”œβ”€β”€ providers.tsx
    β”‚   β”œβ”€β”€ layout.tsx
    β”‚   └── page.tsx
    β”œβ”€β”€ components/
    β”‚   β”œβ”€β”€ layout/
    β”‚   β”œβ”€β”€ navigation/
    β”‚   β”œβ”€β”€ input/
    β”‚   β”œβ”€β”€ loaders/
    β”‚   β”œβ”€β”€ fileHandling/
    β”‚   β”œβ”€β”€ common/
    β”‚   β”œβ”€β”€ modals/
    β”‚   └── index.ts
    β”œβ”€β”€ hooks/
    β”‚   β”œβ”€β”€ documents/
    β”‚   β”‚   β”œβ”€β”€ useDocuments.ts
    β”‚   β”‚   └── ...
    β”‚   β”œβ”€β”€ auth/
    β”‚   β”œβ”€β”€ useModal.ts
    β”‚   β”œβ”€β”€ useToast.ts
    β”‚   └── ...
    β”œβ”€β”€ icons/                      πŸ“ All application icons
    β”œβ”€β”€ shared/
    β”‚   β”œβ”€β”€ models/                 πŸ“ Data models for different domains
    β”‚   β”œβ”€β”€ types/                  πŸ“ Global TypeScript types
    β”‚   └── utils/                  πŸ“ Shared utility functions
    └── theme/
        └── mainTheme.ts           🎨 MUI global theme configuration
    

πŸ’‘ Pro Tip: Always keep file size in check (aim for ~200 lines or less). If a hook becomes too large or handles multiple responsibilities, consider splitting it into smaller, logical parts.

2.2 Backend πŸ—„οΈ

Our backend uses Next.js API routes under src/app/api/. We rely on services in src/app/api/_services/ to handle database logic, ensuring route handlers remain light and easy to maintain.

  1. API Routes & Services

    • src/app/api/ contains Next.js API routes, grouped by feature (auth/, documents/, public_links/, etc.).
    • Each feature folder can have its own subfolders (e.g., [documentId]/, [linkId]/).
    • All database logic goes into src/app/api/_services/ (e.g., authService.ts, documentService.ts, linkService.ts).
  2. No Prisma in Routes

    • Keep route handlers lean: parse requests, call the relevant service, and return a response.
    • The actual Prisma interactions live in service files.
  3. Structure Example

    src/
    └── app/
        β”œβ”€β”€ api/
        β”‚   β”œβ”€β”€ auth/
        β”‚   β”‚   β”œβ”€β”€ [...nextauth]/
        β”‚   β”‚   β”œβ”€β”€ verify/
        β”‚   β”‚   β”œβ”€β”€ register/
        β”‚   β”‚   └── password/
        β”‚   β”‚       β”œβ”€β”€ forgot/route.ts
        β”‚   β”‚       └── reset/route.ts
        β”‚   β”œβ”€β”€ documents/
        β”‚   β”‚   β”œβ”€β”€ route.ts
        β”‚   β”‚   β”œβ”€β”€ [documentId]/
        β”‚   β”‚   β”‚   β”œβ”€β”€ route.ts
        β”‚   β”‚   β”‚   β”œβ”€β”€ links/
        β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ route.ts
        β”‚   β”‚   β”‚   β”‚   └── [linkId]/route.ts
        β”‚   β”‚   β”‚   └── visitors/route.ts
        β”‚   β”œβ”€β”€ public_links/
        β”‚   β”‚   β”œβ”€β”€ [linkId]/route.ts
        β”‚   β”‚   └── [linkId]/access/route.ts
        β”‚   β”œβ”€β”€ profile/
        β”‚   β”‚   β”œβ”€β”€ changeName/
        β”‚   β”‚   β”‚   └── route.ts
        β”‚   β”‚   β”œβ”€β”€ changePassword/
        β”‚   β”‚   β”‚   └── route.ts
        β”‚   β”‚   └── route.ts
        β”‚   β”œβ”€β”€ _services/
        β”‚   β”‚   β”œβ”€β”€ authService.ts
        β”‚   β”‚   β”œβ”€β”€ emailService.ts
        β”‚   β”‚   β”œβ”€β”€ documentService.ts
        β”‚   β”‚   β”œβ”€β”€ linkService.ts
        β”‚   β”‚   └── ...
    
  4. Keeping Services Manageable

    • If a service handles too many responsibilities, split it into multiple files (e.g., documentService.ts, documentAnalyticsService.ts).
    • Use clear function names like getUserById, updateDocument, etc.
  5. Shared Utilities

    • A single file (like src/lib/prisma.ts) often initializes the Prisma client to keep everything consistent.
    • Additional backend helpers (e.g., error formatting, input validation) can live in _services/util/ or src/shared/utils/ if they’re used project-wide.

πŸ’‘ Pro Tip: Keep your async/await usage consistent; mixing it with .then() can lead to confusion. A well-organized backend means fewer frantic searches at 2 AM.


2.3 Summary πŸ“

Frontend Backend
- Feature folders under src/app/ (Next.js App Router).
- Reusable components in src/components/.
- Domain-based hooks in src/hooks/.
- Shared models, types, and utilities in src/shared/.
- Theming in src/theme/.
- Feature-based route folders under src/app/api/.
- All Prisma logic in src/app/api/_services/.
- Route files stay thin, delegating to services.
- Shared config/utilities in src/lib/ or src/shared/utils/.

By following this structure, you ensure that the codebase remains maintainable, discoverable, and easy to expand as new features are added.

  • Keep file sizes small (~200 lines max).
  • Don’t duplicate logicβ€”if something’s used in multiple places, centralize it.

3. GitHub Workflow πŸ™

A well-structured GitHub workflow helps the team stay organized, prioritize tasks, and ensure that every change is tracked and reviewed properly. Below are our conventions for issues, branching, and pull requests in Bluewave Datahall.


3.1 Issues Management πŸ“‘

  1. Creating Issues

    • Provide a clear title and detailed description.
    • Include acceptance criteria, subtasks, or screenshots (if relevant) to help clarify the requirements.
    • Assign a priority level (see 3.2 Issue Priority Levels below) and add labels (e.g., Frontend, Backend, Refactor) as needed to categorize your issue.
  2. Issue Statuses

    • To Do: Newly created issues that haven’t been started.
    • In Progress: Actively being worked on.
    • In Review: A pull request (PR) has been created and is awaiting review.
    • Done: Once the code has been reviewed and deployed successfully, I will close the issue (developers should not close issues themselves).
  3. Ownership & Assignments

    • When you begin work on an issue, assign yourself (if unassigned) and move it to In Progress.
    • If you need help or are blocked, communicate in the issue or tag another developer πŸ’¬.
  4. Don’t Forget ✨

    • Never close issues yourself β€” let the project lead handle it after verifying the merge.
    • Update the issue status promptly to reflect your progress.

3.2 Issue Priority Levels πŸ”‘

Every issue in this project will have one of the following five priorities. Developers should use these levels to decide what to work on next and how quickly an issue should be addressed.

  1. πŸ”₯Critical

    • Definition: Completely obstructs core functionality or causes major service interruptions.
    • Action: Must be resolved before all other tasks. If an issue is deemed β€œHigh Priority” (i.e., critical for an upcoming deadline), it falls under this category. Stop lower-priority work to address it immediately.
  2. ⚑Important

    • Definition: A significant problem or feature that needs resolution before the upcoming release or milestone.
    • Action: Work on these right after addressing any Critical issues. They often involve bugs that risk deadlines or features essential to user satisfaction.
  3. 🌱Nice-to-Have

    • Definition: Useful improvements, UI refinements, or optimizations that add value without being urgent.
    • Action: Tackle these once more pressing issues (Critical or Important) are under control. They often enhance usability or maintainability.
  4. πŸ› οΈBacklog

    • Definition: Tasks or ideas not needed for the current release cycle or immediate roadmap.
    • Action: Schedule these for later or pick them up during quieter periods; they have minimal immediate impact on users.
  5. πŸ“₯Icebox

    • Definition: Low-priority or speculative ideas that may or may not be addressed in the future.
    • Action: No current plans to tackle; revisit periodically to see if new information or resources make them more relevant.

Handling Priorities

  • Critical issues always come firstβ€”address them before everything else.
  • If you finish your assigned tasks or are unsure what to tackle next, check for Critical or Important items.
  • For issues that initially lack clarity or need discussion, add a Needs Review or Question label to them and collaborate with the team to refine their scope.

3.3 Branching Strategy 🌳

A clear branching strategy prevents conflicts and keeps our release process smooth.

  1. Base Branch

    • Always branch off of dev.
    • Never branch from master unless explicitly told.
  2. Branch Naming Conventions

    • feature/ for new features (e.g., feature/document-analytics).
    • fix/ for bug fixes (e.g., fix/login-error).
    • hotfix/ for critical fixes that need immediate attention.
    • refactor/ for refactoring efforts (e.g., refactor/hooks-structure).
  3. No Direct Commits

    • Do not commit or push directly to dev or master.
    • Always work on a feature/fix branch and submit a pull request (PR).
  4. Keep Your Branch Updated

    • Before opening (or merging) a PR, rebase or pull the latest changes from dev to avoid merge conflicts and ensure your branch is in sync.

πŸ’‘ Pro Tip: Keep your branches small and focused. A tidy branch is easier to review and merge!


3.4 Pull Request (PR) Guidelines πŸ“₯

All changes, no matter how small, should be submitted via PR.

  1. When to Create a PR

    • As soon as you have a working slice of functionality (or bug fix), open a PR.
    • This allows for early feedback and avoids massive, hard-to-review PRs.
  2. PR Requirements

    • Base branch: Always set dev as the target.
    • Link issues: Reference related issues using keywords like Closes #123.
    • Description: Provide a concise summary of what changed and why.
    • Screenshots: If there are UI changes, include before/after visuals πŸ“Έ.
  3. Review Process

    • Add me (@mahid797) as a reviewer.
    • Do not merge your own PRβ€”wait for review and approval.
    • Address review comments promptly; if you disagree, provide clear reasoning.
  4. Never Close Issues or Merge Your Own PR

    • After approval, the project lead will handle merging.
    • Once the merge is verified, the project lead will close the issue.
  5. Checklist βœ…

    • Code follows coding and structuring guidelines.
    • Code is formatted using Prettier.
    • No unused variables, imports, or commented code.
    • Issue(s) linked.
    • dev is the merge target.

3.5 Commit Message Conventions πŸ“

Though not strictly enforced, using a consistent pattern makes it easier to scan commit history.

  • Format: <type>(scope): short description

    • Types: feat, fix, refactor, docs, style, etc.
    • Scope: The part of the project affected (e.g., auth, documents).
  • Examples

    • feat(documents): add new endpoint for analytics
    • fix(auth): correct login session bug
    • refactor(hooks): restructure document hooks for clarity

3.6 Final Thoughts 🀝

Following this workflow ensures a clear, auditable history of changes and keeps everyone aligned:

  • Create & assign issues with clear descriptions and priorities.
  • Branch off dev with meaningful names.
  • Open a PR for all changes, link issues, and add me as a reviewer.
  • Don’t merge your own PR or close issuesβ€”wait for final review.