Skip to content

puiusabin/blanc

Repository files navigation

Blanc - Web3 Mail Application

A modern monorepo containing a Next.js web application with Web3 wallet integration, Prisma database layer, and Haraka mail server.

Project Structure

blanc/
├── apps/
│   └── web/                           # @blanc/web - Next.js application
│       ├── src/
│       ├── public/
│       └── package.json
├── packages/
│   ├── database/                      # @blanc/database - Prisma ORM
│   │   ├── prisma/
│   │   │   └── schema.prisma
│   │   ├── src/
│   │   │   ├── client.ts              # Singleton PrismaClient
│   │   │   └── index.ts               # Exports
│   │   └── package.json
│   └── typescript-config/             # @blanc/typescript-config - Shared TS configs
│       ├── base.json
│       ├── nextjs.json
│       └── react.json
├── services/
│   └── haraka/                        # @blanc/mail-server - Haraka SMTP
│       ├── config/
│       ├── plugins/
│       └── package.json
└── package.json                       # Root workspace

Quick Start

Prerequisites

Required Software:

  • Node.js 18+
  • npm 10.9.2+
  • PostgreSQL database (local or hosted via Prisma Postgres)
  • Git

Required Services:

Important: For detailed setup instructions including environment variables, Cloudflare R2 configuration, and troubleshooting, see apps/web/SETUP.md.

Setup

  1. Clone and install

    git clone <repository-url>
    cd blanc
    npm install
  2. Configure environment

    # Root database URL
    cp .env.example .env
    
    # Web app configuration
    cp apps/web/.env.example apps/web/.env.development
  3. Set up database

    # Generate Prisma Client
    npm run db:generate
    
    # Push schema to database (development)
    npm run db:push
  4. Start development

    npm run dev

Visit http://localhost:3000

Available Commands

Development

npm run dev              # Generate Prisma Client + start web app
npm run dev:web          # Start web app only
npm run dev:mail         # Start Haraka mail server

Build & Deploy

npm run build            # Build web app for production
npm run deploy           # Deploy web app to Cloudflare Workers
npm run preview          # Preview Cloudflare deployment locally

Database

npm run db:generate      # Generate Prisma Client
npm run db:push          # Push schema changes (development)
npm run db:migrate       # Create and run migrations
npm run db:studio        # Open Prisma Studio
npm run db:seed          # Seed database

Code Quality

npm run lint             # Lint code
npm run lint:fix         # Fix linting issues
npm run type-check       # TypeScript type checking
npm run format           # Format code with Prettier
npm run check            # Run type-check + lint

Cleanup

npm run clean            # Clean all workspaces
npm run clean:deep       # Deep clean (all node_modules, build artifacts)

Workspace Packages

@blanc/web (apps/web)

Next.js 15 application with:

  • Framework: App Router, React 19, Turbopack
  • Deployment: Cloudflare Workers via OpenNext
  • Web3: wagmi 2.x + viem for wallet integration
  • UI: shadcn/ui components, Tailwind CSS v4
  • State: TanStack Query
  • Database: Integrated with @blanc/database

Development:

cd apps/web
npm run dev              # Start dev server
npm run build            # Production build
npm run type-check       # Type checking
npm run clean            # Clean build artifacts

@blanc/database (packages/database)

Prisma ORM package with:

  • Version: Prisma 6.x
  • Database: PostgreSQL
  • Extensions: Prisma Accelerate for connection pooling
  • Output: packages/database/generated/prisma (gitignored)

Exports:

import { prisma } from "@blanc/database"; // PrismaClient singleton
import type { User, Post } from "@blanc/database"; // Generated types

Usage in apps:

// Add to package.json dependencies
{
  "dependencies": {
    "@blanc/database": "*"
  }
}

// Use in code
import { prisma } from "@blanc/database";

const users = await prisma.user.findMany();

Scripts:

cd packages/database
npm run db:generate      # Generate client
npm run db:push          # Push schema
npm run db:migrate       # Run migrations
npm run db:studio        # Open Studio

@blanc/typescript-config (packages/typescript-config)

