1. Overview
This document details the full implementation of the User Registration feature across Frontend (Next.js 13+ App Router) and Backend (Node.js Microservice).
The system enables users to:
- Register with validated personal details
- Securely store credentials in PostgreSQL
- Receive real-time feedback (success/error)
- Redirect to login upon successful registration
2. System Architecture
Frontend (Next.js) → http://localhost:3002
│
└── POST /auth/register
│
▼
Backend (User Service) → http://localhost:3000
│
└── PostgreSQL (users DB)
Layer
Technology
Frontend
Next.js 13+, React Hook Form, Zod, Tailwind, ShadCN UI
Backend
Node.js, Express, PostgreSQL, bcrypt
Validation
Zod (frontend), Manual (backend)
Communication
REST API (JSON)
Security
CORS, Password Hashing, Input Sanitization
3. Database Schema
Table: users (PostgreSQL)
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
first_name VARCHAR(100),
last_name VARCHAR(100),
profile_image VARCHAR(512),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
is_active BOOLEAN DEFAULT TRUE
);
Auto-update updated_at Trigger
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER users_update_trigger
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_updated_at();
Executed via DBeaver SQL Editor (no migrations)
4. Backend: User Service (services/user-service)
Folder Structure
src/
├── config/
│ └── db.ts
├── models/
│ └── userModel.ts
├── repositories/
│ └── UserRepository.ts
├── routes/
│ └── authRoutes.ts
├── errorHandler.ts
├── index.ts
└── types.ts
4.1 Database Connection (config/db.ts)
export const pool = new Pool({ … });
pool.on(“connect”, () => console.log(“DB CONNECTED”));
pool.on(“error”, (err) => console.error(“DB ERROR:”, err));
Ensures connection health logging.
4.2 User Model (models/userModel.ts)
static async createUser(input: RegisterInput): Promise<User> {
const passwordHash = await bcrypt.hash(password, 12);
await query(INSERT INTO users …, [email, passwordHash, …]);
}
Security:
- Password hashed with bcrypt (salt rounds: 12)
- SQL injection safe via parameterized queries
4.3 Repository Pattern
UserRepository.registerUser() → UserModel.createUser()
Clean separation of concerns.
4.4 API Route (routes/authRoutes.ts)
POST /auth/register
→ Validate email/password
→ Check duplicate
→ Create user
→ Return 201 { userId, email }
Error Handling:
- 400: Missing fields
- 409: Email exists
- 500: Server error
4.5 CORS Configuration (index.ts)
app.use(cors({
origin: “http://localhost:3002”
}));
Allows frontend to call backend.
4.6 Server Startup
const PORT = process.env.USER_SERVICE_PORT || 3000;
app.listen(PORT, () => console.log(`Server running on ${PORT}`));
Uses .env for configuration.
5. Frontend: Registration Page (apps/frontend)
File: src/app/(frontend)/(auth)/register/page.tsx
5.1 Form Validation (Zod + Custom Validators)
const formSchema = z.object({
firstName: validateFirstName,
email: validateEmail,
password: validatePassword,
// … others
}).refine(confirmPassword matches, { path: [“confirmPassword”] });
Validators in src/validate/index.ts
- First/Last Name: Letters only
- Email: Valid format
- Password: 8+ chars, letter, number, special char
- Confirm Password: Must match
5.2 UI Components (ShadCN)
- Form, Input, Button, Card
- Two-column responsive layout
- Real-time validation messages
- Loading state on submit
5.3 Registration Flow (Client-Side)
const onSubmit = async (data) => {
setIsLoading(true);
try {
await registerUserAction(data); // fetch to backend
window.location.href = “/login?registered=true”;
} catch (error) {
setServerError(error.message);
} finally {
setIsLoading(false);
}
};
5.4 API Call (Type-Safe)
async function registerUserAction(data: FormData): Promise<RegisterResponse> {
const payload = { email, password, first_name, last_name };
const res = await fetch(“http://localhost:3000/auth/register”, { … });
const result = await res.json();
if (!res.ok) throw new Error(result.message);
return result;
}
No any types – full TypeScript safety.
5.5 Error Handling
- Client-side (Zod): Field-level messages
- Server-side: Global red banner
- Loading state: Button disabled + text
6. Environment Configuration
.env (user-service)
USER_SERVICE_PORT=3000
DB_USER=postgres
DB_HOST=localhost
DB_NAME=users
DB_PASSWORD=12345
DB_PORT=5432
7. Testing & Verification
Test Case
Expected Result
Valid registration
→ 201, redirect to /login
Duplicate email
→ “Email already registered”
Weak password
→ Zod error
Server down
→ Network error (handled)
DB connection fail
→ Server logs error
8. Security Considerations
Feature
Implementation
Password Storage
bcrypt hash (12 rounds)
SQL Injection
Parameterized queries
XSS
React escapes output
CSRF
Not needed (stateless API)
CORS
Restricted to localhost:3002
Input Validation
Zod (frontend) + backend checks
9. Deployment Notes
Service
Port
Start Command
User Service
3000
npm run dev
Frontend
3002
npm run dev
In production:
- Use HTTPS
- Set NODE_ENV=production
- Use environment secrets
- Add rate limiting
10. Future Enhancements
Feature
Status
Email Verification
Planned
JWT Login
Planned
Password Reset
Planned
Profile Image Upload
Planned
OAuth (Google)
Planned
11. Summary
Completed Features:
- Secure user registration
- Client + server validation
- Responsive UI
- Error handling
- Type-safe code
- Clean architecture
- CORS & environment setup