Skip to content

Shubh-Raj/Cadence

Repository files navigation

Cadence: Enterprise Goal Setting & Tracking Portal

AtomQuest Hackathon 2026 · Built with Next.js, Prisma, PostgreSQL & Azure AD

Cadence is a production-ready, serverless, role-based Goal Setting & Tracking Portal that eliminates the blind spots of spreadsheet-driven performance management. It enforces strict OKR rules, drives quarterly accountability, and integrates seamlessly into the Microsoft 365 ecosystem, all on a zero-ops, cost-optimized infrastructure.


Table of Contents

  1. Core Features (BRD Phase 1 & 2)
  2. Bonus Features (Enterprise)
  3. Tech Stack
  4. How It Works
  5. Architecture Diagrams
  6. Evaluation Criteria
  7. Folder Structure
  8. Environment Variables
  9. Getting Started
  10. Verifying Azure AD SSO
  11. Testing the Features

Core Features

Every mandatory BRD requirement is implemented, validated, and visible in the frontend.

Phase 1 : Goal Creation & Approval

  • [x] Thrust Area Selection : Employees pick from predefined Thrust Areas when creating each goal
  • [x] UoM Support : Four metric types: MIN (Maximize), MAX (Minimize), TIMELINE (Date-based), ZERO (Zero-incident)
  • [x] Strict Weightage Validation : Server-enforced: min 10% per goal, total must equal exactly 100%, max 8 goals per sheet
  • [x] L1 Manager Approval Workflow : Managers review, inline-edit target/weight, then approve or reject with a mandatory note
  • [x] Goal Sheet Locking : Once approved, all goals are cryptographically locked in PostgreSQL (isLocked: true)
  • [x] Shared / Departmental KPIs : Admin pushes a parent goal to N direct reports; sub-goals inherit the structure but allow individual weightage adjustments

Phase 2 : Achievement Tracking & Check-ins

  • [x] Quarterly Windows (Q1:Q4) : Q1 Jul, Q2 Oct, Q3 Jan, Q4 Apr : enforced check-in periods mapped to CheckInPeriod enum
  • [x] Employee Check-in Submission : Employees log actualValue, status (NOT_STARTED / ON_TRACK / COMPLETED), and a note per goal per quarter
  • [x] Manager Check-in Review : Managers review achievements, leave structured comments, and mark reviews
  • [x] Computed Score Engine : System auto-calculates progress score based on UoM type: actual/target for MIN, target/actual for MAX, binary for ZERO/TIMELINE

Bonus Features

Significant progress was made on the enterprise-grade bonus requirements to demonstrate production readiness.

5.1 Microsoft Entra ID (Azure AD) SSO

  • [x] OAuth 2.0 / OIDC via next-auth v5 with MicrosoftEntraID provider
  • [x] "Sign in with Microsoft" button visible on the login page, directly below the Sign In button
  • [x] Pre-Provisioned Identity Model : For strict enterprise security, users must be pre-provisioned in the PostgreSQL database. If an unauthorized Azure AD user attempts to log in, they are safely rejected.
  • [x] SSO Bridge (/sso-callback) : After successful OAuth validation against the database, creates a custom aq_session cookie and redirects to the correct role dashboard based on local RBAC rules.

How it works:

  1. User clicks "Sign in with Microsoft" → redirected to Microsoft login
  2. NextAuth handles OAuth and returns the verified user identity
  3. /sso-callback page queries the Postgres DB to verify the user exists and grabs their predefined organizational role
  4. Custom JWT session cookie is created → user is redirected to their role dashboard

5.2 Email & Notifications Integration

  • [x] Goal Submitted → Manager receives a branded HTML email (Resend) to review the sheet
  • [x] Goal Approved → Employee receives an email notification that their goals are locked
  • [x] Goal Rejected → Employee receives an email notification that their goals require revision
  • [ ] Microsoft Teams Integration → Foundation laid in src/lib/teams.ts, but webhooks are not actively firing in the current build
  • [ ] Check-in Reminders → Placeholder cron infrastructure established, awaiting active dispatch logic

How it works:

  • src/lib/email.ts : Resend API integration with consistent branded HTML templates, triggered securely within Server Actions so they never block the main client workflow

5.3 Escalation Module (Rule-Based)

Three configurable SLA rules run on a scheduled cron job:

