Skip to content

Milestone: M2 — Platform and Client Admin | SOW Reference: FR5 | Requirement Clarity: ✅ Clear | Dev Status: 🟢 Prototyped in POC (logo/hero image upload to S3 not yet implemented — URL-only today) Moved from docs/requirements/tasks/organization-branding-implementation.md — this is the original detailed implementation breakdown, unmodified below. Note it specs S3-based file upload (FileUploadService, uploadLogo, uploadHeroImage) which is the flagged gap: confirm this still needs building for M2.

M2-04 Organization Branding Implementation Tasks

This document breaks down the implementation tasks for creating the organization branding and email template customization features of the REC Verifiable Credentialing Platform. These features enable staffing companies to customize the appearance of landing pages and emails for credential issuance and verification.

Implementation Strategy

The implementation will follow these steps: 1. Enhance the branding entity and create DTOs 2. Implement file upload functionality for logos and images 3. Develop services for branding and email template management 4. Create controllers for branding and email template API endpoints 5. Implement preview functionality for templates

Current Implementation Status

The project currently has:

  1. Branding Entity:
  2. Basic Branding entity with fields for theme, logo, and hero image
  3. Relationship to the Organization entity

  4. Email Template Entity:

  5. Basic EmailTemplate entity with fields for name, subject, and body content
  6. Relationship to the Organization entity

Backend Tasks

Branding DTOs

  • Create app/backend/src/admin/dto/branding.dto.ts
  • Implement UpdateBrandingDto:
    • theme (object, optional): Theme settings (colors, fonts, etc.)
    • logoS3Key (string, optional): S3 key for logo image
    • heroImageS3Key (string, optional): S3 key for hero image
  • Implement BrandingResponseDto:
    • id (string): Branding ID
    • orgId (string): Organization ID
    • theme (object): Theme settings
    • logoUrl (string): URL for logo image
    • heroImageUrl (string): URL for hero image
    • createdAt (string): Creation timestamp
    • updatedAt (string): Last update timestamp
  • Implement ThemeDto:
    • primaryColor (string, optional): Primary brand color
    • secondaryColor (string, optional): Secondary brand color
    • accentColor (string, optional): Accent color
    • fontFamily (string, optional): Primary font family
    • headingFontFamily (string, optional): Heading font family
    • buttonStyle (string, optional): Button style (e.g., "rounded", "square")

Email Template DTOs

  • Create app/backend/src/admin/dto/email-template.dto.ts
  • Implement CreateEmailTemplateDto:
    • name (string, required): Template name
    • subject (string, required): Email subject
    • bodyHtml (string, required): HTML body content
    • bodyText (string, required): Plain text body content
    • variables (array, optional): Allowed placeholder variables
  • Implement UpdateEmailTemplateDto:
    • name (string, optional): Template name
    • subject (string, optional): Email subject
    • bodyHtml (string, optional): HTML body content
    • bodyText (string, optional): Plain text body content
    • variables (array, optional): Allowed placeholder variables
  • Implement EmailTemplateResponseDto:
    • id (string): Template ID
    • orgId (string): Organization ID
    • name (string): Template name
    • subject (string): Email subject
    • bodyHtml (string): HTML body content
    • bodyText (string): Plain text body content
    • variables (array): Allowed placeholder variables
    • createdAt (string): Creation timestamp
    • updatedAt (string): Last update timestamp

File Upload Service

  • Create app/backend/src/admin/services/file-upload.service.ts
  • Implement constructor with dependencies:
    • Inject ConfigService for accessing S3 configuration
    • Inject LoggerService for logging
  • Implement uploadFile method:
    • Parameters: file (Buffer), folder (string), metadata (object)
    • Returns: Promise (S3 file key)
    • Generate a unique file key
    • Upload the file to S3
    • Log the upload operation
  • Implement getFileUrl method:
    • Parameters: fileKey (string)
    • Returns: string (presigned URL)
    • Generate a presigned URL for the file
  • Implement deleteFile method:
    • Parameters: fileKey (string)
    • Returns: Promise
    • Delete the file from S3
    • Log the delete operation

