Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ FRONTEND_URL=http://localhost:5173
# Add a random string here
# In order to generate one, you may use this command: openssl rand -base64 32
BETTER_AUTH_SECRET=

GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=

DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
10 changes: 10 additions & 0 deletions backend/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,15 @@ export const auth = betterAuth({
emailAndPassword: {
enabled: true,
},
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID ?? "",
clientSecret: process.env.GITHUB_CLIENT_SECRET ?? "",
},
discord: {
clientId: process.env.DISCORD_CLIENT_ID ?? "",
clientSecret: process.env.DISCORD_CLIENT_SECRET ?? "",
},
},
trustedOrigins: [process.env.FRONTEND_URL ?? "http://localhost:5173"],
});
1 change: 1 addition & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_APP_URL=http://localhost:5173
50 changes: 50 additions & 0 deletions frontend/app/components/SocialLogIns/SocialLogIns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "~/components/ui/Collapsible";
import { ChevronDown, ChevronUp } from "lucide-react";
import { SiDiscord } from "@icons-pack/react-simple-icons";
import { Button } from "~/components/ui/Button";
import { useState } from "react";
import { authClient } from "~/api/auth";

function SocialLogIns({ logInType }: { logInType: "login" | "signup" }) {
const [collapsibleOpen, setCollapsibleOpen] = useState(false);

return (
<Collapsible
className="space-y-4"
onOpenChange={(value) => setCollapsibleOpen(value)}
>
<div className="flex justify-center items-center gap-4 font-semibold">
More options
<CollapsibleTrigger>
<Button variant="outline">
{collapsibleOpen ? (
<ChevronUp className="h-4 w-4" />
) : (
<ChevronDown className="h-4 w-4" />
)}
</Button>
</CollapsibleTrigger>
</div>
<CollapsibleContent className="block">
<Button
onClick={() =>
void authClient.signIn.social({
provider: "discord",
callbackURL: `${import.meta.env.VITE_APP_URL}/project2/`,
})
}
variant="outline"
>
<SiDiscord className="mr-2 h-4 w-4" />
{logInType === "login" ? "Log in" : "Sign up"} with Discord
</Button>
</CollapsibleContent>
</Collapsible>
);
}

export { SocialLogIns };
2 changes: 1 addition & 1 deletion frontend/app/components/ui/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "cn";

const buttonVariants = cva(
"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none cursor-pointer focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
variants: {
variant: {
Expand Down
19 changes: 19 additions & 0 deletions frontend/app/components/ui/Collapsible.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"

function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
}

function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {
return (
<CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
)
}

function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {
return (
<CollapsiblePrimitive.Panel data-slot="collapsible-content" {...props} />
)
}

export { Collapsible, CollapsibleTrigger, CollapsibleContent }
15 changes: 15 additions & 0 deletions frontend/app/routes/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
import { Input } from "~/components/ui/Input";
import { Spinner } from "~/components/ui/Spinner";
import { toast } from "~/components/ui/Toast";
import { SiGithub } from "@icons-pack/react-simple-icons";
import { SocialLogIns } from "~/components/SocialLogIns/SocialLogIns";

const formSchema = z.object({
email: z.email("Enter a valid email address."),
Expand Down Expand Up @@ -149,6 +151,19 @@ export default function LoginPage() {
</Button>
)}
</form.Subscribe>
<Button
onClick={() =>
void authClient.signIn.social({
provider: "github",
callbackURL: `${import.meta.env.VITE_APP_URL}/project2/`,
})
}
variant="outline"
>
<SiGithub className="mr-2 h-4 w-4" />
Log in with GitHub
</Button>
<SocialLogIns logInType="login" />
<p className="text-muted-foreground">
Don't have an account?{" "}
<Link to="/signup" className="text-primary underline">
Expand Down
15 changes: 15 additions & 0 deletions frontend/app/routes/signup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
import { Input } from "~/components/ui/Input";
import { Spinner } from "~/components/ui/Spinner";
import { toast } from "~/components/ui/Toast";
import { SiGithub } from "@icons-pack/react-simple-icons";
import { SocialLogIns } from "~/components/SocialLogIns/SocialLogIns";

// Matches better-auth's default minPasswordLength.
const MIN_PASSWORD_LENGTH = 8;
Expand Down Expand Up @@ -230,6 +232,19 @@ export default function SignupPage() {
</Button>
)}
</form.Subscribe>
<Button
onClick={() =>
void authClient.signIn.social({
provider: "github",
callbackURL: `${import.meta.env.VITE_APP_URL}/project2/`,
})
}
variant="outline"
>
<SiGithub className="mr-2 h-4 w-4" />
Sign up with GitHub
</Button>
<SocialLogIns logInType="signup" />
<p className="text-muted-foreground">
Already have an account?{" "}
<Link to="/login" className="text-primary underline">
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@apollo/client": "^4.3.1",
"@base-ui/react": "^1.8.0",
"@fontsource-variable/inter": "^5.3.0",
"@icons-pack/react-simple-icons": "^13.15.1",
"@react-router/node": "^8.4.0",
"@react-router/serve": "^8.4.0",
"@tailwindcss/vite": "^4.3.3",
Expand Down
12 changes: 12 additions & 0 deletions frontend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.