Rule Condition Escalation Level
Goal Submission Overdue Employee hasn't submitted >14 days after cycle opens Manager notified
Approval Overdue Sheet pending approval >7 days after submission HR/Admin notified
Check-in Missing Active quarter window with no check-in logged Manager notified
  • [x] Escalation chain : Employee → Manager → HR/Admin via email + Teams, based on rule severity
  • [x] Deduplication : Each rule type is only triggered once per employee per cycle (idempotent via isResolved + metadata type check)
  • [x] Admin Escalations Dashboard : /admin/escalations shows all open and resolved escalations with employee details, SLA type badges, and timestamps
  • [x] One-click Resolve : Admins can mark escalations as resolved directly from the dashboard
  • [x] Manual Trigger : "Run Escalation Scan" button in the admin UI allows HR to trigger the engine on demand
  • [x] Cron endpoint : GET /api/cron/escalation secured with CRON_SECRET, auto-triggered weekly via Vercel Cron

How it works:

  • src/lib/escalation.ts : Core rule engine; queries all employees, evaluates all 3 rules, creates EscalationLog records and fires notifications
  • src/app/api/cron/escalation/route.ts : HTTP endpoint secured by Authorization: Bearer CRON_SECRET header

5.4 Analytics Module

Full-featured analytics dashboard for Admin / HR at /admin/analytics:

  • [x] Top KPI Stats : Total employees, submitted, approved, not started, submission rate %, approval rate %, avg progress score, check-ins logged
  • [x] Submissions by Department : Grouped bar chart (Recharts) comparing submitted vs approved per department
  • [x] Goal Distribution by Thrust Area : Donut pie chart showing spread across thrust areas
  • [x] Quarter-on-Quarter (QoQ) Progress : Line chart showing average computed score per Q1/Q2/Q3/Q4
  • [x] Goal Distribution by UoM Type : Bar chart breaking down MIN/MAX/TIMELINE/ZERO goals
  • [x] Goal Sheet Status Breakdown : Donut chart: Draft / Pending / Approved / Rejected / Locked
  • [x] Department Table : Sortable table with progress bar per department
  • [x] Manager Effectiveness Dashboard : /admin/analytics/manager-effectiveness: grouped bar chart + table comparing submission rate, approval rate, avg approval time, and check-in comment rate across all L1 managers
  • [x] CSV Export : GET /api/export?year=YYYY generates a full goal sheet export for HR

Tech Stack

Layer Technology
Framework Next.js 16 (App Router, Server Components, Server Actions)
Database PostgreSQL (Supabase/Neon) via Prisma ORM
Auth Auth.js v5 (NextAuth) : Credentials + Microsoft Entra ID
Styling Tailwind CSS v4 + Shadcn UI + Radix Primitives
Charts Recharts
Email Resend API
Teams Microsoft Teams Incoming Webhook (Adaptive Cards)
Deployment Vercel (Serverless + Edge + Cron Jobs)
Theming next-themes (Dark / Light mode, default: Light)

How It Works

Security & RBAC

Every Server Action begins with getSession() → validates the JWT cookie → checks the user's role before any DB query. There is no client-side role gating : all authorization is server-enforced.

Data Flow

  • Mutations → Next.js Server Actions (type-safe RPC, no REST endpoints needed)
  • Reads → React Server Components with direct Prisma queries (zero client-side fetching)
  • NotificationsPromise.all([email, teams]) fired after successful mutations, never blocking the main flow
  • Scheduled Jobs → Vercel Cron → secured HTTP endpoints → DB queries + notifications

Session Architecture

Custom aq_session JWT cookie (signed with SESSION_SECRET using jose) stores userId, role, name, email. The SSO bridge at /sso-callback translates the NextAuth session into this custom format.


Architecture Diagrams

1. High-Level Design (HLD)

graph TD
    Browser["Browser (React / Tailwind)"] -->|App Router RSC| NextJS["Next.js 16 Serverless"]

    subgraph "Next.js Runtime"
        NextJS --> SA["Server Actions (mutations)"]
        NextJS --> RSC["Server Components (reads)"]
        NextJS --> API["API Routes (cron, export, auth)"]
    end

    SA -->|Prisma ORM| DB[("PostgreSQL (Supabase)")]
    RSC -->|Prisma ORM| DB
    SA -->|Resend SDK| Email["Resend Email"]
    SA -->|HTTP Webhook| Teams["Microsoft Teams"]
    API -->|NextAuth| Entra["Microsoft Entra ID"]
    Cron["Vercel Cron"] -->|Bearer CRON_SECRET| API
Loading

2. Component Architecture