Branding Service

  • Create app/backend/src/admin/services/branding.service.ts
  • Implement constructor with dependencies:
    • Inject BrandingRepository
    • Inject FileUploadService
    • Inject LoggerService
  • Implement getBranding method:
    • Parameters: organizationId (string)
    • Returns: Promise
    • Get branding for an organization
    • If not found, return default branding
  • Implement updateBranding method:
    • Parameters: organizationId (string), updateBrandingDto (UpdateBrandingDto)
    • Returns: Promise
    • Update branding for an organization
    • Log the update operation
  • Implement uploadLogo method:
    • Parameters: organizationId (string), file (Buffer), mimeType (string)
    • Returns: Promise
    • Upload logo to S3
    • Update branding with new logo S3 key
    • Log the upload operation
  • Implement uploadHeroImage method:
    • Parameters: organizationId (string), file (Buffer), mimeType (string)
    • Returns: Promise
    • Upload hero image to S3
    • Update branding with new hero image S3 key
    • Log the upload operation
  • Implement getDefaultBranding method:
    • Returns: Branding
    • Return default branding settings

Email Template Service

  • Create app/backend/src/admin/services/email-template.service.ts
  • Implement constructor with dependencies:
    • Inject EmailTemplateRepository
    • Inject LoggerService
  • Implement createEmailTemplate method:
    • Parameters: organizationId (string), createEmailTemplateDto (CreateEmailTemplateDto)
    • Returns: Promise
    • Create a new email template
    • Validate HTML content
    • Log the creation operation
  • Implement getEmailTemplates method:
    • Parameters: organizationId (string), filters (object)
    • Returns: Promise<[EmailTemplate[], number]>
    • Get email templates with pagination and filtering
  • Implement getEmailTemplateById method:
    • Parameters: id (string)
    • Returns: Promise
    • Get a single email template by ID
  • Implement updateEmailTemplate method:
    • Parameters: id (string), updateEmailTemplateDto (UpdateEmailTemplateDto)
    • Returns: Promise
    • Update the email template
    • Validate HTML content
    • Log the update operation
  • Implement deleteEmailTemplate method:
    • Parameters: id (string)
    • Returns: Promise
    • Delete the email template
    • Log the delete operation
  • Implement previewEmailTemplate method:
    • Parameters: id (string), data (object)
    • Returns: { subject: string, bodyHtml: string, bodyText: string }
    • Replace variables in the template with provided data
    • Return the rendered template
  • Implement getDefaultTemplates method:
    • Parameters: templateType (string)
    • Returns: Promise
    • Return default email templates for different purposes

Branding Controller

  • Create app/backend/src/admin/controllers/branding.controller.ts
  • Implement constructor with dependencies:
    • Inject BrandingService
  • Implement getBranding endpoint:
    • GET /organizations/:id/branding
    • Parameters: organizationId (path)
    • Returns: BrandingResponseDto
    • Add @Roles decorator to restrict access to appropriate roles
    • Add Swagger documentation
  • Implement updateBranding endpoint:
    • PUT /organizations/:id/branding
    • Parameters: organizationId (path), updateBrandingDto (body)
    • Returns: BrandingResponseDto
    • Add @Roles decorator to restrict access to appropriate roles
    • Add validation using class-validator
    • Add Swagger documentation
  • Implement uploadLogo endpoint:
    • POST /organizations/:id/branding/logo
    • Parameters: organizationId (path), file (multipart/form-data)
    • Returns: BrandingResponseDto
    • Add @Roles decorator to restrict access to appropriate roles
    • Add Swagger documentation
  • Implement uploadHeroImage endpoint:
    • POST /organizations/:id/branding/hero-image
    • Parameters: organizationId (path), file (multipart/form-data)
    • Returns: BrandingResponseDto
    • Add @Roles decorator to restrict access to appropriate roles
    • Add Swagger documentation

Email Template Controller

  • Create app/backend/src/admin/controllers/email-template.controller.ts
  • Implement constructor with dependencies:
    • Inject EmailTemplateService
  • Implement createEmailTemplate endpoint:
    • POST /organizations/:id/email-templates
    • Parameters: organizationId (path), createEmailTemplateDto (body)
    • Returns: EmailTemplateResponseDto
    • Add @Roles decorator to restrict access to appropriate roles
    • Add validation using class-validator
    • Add Swagger documentation
  • Implement getEmailTemplates endpoint:
    • GET /organizations/:id/email-templates
    • Parameters: organizationId (path), pagination and filter params (query)
    • Returns: Array of EmailTemplateResponseDto
    • Add @Roles decorator to restrict access to appropriate roles
    • Add Swagger documentation
  • Implement getEmailTemplateById endpoint:
    • GET /organizations/:id/email-templates/:templateId
    • Parameters: organizationId (path), templateId (path)
    • Returns: EmailTemplateResponseDto
    • Add @Roles decorator to restrict access to appropriate roles
    • Add Swagger documentation
  • Implement updateEmailTemplate endpoint:
    • PUT /organizations/:id/email-templates/:templateId
    • Parameters: organizationId (path), templateId (path), updateEmailTemplateDto (body)
    • Returns: EmailTemplateResponseDto
    • Add @Roles decorator to restrict access to appropriate roles
    • Add validation using class-validator
    • Add Swagger documentation
  • Implement deleteEmailTemplate endpoint:
    • DELETE /organizations/:id/email-templates/:templateId
    • Parameters: organizationId (path), templateId (path)
    • Returns: void
    • Add @Roles decorator to restrict access to appropriate roles
    • Add Swagger documentation
  • Implement previewEmailTemplate endpoint:
    • POST /organizations/:id/email-templates/:templateId/preview
    • Parameters: organizationId (path), templateId (path), previewData (body)
    • Returns: { subject: string, bodyHtml: string, bodyText: string }
    • Add @Roles decorator to restrict access to appropriate roles
    • Add Swagger documentation

Unit Tests

  • Create app/backend/src/admin/services/branding.service.spec.ts
  • Test getBranding method
  • Test updateBranding method
  • Test uploadLogo method
  • Test uploadHeroImage method

  • Create app/backend/src/admin/services/email-template.service.spec.ts

  • Test createEmailTemplate method
  • Test getEmailTemplates method
  • Test getEmailTemplateById method
  • Test updateEmailTemplate method
  • Test deleteEmailTemplate method
  • Test previewEmailTemplate method

Frontend Tasks

Branding Configuration UI

  • Create app/frontend/src/components/branding/BrandingForm.tsx
  • Implement form with the following sections:
    • Color picker for theme colors
    • Font selector for typography
    • Logo upload with preview
    • Hero image upload with preview
  • Add validation for all inputs
  • Implement form submission to API
  • Add success/error handling
  • Add preview functionality

Email Template Editor UI

  • Create app/frontend/src/components/email-templates/TemplateEditor.tsx
  • Implement editor with the following features:
    • Rich text editor for HTML content
    • Plain text editor for text content
    • Subject line input
    • Variable insertion dropdown
    • Preview functionality
  • Add validation for all inputs
  • Implement form submission to API
  • Add success/error handling

Email Template List UI

  • Create app/frontend/src/components/email-templates/TemplateList.tsx
  • Implement list with the following features:
    • Template name and type
    • Creation and update dates
    • Edit and delete buttons
    • Preview button
  • Add filtering and sorting options
  • Implement pagination
  • Add search functionality

Email Template Preview UI

  • Create app/frontend/src/components/email-templates/TemplatePreview.tsx
  • Implement preview with the following features:
    • Rendered HTML preview
    • Plain text preview
    • Test data input form
    • Send test email button
  • Add responsive design for mobile and desktop preview

Dependencies & Assumptions

Prerequisites

  • The Branding entity must be properly defined
  • The EmailTemplate entity must be properly defined
  • S3 or equivalent storage must be available for file storage
  • Email service must be available for sending test emails

Cross-team Needs

  • Frontend team needs to implement the UI components
  • DevOps team needs to configure S3 or equivalent storage
  • QA team needs to test the branding and email template functionality

Implementation Notes

  1. Security Considerations:
  2. All uploaded files must be scanned for malware
  3. HTML content must be sanitized to prevent XSS attacks
  4. Access to branding and email templates must be restricted to authorized users

  5. Performance Considerations:

  6. Image uploads should be optimized for web use
  7. Email template rendering should be efficient
  8. File URLs should be cached where appropriate

  9. Usability Considerations:

  10. Preview functionality should accurately represent the final output
  11. Variable insertion should be intuitive
  12. Color picker should include common presets

  13. Testing Requirements:

  14. Unit tests should cover all service methods
  15. Integration tests should verify the complete workflow
  16. Visual tests should verify the rendering of templates