Skip to content

feat:add password strength indicator to signup form#228

Merged
kunalverma2512 merged 3 commits into
kunalverma2512:mainfrom
akshatsinghai6682-sketch:feature/password-strength-meter
Jun 23, 2026
Merged

feat:add password strength indicator to signup form#228
kunalverma2512 merged 3 commits into
kunalverma2512:mainfrom
akshatsinghai6682-sketch:feature/password-strength-meter

Conversation

@akshatsinghai6682-sketch

@akshatsinghai6682-sketch akshatsinghai6682-sketch commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

📌 Pull Request Summary

🔗 Related Issue

Closes #227


📝 Description

Adds a real-time password strength indicator to the sign-up form, giving users live feedback on password quality before submitting.

Changes Made

  • Added a PasswordStrengthMeter component scoring password strength (Weak / Medium / Strong) based on length, mixed case, numbers, and symbols
  • Wired the meter into SignupPage.jsx, rendering below the password input
  • Styled to match the existing monochrome design system (border-4 border-black, bold uppercase type, no border-radius) — no new colors introduced

Motivation

The sign-up form previously gave no feedback on password strength until after submission. This adds live, actionable guidance so users know how to improve a weak password before creating their account.


🚀 Type of Change

  • New Feature

🧪 Testing

Verification

  • Tested Locally

Test Details