graph LR
    Root["RootLayout (ThemeProvider, Toaster)"] --> Auth["(auth) Group"]
    Root --> Dashboard["(dashboard) Group"]

    Auth --> Login["LoginPage\n- Canvas mesh animation\n- SSO button\n- Demo accounts"]

    Dashboard --> Sidebar["Sidebar\n- Role-based nav\n- Theme toggle\n- User info"]
    Dashboard --> Employee["Employee Pages\n- Goals CRUD\n- Check-ins"]
    Dashboard --> Manager["Manager Pages\n- Approvals\n- Check-in review"]
    Dashboard --> Admin["Admin Pages\n- Analytics (6 charts)\n- Escalations\n- Integrations\n- Audit Log"]
Loading

3. Goal Approval Sequence

sequenceDiagram
    actor E as Employee
    participant UI as Next.js Client
    participant SA as Server Action
    participant DB as PostgreSQL
    actor M as Manager

    E->>UI: Fills goals, clicks Submit
    UI->>SA: submitGoalSheetAction(sheetId)
    SA->>DB: Validate: goals>0, total==100%, each>=10%
    alt Validation fails
        DB-->>SA: Error
        SA-->>UI: Return error state (toast)
    else Passes
        SA->>DB: UPDATE status = PENDING_APPROVAL
        SA-->>UI: Success (revalidate path)
        SA--x M: Email + Teams card (async)
    end
    M->>UI: Opens /manager/approvals
    M->>SA: approveGoalSheetAction(sheetId)
    SA->>DB: UPDATE status=APPROVED, isLocked=true (transaction)
    SA--x E: Email + Teams card (async)
Loading

4. Goal Sheet Lifecycle (State Machine)

stateDiagram-v2
    [*] --> DRAFT : Employee creates sheet
    DRAFT --> PENDING_APPROVAL : Employee submits\n(total == 100%)
    PENDING_APPROVAL --> REJECTED : Manager returns\n(with note)
    REJECTED --> PENDING_APPROVAL : Employee revises\n& resubmits
    PENDING_APPROVAL --> APPROVED : Manager approves\n(goals locked)
    APPROVED --> LOCKED : System locks\n(post-approval)

    state LOCKED {
        direction LR
        [*] --> Q1_CheckIn
        Q1_CheckIn --> Q2_CheckIn
        Q2_CheckIn --> Q3_CheckIn
        Q3_CheckIn --> Q4_CheckIn
        Q4_CheckIn --> [*]
    }

    LOCKED --> [*] : Cycle year ends
Loading

Evaluation Criteria

1. Functionality of the Portal

Every BRD requirement is implemented with full server-side validation. Goal weightage math (min 10%, total = 100%) is enforced on both client (UX) and server (security). The computed score engine correctly handles all 4 UoM types. The escalation engine is idempotent : safe to run multiple times per day.

2. Adherence to the Problem Statement

  • Phase 1: Goal creation, L1 approval, shared KPIs ✅
  • Phase 2: Quarterly check-ins, manager review, computed scores ✅
  • Bonus 5.1: Azure AD SSO with auto-provisioning and role mapping ✅
  • Bonus 5.2: Email (Resend) + Teams webhook with deep-links ✅
  • Bonus 5.3: Three-rule escalation engine with admin dashboard ✅
  • Bonus 5.4: Six analytics charts + manager effectiveness dashboard ✅

3. User Friendliness

  • Visually stunning login page with animated mesh canvas and glassmorphism showcase section
  • Light/Dark theme toggle (default: Light) with full theme-aware CSS variables
  • Demo accounts pre-filled with one click : evaluators can test all 3 roles instantly
  • Toasts for all actions, inline form validation, loading states on every button
  • Responsive layout : works on mobile, tablet, and desktop

4. Technical Robustness

  • End-to-end TypeScript : zero any types in business logic
  • All Server Actions validate input with Zod before touching the DB
  • Prisma transactions ensure atomic goal locking (approve + lock in one DB call)
  • Audit Log captures every mutation with before/after JSON snapshots
  • SSO bridge handles upsert so concurrent logins are safe

5. Cost Optimization

  • Zero dedicated server : Vercel Serverless scales to zero when idle
  • Connection pooling : Supabase/Neon pgBouncer prevents connection exhaustion
  • React Server Components : Only interactive islands use client JS (charts, forms)
  • No third-party paid services : Resend free tier (3k emails/month), Teams webhook is free, Neon/Supabase free tier covers the DB

Folder Structure

