create-lacspace-app 1.9.0 → 1.10.0
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 +215 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -174,6 +174,23 @@ body {
|
|
|
174
174
|
/* indeterminate progress bar (used by the "under development" pages) */
|
|
175
175
|
@keyframes loadbar { 0% { transform: translateX(-120%); } 100% { transform: translateX(340%); } }
|
|
176
176
|
|
|
177
|
+
/* ambient motion for illustrations & the aurora background */
|
|
178
|
+
@keyframes floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-16px); } }
|
|
179
|
+
@keyframes spin-slow { to { transform: rotate(360deg); } }
|
|
180
|
+
@keyframes gradient-pan { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
|
|
181
|
+
@keyframes marquee-x { from { transform: translateX(0); } to { transform: translateX(-50%); } }
|
|
182
|
+
.animate-floaty { animation: floaty 6s ease-in-out infinite; }
|
|
183
|
+
.animate-floaty-slow { animation: floaty 9s ease-in-out infinite; }
|
|
184
|
+
.animate-spin-slow { animation: spin-slow 26s linear infinite; }
|
|
185
|
+
.gradient-text-animated {
|
|
186
|
+
background: linear-gradient(120deg, var(--accent-from), var(--accent-to), var(--accent-from));
|
|
187
|
+
background-size: 200% 200%;
|
|
188
|
+
-webkit-background-clip: text; background-clip: text; color: transparent;
|
|
189
|
+
animation: gradient-pan 6s ease infinite;
|
|
190
|
+
}
|
|
191
|
+
.marquee-track { display: flex; width: max-content; animation: marquee-x 32s linear infinite; }
|
|
192
|
+
.marquee-mask { -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
|
|
193
|
+
|
|
177
194
|
/* soft entrance for content */
|
|
178
195
|
@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
|
|
179
196
|
main > section, main > * { animation: rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) both; }
|
|
@@ -407,14 +424,21 @@ function homePage(ctx) {
|
|
|
407
424
|
if (ctx.template.key === "dashboard") return dashboardHome(ctx);
|
|
408
425
|
const shell = (inner) => `import { site } from "@/lib/site";
|
|
409
426
|
import { LiveStats } from "@/components/live-stats";
|
|
427
|
+
import { Aurora } from "@/components/aurora";
|
|
428
|
+
import { HeroArt } from "@/components/hero-art";
|
|
410
429
|
|
|
411
430
|
// \u2728 Self-canonical home page \u2014 one line, full SEO (title, canonical, OG, Twitter).
|
|
412
431
|
export const metadata = site.meta({ title: ${JSON.stringify(n)}, path: "/" });
|
|
413
432
|
|
|
414
433
|
export default function Home() {
|
|
415
434
|
return (
|
|
416
|
-
<main className="min-h-screen">
|
|
435
|
+
<main className="relative min-h-screen overflow-hidden">
|
|
436
|
+
{/* \u2728 Animated, theme-aware gradient backdrop */}
|
|
437
|
+
<Aurora />
|
|
417
438
|
${inner}
|
|
439
|
+
${showcaseSection(ctx)}
|
|
440
|
+
${marqueeSection(ctx)}
|
|
441
|
+
${faqSection(ctx)}
|
|
418
442
|
${builtWithSection(ctx)}
|
|
419
443
|
</main>
|
|
420
444
|
);
|
|
@@ -1433,6 +1457,8 @@ function buildFiles(ctx) {
|
|
|
1433
1457
|
files["components/site-header.tsx"] = siteHeader(ctx);
|
|
1434
1458
|
files["components/site-footer.tsx"] = siteFooter(ctx);
|
|
1435
1459
|
files["components/announcement-bar.tsx"] = announcementBar();
|
|
1460
|
+
files["components/aurora.tsx"] = aurora();
|
|
1461
|
+
files["components/hero-art.tsx"] = heroArt(ctx);
|
|
1436
1462
|
}
|
|
1437
1463
|
for (const page of stubPages(ctx)) {
|
|
1438
1464
|
files[`app${page.path}/page.tsx`] = isDash ? dashboardStubPage(page) : underDevPage(page);
|
|
@@ -2302,6 +2328,194 @@ function realPageFiles(ctx) {
|
|
|
2302
2328
|
}
|
|
2303
2329
|
return f;
|
|
2304
2330
|
}
|
|
2331
|
+
function creativeData(ctx) {
|
|
2332
|
+
const n = ctx.template.siteName;
|
|
2333
|
+
const map = {
|
|
2334
|
+
personal: {
|
|
2335
|
+
emoji: "\u{1F44B}",
|
|
2336
|
+
chips: ["Design", "Code", "Ship"],
|
|
2337
|
+
showcaseTitle: "Design & build, end to end",
|
|
2338
|
+
showcaseLead: `${n} turns ideas into polished products \u2014 from the first sketch to the last pixel.`,
|
|
2339
|
+
bullets: ["10+ years shipping web & mobile", "Design systems that scale", "Obsessed with the details"],
|
|
2340
|
+
marqueeLabel: "Worked with",
|
|
2341
|
+
marquee: ["Aurora", "Northwind", "Lumen", "Harbor", "Cadence", "Meadow"],
|
|
2342
|
+
faq: [
|
|
2343
|
+
{ q: "Are you available for freelance?", a: "Yes \u2014 I take on a couple of projects each quarter. Reach out via the contact page." },
|
|
2344
|
+
{ q: "What do you work with?", a: "React, Next.js and TypeScript, with a lot of care for UX and performance." },
|
|
2345
|
+
{ q: "Do you do both design and development?", a: "Both \u2014 I can take a project from concept all the way to production." }
|
|
2346
|
+
]
|
|
2347
|
+
},
|
|
2348
|
+
business: {
|
|
2349
|
+
emoji: "\u{1F3E2}",
|
|
2350
|
+
chips: ["Strategy", "Design", "Launch"],
|
|
2351
|
+
showcaseTitle: "Everything you need to grow",
|
|
2352
|
+
showcaseLead: `${n} partners with you from strategy to launch \u2014 one senior team, accountable for outcomes.`,
|
|
2353
|
+
bullets: ["Senior team, no hand-offs", "Fixed timelines & clear pricing", "We sweat the details"],
|
|
2354
|
+
marqueeLabel: "Trusted by teams at",
|
|
2355
|
+
marquee: ["Northwind", "Globex", "Initech", "Umbrella", "Soylent", "Hooli"],
|
|
2356
|
+
faq: [
|
|
2357
|
+
{ q: "How do engagements work?", a: "We scope a clear plan, agree a fixed timeline, and ship in weekly increments." },
|
|
2358
|
+
{ q: "What does it cost?", a: "See our pricing page for plans, or contact us for a custom quote." },
|
|
2359
|
+
{ q: "How soon can we start?", a: "Usually within two weeks. Get in touch to check availability." }
|
|
2360
|
+
]
|
|
2361
|
+
},
|
|
2362
|
+
ecommerce: {
|
|
2363
|
+
emoji: "\u{1F6CD}\uFE0F",
|
|
2364
|
+
chips: ["Shop", "Bag", "Checkout"],
|
|
2365
|
+
showcaseTitle: "Thoughtfully made, delivered fast",
|
|
2366
|
+
showcaseLead: `${n} curates beautiful things and ships them worldwide \u2014 with easy returns, always.`,
|
|
2367
|
+
bullets: ["Free worldwide shipping", "30-day easy returns", "Sustainably sourced"],
|
|
2368
|
+
marqueeLabel: "Why shop with us",
|
|
2369
|
+
marquee: ["Free shipping", "Easy returns", "Secure checkout", "Ethically made", "Gift wrapping", "Loved by 10k+"],
|
|
2370
|
+
faq: [
|
|
2371
|
+
{ q: "How long is shipping?", a: "Most orders arrive in 3\u20135 business days with free worldwide shipping." },
|
|
2372
|
+
{ q: "What's your return policy?", a: "30 days, no questions asked \u2014 see the returns page for details." },
|
|
2373
|
+
{ q: "Is checkout secure?", a: "Yes \u2014 payments are encrypted and we never store your card details." }
|
|
2374
|
+
]
|
|
2375
|
+
},
|
|
2376
|
+
saas: {
|
|
2377
|
+
emoji: "\u26A1",
|
|
2378
|
+
chips: ["Analytics", "Billing", "API"],
|
|
2379
|
+
showcaseTitle: "The platform your team will love",
|
|
2380
|
+
showcaseLead: `${n} brings analytics, billing and automation into one fast, secure place.`,
|
|
2381
|
+
bullets: ["Set up in minutes", "SOC 2-ready security", "Scales with you"],
|
|
2382
|
+
marqueeLabel: "Powering teams at",
|
|
2383
|
+
marquee: ["Globex", "Initech", "Hooli", "Pied Piper", "Umbrella", "Stark"],
|
|
2384
|
+
faq: [
|
|
2385
|
+
{ q: "Is there a free plan?", a: "Yes \u2014 start free and upgrade when you're ready. See the pricing page." },
|
|
2386
|
+
{ q: "How is my data secured?", a: "Encryption in transit and at rest, audit logs, and SSO on higher plans." },
|
|
2387
|
+
{ q: "Can I self-host?", a: "Contact sales \u2014 we offer flexible deployment options." }
|
|
2388
|
+
]
|
|
2389
|
+
},
|
|
2390
|
+
blog: {
|
|
2391
|
+
emoji: "\u270D\uFE0F",
|
|
2392
|
+
chips: ["Essays", "Notes", "Stories"],
|
|
2393
|
+
showcaseTitle: "Words worth your time",
|
|
2394
|
+
showcaseLead: `${n} publishes essays and notes on building things that matter \u2014 no fluff.`,
|
|
2395
|
+
bullets: ["New pieces most weeks", "No clickbait, ever", "Written by practitioners"],
|
|
2396
|
+
marqueeLabel: "Topics we cover",
|
|
2397
|
+
marquee: ["Engineering", "Design", "Product", "Culture", "Tutorials", "Announcements"],
|
|
2398
|
+
faq: [
|
|
2399
|
+
{ q: "How often do you publish?", a: "A new piece most weeks \u2014 subscribe so you never miss one." },
|
|
2400
|
+
{ q: "Can I contribute?", a: "We love guest posts. Pitch us via the contact page." },
|
|
2401
|
+
{ q: "Is there a newsletter?", a: "Yes \u2014 head to the newsletter page to join." }
|
|
2402
|
+
]
|
|
2403
|
+
},
|
|
2404
|
+
docs: {
|
|
2405
|
+
emoji: "\u{1F4DA}",
|
|
2406
|
+
chips: ["Guides", "API", "Examples"],
|
|
2407
|
+
showcaseTitle: "Everything you need to build",
|
|
2408
|
+
showcaseLead: `${n} gives you guides, API references and copy-paste examples \u2014 all in one place.`,
|
|
2409
|
+
bullets: ["Quickstart in 5 minutes", "Searchable & versioned", "Real, runnable examples"],
|
|
2410
|
+
marqueeLabel: "What you'll find",
|
|
2411
|
+
marquee: ["Quickstart", "Guides", "API reference", "Examples", "Migrations", "Troubleshooting"],
|
|
2412
|
+
faq: [
|
|
2413
|
+
{ q: "Where do I start?", a: "Head to the guides for a 5-minute quickstart." },
|
|
2414
|
+
{ q: "Is there an API reference?", a: "Yes \u2014 the API page has the full reference." },
|
|
2415
|
+
{ q: "How do I report a docs issue?", a: "Use the contact page \u2014 we fix docs fast." }
|
|
2416
|
+
]
|
|
2417
|
+
},
|
|
2418
|
+
restaurant: {
|
|
2419
|
+
emoji: "\u{1F377}",
|
|
2420
|
+
chips: ["Menu", "Wine", "Reserve"],
|
|
2421
|
+
showcaseTitle: "Seasonal plates, natural wine",
|
|
2422
|
+
showcaseLead: `${n} serves ingredient-led plates and natural wine in a warm, low-lit room.`,
|
|
2423
|
+
bullets: ["Menu changes with the seasons", "Natural, low-intervention wine", "Walk-ins welcome"],
|
|
2424
|
+
marqueeLabel: "On the pass",
|
|
2425
|
+
marquee: ["Wood-fired", "Local produce", "Natural wine", "House-made pasta", "Seasonal", "Fresh sourdough"],
|
|
2426
|
+
faq: [
|
|
2427
|
+
{ q: "Do you take reservations?", a: "Yes \u2014 book via the reservations page. Walk-ins are welcome too." },
|
|
2428
|
+
{ q: "Any dietary options?", a: "Plenty \u2014 vegetarian and vegan plates change weekly. Just ask about allergies." },
|
|
2429
|
+
{ q: "When are you open?", a: "Wednesday to Sunday, 5pm till late." }
|
|
2430
|
+
]
|
|
2431
|
+
}
|
|
2432
|
+
};
|
|
2433
|
+
return map[ctx.template.key] ?? map.business;
|
|
2434
|
+
}
|
|
2435
|
+
var aurora = () => `export function Aurora() {
|
|
2436
|
+
return (
|
|
2437
|
+
<div aria-hidden className="pointer-events-none absolute inset-x-0 top-0 -z-10 h-[720px] overflow-hidden">
|
|
2438
|
+
<div className="absolute -left-20 -top-16 h-96 w-96 rounded-full opacity-30 blur-3xl animate-floaty" style={{ background: "radial-gradient(circle, var(--accent-from), transparent 70%)" }} />
|
|
2439
|
+
<div className="absolute -right-10 top-40 h-80 w-80 rounded-full opacity-25 blur-3xl animate-floaty-slow" style={{ background: "radial-gradient(circle, var(--accent-to), transparent 70%)" }} />
|
|
2440
|
+
<div className="absolute left-1/3 top-72 h-72 w-72 rounded-full opacity-20 blur-3xl animate-floaty" style={{ background: "radial-gradient(circle, var(--accent-to), transparent 70%)" }} />
|
|
2441
|
+
</div>
|
|
2442
|
+
);
|
|
2443
|
+
}
|
|
2444
|
+
`;
|
|
2445
|
+
var heroArt = (ctx) => {
|
|
2446
|
+
const d = creativeData(ctx);
|
|
2447
|
+
const initials = ctx.template.siteName.trim().split(/\s+/).slice(0, 2).map((w) => (w[0] ?? "").toUpperCase()).join("") || "A";
|
|
2448
|
+
return `export function HeroArt() {
|
|
2449
|
+
return (
|
|
2450
|
+
<div className="relative mx-auto aspect-square w-full max-w-sm select-none">
|
|
2451
|
+
{/* orbiting rings */}
|
|
2452
|
+
<div className="absolute inset-0 rounded-full border border-hairline animate-spin-slow" />
|
|
2453
|
+
<div className="absolute inset-10 rounded-full border border-hairline animate-spin-slow" style={{ animationDirection: "reverse" }} />
|
|
2454
|
+
<div className="absolute inset-0 rounded-full opacity-40 blur-2xl gradient-bg" />
|
|
2455
|
+
{/* center badge with the platform initials */}
|
|
2456
|
+
<div className="absolute left-1/2 top-1/2 flex h-28 w-28 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-3xl gradient-bg text-4xl font-black text-black shadow-2xl animate-floaty">
|
|
2457
|
+
${JSON.stringify(initials)}
|
|
2458
|
+
</div>
|
|
2459
|
+
{/* floating labels */}
|
|
2460
|
+
<div className="absolute left-0 top-10 flex items-center gap-2 rounded-xl border border-hairline bg-app px-3 py-2 text-xs font-medium shadow-lg animate-floaty">
|
|
2461
|
+
<span>${d.emoji}</span> ${JSON.stringify(d.chips[0])}
|
|
2462
|
+
</div>
|
|
2463
|
+
<div className="absolute right-0 top-28 rounded-xl border border-hairline bg-app px-3 py-2 text-xs font-medium shadow-lg animate-floaty-slow">
|
|
2464
|
+
${JSON.stringify(d.chips[1])}
|
|
2465
|
+
</div>
|
|
2466
|
+
<div className="absolute bottom-8 left-6 rounded-xl border border-hairline bg-app px-3 py-2 text-xs font-medium shadow-lg animate-floaty" style={{ animationDelay: "1.2s" }}>
|
|
2467
|
+
${JSON.stringify(d.chips[2])}
|
|
2468
|
+
</div>
|
|
2469
|
+
</div>
|
|
2470
|
+
);
|
|
2471
|
+
}
|
|
2472
|
+
`;
|
|
2473
|
+
};
|
|
2474
|
+
var showcaseSection = (ctx) => {
|
|
2475
|
+
const d = creativeData(ctx);
|
|
2476
|
+
const bullets = d.bullets.map((b) => `<li className="flex items-center gap-2 text-muted"><span className="text-[color:var(--accent-to)]">\u2713</span> ${b}</li>`).join("\n ");
|
|
2477
|
+
return `<section className="mx-auto grid max-w-6xl items-center gap-12 px-6 py-20 md:grid-cols-2">
|
|
2478
|
+
<div>
|
|
2479
|
+
<p className="text-sm font-semibold uppercase tracking-widest text-faint">${ctx.template.siteName}</p>
|
|
2480
|
+
<h2 className="mt-3 text-3xl font-bold sm:text-4xl">${d.showcaseTitle}</h2>
|
|
2481
|
+
<p className="mt-4 max-w-md text-lg text-muted">${d.showcaseLead}</p>
|
|
2482
|
+
<ul className="mt-6 space-y-3 text-sm">
|
|
2483
|
+
${bullets}
|
|
2484
|
+
</ul>
|
|
2485
|
+
</div>
|
|
2486
|
+
<HeroArt />
|
|
2487
|
+
</section>`;
|
|
2488
|
+
};
|
|
2489
|
+
var marqueeSection = (ctx) => {
|
|
2490
|
+
const d = creativeData(ctx);
|
|
2491
|
+
const chip = (t) => `<span className="rounded-full border border-hairline bg-surface px-5 py-2 text-sm font-medium text-muted">${t}</span>`;
|
|
2492
|
+
const track = d.marquee.map(chip).join("\n ");
|
|
2493
|
+
return `<section className="border-y border-hairline py-10">
|
|
2494
|
+
<p className="mb-6 text-center text-xs font-semibold uppercase tracking-widest text-faint">${d.marqueeLabel}</p>
|
|
2495
|
+
<div className="marquee-mask overflow-hidden">
|
|
2496
|
+
<div className="marquee-track gap-4">
|
|
2497
|
+
${track}
|
|
2498
|
+
${track}
|
|
2499
|
+
</div>
|
|
2500
|
+
</div>
|
|
2501
|
+
</section>`;
|
|
2502
|
+
};
|
|
2503
|
+
var faqSection = (ctx) => {
|
|
2504
|
+
const d = creativeData(ctx);
|
|
2505
|
+
const items = d.faq.map((f) => `<details className="group rounded-2xl border border-hairline bg-surface p-5">
|
|
2506
|
+
<summary className="flex cursor-pointer list-none items-center justify-between gap-4 font-medium">
|
|
2507
|
+
${f.q}
|
|
2508
|
+
<span className="text-muted transition group-open:rotate-45">+</span>
|
|
2509
|
+
</summary>
|
|
2510
|
+
<p className="mt-3 text-sm leading-relaxed text-muted">${f.a}</p>
|
|
2511
|
+
</details>`).join("\n ");
|
|
2512
|
+
return `<section className="mx-auto max-w-3xl px-6 py-20">
|
|
2513
|
+
<h2 className="text-center text-3xl font-bold">Frequently asked</h2>
|
|
2514
|
+
<div className="mt-10 space-y-3">
|
|
2515
|
+
${items}
|
|
2516
|
+
</div>
|
|
2517
|
+
</section>`;
|
|
2518
|
+
};
|
|
2305
2519
|
function parseArgs(list) {
|
|
2306
2520
|
const a = { yes: false, install: true, git: true, pm: "npm", help: false };
|
|
2307
2521
|
for (let i = 0; i < list.length; i++) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-lacspace-app",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Scaffold a beautiful, production-ready Next.js app from a Lacspace template — portfolio, business, e-commerce, SaaS, blog, docs, dashboard or restaurant — pre-wired with SEO, security headers, sitemap and robots. Like create-next-app, but you start gorgeous.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|