Tested by entering passwords of varying strength (e.g. abc, Abcdefgh1, Abc123!@#) and confirming the bar, label, and checklist update live and correctly. Confirmed existing form validation (6+ character minimum, submit button disabled state) is unaffected.


📸 Screenshots / Demo (If Applicable)

8FEB1B54-AF8B-4E28-83D4-6B8A2ED791F6

✅ Checklist

  • I have read and followed the contribution guidelines.
  • I have self-reviewed my changes.
  • My changes are limited to the scope of this issue.
  • Documentation has been updated where necessary.
  • No unnecessary files or unrelated changes have been included.
  • The related issue has been linked correctly.
  • All applicable testing and validation steps have been completed.

📚 Additional Notes

None.

Summary by CodeRabbit

  • New Features
    • Added a real-time password strength indicator to the Step 1 sign-up form, including a Weak/Medium/Strong label with a visual meter
    • Added a password requirements checklist that updates instantly as the user types
  • Bug Fixes
    • Improved sign-up step/redirect handling so the jump to the next step occurs more reliably after navigation

Signed-off-by: Akshat Singhai <akshatsinghai6682@gmail.com>
@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown

@akshatsinghai6682-sketch is attempting to deploy a commit to the Kunal Verma's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown

🎉 Welcome to CodeLens — Thank You for Your Contribution!

Hey @akshatsinghai6682-sketch! 👋

We are genuinely excited to have you here. Every single PR — big or small — makes CodeLens better, and yours is no exception. Take a moment to review the checklist below to help us merge your work quickly and smoothly.

✅ Before Requesting a Review

  • Keep code clean, readable, and consistent with the existing codebase
  • Avoid unrelated or unnecessary file changes
  • Make sure the UI is fully responsive across all device sizes
  • Attach screenshots or a short screen recording for any UI changes
  • Resolve all merge conflicts before marking the PR as ready
  • Do not submit AI-generated, copy-pasted, or low-effort implementations

💬 Join Our Community Channel — This is Mandatory

Being part of our communication channel is compulsory for all contributors, not optional.

📡 Join the CodeLens Matrix Channel

Why join? This is where all important announcements, PR review updates, contribution discussions, and maintainer decisions happen in real time. Contributors who are not in the channel regularly miss critical context and updates, which often leads to duplicated or misaligned work. Staying connected here is what keeps the community strong and your contributions impactful.


We are rooting for you! If you have any questions, drop them in the channel or comment right here on this PR. Let's build something great together. 🚀✨

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c29ab71a-c4df-4ba8-a149-dd38487e500e

📥 Commits

Reviewing files that changed from the base of the PR and between a2cc6e4 and 42af443.

📒 Files selected for processing (1)
  • frontend/src/pages/SignupPage.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/pages/SignupPage.jsx

📝 Walkthrough

Walkthrough

SignupPage.jsx gains an inline password-strength feature: pure helper functions score passwords 0–5 and map scores to "Weak/Medium/Strong" labels; StrengthCheckItem and PasswordStrengthMeter components render a segmented bar and criteria checklist. The meter is inserted below the password field in Step 1, and an eslint-disable-next-line comment is added to the existing router-state redirect effect.

Changes

Password Strength Indicator in Signup Form

Layer / File(s) Summary
Scoring logic and UI components
frontend/src/pages/SignupPage.jsx
Adds getPasswordStrength (0–5 scorer), a default checklist generator, and StrengthCheckItem/PasswordStrengthMeter components that render a monochrome segmented bar and a per-criterion checklist.
Form wiring and minor adjustments
frontend/src/pages/SignupPage.jsx
Renders PasswordStrengthMeter beneath the password input in Step 1, driven by password state; adds eslint-disable-next-line react-hooks/exhaustive-deps on the skipToStep2 effect.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • kunalverma2512/CodeLens#223: Both PRs modify the location.state-driven Step 2 redirect logic in SignupPage.jsx, with this PR adding the eslint-disable annotation and explicit empty dependency array to the skipToStep2 effect.

Suggested labels

enhancement, Frontend, UI/UX, quality:clean

Poem

🐇 Hop hop, I type a pass,
The little bar fills up like grass!
Weak, Medium, Strong it reads,
Meeting all the checklist needs.
No more guessing, just pure glee —
Strong passwords, plain as can be! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main feature added: a password strength indicator for the signup form, which matches the core objective of the changeset.
Description check ✅ Passed The description is comprehensive, following the required template with all critical sections completed: related issue linked (#227), clear motivation, specific changes listed, type of change selected, local testing verified, and checklist items checked. Only documentation update is unchecked, which is appropriate for this feature.
Linked Issues check ✅ Passed The PR successfully implements all requirements from issue #227: password strength scoring (length, mixed case, numbers, symbols), real-time feedback as users type, monochrome design (segmented bar, bold labels), optional checklist, and no backend changes. The critical issues identified in code review were addressed in a subsequent commit.
Out of Scope Changes check ✅ Passed All changes are directly related to adding the password strength indicator feature. The modifications to SignupPage.jsx (helpers, UI components, styling, router-state annotation) are within scope and necessary for the feature implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/pages/SignupPage.jsx`:
- Around line 20-24: The password strength validation object includes a
`longLength` criterion (password >= 12 characters) that affects the strength
score, but this criterion is not displayed in the user-facing checklist which
only shows four items (case, number, symbol, and lowercase/uppercase). To fix
this discrepancy, add a checklist item for the `longLength` criterion so users
can see all five criteria that contribute to their password strength score,
ensuring the displayed checks fully match the scoring logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bcf7616f-52ea-4522-8907-53dcc18a653f

📥 Commits

Reviewing files that changed from the base of the PR and between d53abef and 65815ee.

📒 Files selected for processing (1)
  • frontend/src/pages/SignupPage.jsx

Comment thread frontend/src/pages/SignupPage.jsx
@akshatsinghai6682-sketch

Copy link
Copy Markdown
Contributor Author

@kunalverma2512 just following up on the pr are there any changes required

@kunalverma2512

Copy link
Copy Markdown
Owner

@akshatsinghai6682-sketch I will now tomorrow as today it was a bit busy time

@akshatsinghai6682-sketch

Copy link
Copy Markdown
Contributor Author

@akshatsinghai6682-sketch I will now tomorrow as today it was a bit busy time

sure @kunalverma2512

@kunalverma2512

Copy link
Copy Markdown
Owner

@coderabbitai Please perform a deep, codebase-aware review of this PR.

Focus on the following areas:

  1. Codebase Compatibility

    • Review all changed files as well as nearby/related files that interact with this implementation.
    • Verify that the approach is fully aligned with our existing architecture, coding patterns, conventions, and project standards.
    • Identify any hidden regressions or inconsistencies introduced by this PR.
  2. Scope Validation

    • Check whether any changes are unnecessary, unrelated to the issue, or exceed the intended scope of the task.
    • Flag any modifications that should not be part of this PR.
  3. Backend & Security Impact

    • Thoroughly analyze whether these changes could negatively affect existing backend behavior.
    • Pay special attention to authentication, validation, password handling, API contracts, database interactions, and edge cases.
    • Since our system currently enforces a 6-character password policy, verify that this PR does not introduce conflicts, unexpected behavior, or migration concerns related to that logic.
  4. UI/UX Review

    • Evaluate the user experience of the implemented solution.
    • Suggest concrete improvements for usability, accessibility, visual consistency, responsiveness, error states, loading states, and overall polish.
  5. Quality Grading

    • Provide separate ratings (1–10) for:

      • Correctness
      • Code Quality
      • Maintainability
      • Security
      • Performance
      • UI/UX
      • Scope Adherence
      • Overall Merge Readiness
  6. Additional Improvements

    • Review the modified files and surrounding code for further refactoring opportunities.
    • Identify technical debt, missing validations, potential optimizations, or architectural improvements.
  7. Future Issue Discovery

    • Based on your review, identify any meaningful follow-up issues that could be created.

    • For each suggested issue, explain:

      • The problem
      • Why it matters
      • Expected impact
      • Suggested implementation approach
  8. Final Verdict

    • Is this PR ready to merge?

    • If not, classify findings as:

      • Must Fix Before Merge
      • Recommended Improvements
      • Nice-to-Have Enhancements

Please be extremely critical and detailed. Do not limit the review to the changed lines only—analyze the broader impact on the repository and existing functionality.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Repository =="
git remote -v | sed -n '1,4p'
echo

echo "== PR branch status =="
git status --short
echo

echo "== Changed files vs base =="
BASE_REF="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master 2>/dev/null || true)"
if [ -n "${BASE_REF}" ]; then
  git diff --name-status "${BASE_REF}"...HEAD
else
  git diff --name-status HEAD~1...HEAD || true
fi
echo

echo "== Diff stat =="
if [ -n "${BASE_REF}" ]; then
  git diff --stat "${BASE_REF}"...HEAD
else
  git diff --stat HEAD~1...HEAD || true
fi
echo

echo "== Locate SignupPage.jsx =="
fd -a 'SignupPage\.jsx$' .
echo

SIGNUP_FILE="$(fd 'SignupPage\.jsx$' . | head -n 1 || true)"
if [ -n "${SIGNUP_FILE}" ]; then
  echo "== AST outline for ${SIGNUP_FILE} =="
  ast-grep outline "${SIGNUP_FILE}" --view expanded || true
  echo

  echo "== Full numbered ${SIGNUP_FILE} =="
  nl -ba "${SIGNUP_FILE}" | sed -n '1,280p'
  echo

  echo "== Remaining numbered ${SIGNUP_FILE} if any =="
  nl -ba "${SIGNUP_FILE}" | sed -n '281,560p'
  echo
fi

echo "== Diff for SignupPage.jsx =="
if [ -n "${BASE_REF}" ] && [ -n "${SIGNUP_FILE:-}" ]; then
  git diff --find-renames -- "${SIGNUP_FILE}" | sed -n '1,260p'
fi
echo

echo "== Find auth/signup frontend call sites =="
rg -n -C3 --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  '\b(signup|signUp|register|create account|createAccount)\b|/auth/register|/auth/signup|/register' .
echo

echo "== Find backend password validation and auth routes =="
rg -n -C4 --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  '\bpassword\b|register|signup|signUp|User\.create|bcrypt|hash' .
echo

echo "== Locate package/config files =="
fd -a 'package\.json$|eslint|vite\.config|tailwind\.config|postcss\.config|README\.md$' .
echo

echo "== Relevant package.json files =="
while IFS= read -r f; do
  echo "--- ${f} ---"
  sed -n '1,220p' "${f}"
done < <(fd 'package\.json$' .)

Length of output: 3245


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Repository =="
git remote -v | sed -n '1,4p'
echo

echo "== PR branch status =="
git status --short
echo

echo "== Changed files vs base =="
BASE_REF="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master 2>/dev/null || true)"
if [ -n "${BASE_REF}" ]; then
  git diff --name-status "${BASE_REF}"...HEAD
else
  git diff --name-status HEAD~1...HEAD || true
fi
echo

echo "== Diff stat =="
if [ -n "${BASE_REF}" ]; then
  git diff --stat "${BASE_REF}"...HEAD
else
  git diff --stat HEAD~1...HEAD || true
fi
echo

echo "== Locate SignupPage.jsx =="
fd -a 'SignupPage\.jsx$' .
echo

SIGNUP_FILE="$(fd 'SignupPage\.jsx$' . | head -n 1 || true)"
if [ -n "${SIGNUP_FILE}" ]; then
  echo "== AST outline for ${SIGNUP_FILE} =="
  ast-grep outline "${SIGNUP_FILE}" --view expanded || true
  echo

  echo "== Full numbered ${SIGNUP_FILE} =="
  nl -ba "${SIGNUP_FILE}" | sed -n '1,280p'
  echo

  echo "== Remaining numbered ${SIGNUP_FILE} if any =="
  nl -ba "${SIGNUP_FILE}" | sed -n '281,560p'
  echo
fi

echo "== Diff for SignupPage.jsx =="
if [ -n "${BASE_REF}" ] && [ -n "${SIGNUP_FILE:-}" ]; then
  git diff --find-renames -- "${SIGNUP_FILE}" | sed -n '1,260p'
fi
echo

echo "== Find auth/signup frontend call sites =="
rg -n -C3 --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  '\b(signup|signUp|register|create account|createAccount)\b|/auth/register|/auth/signup|/register' .
echo

echo "== Find backend password validation and auth routes =="
rg -n -C4 --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  '\bpassword\b|register|signup|signUp|User\.create|bcrypt|hash' .
echo

echo "== Locate package/config files =="
fd -a 'package\.json$|eslint|vite\.config|tailwind\.config|postcss\.config|README\.md$' .
echo

echo "== Relevant package.json files =="
while IFS= read -r f; do
  echo "--- ${f} ---"
  sed -n '1,220p' "${f}"
done < <(fd 'package\.json$' .)

Length of output: 3245


🏁 Script executed:

#!/bin/bash
set -u

num() { awk '{printf "%6d  %s\n", NR, $0}' "$1"; }

BASE_REF="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master 2>/dev/null || true)"
SIGNUP_FILE="$(fd 'SignupPage\.jsx$' . | head -n 1 || true)"

echo "== Changed files vs base =="
if [ -n "${BASE_REF}" ]; then
  git diff --name-status "${BASE_REF}"...HEAD
else
  git diff --name-status HEAD~1...HEAD || true
fi
echo

echo "== Full numbered SignupPage.jsx =="
if [ -n "${SIGNUP_FILE}" ]; then
  num "${SIGNUP_FILE}" | sed -n '1,420p'
fi
echo

echo "== Diff for SignupPage.jsx =="
if [ -n "${BASE_REF}" ] && [ -n "${SIGNUP_FILE}" ]; then
  git diff --find-renames "${BASE_REF}"...HEAD -- "${SIGNUP_FILE}" | sed -n '1,320p'
fi
echo

echo "== Frontend pages/components outline =="
fd '\.(jsx|js|tsx|ts)$' frontend/src 2>/dev/null | sed -n '1,120p'
echo

echo "== Signup/auth frontend context =="
rg -n -C4 --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  'SignupPage|signup|signUp|register|auth/register|auth/signup|create account|Create Account|VITE_API_BASE_URL|localStorage|token' frontend src . 2>/dev/null | sed -n '1,420p'
echo

echo "== Backend auth/password context =="
rg -n -C5 --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  'router\.(post|get).*register|register|signup|signUp|password|bcrypt|jwt|User\.create|User\.findOne|hash' backend server api . 2>/dev/null | sed -n '1,520p'
echo

echo "== Relevant auth/backend files by name =="
fd -i 'auth|user|signup|register|route|controller|model|schema|server|app' . | sed -n '1,220p'
echo

echo "== Package/config files =="
fd 'package\.json$|eslint|vite\.config|tailwind\.config|postcss\.config|README\.md$' . | sed -n '1,120p'
echo

echo "== package.json contents =="
while IFS= read -r f; do
  echo "--- ${f} ---"
  sed -n '1,220p' "${f}"
done < <(fd 'package\.json$' .)

Length of output: 94887


🏁 Script executed:

#!/bin/bash
set -u

num() { awk '{printf "%6d  %s\n", NR, $0}' "$1"; }

BASE_REF="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master 2>/dev/null || true)"
SIGNUP_FILE="$(fd 'SignupPage\.jsx$' . | head -n 1 || true)"

echo "== Changed files vs base =="
if [ -n "${BASE_REF}" ]; then
  git diff --name-status "${BASE_REF}"...HEAD
else
  git diff --name-status HEAD~1...HEAD || true
fi
echo

echo "== Full numbered SignupPage.jsx =="
if [ -n "${SIGNUP_FILE}" ]; then
  num "${SIGNUP_FILE}" | sed -n '1,420p'
fi
echo

echo "== Diff for SignupPage.jsx =="
if [ -n "${BASE_REF}" ] && [ -n "${SIGNUP_FILE}" ]; then
  git diff --find-renames "${BASE_REF}"...HEAD -- "${SIGNUP_FILE}" | sed -n '1,320p'
fi
echo

echo "== Frontend pages/components outline =="
fd '\.(jsx|js|tsx|ts)$' frontend/src 2>/dev/null | sed -n '1,120p'
echo

echo "== Signup/auth frontend context =="
rg -n -C4 --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  'SignupPage|signup|signUp|register|auth/register|auth/signup|create account|Create Account|VITE_API_BASE_URL|localStorage|token' frontend src . 2>/dev/null | sed -n '1,420p'
echo

echo "== Backend auth/password context =="
rg -n -C5 --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  'router\.(post|get).*register|register|signup|signUp|password|bcrypt|jwt|User\.create|User\.findOne|hash' backend server api . 2>/dev/null | sed -n '1,520p'
echo

echo "== Relevant auth/backend files by name =="
fd -i 'auth|user|signup|register|route|controller|model|schema|server|app' . | sed -n '1,220p'
echo

echo "== Package/config files =="
fd 'package\.json$|eslint|vite\.config|tailwind\.config|postcss\.config|README\.md$' . | sed -n '1,120p'
echo

echo "== package.json contents =="
while IFS= read -r f; do
  echo "--- ${f} ---"
  sed -n '1,220p' "${f}"
done < <(fd 'package\.json$' .)

Length of output: 91721


🏁 Script executed:

#!/bin/bash
set -u

num() { awk '{printf "%6d  %s\n", NR, $0}' "$1"; }

for f in \
  frontend/src/services/authService.js \
  frontend/src/services/api.js \
  frontend/src/context/AuthContext.jsx \
  server/modules/auth/routes.js \
  server/modules/auth/controller.js \
  server/modules/auth/service.js \
  server/modules/auth/validation.js \
  server/models/User.js
do
  if [ -f "$f" ]; then
    echo "== ${f} =="
    num "$f" | sed -n '1,260p'
    echo
  else
    echo "== missing ${f} =="
  fi
done

echo "== frontend eslint config =="
if [ -f frontend/eslint.config.js ]; then
  num frontend/eslint.config.js | sed -n '1,220p'
fi

echo "== frontend package.json =="
if [ -f frontend/package.json ]; then
  num frontend/package.json | sed -n '1,220p'
fi

Length of output: 45643


🏁 Script executed:

#!/bin/bash
set -u

num() { awk '{printf "%6d  %s\n", NR, $0}' "$1"; }

for f in \
  frontend/src/services/authService.js \
  frontend/src/services/api.js \
  frontend/src/context/AuthContext.jsx \
  server/modules/auth/routes.js \
  server/modules/auth/controller.js \
  server/modules/auth/service.js \
  server/modules/auth/validation.js \
  server/models/User.js
do
  if [ -f "$f" ]; then
    echo "== ${f} =="
    num "$f" | sed -n '1,260p'
    echo
  else
    echo "== missing ${f} =="
  fi
done

echo "== frontend eslint config =="
if [ -f frontend/eslint.config.js ]; then
  num frontend/eslint.config.js | sed -n '1,220p'
fi

echo "== frontend package.json =="
if [ -f frontend/package.json ]; then
  num frontend/package.json | sed -n '1,220p'
fi

Length of output: 45643



@kunalverma2512 The PR description image shows the CodeLens sign-up page in a monochrome, thick-border style. The header contains CODELENS, nav links (EXPLORE, FAQ, ABOUT, TOOLS, CONTACT US), and action buttons (APEX, LOGIN, SIGN UP). The centered sign-up card includes SIGN UP WITH GITHUB, an OR REGISTER WITH EMAIL divider, FULL NAME, EMAIL, and PASSWORD inputs, a filled password strength bar labeled STRONG, checklist items (8+ CHARACTERS, UPPER & LOWER, A NUMBER, A SYMBOL), and a large CREATE ACCOUNT button.

Deep PR Review: Password Strength Meter

I reviewed the changed file plus related auth/signup flow:

  • Changed file: frontend/src/pages/SignupPage.jsx
  • Related frontend files:
    • frontend/src/services/authService.js
    • frontend/src/services/api.js
    • frontend/src/context/AuthContext.jsx
    • route wiring around /signup
  • Related backend/security files:
    • server/modules/auth/routes.js
    • server/modules/auth/controller.js
    • server/modules/auth/service.js
    • server/modules/auth/validation.js
    • server/models/User.js

Final Verdict

Not quite ready to merge as-is.

The implementation is close and does not appear to break backend behavior, but I would fix one correctness/UX issue before merge: the current scoring can label a password Strong even when one of the visible core criteria is still unmet.


Must Fix Before Merge

1. Strong can be shown while a visible required criterion is unchecked

Location: frontend/src/pages/SignupPage.jsx, Lines 18-30, Line 50, Lines 70-74

The scoring includes a hidden longLength check:

const checks = {
  length: password.length >= 8,
  longLength: password.length >= 12,
  case: /[a-z]/.test(password) && /[A-Z]/.test(password),
  number: /\d/.test(password),
  symbol: /[^A-Za-z0-9]/.test(password),
};

But the checklist only displays:

  • 8+ Characters
  • Upper & Lower
  • A Number
  • A Symbol

This means a password like:

aaaaaaaaaaaa1!

can score:

  • length: true
  • longLength: true
  • case: false
  • number: true
  • symbol: true

Score = 4, label = Strong, while Upper & Lower remains unchecked.

That creates contradictory feedback: the UI says the password is Strong, but also says one of the visible strength criteria is missing.

Why it matters:

  • It weakens the credibility of the password meter.
  • It conflicts with the stated issue objective of actionable feedback based on mixed case, number, symbol, and length.
  • It can encourage users to stop improving a password even when the checklist still indicates a missing criterion.

Suggested fix:

Either expose the 12+ character criterion in the checklist, or prevent the hidden length bonus from making the password Strong unless all core checks pass.

A safer scoring model:

function getPasswordStrength(password) {
  const checks = {
    length: password.length >= 8,
    longLength: password.length >= 12,
    case: /[a-z]/.test(password) && /[A-Z]/.test(password),
    number: /\d/.test(password),
    symbol: /[^A-Za-z0-9]/.test(password),
  };

  if (!password) {
    return { score: 0, label: "", checks };
  }

  const coreChecksMet =
    checks.length && checks.case && checks.number && checks.symbol;

  const score = [
    checks.length,
    checks.case,
    checks.number,
    checks.symbol,
    checks.longLength,
  ].filter(Boolean).length;

  let label = "Weak";
  if (coreChecksMet && checks.longLength) {
    label = "Strong";
  } else if (score >= 3) {
    label = "Medium";
  }

  return { score, label, checks };
}

Or, if the intended policy is “Strong = all four visible checks,” then make the label logic even simpler:

const visibleScore = [checks.length, checks.case, checks.number, checks.symbol].filter(Boolean).length;

let label = "Weak";
if (visibleScore >= 4) label = "Strong";
else if (visibleScore >= 3) label = "Medium";

Recommended Improvements

2. Move PasswordStrengthMeter out of SignupPage.jsx

Location: frontend/src/pages/SignupPage.jsx, Lines 39-92

The project already has a clear component structure under frontend/src/components/. The new component is currently inline inside a page file, and the comments even say:

TODO: move to components/PasswordStrengthMeter.jsx if the project
has a components folder.

The project does have a components folder, so this TODO should not ship.

Recommended structure:

frontend/src/components/auth/PasswordStrengthMeter.jsx

Then SignupPage.jsx would import it:

import PasswordStrengthMeter from "../components/auth/PasswordStrengthMeter";

Why it matters:

  • Keeps SignupPage.jsx focused on form flow.
  • Makes the component reusable for reset password / change password flows.
  • Makes future testing easier.
  • Avoids shipping TODO comments for work that can be done now.

3. Extract password scoring into a small utility

Location: frontend/src/pages/SignupPage.jsx, Lines 13-37

The comment says the scoring is “easy to unit test,” but it is not exported and lives inside the page file.

Suggested location:

frontend/src/utils/passwordStrength.js

Example:

export function getPasswordStrength(password) {
  // scoring logic
}

Then the component can import it.

Why it matters:

  • Keeps business/scoring logic separate from rendering.
  • Makes it easy to add tests for edge cases:
    • empty password
    • 6-character valid-but-weak password
    • 8+ lowercase only
    • mixed case only
    • no symbol
    • no number
    • 12+ bonus behavior

4. Improve accessibility by connecting the meter to the password input

Location: frontend/src/pages/SignupPage.jsx, Lines 304-321 and Lines 52-75

The meter is visible and the label uses role="status", which is a good start. However, the password input is not associated with the strength feedback via aria-describedby.

Recommended approach:

<input
  type="password"
  aria-describedby="password-error password-strength"
/>

<div id="password-strength">
  <PasswordStrengthMeter password={password} />
</div>

Also consider giving the checklist status semantic labels instead of relying on visual symbols:

<span aria-hidden="true">{ok ? "✓" : "·"}</span>
<span className="sr-only">{ok ? "Met:" : "Not met:"}</span>

Why it matters:

Screen reader users should receive the same actionable password feedback as sighted users.


5. Remove or resolve shipping TODO comments

Location: frontend/src/pages/SignupPage.jsx, Lines 11 and 43-44

These TODOs describe work that is already clearly possible in this codebase:

TODO: move to utils/passwordStrength.js if the project has a utils folder.
TODO: move to components/PasswordStrengthMeter.jsx if the project has a components folder.

The components folder exists. If there is no utils folder yet, either create one or remove the TODO and keep the helper local intentionally.


6. Add newline at end of file

Location: frontend/src/pages/SignupPage.jsx, file end

The diff shows:

\ No newline at end of file

This is minor, but should be fixed for repository hygiene and POSIX/editor consistency.


Scope Validation

In scope

The following changes are aligned with Issue #227 and the PR objective:

  • Adds real-time feedback below the password field.
  • Keeps the existing 6-character submit policy.
  • Uses no new dependencies.
  • Uses monochrome styling instead of color-coded strength.
  • Keeps backend untouched.

Slightly out of scope / cleanup noise

The diff also reformats existing state declarations:

-  const [step, setStep]           = useState(1);
+  const [step, setStep] = useState(1);

This is harmless, but unrelated. It is not a blocker.

The eslint-disable-next-line react-hooks/exhaustive-deps comment was also reindented around Line 137. Since this PR is about password feedback, I would avoid touching unrelated hook suppression unless intentionally fixing that hook.


Backend & Security Impact

Backend behavior

No backend files are changed. The signup API path remains:

SignupPage.jsx → authService.register(name, email, password) → POST /auth/register

Relevant confirmation:

  • frontend/src/services/authService.js, Lines 5-7 posts { name, email, password }.
  • server/modules/auth/routes.js, Line 38 validates and handles /register.
  • server/modules/auth/validation.js, Line 6 still enforces password.min(6).
  • server/models/User.js, Line 7 still has minlength: 6.
  • server/modules/auth/service.js, Lines 20-39 still hashes the password and sends OTP.

Password policy compatibility

The PR does not conflict with the current 6-character policy.

Frontend:

const isPasswordValid = password.length >= 6;

Backend:

password: z.string().min(6, "Password must be at least 6 characters")

Database model:

password: { type: String, required: true, minlength: 6, select: false }

So a 6-character password can still be submitted. The strength meter only provides guidance; it does not enforce 8/12 characters, mixed case, number, or symbol.

Security impact

Positive:

  • Encourages stronger passwords without changing backend policy.
  • Does not expose the password value outside the existing React state.
  • Does not add third-party password scoring dependencies.
  • Does not change hashing, OTP, cookies, auth routes, or database behavior.

Caveat:

  • This is UX guidance only. Users can still submit weak 6-character passwords. That is consistent with current policy, but should be documented as intentional.

UI/UX Review

Good

  • Real-time feedback appears directly under the password input.
  • Monochrome styling matches the existing visual language.
  • Checklist is actionable and easy to understand.
  • Meter does not block valid 6-character passwords, avoiding sudden policy escalation.
  • Submit button behavior remains consistent with current validation.

Needs polish

  • Strong can conflict with unchecked checklist criteria due to hidden longLength.
  • The meter disappears entirely when the password is empty. That is acceptable, but showing the checklist upfront could better communicate expectations before typing.
  • Accessibility linkage between the input and feedback should be improved.
  • On small screens, the two-column checklist may become cramped. Consider grid-cols-1 sm:grid-cols-2.
  • The label alone (Weak, Medium, Strong) may not be descriptive enough for assistive technologies.

Suggested checklist layout improvement:

<ul className="grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-1.5">

Code Quality & Maintainability

Strengths

  • Scoring function is pure.
  • Rendering logic is simple.
  • No unnecessary dependency added.
  • The feature is localized and low-risk.

Weaknesses

  • Inline component increases SignupPage.jsx size.
  • Helper is not exported/testable despite comment.
  • Hidden longLength scoring criterion is not visible in the checklist.
  • TODO comments should not be shipped when the repository already has the relevant structure.
  • No tests were added for password scoring edge cases.

Quality Grading

Category Rating Notes
Correctness 7/10 Core feature works, but Strong can be inaccurate when a visible criterion is missing.
Code Quality 7/10 Simple implementation, but too much logic/component code is inline in the page.
Maintainability 6/10 Should extract component and scoring helper before this grows further.
Security 8/10 No backend/security regression; keeps 6-char policy. Meter is advisory only.
Performance 10/10 Regex checks on each keystroke are trivial.
UI/UX 7/10 Good visual integration, but accessibility and scoring consistency need polish.
Scope Adherence 8/10 Mostly scoped; minor unrelated formatting/hook-comment noise.
Overall Merge Readiness 7/10 Close, but I recommend fixing the misleading Strong classification first.

Future Issue Discovery

Issue 1: Extract reusable PasswordStrengthMeter

Problem: Password strength UI is embedded in SignupPage.jsx.

Why it matters: Reset password and future change-password flows may need the same feedback.

Expected impact: Better reuse, smaller page component, easier testing.

Suggested implementation:

  • Create frontend/src/components/auth/PasswordStrengthMeter.jsx.
  • Move PasswordStrengthMeter and StrengthCheckItem.
  • Import it in SignupPage.jsx.

Issue 2: Add password strength utility tests

Problem: Password scoring has edge cases and currently no test coverage.

Why it matters: Classification logic can regress easily, especially around 8+ vs 12+ length and hidden bonus criteria.

Expected impact: Prevents misleading labels like Strong with missing visible criteria.

Suggested implementation:

  • Extract getPasswordStrength.
  • Add tests for representative weak/medium/strong passwords.
  • Explicitly test that Strong requires the intended core criteria.

Issue 3: Align password guidance across signup, reset password, and account settings

Problem: Signup now gives strength feedback, but reset password likely still only enforces minimum length.

Why it matters: Users should receive consistent password guidance everywhere passwords are created.

Expected impact: Better security posture and consistent UX.

Suggested implementation:

  • Reuse the extracted meter in forgot/reset password flow.
  • Keep backend minimum at 6 unless a separate policy-change issue is approved.

Issue 4: Improve form accessibility across auth pages

Problem: Existing auth forms rely heavily on visual styling and could better connect labels, errors, and dynamic feedback.

Why it matters: Accessibility affects keyboard and screen-reader users.

Expected impact: Better WCAG alignment and more robust auth UX.

Suggested implementation:

  • Add explicit htmlFor / id pairs for labels and inputs.
  • Use aria-describedby for errors and helper text.
  • Ensure dynamic status updates are meaningful and not noisy.

Issue 5: Clean up outdated auth documentation

Problem: Some README snippets mention localStorage tokens, but current code uses HttpOnly cookies via withCredentials.

Why it matters: Inconsistent docs can mislead contributors working on auth.

Expected impact: Reduces onboarding confusion and prevents accidental reintroduction of token-in-localStorage patterns.

Suggested implementation:

  • Update auth docs to reflect cookie-based session management.
  • Remove stale localStorage references where no longer accurate.

Recommended Merge Path

Before merge:

  1. Fix password strength classification so Strong cannot appear while a visible core criterion is missing.
  2. Add newline at EOF.
  3. Remove or resolve TODO comments.

Preferably before merge, but acceptable as follow-up if you want to keep this PR small:

  1. Extract PasswordStrengthMeter to frontend/src/components/auth/PasswordStrengthMeter.jsx.
  2. Extract getPasswordStrength to a utility.
  3. Add scoring tests.
  4. Improve aria-describedby and checklist semantics.

@kunalverma2512

Copy link
Copy Markdown
Owner

@coderabbitai just tell for this issue i.e for scope of ths PR whats left to proceed to ready to merge

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@kunalverma2512 Here are the 3 things to fix in this PR before it's ready to merge:


1. Fix the misleading Strong label (correctness bug)

A password like aaaaaaaaaaaa1! scores as Strong even though Upper & Lower is unchecked in the visible checklist. That's contradictory feedback.

Quick fix — base Strong only on the four visible criteria:

const visibleScore = [checks.length, checks.case, checks.number, checks.symbol].filter(Boolean).length;

let label = "Weak";
if (visibleScore >= 4) label = "Strong";
else if (visibleScore >= 3) label = "Medium";

2. Remove the TODO comments (ships unfinished notes)

These two comments should not be in a merged PR when the project already has the relevant folders:

// TODO: move to utils/passwordStrength.js if the project has a utils folder.
// TODO: move to components/PasswordStrengthMeter.jsx if the project has a components folder.

Either do the extraction now, or remove the TODOs and keep the code inline intentionally.


3. Add a newline at end of file (POSIX hygiene)

The diff ends with:

\ No newline at end of file

Just add a newline at the bottom of SignupPage.jsx.


Everything else (extracting the component, adding tests, accessibility improvements) I flagged as recommended follow-ups, not blockers for this PR.

@kunalverma2512

Copy link
Copy Markdown
Owner

@akshatsinghai6682-sketch See this comment and resolve issue 1 , and remove those comments said in issue 2 and dont do that extract work and resolve issue 3

@akshatsinghai6682-sketch

Copy link
Copy Markdown
Contributor Author

@kunalverma2512 ok

Signed-off-by: Akshat Singhai <akshatsinghai6682@gmail.com>
@akshatsinghai6682-sketch

Copy link
Copy Markdown
Contributor Author

@kunalverma2512 I've addressed the requested changes:

  • Fixed the password strength classification issue.
  • Removed the TODO comments.
  • Added a newline at the end of the file.

The changes have been pushed. Please review when you get a chance. Thank you!

@kunalverma2512

Copy link
Copy Markdown
Owner

@coderabbitai please review the latest commit and check with previous dicsussion that is this read to merge now ?

also check if this got merged then will it created any chaos in production while sign up ? i.e any backend issue will come with this frontend work done in this PR

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -u

num() { awk '{printf "%6d  %s\n", NR, $0}' "$1"; }

SIGNUP_FILE="$(fd 'SignupPage\.jsx$' . | head -n 1 || true)"
echo "== File: ${SIGNUP_FILE} =="
num "${SIGNUP_FILE}"
echo
echo "== EOF check (last 3 bytes hex) =="
tail -c 3 "${SIGNUP_FILE}" | xxd
echo
echo "== TODO check =="
rg -n 'TODO' "${SIGNUP_FILE}" || echo "No TODOs found"
echo
echo "== getPasswordStrength / label logic =="
rg -n 'Strong|Medium|Weak|visibleScore|longLength|label' "${SIGNUP_FILE}"
echo
echo "== Latest git log (last 3 commits) =="
git log --oneline -3
echo
echo "== Diff vs base for SignupPage.jsx =="
BASE_REF="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master 2>/dev/null || true)"
if [ -n "${BASE_REF}" ] && [ -n "${SIGNUP_FILE}" ]; then
  git diff --find-renames "${BASE_REF}"...HEAD -- "${SIGNUP_FILE}"
fi

Length of output: 26424



@kunalverma2512 Here's what I found from the latest commit.


Status of the 3 Must-Fix Items

# Issue Status
1 Strong label only when all 4 visible criteria met ✅ Fixed correctly
2 TODO comments removed ✅ Fixed correctly
3 Newline at end of file ❌ Still missing

Fix #1 — Confirmed correct ✅

The scoring now correctly uses visibleScore for the label:

const visibleScore = [checks.length, checks.case, checks.number, checks.symbol].filter(Boolean).length;

if (visibleScore === 4) label = "Strong";
else if (visibleScore >= 3) label = "Medium";

Strong can only appear when all four visible checklist items are checked. The hidden longLength bonus still feeds the segment bar fill count (cosmetic only), which is acceptable.

Fix #2 — Confirmed correct ✅

rg found zero TODO comments remaining in the file.

Fix #3 — Still not done ❌

The diff still ends with:

+}
\ No newline at end of file

@akshatsinghai6682-sketch just needs to open SignupPage.jsx and save it with a trailing newline. In most editors: place cursor at the very end of the file → press Enter once → save.


Production / Backend Safety ✅

No risk at all. This PR:

  • Touches only frontend/src/pages/SignupPage.jsx
  • Does not change any backend file (routes.js, controller.js, service.js, validation.js, User.js)
  • Does not change the API call in authService.js — still posts { name, email, password } to /auth/register
  • Does not change the 6-character minimum — the submit button still requires password.length >= 6 (Line 117)
  • The strength meter is advisory only — users can still submit a "Weak" password as long as it's ≥ 6 characters

There will be no chaos in production from this merge.


One-liner remaining action for @akshatsinghai6682-sketch

Just add a newline at the end of frontend/src/pages/SignupPage.jsx and push. After that, this PR is ready to merge.

(🐰)

@kunalverma2512

Copy link
Copy Markdown
Owner

@akshatsinghai6682-sketch I think now its ready to merge but take care next time to give EOF in changed files

@kunalverma2512 kunalverma2512 self-requested a review June 23, 2026 17:00
@kunalverma2512 kunalverma2512 merged commit d117b98 into kunalverma2512:main Jun 23, 2026
1 of 2 checks passed
@akshatsinghai6682-sketch akshatsinghai6682-sketch deleted the feature/password-strength-meter branch June 23, 2026 17:01
@akshatsinghai6682-sketch

Copy link
Copy Markdown
Contributor Author

ok @kunalverma2512 thanks for the suggestion and your valuable review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add password strength indicator to sign-up form

2 participants