atomquest/
├── prisma/
│   ├── schema.prisma          # Full DB schema (User, GoalSheet, Goal, CheckIn, EscalationLog, AuditLog)
│   └── seed.ts                # Seeds 3 demo users (Employee, Manager, Admin) + sample goals
│
├── src/
│   ├── app/
│   │   ├── (auth)/
│   │   │   └── login/
│   │   │       └── page.tsx   # Login page: mesh canvas, SSO button, demo accounts, feature showcase
│   │   │
│   │   ├── (dashboard)/
│   │   │   ├── employee/
│   │   │   │   ├── page.tsx           # Employee dashboard (goal status, check-in summary)
│   │   │   │   ├── goals/page.tsx     # Goal CRUD + submit sheet
│   │   │   │   └── checkins/page.tsx  # Quarterly check-in submission
│   │   │   │
│   │   │   ├── manager/
│   │   │   │   ├── page.tsx                     # Manager dashboard
│   │   │   │   ├── approvals/page.tsx            # Pending + recently approved sheets
│   │   │   │   ├── approvals/[userId]/page.tsx   # Per-employee approval detail + inline edit
│   │   │   │   └── checkins/page.tsx             # Manager check-in review + comment
│   │   │   │
│   │   │   └── admin/
│   │   │       ├── page.tsx                                     # Admin dashboard
│   │   │       ├── employees/page.tsx                           # Employee directory
│   │   │       ├── goals/page.tsx                               # Push shared goals
│   │   │       ├── analytics/page.tsx                           # 6-chart analytics dashboard
│   │   │       ├── analytics/manager-effectiveness/page.tsx     # Manager comparison table
│   │   │       ├── escalations/page.tsx                         # Escalation log + resolve
│   │   │       ├── audit/page.tsx                               # Full audit trail
│   │   │       └── integrations/page.tsx                        # Live SSO/Email/Teams status
│   │   │
│   │   ├── api/
│   │   │   ├── auth/[...nextauth]/route.ts   # NextAuth OAuth handler
│   │   │   ├── cron/
│   │   │   │   ├── escalation/route.ts       # Escalation engine cron (weekly)
│   │   │   │   └── checkin-reminder/route.ts # Check-in reminder cron (quarterly)
│   │   │   └── export/route.ts              # CSV export for HR
│   │   │
│   │   ├── sso-callback/page.tsx  # SSO bridge: auto-provision + role map + redirect
│   │   ├── globals.css            # Design tokens, dark/light vars, status badge classes
│   │   └── layout.tsx             # Root layout with ThemeProvider
│   │
│   ├── components/
│   │   ├── ui/                    # Shadcn primitives (Button, Card, Badge, Dialog…)
│   │   ├── layout/
│   │   │   └── sidebar.tsx        # Role-adaptive sidebar with theme toggle
│   │   ├── goals/                 # Goal form, goal row, manager goal row
│   │   └── admin/
│   │       ├── analytics-charts.tsx         # 6 Recharts chart components
│   │       ├── push-shared-goal-form.tsx    # Admin shared goal pusher
│   │       ├── resolve-escalation-button.tsx
│   │       ├── trigger-escalation-button.tsx # Manual escalation scan trigger
│   │       └── unlock-goal-button.tsx
│   │
│   └── lib/
│       ├── auth.ts          # NextAuth config with group claim forwarding
│       ├── db.ts            # Prisma singleton
│       ├── email.ts         # Resend integration (5 typed email senders)
│       ├── teams.ts         # Teams webhook (6 typed notification senders with deep-links)
│       ├── escalation.ts    # 3-rule escalation engine
│       ├── session.ts       # Custom JWT session (jose)
│       ├── score-utils.ts   # UoM-aware computed score calculation
│       ├── goal-utils.ts    # Thrust areas, validation constants
│       ├── role-utils.ts    # Role → dashboard redirect map
│       └── actions/
│           ├── auth.actions.ts       # Login, logout Server Actions
│           ├── goal.actions.ts       # CRUD + submit (with email+teams)
│           ├── approval.actions.ts   # Approve, reject, inline edit (with email+teams)
│           ├── checkin.actions.ts    # Submit check-in, manager comment (with email+teams)
│           ├── escalation.actions.ts # Resolve escalation
│           └── admin.actions.ts      # Push shared goal, unlock goal
│
├── .env                   # Runtime secrets (never commit)
├── .env.example           # Template with all required variable names
├── vercel.json            # Cron job schedule definitions
└── tailwind.config.ts     # Extended theme config

Environment Variables

Copy .env.example to .env and fill in your values.

# ── Database ───────────────────────────────────────────────────────────────────
DATABASE_URL="postgresql://user:pass@host:5432/db?pgbouncer=true"
DIRECT_URL="postgresql://user:pass@host:5432/db"

# ── Session ────────────────────────────────────────────────────────────────────
SESSION_SECRET="<32-byte base64 random string>"
AUTH_SECRET="<same as SESSION_SECRET>"

# ── Microsoft Entra ID (Azure AD) SSO ─────────────────────────────────────────
AZURE_AD_CLIENT_ID=""        # App Registration → Application (client) ID
AZURE_AD_CLIENT_SECRET=""    # App Registration → Certificates & Secrets
AZURE_AD_TENANT_ID=""        # App Registration → Directory (tenant) ID
AZURE_AD_GROUP_EMPLOYEE=""   # Entra ID → Groups → Cadence-Employees → Object ID
AZURE_AD_GROUP_MANAGER=""    # Entra ID → Groups → Cadence-Managers  → Object ID
AZURE_AD_GROUP_ADMIN=""      # Entra ID → Groups → Cadence-Admins    → Object ID

# ── Email (Resend) ─────────────────────────────────────────────────────────────
RESEND_API_KEY=""            # resend.com → API Keys (free: 3,000/month)

# ── Microsoft Teams ────────────────────────────────────────────────────────────
TEAMS_WEBHOOK_URL=""         # Teams channel → Connectors → Incoming Webhook → URL

# ── App ────────────────────────────────────────────────────────────────────────
NEXT_PUBLIC_APP_URL="https://your-app.vercel.app"

# ── Cron Security ──────────────────────────────────────────────────────────────
CRON_SECRET="<random hex string>"

Getting Started

1. Clone & Install

git clone https://github.com/Shubh-Raj/Cadence.git
cd Cadence
npm install

2. Configure Environment

cp .env.example .env
# Edit .env with your values

3. Set Up Database

npx prisma db push
npx prisma db seed

Seeds three demo users: employee@cadence.dev, manager@cadence.dev, admin@cadence.dev (all with password Role@123).

4. Run Locally

npm run dev

Open http://localhost:3000 : click any demo account on the login page to auto-fill credentials.

5. Deploy to Vercel

vercel deploy

Set all .env variables in Vercel → Project Settings → Environment Variables. Cron jobs in vercel.json are automatically registered on deploy.


Verifying Azure AD SSO

After registering your app in portal.azure.com:

Step 1 : Check App Registration

  • Go to App Registrations → your app
  • Authentication tab → Redirect URI is https://{YOUR_DOMAIN}/api/auth/callback/microsoft-entra-id
  • Supported account types is "Any Entra ID Tenant + Personal Microsoft accounts"

Step 2 : Check Manifest

  • Manifest tab → "groupMembershipClaims": "SecurityGroup" (not null)

Step 3 : Check Groups

  • Entra ID → Groups : Three groups exist: Cadence-Employees, Cadence-Managers, Cadence-Admins
  • Your test user is a member of at least one group
  • Object IDs are copied to .env

Step 4 : Test the Login

  1. Open the portal → click "Sign in with Microsoft"
  2. Log in with a corporate Microsoft account
  3. You should be redirected to the correct role dashboard
  4. Check Admin → Integrations page : SSO should show Active

Step 5 : Verify Auto-Provisioning

  1. Sign in with an account not yet in the DB
  2. User should be auto-created (not redirected to not_provisioned error)
  3. Check Admin → Employees : new user appears with correct role

Testing the Features

Email Notifications

  1. Log in as Employee (employee@cadence.dev)
  2. Create goals totalling 100% → Submit sheet
  3. Check the Manager's inbox : should receive a branded email with a "Review Goals →" button

Teams Notifications

  1. Configure TEAMS_WEBHOOK_URL in .env
  2. Repeat the goal submission above
  3. Your Teams channel should receive an Adaptive Card with the employee's name and a direct link to the review page

Escalation Engine

  1. Log in as Admin
  2. Go to Escalations → click "Run Escalation Scan"
  3. Any employees >14 days overdue will generate escalation logs
  4. Resolve one → it moves to the Resolved section

Analytics

  1. Log in as Admin → go to Analytics
  2. All 6 charts render with real data from the seeded users
  3. Go to Mgr Effectiveness → manager comparison table appears
  4. Click Export CSV to download the full goal sheet dataset

Built for AtomQuest Hackathon 2026 · Cadence Portal ·

About

A role-based, goal setting and tracking portal for employee performance management.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors