nextjs-hackathon-stack 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -18,9 +18,6 @@ function printBanner() {
18
18
  function success(msg) {
19
19
  p.log.success(msg);
20
20
  }
21
- function info(msg) {
22
- p.log.info(msg);
23
- }
24
21
  function outro2(msg) {
25
22
  p.outro(pc.green(msg));
26
23
  }
@@ -112,29 +109,29 @@ async function scaffold(projectName, skipInstall) {
112
109
  p3.log.error(stderr || "npm install failed");
113
110
  p3.log.info("You can install manually: cd " + projectName + " && npm install");
114
111
  }
115
- info("Running shadcn/ui init...");
112
+ spinner2.start("Initializing shadcn/ui");
116
113
  try {
117
- execSync("npx shadcn@latest init --yes --defaults", {
114
+ execSync("npx shadcn@latest init --yes --defaults --force --silent", {
118
115
  cwd: targetDir,
119
- stdio: "inherit"
116
+ stdio: "pipe"
120
117
  });
121
- success("shadcn/ui initialized");
118
+ spinner2.stop("shadcn/ui initialized");
122
119
  } catch {
123
- p3.log.warn("shadcn/ui init failed \u2014 run manually: npx shadcn@latest init");
120
+ spinner2.stop("shadcn/ui init failed \u2014 run manually: npx shadcn@latest init");
124
121
  }
125
- info("Adding shadcn/ui base components...");
126
122
  const components = ["button", "input", "card", "form", "label"];
127
123
  for (const component of components) {
124
+ spinner2.start(`Adding shadcn/ui component: ${component}`);
128
125
  try {
129
- execSync(`npx shadcn@latest add ${component} --yes`, {
126
+ execSync(`npx shadcn@latest add ${component} --yes --silent`, {
130
127
  cwd: targetDir,
131
- stdio: "ignore"
128
+ stdio: "pipe"
132
129
  });
130
+ spinner2.stop(`Added shadcn/ui component: ${component}`);
133
131
  } catch {
134
- p3.log.warn(`Failed to add component: ${component}`);
132
+ spinner2.stop(`Failed to add component: ${component}`);
135
133
  }
136
134
  }
137
- success("shadcn/ui components added");
138
135
  }
139
136
  success(pc2.bold(`Project "${projectName}" created!`));
140
137
  console.log(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextjs-hackathon-stack",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Scaffold a full-stack Next.js hackathon starter",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,9 +2,14 @@ import { LoginForm } from "@/features/auth/components/login-form";
2
2
 
3
3
  export default function LoginPage() {
4
4
  return (
5
- <main className="flex min-h-screen items-center justify-center">
6
- <div className="w-full max-w-md p-8">
7
- <h1 className="mb-8 text-2xl font-bold">Sign in</h1>
5
+ <main className="flex min-h-screen items-center justify-center bg-muted/40 px-4">
6
+ <div className="w-full max-w-sm space-y-6">
7
+ <div className="text-center">
8
+ <h1 className="text-3xl font-bold tracking-tight">Welcome back</h1>
9
+ <p className="mt-2 text-sm text-muted-foreground">
10
+ Sign in to your account to continue
11
+ </p>
12
+ </div>
8
13
  <LoginForm />
9
14
  </div>
10
15
  </main>
@@ -5,6 +5,10 @@ import { useForm } from "react-hook-form";
5
5
  import { zodResolver } from "@hookform/resolvers/zod";
6
6
  import { z } from "zod";
7
7
  import { loginAction, type LoginActionState } from "../actions/login.action";
8
+ import { Button } from "@/components/ui/button";
9
+ import { Input } from "@/components/ui/input";
10
+ import { Label } from "@/components/ui/label";
11
+ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
8
12
 
9
13
  const schema = z.object({
10
14
  email: z.string().email("Invalid email"),
@@ -32,49 +36,52 @@ export function LoginForm() {
32
36
  });
33
37
 
34
38
  return (
35
- <form onSubmit={onSubmit} data-testid="login-form" className="space-y-4">
36
- {state.status === "error" && (
37
- <p role="alert" className="text-sm text-red-600">
38
- {state.message}
39
- </p>
40
- )}
41
- <div>
42
- <label htmlFor="email" className="block text-sm font-medium">
43
- Email
44
- </label>
45
- <input
46
- id="email"
47
- type="email"
48
- autoComplete="email"
49
- {...register("email")}
50
- className="mt-1 block w-full rounded border px-3 py-2"
51
- />
52
- {errors.email && (
53
- <p className="mt-1 text-sm text-red-600">{errors.email.message}</p>
54
- )}
55
- </div>
56
- <div>
57
- <label htmlFor="password" className="block text-sm font-medium">
58
- Password
59
- </label>
60
- <input
61
- id="password"
62
- type="password"
63
- autoComplete="current-password"
64
- {...register("password")}
65
- className="mt-1 block w-full rounded border px-3 py-2"
66
- />
67
- {errors.password && (
68
- <p className="mt-1 text-sm text-red-600">{errors.password.message}</p>
69
- )}
70
- </div>
71
- <button
72
- type="submit"
73
- disabled={isPending}
74
- className="w-full rounded bg-primary px-4 py-2 text-primary-foreground disabled:opacity-50"
75
- >
76
- {isPending ? "Signing in..." : "Sign in"}
77
- </button>
78
- </form>
39
+ <Card>
40
+ <CardHeader>
41
+ <CardTitle>Sign in</CardTitle>
42
+ <CardDescription>Enter your email and password below</CardDescription>
43
+ </CardHeader>
44
+ <CardContent>
45
+ <form onSubmit={onSubmit} data-testid="login-form" className="space-y-4">
46
+ {state.status === "error" && (
47
+ <p role="alert" className="rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive">
48
+ {state.message}
49
+ </p>
50
+ )}
51
+
52
+ <div className="space-y-1.5">
53
+ <Label htmlFor="email">Email</Label>
54
+ <Input
55
+ id="email"
56
+ type="email"
57
+ autoComplete="email"
58
+ placeholder="you@example.com"
59
+ {...register("email")}
60
+ />
61
+ {errors.email && (
62
+ <p className="text-sm text-destructive">{errors.email.message}</p>
63
+ )}
64
+ </div>
65
+
66
+ <div className="space-y-1.5">
67
+ <Label htmlFor="password">Password</Label>
68
+ <Input
69
+ id="password"
70
+ type="password"
71
+ autoComplete="current-password"
72
+ placeholder="••••••••"
73
+ {...register("password")}
74
+ />
75
+ {errors.password && (
76
+ <p className="text-sm text-destructive">{errors.password.message}</p>
77
+ )}
78
+ </div>
79
+
80
+ <Button type="submit" className="w-full" disabled={isPending}>
81
+ {isPending ? "Signing in…" : "Sign in"}
82
+ </Button>
83
+ </form>
84
+ </CardContent>
85
+ </Card>
79
86
  );
80
87
  }