Skip to content

sassongal/revWave

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

21 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌊 revWave

Digital reputation management SaaS for local businesses, focused on Google Reviews

License TypeScript Next.js NestJS

✨ Features

  • πŸ”— Google Business Profile Integration - OAuth2 integration with automatic token refresh
  • πŸ’¬ Reviews Inbox - Centralized review management with AI-powered reply suggestions
  • πŸ“± Smart NFC/QR Tags - Intelligent redirect system for review collection
  • πŸ‘₯ Mini CRM - Customer contact management and segmentation
  • πŸ“§ Email Campaigns - Targeted customer engagement campaigns
  • πŸ“Š Analytics Dashboard - Comprehensive business insights

πŸ—οΈ Tech Stack

Frontend

  • Framework: Next.js 14 (App Router)
  • Language: TypeScript
  • Styling: Tailwind CSS
  • State Management: React Hooks + Server Components

Backend

  • Framework: NestJS
  • Language: TypeScript
  • Authentication: Passport.js with Google OAuth2
  • Session Management: Redis + express-session

Database & Infrastructure

  • Database: PostgreSQL 16
  • ORM: Prisma
  • Cache: Redis 7
  • Monorepo: pnpm workspaces

Security

  • Token Encryption: AES-256-GCM
  • Session Storage: HttpOnly cookies with Redis backing
  • OAuth: Google OAuth2 with automatic token refresh
  • Tenant Isolation: Row-level security

πŸš€ Quick Start

Prerequisites

  • Node.js 20 LTS or higher
  • pnpm 9+
  • Docker & Docker Compose

1️⃣ Clone and Install

git clone https://github.com/sassongal/revWave.git
cd revWave
pnpm install

2️⃣ Environment Setup

# Copy environment template
cp .env.example .env

# Edit .env with your configuration
# Required variables:
# - DATABASE_URL
# - GOOGLE_CLIENT_ID & GOOGLE_CLIENT_SECRET (for user auth)
# - GOOGLE_BUSINESS_CLIENT_ID & GOOGLE_BUSINESS_CLIENT_SECRET (for integrations)
# - SESSION_SECRET (generate with: openssl rand -base64 32)
# - ENCRYPTION_KEY (generate with: openssl rand -base64 32)

3️⃣ Start Infrastructure

# Start PostgreSQL, Redis, pgAdmin, Redis Commander
pnpm docker:up

# Verify services are running
docker ps

4️⃣ Database Setup

# Generate Prisma client
pnpm db:generate

# Run migrations
pnpm db:migrate:dev

# (Optional) Seed development data
pnpm db:seed

5️⃣ Start Development Servers

# Start both API and Web concurrently
pnpm dev

# Or start individually:
pnpm dev:api   # http://localhost:3001
pnpm dev:web   # http://localhost:3000

βœ… Verification

Once everything is running, verify the services:

Service URL Credentials
Web App http://localhost:3000 -
API Health http://localhost:3001/health -
pgAdmin http://localhost:5050 admin@revwave.local / admin123
Redis Commander http://localhost:8081 -

πŸ” Google OAuth Setup

User Authentication (Login)

  1. Go to Google Cloud Console
  2. Create a new project or select existing
  3. Enable Google+ API
  4. Navigate to Credentials β†’ Create Credentials β†’ OAuth 2.0 Client ID
  5. Configure OAuth consent screen (add your email as test user)
  6. Create OAuth client:
    • Application type: Web application
    • Authorized redirect URIs: http://localhost:3001/auth/google/callback
  7. Copy credentials to .env:
    GOOGLE_CLIENT_ID="your-client-id"
    GOOGLE_CLIENT_SECRET="your-client-secret"
    

Google Business Profile Integration

  1. In the same Google Cloud project
  2. Enable Google My Business API
  3. Create another OAuth 2.0 Client ID (or use the same)
  4. Add redirect URI: http://localhost:3001/integrations/google/callback
  5. Add to .env:
    GOOGLE_BUSINESS_CLIENT_ID="your-business-client-id"
    GOOGLE_BUSINESS_CLIENT_SECRET="your-business-client-secret"
    

πŸ“ Project Structure

revWave/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ api/                    # NestJS backend
β”‚   β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”‚   β”œβ”€β”€ auth/          # Authentication (Google OAuth, sessions)
β”‚   β”‚   β”‚   β”œβ”€β”€ integrations/  # Google Business Profile integration
β”‚   β”‚   β”‚   β”œβ”€β”€ common/        # Guards, decorators, crypto
β”‚   β”‚   β”‚   β”œβ”€β”€ database/      # Prisma service
β”‚   β”‚   β”‚   └── health/        # Health check endpoint
β”‚   β”‚   └── test/
β”‚   └── web/                    # Next.js frontend
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ app/           # App router pages
β”‚       β”‚   β”œβ”€β”€ components/    # React components
β”‚       β”‚   └── lib/           # Utilities, API client
β”‚       └── public/
β”œβ”€β”€ packages/
β”‚   └── db/                     # Shared Prisma schema
β”‚       β”œβ”€β”€ prisma/
β”‚       β”‚   β”œβ”€β”€ schema.prisma  # Database schema
β”‚       β”‚   β”œβ”€β”€ migrations/    # Migration history
β”‚       β”‚   └── seed.ts        # Seed data
β”‚       └── src/
β”œβ”€β”€ infra/                      # Docker infrastructure
β”‚   └── docker-compose.yml
β”œβ”€β”€ docs/                       # Documentation
└── package.json                # Root package.json

