GitHub

Folder Structure

Comprehensive guide to Mail Assist's project organization, file structure, and architectural patterns for maintainable and scalable code.

Project Overview

Mail Assist follows Next.js 14 App Router conventions with a clean, organized structure that separates concerns and promotes code reusability.

project-structure.txt
mail-assist/
├── app/                          # Next.js App Router pages
│   ├── (auth)/                   # Auth route group
│   │   ├── login/
│   │   │   └── page.tsx
│   │   └── signup/
│   │       └── page.tsx
│   ├── dashboard/                # Protected dashboard routes
│   │   ├── page.tsx
│   │   ├── history/
│   │   │   └── page.tsx
│   │   └── send/
│   │       └── page.tsx
│   ├── api/                      # API routes
│   │   ├── send/
│   │   │   └── route.ts
│   │   ├── custom-mail/
│   │   │   └── route.ts
│   │   └── user-mails/
│   │       └── route.ts
│   ├── globals.css               # Global styles
│   ├── layout.tsx                # Root layout
│   ├── page.tsx                  # Homepage
│   ├── loading.tsx               # Global loading UI
│   └── not-found.tsx             # 404 page
project-structure.txt
├── components/                   # Reusable components
│   ├── ui/                       # ShadCN/UI components
│   │   ├── button.tsx
│   │   ├── input.tsx
│   │   ├── card.tsx
│   │   └── ...
│   ├── auth/                     # Authentication components
│   │   ├── login-form.tsx
│   │   ├── signup-form.tsx
│   │   └── auth-provider.tsx
│   ├── email/                    # Email-related components
│   │   ├── email-composer.tsx
│   │   ├── email-preview.tsx
│   │   ├── template-selector.tsx
│   │   └── email-history.tsx
project-structure.txt
├── lib/                          # Utility libraries
│   ├── supabase/                 # Supabase configuration
│   │   ├── client.ts
│   │   ├── server.ts
│   │   └── types.ts
│   ├── resend/                   # Resend configuration
│   │   └── client.ts
│   ├── utils.ts                  # General utilities
│   ├── validations.ts            # Form validation schemas
│   └── constants.ts              # App constants
├── hooks/                        # Custom React hooks
│   ├── use-auth.ts
│   ├── use-credits.ts
│   └── use-email-history.ts
project-structure.txt
├── types/                        # TypeScript type definitions
│   ├── auth.ts
│   ├── email.ts
│   └── database.ts
├── templates/                    # Email templates
│   ├── welcome.tsx
│   ├── newsletter.tsx
│   └── notification.tsx
├── public/                       # Static assets
│   ├── images/
│   ├── icons/
│   └── favicon.ico
├── .env.example                  # Environment variables template
├── .env.local                    # Local environment variables
├── next.config.js                # Next.js configuration
├── tailwind.config.js            # Tailwind CSS configuration
├── tsconfig.json                 # TypeScript configuration
├── package.json                  # Dependencies and scripts
└── README.md                     # Project documentation

App Directory Structure

The app directory contains all pages, layouts, and API routes following Next.js 14 App Router conventions.

Route Groups

Route Groups
Folders wrapped in parentheses like (auth) are route groups that organize routes without affecting the URL structure.
app/(auth)/layout.tsx
export default function AuthLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-50">
      <div className="max-w-md w-full space-y-8">
        {children}
      </div>
    </div>
  )
}

API Routes Structure

API routes are organized by functionality with clear naming conventions and consistent response patterns.

api-structure.txt
app/api/
├── send/
│   └── route.ts              # Main email sending endpoint
├── custom-mail/
│   └── route.ts              # Custom email handling
├── user-mails/
│   └── route.ts              # Email history retrieval
api-structure.txt
├── auth/
│   ├── callback/
│   │   └── route.ts          # Auth callback handler
│   └── signout/
│       └── route.ts          # Sign out handler
└── credits/
    ├── balance/
    │   └── route.ts          # Get credit balance
    └── purchase/
        └── route.ts          # Purchase credits (future)

Components Organization

Components are organized by feature and responsibility, promoting reusability and maintainability across the application.

UI Components

The components/ui directory contains all ShadCN/UI components that provide the design system foundation.

ui-components.txt
components/ui/
├── button.tsx                # Button variants and sizes
├── input.tsx                 # Form input components
├── card.tsx                  # Card layouts
├── dialog.tsx                # Modal dialogs
├── dropdown-menu.tsx         # Dropdown menus
ui-components.txt
├── form.tsx                  # Form components
├── label.tsx                 # Form labels
├── select.tsx                # Select dropdowns
├── textarea.tsx              # Text areas
├── toast.tsx                 # Toast notifications
├── tooltip.tsx               # Tooltips
└── ...                       # Other UI primitives

Feature Components

Feature-specific components are grouped by functionality for better organization and easier maintenance.

Auth Components

components/auth/
├── login-form.tsx
├── signup-form.tsx
├── forgot-password.tsx
├── auth-provider.tsx
└── protected-route.tsx

Email Components

components/email/
├── email-composer.tsx
├── email-preview.tsx
├── template-selector.tsx
├── email-history.tsx
└── credit-indicator.tsx

Library Directory

The lib directory contains configuration files, utilities, and service integrations that are used throughout the application.

Supabase Configuration

lib/supabase/client.ts
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import type { Database } from './types'

export const createClient = () => 
  createClientComponentClient<Database>()
lib/supabase/server.ts
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import type { Database } from './types'

export const createServerClient = () => 
  createServerComponentClient<Database>({ cookies })

Utility Functions

lib/utils.ts
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}
lib/utils.ts
export function formatDate(date: string | Date) {
  return new Intl.DateTimeFormat('en-US', {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  }).format(new Date(date))
}
lib/utils.ts
export function validateEmail(email: string) {
  const emailRegex = /^[^s@]+@[^s@]+.[^s@]+$/
  return emailRegex.test(email)
}
lib/utils.ts
export function calculateCreditsNeeded(mailType: 'custom' | 'template') {
  return mailType === 'custom' ? 5 : 10
}

Custom Hooks

Custom React hooks encapsulate reusable logic and state management for common operations throughout the application.

Authentication Hook

hooks/use-auth.ts
import { useEffect, useState } from 'react'
import { createClient } from '@/lib/supabase/client'
import type { User } from '@supabase/auth-helpers-nextjs'

export function useAuth() {
  const [user, setUser] = useState<User | null>(null)
  const [loading, setLoading] = useState(true)
  const supabase = createClient()
hooks/use-auth.ts
useEffect(() => {
    const getUser = async () => {
      const { data: { session } } = await supabase.auth.getSession()
      setUser(session?.user ?? null)
      setLoading(false)
    }

    getUser()
hooks/use-auth.ts
const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (event, session) => {
        setUser(session?.user ?? null)
        setLoading(false)
      }
    )

    return () => subscription.unsubscribe()
  }, [supabase.auth])

  return { user, loading }
}

Credits Management Hook

hooks/use-credits.ts
import { useEffect, useState } from 'react'
import { createClient } from '@/lib/supabase/client'
import { useAuth } from './use-auth'

export function useCredits() {
  const [credits, setCredits] = useState<number>(0)
  const [loading, setLoading] = useState(true)
  const { user } = useAuth()
  const supabase = createClient()
hooks/use-credits.ts
useEffect(() => {
    if (!user) return

    const fetchCredits = async () => {
      const { data, error } = await supabase
        .from('profiles')
        .select('credits')
        .eq('id', user.id)
        .single()

      if (data && !error) {
        setCredits(data.credits)
      }
      setLoading(false)
    }

    fetchCredits()
  }, [user, supabase])
hooks/use-credits.ts
const refreshCredits = async () => {
    if (!user) return

    const { data, error } = await supabase
      .from('profiles')
      .select('credits')
      .eq('id', user.id)
      .single()

    if (data && !error) {
      setCredits(data.credits)
    }
  }

  return { credits, loading, refreshCredits }
}

Type Definitions

TypeScript type definitions are organized by domain to ensure type safety and better developer experience across the application.

Database Types

types/database.ts
export interface Database {
  public: {
    Tables: {
      profiles: {
        Row: {
          id: string
          email: string | null
          credits: number
          created_at: string
          updated_at: string
        }
types/database.ts
Insert: {
          id: string
          email?: string | null
          credits?: number
          created_at?: string
          updated_at?: string
        }
        Update: {
          id?: string
          email?: string | null
          credits?: number
          created_at?: string
          updated_at?: string
        }
      }
types/database.ts
user_mails: {
        Row: {
          id: string
          user_id: string
          recipient_email: string
          subject: string
          content: string
          mail_type: 'custom' | 'template'
          credits_used: number
          sent_at: string
        }
types/database.ts
Insert: {
          id?: string
          user_id: string
          recipient_email: string
          subject: string
          content: string
          mail_type: 'custom' | 'template'
          credits_used: number
          sent_at?: string
        }
        Update: {
          id?: string
          user_id?: string
          recipient_email?: string
          subject?: string
          content?: string
          mail_type?: 'custom' | 'template'
          credits_used?: number
          sent_at?: string
        }
      }
    }
  }
}

Email Types

types/email.ts
export interface EmailData {
  to: string
  subject: string
  html: string
  mailType: 'custom' | 'template'
}

export interface EmailResponse {
  success: boolean
  messageId?: string
  creditsUsed?: number
  remainingCredits?: number
  error?: string
}
types/email.ts
export interface EmailHistoryItem {
  id: string
  recipient_email: string
  subject: string
  content: string
  mail_type: 'custom' | 'template'
  credits_used: number
  sent_at: string
}

export interface EmailTemplate {
  id: string
  name: string
  description: string
  html: string
  preview: string
  category: 'welcome' | 'newsletter' | 'notification' | 'marketing'
}

Email Templates

Email templates are React components that generate HTML for different email types, providing consistent branding and responsive design.

templates/welcome.tsx
interface WelcomeEmailProps {
  userName: string
  loginUrl: string
}

export function WelcomeEmail({ userName, loginUrl }: WelcomeEmailProps) {
  return (
    <div style={{ fontFamily: 'Arial, sans-serif', maxWidth: '600px', margin: '0 auto' }}>
      <div style={{ backgroundColor: '#f8f9fa', padding: '40px 20px', textAlign: 'center' }}>
templates/welcome.tsx
<h1 style={{ color: '#333', marginBottom: '20px' }}>
          Welcome to Mail Assist, {userName}!
        </h1>
        <p style={{ color: '#666', fontSize: '16px', lineHeight: '1.5' }}>
          Thank you for joining Mail Assist. We're excited to help you send 
          beautiful emails with ease.
        </p>
templates/welcome.tsx
<a 
          href={loginUrl}
          style={{
            display: 'inline-block',
            backgroundColor: '#007bff',
            color: 'white',
            padding: '12px 24px',
            textDecoration: 'none',
            borderRadius: '6px',
            marginTop: '20px'
          }}
        >
          Get Started
        </a>
      </div>
    </div>
  )
}

Configuration Files

Key configuration files that control the behavior and setup of the Mail Assist application.

Next.js Configuration

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverActions: true,
  },
  images: {
    domains: ['images.unsplash.com'],
  },
  env: {
    CUSTOM_KEY: process.env.CUSTOM_KEY,
  },
}

module.exports = nextConfig

Tailwind Configuration

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: ["class"],
  content: [
    './pages/**/*.{ts,tsx}',
    './components/**/*.{ts,tsx}',
    './app/**/*.{ts,tsx}',
    './src/**/*.{ts,tsx}',
  ],
tailwind.config.js
theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    extend: {
      colors: {
        border: "hsl(var(--border))",
        input: "hsl(var(--input))",
        ring: "hsl(var(--ring))",
        background: "hsl(var(--background))",
        foreground: "hsl(var(--foreground))",
tailwind.config.js
primary: {
          DEFAULT: "hsl(var(--primary))",
          foreground: "hsl(var(--primary-foreground))",
        },
        secondary: {
          DEFAULT: "hsl(var(--secondary))",
          foreground: "hsl(var(--secondary-foreground))",
        },
        destructive: {
          DEFAULT: "hsl(var(--destructive))",
          foreground: "hsl(var(--destructive-foreground))",
        },
tailwind.config.js
muted: {
          DEFAULT: "hsl(var(--muted))",
          foreground: "hsl(var(--muted-foreground))",
        },
        accent: {
          DEFAULT: "hsl(var(--accent))",
          foreground: "hsl(var(--accent-foreground))",
        },
        popover: {
          DEFAULT: "hsl(var(--popover))",
          foreground: "hsl(var(--popover-foreground))",
        },
        card: {
          DEFAULT: "hsl(var(--card))",
          foreground: "hsl(var(--card-foreground))",
        },
      },
tailwind.config.js
borderRadius: {
        lg: "var(--radius)",
        md: "calc(var(--radius) - 2px)",
        sm: "calc(var(--radius) - 4px)",
      },
      keyframes: {
        "accordion-down": {
          from: { height: 0 },
          to: { height: "var(--radix-accordion-content-height)" },
        },
        "accordion-up": {
          from: { height: "var(--radix-accordion-content-height)" },
          to: { height: 0 },
        },
      },
tailwind.config.js
animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
}

Best Practices

Follow these conventions and best practices when working with the Mail Assist codebase.

Naming Conventions

  • Components - PascalCase (e.g., EmailComposer.tsx)
  • Files - kebab-case (e.g., email-composer.tsx)
  • Directories - kebab-case (e.g., email-templates/)
  • Variables - camelCase (e.g., emailData)
  • Constants - UPPER_SNAKE_CASE (e.g., MAX_CREDITS)

Import Organization

import-example.ts
// 1. React and Next.js imports
import React from 'react'
import { NextRequest, NextResponse } from 'next/server'

// 2. Third-party library imports
import { z } from 'zod'
import { Resend } from 'resend'
import-example.ts
// 3. Internal imports (absolute paths)
import { createServerClient } from '@/lib/supabase/server'
import { validateEmail } from '@/lib/utils'
import { Button } from '@/components/ui/button'

// 4. Relative imports
import './styles.css'

// 5. Type imports (separate from value imports)
import type { EmailData } from '@/types/email'
Well-Organized Codebase
This folder structure promotes maintainability, scalability, and developer productivity. Each directory has a clear purpose and follows established conventions.

Development Workflow

Recommended workflow for developing new features and maintaining the Mail Assist codebase.

  1. Feature Planning - Identify components and files needed
  2. Type Definitions - Define TypeScript interfaces first
  3. Component Development - Build UI components with proper props
  4. API Integration - Connect components to backend services
  5. Testing - Test functionality and edge cases
  6. Documentation - Update relevant documentation
Scalable Architecture
This structure is designed to grow with your application. As you add features, follow the established patterns for consistency and maintainability.