create-spine 1.0.0 → 1.0.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.
Files changed (42) hide show
  1. package/index.js +22 -1
  2. package/package.json +1 -1
  3. package/template/AGENTS.md +5 -0
  4. package/template/CLAUDE.md +1 -0
  5. package/template/README.md +37 -0
  6. package/template/app/Refund/page.tsx +340 -0
  7. package/template/app/api/auth/[...nextauth]/route.ts +6 -0
  8. package/template/app/api/generate/route.ts +57 -0
  9. package/template/app/dashboard/page.tsx +713 -0
  10. package/template/app/faq/page.tsx +343 -0
  11. package/template/app/globals.css +130 -0
  12. package/template/app/layout.tsx +33 -0
  13. package/template/app/page.tsx +650 -0
  14. package/template/app/pricing/page.tsx +23 -0
  15. package/template/app/privacy/page.tsx +328 -0
  16. package/template/app/terms/page.tsx +12 -0
  17. package/template/components/ui/badge.tsx +52 -0
  18. package/template/components/ui/button.tsx +58 -0
  19. package/template/components/ui/card.tsx +103 -0
  20. package/template/components/ui/separator.tsx +25 -0
  21. package/template/components/ui/textarea.tsx +18 -0
  22. package/template/components/ui/ui/footer/page.tsx +103 -0
  23. package/template/components/ui/ui/navbar/navbar.tsx +0 -0
  24. package/template/components.json +25 -0
  25. package/template/desktop.ini +6 -0
  26. package/template/eslint.config.mjs +18 -0
  27. package/template/lib/auth.ts +19 -0
  28. package/template/lib/prisma.ts +7 -0
  29. package/template/lib/utils.ts +6 -0
  30. package/template/next.config.ts +7 -0
  31. package/template/package-lock.json +9794 -0
  32. package/template/package.json +35 -0
  33. package/template/postcss.config.mjs +7 -0
  34. package/template/public/X.svg +1 -0
  35. package/template/public/github.svg +2 -0
  36. package/template/public/google.svg +2 -0
  37. package/template/src/components/ui/badge.tsx +58 -0
  38. package/template/src/components/ui/button.tsx +90 -0
  39. package/template/src/components/ui/card.tsx +103 -0
  40. package/template/src/components/ui/textarea.tsx +29 -0
  41. package/template/src/lib/utils.ts +6 -0
  42. package/template/tsconfig.json +34 -0
package/index.js CHANGED
@@ -1,2 +1,23 @@
1
1
  #!/usr/bin/env node
2
- console.log("Hello from create-spine! It works.");
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+ const { execSync } = require("child_process");
5
+
6
+ const projectName = process.argv[2] || "my-spinekit-app";
7
+ const templateDir = path.join(__dirname, "template");
8
+ const targetDir = path.join(process.cwd(), projectName);
9
+
10
+ if (fs.existsSync(targetDir)) {
11
+ console.error(`Folder "${projectName}" already exists. Pick a different name.`);
12
+ process.exit(1);
13
+ }
14
+
15
+ fs.cpSync(templateDir, targetDir, { recursive: true });
16
+ console.log(`\nCreated ${projectName}`);
17
+
18
+ console.log(`\nInstalling dependencies...\n`);
19
+ execSync("npm install", { cwd: targetDir, stdio: "inherit" });
20
+
21
+ console.log(`\nAll done! Run this to start:`);
22
+ console.log(` cd ${projectName}`);
23
+ console.log(` npm run dev\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-spine",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "",
5
5
  "main": "index.js", "bin": { "create-spine": "./index.js" },
6
6
  "scripts": {
@@ -0,0 +1,5 @@
1
+ <!-- BEGIN:nextjs-agent-rules -->
2
+ # This is NOT the Next.js you know
3
+
4
+ This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
5
+ <!-- END:nextjs-agent-rules -->
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -0,0 +1,37 @@
1
+ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
2
+
3
+ ## Getting Started
4
+
5
+ First, run the development server:
6
+
7
+ ```bash
8
+ npm run dev
9
+ # or
10
+ yarn dev
11
+ # or
12
+ pnpm dev
13
+ # or
14
+ bun dev
15
+ ```
16
+
17
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18
+
19
+ You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
20
+
21
+ This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
22
+
23
+ ## Learn More
24
+
25
+ To learn more about Next.js, take a look at the following resources:
26
+
27
+ - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28
+ - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29
+
30
+ You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
31
+
32
+ ## Deploy on Vercel
33
+
34
+ The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35
+
36
+ Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
37
+ # SPINEKIT
@@ -0,0 +1,340 @@
1
+ import type { Metadata } from "next";
2
+ import type { ReactNode } from "react";
3
+ import { Card, CardContent } from "@/components/ui/card";
4
+ import {
5
+ Table,
6
+ TableBody,
7
+ TableCell,
8
+ TableHead,
9
+ TableHeader,
10
+ TableRow,
11
+ } from "@/components/ui/table";
12
+ import { Reveal } from "@/components/reveal";
13
+
14
+ export const metadata: Metadata = {
15
+ title: "Refund Policy — Oshunt",
16
+ description: "Oshunt's returns, refunds, and exchange policy.",
17
+ };
18
+
19
+ const quickFacts = [
20
+ { num: "30", label: "days to request a return" },
21
+ { num: "5–7", label: "business days to process" },
22
+ { num: "100%", label: "refund on eligible items" },
23
+ ];
24
+
25
+ const shippingRows = [
26
+ { reason: "Changed your mind, wrong size/shade", payer: "Customer" },
27
+ { reason: "Damaged, defective, or incorrect item shipped", payer: "Oshunt" },
28
+ ];
29
+
30
+ const sectionIndex = [
31
+ { id: "returns-window", num: "01", title: "Returns window" },
32
+ { id: "not-returnable", num: "02", title: "What can't be returned" },
33
+ { id: "start-a-return", num: "03", title: "How to start a return" },
34
+ { id: "refunds", num: "04", title: "Refunds" },
35
+ { id: "damaged-items", num: "05", title: "Damaged, defective, or incorrect items" },
36
+ { id: "exchanges", num: "06", title: "Exchanges" },
37
+ { id: "late-refunds", num: "07", title: "Late or missing refunds" },
38
+ { id: "sale-items", num: "08", title: "Sale items" },
39
+ { id: "shipping-costs", num: "09", title: "Shipping costs for returns" },
40
+ ];
41
+
42
+ export default function RefundPolicyPage() {
43
+ return (
44
+ <div className="bg-[#FAF8F2] text-[#12201D] font-sans antialiased">
45
+ <style>{`
46
+ @import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=Inter:wght@400;500;600&display=swap');
47
+ .font-serif { font-family: 'Fraunces', ui-serif, Georgia, serif; font-optical-sizing: auto; }
48
+ .font-sans { font-family: 'Inter', ui-sans-serif, system-ui, sans-serif; }
49
+
50
+ @keyframes gentle-breathe {
51
+ 0%, 100% { transform: scale(1); opacity: 0.5; }
52
+ 50% { transform: scale(1.05); opacity: 0.85; }
53
+ }
54
+ .ambient-ring { animation: gentle-breathe 9s ease-in-out infinite; }
55
+ .ambient-ring-slow { animation: gentle-breathe 12s ease-in-out infinite; animation-delay: 1.2s; }
56
+
57
+ @media (prefers-reduced-motion: reduce) {
58
+ .ambient-ring, .ambient-ring-slow { animation: none; }
59
+ }
60
+ `}</style>
61
+
62
+ {/* Very faint paper-grain — reinforces the print/editorial feel without weighing the page down */}
63
+ <div
64
+ aria-hidden
65
+ className="pointer-events-none fixed inset-0 z-[1] opacity-[0.025] mix-blend-multiply"
66
+ style={{ backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")` }}
67
+ />
68
+
69
+ {/* Hero */}
70
+ <section className="relative overflow-hidden bg-[#0E2E2B] px-6 pb-14 pt-18 text-[#FBF6E9] sm:pb-16 sm:pt-24">
71
+ <div
72
+ aria-hidden
73
+ className="ambient-ring pointer-events-none absolute -bottom-24 -right-16 h-64 w-64 rounded-full border border-white/10"
74
+ />
75
+ <div
76
+ aria-hidden
77
+ className="ambient-ring-slow pointer-events-none absolute -bottom-10 right-2 h-44 w-44 rounded-full border border-white/10"
78
+ />
79
+ <Reveal className="relative z-10 mx-auto max-w-3xl">
80
+ <p className="mb-4 text-xs font-medium uppercase tracking-[0.14em] text-[#F0DFA8]">
81
+ Oshunt · customer care
82
+ </p>
83
+ <h1 className="font-serif text-4xl font-medium leading-tight tracking-tight sm:text-[44px]">
84
+ Refund policy
85
+ </h1>
86
+ <p className="mt-4 max-w-lg text-[16.5px] text-[#FBF6E9]/80">
87
+ We want you to love what you ordered. If something isn&apos;t
88
+ right, here&apos;s exactly how returns, refunds, and exchanges
89
+ work.
90
+ </p>
91
+ <p className="mt-7 text-[13px] text-[#FBF6E9]/60">
92
+ Last updated:{" "}
93
+ <span className="rounded bg-[#B9862E]/25 px-1.5 py-0.5 text-[#F0DFA8]">
94
+ [Month DD, YYYY]
95
+ </span>
96
+ </p>
97
+ </Reveal>
98
+ </section>
99
+
100
+ <main className="relative mx-auto max-w-3xl px-6 pb-24 pt-12">
101
+ {/* Quick facts — kept as one seamless bar with hairline dividers rather than
102
+ three separate cards; that was already the right call for this row. */}
103
+ <Reveal>
104
+ <Card className="mb-6 overflow-hidden border-[#DCD4BE] p-0 shadow-none">
105
+ <div className="grid grid-cols-1 gap-px bg-[#DCD4BE] sm:grid-cols-3">
106
+ {quickFacts.map((fact) => (
107
+ <div key={fact.label} className="bg-white px-5 py-6 transition-colors hover:bg-[#FBF6E9]/60">
108
+ <span className="block font-serif text-2xl text-[#153F3A]">
109
+ {fact.num}
110
+ </span>
111
+ <span className="text-[13px] text-[#4C5B57]">
112
+ {fact.label}
113
+ </span>
114
+ </div>
115
+ ))}
116
+ </div>
117
+ </Card>
118
+ </Reveal>
119
+
120
+ {/* On this page */}
121
+ <Reveal delay={80}>
122
+ <Card className="mb-14 border-[#DCD4BE] bg-white shadow-none">
123
+ <CardContent className="p-6">
124
+ <p className="mb-3 text-xs font-semibold uppercase tracking-[0.14em] text-[#4C5B57]">
125
+ On this page
126
+ </p>
127
+ <nav className="grid grid-cols-1 gap-x-6 gap-y-1.5 sm:grid-cols-2">
128
+ {sectionIndex.map((s) => (
129
+ <a
130
+ key={s.id}
131
+ href={`#${s.id}`}
132
+ className="rounded-sm text-sm text-[#4C5B57] transition-colors hover:text-[#B9862E] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#B9862E]"
133
+ >
134
+ {s.num}. {s.title}
135
+ </a>
136
+ ))}
137
+ </nav>
138
+ </CardContent>
139
+ </Card>
140
+ </Reveal>
141
+
142
+ <PolicySection id="returns-window" index="01" title="Returns window">
143
+ <p>
144
+ You have <strong>30 calendar days</strong> from the delivery date
145
+ to request a return. After 30 days, we&apos;re unable to offer a
146
+ refund or exchange.
147
+ </p>
148
+ <p>
149
+ To be eligible, your item must be unused, in its original
150
+ condition, and in the original packaging. We may ask for proof of
151
+ purchase, such as your order number or receipt.
152
+ </p>
153
+ </PolicySection>
154
+
155
+ <PolicySection id="not-returnable" index="02" title="What can't be returned">
156
+ <p>
157
+ For hygiene and safety reasons, the following items can&apos;t be
158
+ returned unless they arrive damaged or defective:
159
+ </p>
160
+ <ul className="mb-3 list-disc space-y-2 pl-5 marker:text-[#B9862E]">
161
+ <li>Opened or used skincare, haircare, or beauty products</li>
162
+ <li>Items with a broken seal or removed hygiene sticker</li>
163
+ <li>Gift cards</li>
164
+ <li>Final sale or clearance items, marked as such at checkout</li>
165
+ </ul>
166
+ </PolicySection>
167
+
168
+ <PolicySection id="start-a-return" index="03" title="How to start a return">
169
+ <ul className="mb-3 list-disc space-y-2 pl-5 marker:text-[#B9862E]">
170
+ <li>
171
+ Email{" "}
172
+ <span className="rounded bg-[#B9862E]/15 px-1.5 py-0.5 text-[#7A5717]">
173
+ [returns@oshunt.com]
174
+ </span>{" "}
175
+ with your order number and the reason for your return.
176
+ </li>
177
+ <li>
178
+ We&apos;ll confirm eligibility and send you a return shipping
179
+ label and instructions.
180
+ </li>
181
+ <li>
182
+ Pack the item securely in its original packaging and drop it
183
+ off at the specified carrier.
184
+ </li>
185
+ </ul>
186
+ <p>
187
+ Items sent back without first requesting a return may not be
188
+ accepted.
189
+ </p>
190
+ </PolicySection>
191
+
192
+ <PolicySection id="refunds" index="04" title="Refunds">
193
+ <p>
194
+ Once we receive and inspect your return, we&apos;ll notify you by
195
+ email whether it&apos;s approved. Approved refunds are issued to
196
+ your original payment method within{" "}
197
+ <strong>5–7 business days</strong>. Your bank or card provider
198
+ may take a few additional days to post the refund.
199
+ </p>
200
+ <div className="my-4 rounded-r-xl border-l-2 border-[#B9862E] bg-[#FBF6E9] px-5 py-4">
201
+ <p className="text-[14.5px] text-[#0E2E2B]">
202
+ Original shipping fees are non-refundable, unless the return is
203
+ due to our error (wrong or defective item).
204
+ </p>
205
+ </div>
206
+ </PolicySection>
207
+
208
+ <PolicySection id="damaged-items" index="05" title="Damaged, defective, or incorrect items">
209
+ <p>
210
+ If your order arrives damaged, defective, or different from what
211
+ you ordered, contact us within{" "}
212
+ <strong>7 days of delivery</strong> with a photo of the item.
213
+ We&apos;ll cover return shipping and send a replacement or full
214
+ refund, whichever you prefer.
215
+ </p>
216
+ </PolicySection>
217
+
218
+ <PolicySection id="exchanges" index="06" title="Exchanges">
219
+ <p>
220
+ The fastest way to get a different size, shade, or product is to
221
+ return the original item and place a new order. If you&apos;d
222
+ rather exchange directly, mention this when you email us and
223
+ we&apos;ll do our best to accommodate it, subject to stock.
224
+ </p>
225
+ </PolicySection>
226
+
227
+ <PolicySection id="late-refunds" index="07" title="Late or missing refunds">
228
+ <p>
229
+ If it&apos;s been longer than 10 business days since your refund
230
+ was approved:
231
+ </p>
232
+ <ul className="mb-3 list-disc space-y-2 pl-5 marker:text-[#B9862E]">
233
+ <li>Check your bank account again</li>
234
+ <li>Contact your card provider — posting times vary</li>
235
+ <li>
236
+ If it&apos;s still missing, reach out to us at{" "}
237
+ <span className="rounded bg-[#B9862E]/15 px-1.5 py-0.5 text-[#7A5717]">
238
+ [returns@oshunt.com]
239
+ </span>
240
+ </li>
241
+ </ul>
242
+ </PolicySection>
243
+
244
+ <PolicySection id="sale-items" index="08" title="Sale items">
245
+ <p>
246
+ Only regular-priced items are eligible for a refund. Items
247
+ purchased on sale or with a discount code are final sale, unless
248
+ the item arrived damaged or defective.
249
+ </p>
250
+ </PolicySection>
251
+
252
+ <PolicySection id="shipping-costs" index="09" title="Shipping costs for returns">
253
+ <Card className="mb-5 mt-4 overflow-hidden border-[#DCD4BE] p-0 shadow-none">
254
+ <Table>
255
+ <TableHeader>
256
+ <TableRow className="border-[#DCD4BE] hover:bg-transparent">
257
+ <TableHead className="bg-[#FBF6E9] font-semibold text-[#153F3A]">
258
+ Reason for return
259
+ </TableHead>
260
+ <TableHead className="bg-[#FBF6E9] font-semibold text-[#153F3A]">
261
+ Who pays return shipping
262
+ </TableHead>
263
+ </TableRow>
264
+ </TableHeader>
265
+ <TableBody>
266
+ {shippingRows.map((row) => (
267
+ <TableRow key={row.reason} className="border-[#DCD4BE] hover:bg-[#FBF6E9]/60">
268
+ <TableCell className="text-[#4C5B57]">{row.reason}</TableCell>
269
+ <TableCell className="text-[#4C5B57]">{row.payer}</TableCell>
270
+ </TableRow>
271
+ ))}
272
+ </TableBody>
273
+ </Table>
274
+ </Card>
275
+ </PolicySection>
276
+
277
+ {/* Contact card */}
278
+ <Reveal>
279
+ <Card className="mt-14 border-none bg-[#153F3A] shadow-none">
280
+ <CardContent className="p-8 text-[#FBF6E9]">
281
+ <h2 className="mb-3 font-serif text-xl font-medium text-[#F0DFA8]">
282
+ Need a hand?
283
+ </h2>
284
+ <p className="mb-2 text-[#FBF6E9]/80">
285
+ Our team is happy to help with any return, refund, or order
286
+ question.
287
+ </p>
288
+ <p className="text-[#FBF6E9]/80">
289
+ Email{" "}
290
+ <a
291
+ href="mailto:returns@oshunt.com"
292
+ className="border-b border-[#F0DFA8]/40 text-[#F0DFA8] no-underline transition-colors hover:border-[#F0DFA8] hover:text-[#FBF6E9] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#F0DFA8] rounded-sm"
293
+ >
294
+ returns@oshunt.com
295
+ </a>{" "}
296
+ or visit our{" "}
297
+ <span className="rounded bg-[#B9862E]/25 px-1.5 py-0.5">
298
+ [Contact Us page]
299
+ </span>
300
+ .
301
+ </p>
302
+ </CardContent>
303
+ </Card>
304
+ </Reveal>
305
+ </main>
306
+
307
+ <footer className="relative px-6 pb-10 pt-7 text-center text-[12.5px] text-[#4C5B57]">
308
+ This page is a template and should be reviewed against your actual
309
+ shipping, fulfillment, and local consumer-protection requirements
310
+ before publishing. It is not legal advice.
311
+ </footer>
312
+ </div>
313
+ );
314
+ }
315
+
316
+ function PolicySection({
317
+ id,
318
+ index,
319
+ title,
320
+ children,
321
+ }: {
322
+ id: string;
323
+ index: string;
324
+ title: string;
325
+ children: ReactNode;
326
+ }) {
327
+ return (
328
+ <section id={id} className="mb-11 scroll-mt-8">
329
+ <h2 className="mb-3.5 flex items-baseline gap-2.5 font-serif text-xl font-medium text-[#153F3A]">
330
+ <span className="font-sans text-sm font-semibold text-[#B9862E]">
331
+ {index}
332
+ </span>
333
+ {title}
334
+ </h2>
335
+ <div className="space-y-3 text-[15.5px] leading-relaxed text-[#4C5B57]">
336
+ {children}
337
+ </div>
338
+ </section>
339
+ );
340
+ }
@@ -0,0 +1,6 @@
1
+ import NextAuth from "next-auth";
2
+ import { authOptions } from ".lib/auth";
3
+
4
+ const handler = NextAuth(authOptions);
5
+
6
+ export { handler as GET, handler as POST };
@@ -0,0 +1,57 @@
1
+ import { GoogleGenerativeAI } from "@google/generative-ai";
2
+ import { NextResponse } from "next/server";
3
+
4
+ // Initialize the Gemini Engine
5
+ const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY || "");
6
+
7
+ export async function POST(req: Request) {
8
+ try {
9
+ // 1. Grab the user's prompt and chosen stack from the frontend
10
+ const body = await req.json();
11
+ const { prompt, stack } = body;
12
+
13
+ if (!prompt) {
14
+ return NextResponse.json({ error: "Prompt is required" }, { status: 400 });
15
+ }
16
+
17
+ // 2. Configure Gemini to guarantee a strict JSON response
18
+ const model = genAI.getGenerativeModel({
19
+ model: "gemini-2.5-flash",
20
+ generationConfig: { responseMimeType: "application/json" }
21
+ });
22
+
23
+ // 3. The Master System Architect Prompt
24
+ const systemInstruction = `
25
+ You are Spine, an elite backend architect.
26
+ The user wants to build this application: "${prompt}"
27
+ They have selected this base stack: ${stack}
28
+
29
+ Your job is to analyze the prompt and generate the custom backend logic needed for this app.
30
+ Return ONLY valid JSON with this exact structure:
31
+ {
32
+ "schemaCode": "// prisma/schema.prisma\\n// Write the complete Prisma schema models here...",
33
+ "apiRoutes": [
34
+ {
35
+ "folderPath": "the-name-of-the-route-folder",
36
+ "code": "// src/app/api/folder-name/route.ts\\n// Write the full GET/POST controllers here..."
37
+ }
38
+ ],
39
+ "readme": "# Custom Architecture Blueprint\\n// Write a short explanation of what you built..."
40
+ }
41
+ `;
42
+
43
+ // 4. Send to Gemini and parse the result
44
+ const result = await model.generateContent(systemInstruction);
45
+ const text = result.response.text();
46
+ const blueprint = JSON.parse(text);
47
+
48
+ return NextResponse.json({ success: true, blueprint });
49
+
50
+ } catch (error) {
51
+ console.error("Gemini API Error:", error);
52
+ return NextResponse.json(
53
+ { success: false, error: "Failed to generate architecture." },
54
+ { status: 500 }
55
+ );
56
+ }
57
+ }