Shared TypeScript configurations:

  • base.json - Base configuration
  • nextjs.json - Next.js specific (extends base)
  • react.json - React specific (extends base)

Usage:

{
  "extends": "@blanc/typescript-config/nextjs.json",
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

@blanc/mail-server (services/haraka)

Haraka SMTP server with:

  • Authentication: Wallet-based (custom plugin)
  • Database: PostgreSQL via @blanc/database
  • Encryption: PGP support
  • Ports: 25 (SMTP), 587 (Submission), 465 (SMTPS)

Scripts:

cd services/haraka
npm run dev              # Development mode
npm start                # Production mode
npm run clean            # Clean queue/logs

Database Setup

Option 1: Local PostgreSQL

  1. Install PostgreSQL
  2. Create database:
    CREATE DATABASE blanc;
  3. Update .env:
    DATABASE_URL="postgresql://user:password@localhost:5432/blanc"

Option 2: Prisma Postgres (Recommended)

  1. Sign up at https://console.prisma.io
  2. Create new database
  3. Copy connection string to .env:
    DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=YOUR_API_KEY"

Working with Schema

Edit packages/database/prisma/schema.prisma:

generator client {
  provider = "prisma-client"
  output   = "../generated/prisma"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
}

After changes:

npm run db:generate      # Regenerate client
npm run db:push          # Apply to database

Environment Variables

Root .env

# Database
DATABASE_URL="postgresql://user:password@localhost:5432/blanc"

# Cloudflare R2 Storage (shared with web app and Haraka)
R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
R2_ACCESS_KEY_ID=your_r2_access_key_id
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key
R2_BUCKET_NAME=mail-storage
R2_ACCOUNT_ID=your_cloudflare_account_id

apps/web/.env.local

# Session Secret (minimum 32 characters)
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
SESSION_SECRET=your_64_character_session_secret

# WalletConnect (get from https://cloud.walletconnect.com)
NEXT_PUBLIC_WC_PROJECT_ID=your_project_id

# Cloudflare R2 Storage
R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
R2_ACCESS_KEY_ID=your_r2_access_key_id
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key
R2_BUCKET_NAME=mail-storage
R2_ACCOUNT_ID=your_cloudflare_account_id

Note: For detailed setup instructions, see apps/web/SETUP.md.

Monorepo Workflow

Adding Dependencies

To a specific workspace:

npm install <package> --workspace=@blanc/web
npm install -D <package> --workspace=@blanc/database

To root (shared dev tools):

npm install -D <package> -w

Inter-package Dependencies

Packages reference each other using workspace protocol:

{
  "dependencies": {
    "@blanc/database": "*",
    "@blanc/typescript-config": "*"
  }
}

Running Workspace Scripts

# From root
npm run dev --workspace=@blanc/web

# Or use shortcuts
npm run dev:web
npm run dev:mail

Development Best Practices

  1. Always generate Prisma Client first:

    npm run db:generate
  2. Use workspace dependencies:

    • Reference other packages with @blanc/*
    • Use "*" version for workspace packages
  3. Run quality checks before committing:

    npm run check          # Type-check + lint
    npm run format         # Format code
  4. Clean when switching branches:

    npm run clean

Deployment

Web App (Cloudflare Workers)

npm run deploy

Requirements:

  • Cloudflare account with Workers
  • Set environment variables:
    • CLOUDFLARE_API_TOKEN
    • CLOUDFLARE_ACCOUNT_ID

Or use GitHub Actions:

  • Workflow: .github/workflows/deploy-app.yml
  • Triggers on push to main

Contributing

  1. Create feature branch
  2. Make changes
  3. Run quality checks: npm run check
  4. Format code: npm run format
  5. Test locally
  6. Submit PR

Package Naming Convention

All packages use the @blanc scope:

  • @blanc/web - Web application
  • @blanc/database - Database/ORM layer
  • @blanc/typescript-config - Shared TypeScript configs
  • @blanc/mail-server - Mail server service

License

GNU General Public License v3.0

About

Zero-knowledge encrypted email using wallets as identity. No passwords, no personal data stored.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published