{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "password-based-auth-vue",
  "title": "Password Based Auth flow for Vue and Supabase",
  "description": "Password Based Auth flow for Vue and Supabase",
  "dependencies": [
    "@supabase/supabase-js@latest"
  ],
  "registryDependencies": [
    "button",
    "card",
    "input",
    "label"
  ],
  "files": [
    {
      "path": "registry/default/password-based-auth/vue/components/login-form.vue",
      "content": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { createClient } from \"@/lib/supabase/client\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\n\nconst email = ref(\"\")\nconst error = ref<string | null>(null)\nconst success = ref(false)\nconst isLoading = ref(false)\n\nconst handleForgotPassword = async (e: Event) => {\n  e.preventDefault()\n  const supabase = createClient()\n  isLoading.value = true\n  error.value = null\n\n  try {\n    const { error: supabaseError } = await supabase.auth.resetPasswordForEmail(email.value, {\n      redirectTo: \"http://localhost:3000/update-password\",\n    })\n    if (supabaseError) throw supabaseError\n    success.value = true\n  } catch (err: unknown) {\n    error.value = err instanceof Error ? err.message : \"An error occurred\"\n  } finally {\n    isLoading.value = false\n  }\n}\n</script>\n\n<template>\n  <div class=\"flex flex-col gap-6\">\n    <Card v-if=\"success\">\n      <CardHeader>\n        <CardTitle class=\"text-2xl\">Check Your Email</CardTitle>\n        <CardDescription>Password reset instructions sent</CardDescription>\n      </CardHeader>\n      <CardContent>\n        <p class=\"text-sm text-muted-foreground\">\n          If you registered using your email and password, you will receive a password reset email.\n        </p>\n      </CardContent>\n    </Card>\n\n    <Card v-else>\n      <CardHeader>\n        <CardTitle class=\"text-2xl\">Reset Your Password</CardTitle>\n        <CardDescription>\n          Type in your email and we&apos;ll send you a link to reset your password\n        </CardDescription>\n      </CardHeader>\n      <CardContent>\n        <form @submit=\"handleForgotPassword\">\n          <div class=\"flex flex-col gap-6\">\n            <div class=\"grid gap-2\">\n              <Label for=\"email\">Email</Label>\n              <Input\n                id=\"email\"\n                type=\"email\"\n                placeholder=\"m@example.com\"\n                required\n                v-model=\"email\"\n              />\n            </div>\n            <p v-if=\"error\" class=\"text-sm text-red-500\">{{ error }}</p>\n            <Button type=\"submit\" class=\"w-full\" :disabled=\"isLoading\">\n              {{ isLoading ? \"Sending...\" : \"Send reset email\" }}\n            </Button>\n          </div>\n          <div class=\"mt-4 text-center text-sm\">\n            Already have an account?\n            <a href=\"/login\" class=\"underline underline-offset-4\">Sign in</a>\n          </div>\n        </form>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:component",
      "target": "components/login-form.vue"
    },
    {
      "path": "registry/default/password-based-auth/vue/components/sign-up-form.vue",
      "content": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { createClient } from \"@/lib/supabase/client\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\n\nconst email = ref(\"\")\nconst password = ref(\"\")\nconst repeatPassword = ref(\"\")\nconst error = ref<string | null>(null)\nconst isLoading = ref(false)\nconst success = ref(false)\n\nconst handleSignUp = async () => {\n  const supabase = createClient()\n  error.value = null\n\n  if (password.value !== repeatPassword.value) {\n    error.value = \"Passwords do not match\"\n    return\n  }\n\n  isLoading.value = true\n  try {\n    const { error: supabaseError } = await supabase.auth.signUp({\n      email: email.value,\n      password: password.value,\n    })\n    if (supabaseError) throw supabaseError\n    success.value = true\n  } catch (err: unknown) {\n    error.value = err instanceof Error ? err.message : \"An error occurred\"\n  } finally {\n    isLoading.value = false\n  }\n}\n</script>\n\n<template>\n  <div class=\"flex flex-col gap-6\">\n    <Card v-if=\"success\">\n      <CardHeader>\n        <CardTitle class=\"text-2xl\">Thank you for signing up!</CardTitle>\n        <CardDescription>Check your email to confirm</CardDescription>\n      </CardHeader>\n      <CardContent>\n        <p class=\"text-sm text-muted-foreground\">\n          You've successfully signed up. Please check your email to confirm your account before\n          signing in.\n        </p>\n      </CardContent>\n    </Card>\n\n    <Card v-else>\n      <CardHeader>\n        <CardTitle class=\"text-2xl\">Sign up</CardTitle>\n        <CardDescription>Create a new account</CardDescription>\n      </CardHeader>\n      <CardContent>\n        <form @submit.prevent=\"handleSignUp\">\n          <div class=\"flex flex-col gap-6\">\n            <!-- Email -->\n            <div class=\"grid gap-2\">\n              <Label for=\"email\">Email</Label>\n              <Input\n                id=\"email\"\n                type=\"email\"\n                placeholder=\"m@example.com\"\n                required\n                v-model=\"email\"\n              />\n            </div>\n\n            <!-- Password -->\n            <div class=\"grid gap-2\">\n              <div class=\"flex items-center\">\n                <Label for=\"password\">Password</Label>\n              </div>\n              <Input\n                id=\"password\"\n                type=\"password\"\n                required\n                v-model=\"password\"\n              />\n            </div>\n\n            <!-- Repeat Password -->\n            <div class=\"grid gap-2\">\n              <div class=\"flex items-center\">\n                <Label for=\"repeat-password\">Repeat Password</Label>\n              </div>\n              <Input\n                id=\"repeat-password\"\n                type=\"password\"\n                required\n                v-model=\"repeatPassword\"\n              />\n            </div>\n\n            <!-- Error -->\n            <p v-if=\"error\" class=\"text-sm text-red-500\">{{ error }}</p>\n\n            <!-- Submit -->\n            <Button type=\"submit\" class=\"w-full\" :disabled=\"isLoading\">\n              {{ isLoading ? \"Creating an account...\" : \"Sign up\" }}\n            </Button>\n          </div>\n\n          <div class=\"mt-4 text-center text-sm\">\n            Already have an account?\n            <a href=\"/login\" class=\"underline underline-offset-4\">Sign in</a>\n          </div>\n        </form>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:component",
      "target": "components/sign-up-form.vue"
    },
    {
      "path": "registry/default/password-based-auth/vue/components/forgot-password-form.vue",
      "content": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { createClient } from \"@/lib/supabase/client\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\n\n\nconst email = ref(\"\")\nconst error = ref<string | null>(null)\nconst success = ref(false)\nconst isLoading = ref(false)\n\nconst handleForgotPassword = async (e: Event) => {\n  e.preventDefault()\n  const supabase = createClient()\n  isLoading.value = true\n  error.value = null\n\n  try {\n    const { error: supabaseError } = await supabase.auth.resetPasswordForEmail(email.value, {\n      redirectTo: \"http://localhost:3000/update-password\",\n    })\n    if (supabaseError) throw supabaseError\n    success.value = true\n  } catch (err: unknown) {\n    error.value = err instanceof Error ? err.message : \"An error occurred\"\n  } finally {\n    isLoading.value = false\n  }\n}\n</script>\n\n<template>\n  <div class=\"flex flex-col gap-6\">\n    <Card v-if=\"success\">\n      <CardHeader>\n        <CardTitle class=\"text-2xl\">Check Your Email</CardTitle>\n        <CardDescription>Password reset instructions sent</CardDescription>\n      </CardHeader>\n      <CardContent>\n        <p class=\"text-sm text-muted-foreground\">\n          If you registered using your email and password, you will receive a password reset email.\n        </p>\n      </CardContent>\n    </Card>\n\n    <Card v-else>\n      <CardHeader>\n        <CardTitle class=\"text-2xl\">Reset Your Password</CardTitle>\n        <CardDescription>\n          Type in your email and we&apos;ll send you a link to reset your password\n        </CardDescription>\n      </CardHeader>\n      <CardContent>\n        <form @submit=\"handleForgotPassword\">\n          <div class=\"flex flex-col gap-6\">\n            <div class=\"grid gap-2\">\n              <Label for=\"email\">Email</Label>\n              <Input\n                id=\"email\"\n                type=\"email\"\n                placeholder=\"m@example.com\"\n                required\n                v-model=\"email\"\n              />\n            </div>\n            <p v-if=\"error\" class=\"text-sm text-red-500\">{{ error }}</p>\n            <Button type=\"submit\" class=\"w-full\" :disabled=\"isLoading\">\n              {{ isLoading ? \"Sending...\" : \"Send reset email\" }}\n            </Button>\n          </div>\n          <div class=\"mt-4 text-center text-sm\">\n            Already have an account?\n            <a href=\"/login\" class=\"underline underline-offset-4\">Sign in</a>\n          </div>\n        </form>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:component",
      "target": "components/forgot-password-form.vue"
    },
    {
      "path": "registry/default/password-based-auth/vue/components/update-password-form.vue",
      "content": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { createClient } from \"@/lib/supabase/client\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\n\nconst password = ref(\"\")\nconst error = ref<string | null>(null)\nconst isLoading = ref(false)\n\nconst handleUpdatePassword = async () => {\n  const supabase = createClient()\n  isLoading.value = true\n  error.value = null\n\n  try {\n    const { error: supabaseError } = await supabase.auth.updateUser({\n      password: password.value,\n    })\n    if (supabaseError) throw supabaseError\n    // Redirect user after successful password update\n    location.href = \"/protected\"\n  } catch (err: unknown) {\n    error.value = err instanceof Error ? err.message : \"An error occurred\"\n  } finally {\n    isLoading.value = false\n  }\n}\n</script>\n\n<template>\n  <div class=\"flex flex-col gap-6\">\n    <Card>\n      <CardHeader>\n        <CardTitle class=\"text-2xl\">Reset Your Password</CardTitle>\n        <CardDescription>Please enter your new password below.</CardDescription>\n      </CardHeader>\n      <CardContent>\n        <form @submit.prevent=\"handleUpdatePassword\">\n          <div class=\"flex flex-col gap-6\">\n            <div class=\"grid gap-2\">\n              <Label for=\"password\">New password</Label>\n              <Input\n                id=\"password\"\n                type=\"password\"\n                placeholder=\"New password\"\n                required\n                v-model=\"password\"\n              />\n            </div>\n            <p v-if=\"error\" class=\"text-sm text-red-500\">{{ error }}</p>\n            <Button type=\"submit\" class=\"w-full\" :disabled=\"isLoading\">\n              {{ isLoading ? \"Saving...\" : \"Save new password\" }}\n            </Button>\n          </div>\n        </form>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:component",
      "target": "components/update-password-form.vue"
    }
  ],
  "type": "registry:block"
}