πŸ› οΈ Available Scripts

Development

pnpm dev              # Start all apps in development mode
pnpm dev:api          # Start API only
pnpm dev:web          # Start web only

Database

pnpm db:generate      # Generate Prisma client
pnpm db:migrate       # Run production migrations
pnpm db:migrate:dev   # Run development migrations
pnpm db:push          # Push schema to database (dev only)
pnpm db:studio        # Open Prisma Studio
pnpm db:seed          # Seed database
pnpm db:reset         # Reset database (dev only)

Docker

pnpm docker:up        # Start infrastructure
pnpm docker:down      # Stop infrastructure
pnpm docker:logs      # View logs

Code Quality

pnpm lint             # Lint all packages
pnpm lint:fix         # Fix linting issues
pnpm format           # Format code with Prettier
pnpm typecheck        # Type check all packages
pnpm test             # Run tests

Build

pnpm build            # Build all packages
pnpm build:api        # Build API only
pnpm build:web        # Build web only

πŸ§ͺ Testing

Unit Tests

# Run all tests
pnpm test

# Run tests for specific module
pnpm test contacts.service.spec.ts
pnpm test campaigns.service.spec.ts
pnpm test unsubscribe.service.spec.ts

# Run tests with coverage
pnpm test:cov

Manual Test Flow

1. Start services:

pnpm docker:up
pnpm db:generate
pnpm db:migrate:dev
pnpm dev

2. Test Authentication:

  • Visit http://localhost:3000
  • Click "Sign in with Google"
  • Complete OAuth flow
  • Should redirect to dashboard
  • Verify session cookie is set (HttpOnly)

3. Test Contacts Management:

  • Navigate to /crm/contacts
  • Click "Add Contact"
  • Fill form: email (required), name, phone, source
  • Submit and verify contact appears in table
  • Test "Revoke Consent" action
  • Verify contact status changes to "Unsubscribed"

4. Test Campaign Creation:

  • Navigate to /crm/campaigns
  • Click "New Campaign"
  • Fill form:
    • Name: "Test Campaign"
    • Subject: "Test Email"
    • Body (HTML): <h1>Hello</h1><p>This is a test email.</p>
  • Submit and verify redirect to campaign detail page

5. Test Campaign Sending:

  • On campaign detail page, click "Send Campaign"
  • Confirm sending
  • Verify:
    • Campaign status changes to "scheduled" then "sent"
    • Recipients are created (only for subscribed contacts)
    • Delivery report shows stats (total, sent, failed, skipped)

6. Test Unsubscribe Flow:

  • Find a campaign recipient with unsubscribe token
  • Visit: http://localhost:3000/unsubscribe/{token}
  • Verify:
    • Page redirects to API endpoint
    • API processes unsubscribe
    • Redirects back with success message
    • Contact consent status is revoked
    • Recipient status is skipped_unsubscribed (if pending)

7. Test API Endpoints:

# Check health
curl http://localhost:3001/health

# Get campaigns (requires auth cookie)
curl -b cookies.txt http://localhost:3001/campaigns

# Create campaign (requires auth cookie)
curl -X POST -b cookies.txt \
  -H "Content-Type: application/json" \
  -d '{"name":"Test","subject":"Test","bodyHtml":"<p>Test</p>"}' \
  http://localhost:3001/campaigns

# Test unsubscribe (public, no auth)
curl http://localhost:3001/unsubscribe/{valid-token}

8. Verify Database:

  • Open pgAdmin: http://localhost:5050
  • Check tables:
    • contacts - verify tenant scoping
    • campaigns - verify tenant scoping
    • campaign_recipients - verify unsubscribe tokens
    • Verify all queries include tenant_id filter

πŸ“Š Database Schema

The application uses a multi-tenant architecture with the following core models:

  • User - Application users (Google OAuth)
  • Tenant - Customer organizations (auto-created on first login)
  • Membership - User-to-Tenant relationships with roles
  • Session - Server-side session storage
  • Integration - Google Business Profile connections (encrypted tokens)
  • Location - Business locations from Google
  • Review - Customer reviews
  • Tag - NFC/QR tags for review collection
  • Contact - CRM contacts
  • Campaign - Email campaigns

πŸ”’ Security

  • βœ… HttpOnly Cookies - Session cookies not accessible via JavaScript
  • βœ… Token Encryption - OAuth tokens encrypted at rest with AES-256-GCM
  • βœ… Tenant Isolation - All queries scoped to tenant context
  • βœ… CSRF Protection - SameSite cookie attribute
  • βœ… Rate Limiting - Configurable rate limits on public endpoints
  • βœ… Environment Variables - Sensitive config never committed

πŸ“š Documentation

🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for details.

πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

πŸ“ž Support


Made with ❀️ for local businesses

About

🌊 Digital reputation management SaaS for local businesses - Google Reviews, NFC tags, AI-powered responses

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages