A robust, type-safe authentication package built with NextAuth.js (Auth.js), Effect, and Prisma ORM. This package provides a complete authentication solution that can be easily integrated into other Next.js projects.
- Complete Authentication System: User registration, login, password reset, and two-factor authentication
- Type-Safe: Built with TypeScript and Effect for robust error handling
- Database Integration: Prisma ORM with PostgreSQL support
- Modern Architecture: Built with Effect for functional programming patterns
- Easy Integration: Simple exports for quick setup in other projects
- Security: Bcrypt password hashing, JWT tokens, and secure session management
This monorepo contains the following packages:
@repo/auth
: Core authentication package with NextAuth.js integration@repo/db
: Database layer with Prisma ORM and Effect services@repo/ui
: Shared UI components@repo/eslint-config
: ESLint configurations@repo/typescript-config
: TypeScript configurations
- Authentication: NextAuth.js (Auth.js v5)
- Functional Programming: Effect for error handling and side effects
- Database: Prisma ORM with PostgreSQL
- Password Security: bcryptjs
- JWT: jose for token handling
- Email: Resend for transactional emails
- Monorepo: Turborepo for efficient development
# Clone the repository
git clone <your-repo-url>
cd next-auth
# Install dependencies
pnpm install
# Set up environment variables
cp .env.example .env.local
# Database
DATABASE_URL="postgresql://user:password@localhost:5432/dbname"
# NextAuth
NEXTAUTH_SECRET="your-secret-key"
NEXTAUTH_URL="http://localhost:3000"
# Email (Resend)
RESEND_API_KEY="your-resend-api-key"
# Generate Prisma client
pnpm --filter @repo/db db:generate
# Run migrations
pnpm --filter @repo/db db:migrate
# Or push schema changes
pnpm --filter @repo/db db:push
# Start development mode for all packages
pnpm dev
# Build all packages
pnpm build
# Lint all packages
pnpm lint
// In your Next.js app
import { authOptions } from '@repo/auth/options';
import NextAuth from 'next-auth';
export const { handlers, auth } = NextAuth(authOptions);
// API routes
export const GET = handlers.GET;
export const POST = handlers.POST;
import { registerUser } from '@repo/auth/signup';
import { Effect } from 'effect';
const handleSignup = async (email: string, password: string) => {
const result = await Effect.runPromise(
registerUser({ email, password })
);
if (Effect.isSuccess(result)) {
// User created successfully
console.log('User created:', result.value);
} else {
// Handle error
console.error('Error:', result.error);
}
};
import { loginEffect } from '@repo/auth/login';
import { useRouter } from 'next/navigation';
const handleLogin = async (email: string, password: string) => {
const router = useRouter();
const result = await Effect.runPromise(
loginEffect(email, password, router)
);
if (Effect.isSuccess(result)) {
// Login successful, user redirected to dashboard
} else {
// Handle login error
console.error('Login failed:', result.error);
}
};
import { forgotPasswordRoute } from '@repo/auth/forgot-password-route';
import { resetPasswordRoute } from '@repo/auth/reset-password-route';
// Use in your API routes
export const POST = forgotPasswordRoute;
export const PUT = resetPasswordRoute;
The package uses Effect for functional error handling and side effects:
import { Effect } from 'effect';
// All database operations are wrapped in Effect
const userResult = yield* findUserByEmail(email);
// Error handling with Effect
const result = yield* Effect.tryPromise({
try: () => bcrypt.compare(password, user.password!),
catch: (err) => new Error(`Password comparison failed: ${err}`)
});
Database operations are abstracted through a service layer:
import { PrismaServiceLive, findUserByEmail } from '@repo/db';
const userEffect = Effect.gen(function* () {
const user = yield* findUserByEmail(email);
// ... rest of the logic
}).pipe(Effect.provide(PrismaServiceLive));
packages/
βββ auth/ # Authentication package
β βββ src/
β β βββ options.ts # NextAuth configuration
β β βββ login.ts # Login logic with Effect
β β βββ signup.ts # User registration
β β βββ next.ts # Next.js integration
β β βββ reset-password/ # Password reset functionality
β βββ package.json
βββ db/ # Database package
β βββ src/
β β βββ prisma-service.ts # Effect-based Prisma service
β β βββ query.ts # Database queries
β β βββ index.ts # Exports
β βββ prisma/ # Prisma schema and migrations
β βββ package.json
βββ ui/ # Shared UI components
- Database Changes: Update the Prisma schema in
packages/db/prisma/schema.prisma
- New Queries: Add to
packages/db/src/query.ts
- Auth Logic: Add to
packages/auth/src/
- Build: Run
pnpm build
to generate types and build packages
@repo/auth/options
- NextAuth configuration@repo/auth/next
- Next.js integration helpers@repo/auth/login
- Login functionality@repo/auth/signup
- User registration@repo/auth/signup-route
- Signup API route@repo/auth/forgot-password-route
- Password reset request@repo/auth/reset-password-route
- Password reset@repo/auth/crypto-service
- JWT and crypto utilities
@repo/db
- Main database client and services@repo/db/prisma
- Prisma client instance@repo/db/query
- Database query functions@repo/db/prisma-service
- Effect-based Prisma service
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is licensed under the MIT License.