@pylonsync/create-pylon 0.3.274 → 0.3.276
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/bin/create-pylon.js +80 -0
- package/package.json +1 -1
- package/templates/ARCHETYPES.md +339 -0
- package/templates/agency/.env.example +12 -0
- package/templates/agency/AGENTS.md +61 -0
- package/templates/agency/README.md +90 -0
- package/templates/agency/app/auth-form.tsx +129 -0
- package/templates/agency/app/contact-form.tsx +258 -0
- package/templates/agency/app/dashboard/dashboard-client.tsx +1440 -0
- package/templates/agency/app/dashboard/page.tsx +70 -0
- package/templates/agency/app/error.tsx +26 -0
- package/templates/agency/app/globals.css +148 -0
- package/templates/agency/app/layout.tsx +174 -0
- package/templates/agency/app/login/page.tsx +39 -0
- package/templates/agency/app/not-found.tsx +19 -0
- package/templates/agency/app/page.tsx +249 -0
- package/templates/agency/app/robots.ts +12 -0
- package/templates/agency/app/seeder.tsx +26 -0
- package/templates/agency/app/sitemap.ts +9 -0
- package/templates/agency/app/work/[slug]/page.tsx +182 -0
- package/templates/agency/app/work/page.tsx +83 -0
- package/templates/agency/app.ts +284 -0
- package/templates/agency/components/marketing.tsx +187 -0
- package/templates/agency/components/section-scroller.tsx +35 -0
- package/templates/agency/components/ui/button.tsx +56 -0
- package/templates/agency/components/ui/card.tsx +90 -0
- package/templates/agency/components.json +20 -0
- package/templates/agency/functions/bookInquiry.ts +42 -0
- package/templates/agency/functions/clientsForOwner.ts +27 -0
- package/templates/agency/functions/declineInquiry.ts +41 -0
- package/templates/agency/functions/deleteClient.ts +27 -0
- package/templates/agency/functions/deleteInvoice.ts +19 -0
- package/templates/agency/functions/deleteProject.ts +20 -0
- package/templates/agency/functions/inquiriesForOwner.ts +31 -0
- package/templates/agency/functions/invoicesForOwner.ts +27 -0
- package/templates/agency/functions/seedCapacity.ts +26 -0
- package/templates/agency/functions/seedProjects.ts +41 -0
- package/templates/agency/functions/seedStudioBackoffice.ts +74 -0
- package/templates/agency/functions/setCapacity.ts +32 -0
- package/templates/agency/functions/setInvoiceStatus.ts +27 -0
- package/templates/agency/functions/setProjectFlags.ts +35 -0
- package/templates/agency/functions/submitInquiry.ts +55 -0
- package/templates/agency/functions/upsertClient.ts +73 -0
- package/templates/agency/functions/upsertInvoice.ts +113 -0
- package/templates/agency/functions/upsertProject.ts +97 -0
- package/templates/agency/gitignore +10 -0
- package/templates/agency/lib/agency.ts +189 -0
- package/templates/agency/lib/invoice-pdf.tsx +174 -0
- package/templates/agency/lib/owner.ts +26 -0
- package/templates/agency/lib/site.config.ts +418 -0
- package/templates/agency/lib/utils.ts +10 -0
- package/templates/agency/package.json +35 -0
- package/templates/agency/tsconfig.json +18 -0
- package/templates/ai-chat/.env.example +33 -0
- package/templates/ai-chat/AGENTS.md +61 -0
- package/templates/ai-chat/README.md +99 -0
- package/templates/ai-chat/app/auth-form.tsx +124 -0
- package/templates/ai-chat/app/chat-client.tsx +727 -0
- package/templates/ai-chat/app/error.tsx +26 -0
- package/templates/ai-chat/app/globals.css +148 -0
- package/templates/ai-chat/app/layout.tsx +75 -0
- package/templates/ai-chat/app/login/page.tsx +39 -0
- package/templates/ai-chat/app/not-found.tsx +19 -0
- package/templates/ai-chat/app/page.tsx +23 -0
- package/templates/ai-chat/app.ts +121 -0
- package/templates/ai-chat/components.json +20 -0
- package/templates/ai-chat/functions/deleteConversation.ts +33 -0
- package/templates/ai-chat/gitignore +10 -0
- package/templates/ai-chat/lib/site.config.ts +103 -0
- package/templates/ai-chat/lib/utils.ts +10 -0
- package/templates/ai-chat/package.json +34 -0
- package/templates/ai-chat/tsconfig.json +18 -0
- package/templates/ai-studio/.env.example +19 -0
- package/templates/ai-studio/AGENTS.md +61 -0
- package/templates/ai-studio/README.md +83 -0
- package/templates/ai-studio/app/auth-form.tsx +124 -0
- package/templates/ai-studio/app/error.tsx +26 -0
- package/templates/ai-studio/app/globals.css +148 -0
- package/templates/ai-studio/app/layout.tsx +75 -0
- package/templates/ai-studio/app/login/page.tsx +39 -0
- package/templates/ai-studio/app/not-found.tsx +19 -0
- package/templates/ai-studio/app/page.tsx +34 -0
- package/templates/ai-studio/app/studio-client.tsx +357 -0
- package/templates/ai-studio/app.ts +108 -0
- package/templates/ai-studio/components.json +20 -0
- package/templates/ai-studio/functions/_getGeneration.ts +25 -0
- package/templates/ai-studio/functions/_updateGeneration.ts +37 -0
- package/templates/ai-studio/functions/generate.ts +42 -0
- package/templates/ai-studio/functions/pollGeneration.ts +134 -0
- package/templates/ai-studio/gitignore +10 -0
- package/templates/ai-studio/lib/site.config.ts +80 -0
- package/templates/ai-studio/lib/studio.ts +52 -0
- package/templates/ai-studio/lib/utils.ts +10 -0
- package/templates/ai-studio/package.json +34 -0
- package/templates/ai-studio/tsconfig.json +18 -0
- package/templates/creator/.env.example +12 -0
- package/templates/creator/AGENTS.md +61 -0
- package/templates/creator/README.md +67 -0
- package/templates/creator/app/auth-form.tsx +129 -0
- package/templates/creator/app/dashboard/dashboard-client.tsx +297 -0
- package/templates/creator/app/dashboard/page.tsx +70 -0
- package/templates/creator/app/error.tsx +26 -0
- package/templates/creator/app/globals.css +148 -0
- package/templates/creator/app/layout.tsx +160 -0
- package/templates/creator/app/login/page.tsx +39 -0
- package/templates/creator/app/newsletter-signup.tsx +162 -0
- package/templates/creator/app/not-found.tsx +19 -0
- package/templates/creator/app/page.tsx +160 -0
- package/templates/creator/app/robots.ts +12 -0
- package/templates/creator/app/sitemap.ts +9 -0
- package/templates/creator/app.ts +134 -0
- package/templates/creator/components/marketing.tsx +148 -0
- package/templates/creator/components/section-scroller.tsx +35 -0
- package/templates/creator/components/ui/button.tsx +56 -0
- package/templates/creator/components/ui/card.tsx +90 -0
- package/templates/creator/components.json +20 -0
- package/templates/creator/functions/subscribe.ts +82 -0
- package/templates/creator/functions/subscriberStats.ts +75 -0
- package/templates/creator/gitignore +10 -0
- package/templates/creator/lib/owner.ts +26 -0
- package/templates/creator/lib/site.config.ts +173 -0
- package/templates/creator/lib/stats.ts +30 -0
- package/templates/creator/lib/utils.ts +10 -0
- package/templates/creator/package.json +34 -0
- package/templates/creator/tsconfig.json +18 -0
- package/templates/default/app/layout.tsx +26 -27
- package/templates/default/app/page.tsx +90 -274
- package/templates/default/lib/products.ts +9 -122
- package/templates/default/lib/site.config.ts +739 -0
- package/templates/default/lib/site.ts +14 -261
- package/templates/directory/.env.example +12 -0
- package/templates/directory/AGENTS.md +61 -0
- package/templates/directory/README.md +80 -0
- package/templates/directory/app/auth-form.tsx +129 -0
- package/templates/directory/app/dashboard/dashboard-client.tsx +205 -0
- package/templates/directory/app/dashboard/page.tsx +70 -0
- package/templates/directory/app/directory-browse.tsx +328 -0
- package/templates/directory/app/error.tsx +26 -0
- package/templates/directory/app/globals.css +148 -0
- package/templates/directory/app/layout.tsx +171 -0
- package/templates/directory/app/login/page.tsx +39 -0
- package/templates/directory/app/not-found.tsx +19 -0
- package/templates/directory/app/page.tsx +50 -0
- package/templates/directory/app/robots.ts +12 -0
- package/templates/directory/app/sitemap.ts +9 -0
- package/templates/directory/app/submit/page.tsx +30 -0
- package/templates/directory/app/submit-form.tsx +151 -0
- package/templates/directory/app.ts +146 -0
- package/templates/directory/components/marketing.tsx +148 -0
- package/templates/directory/components/section-scroller.tsx +35 -0
- package/templates/directory/components/ui/button.tsx +56 -0
- package/templates/directory/components/ui/card.tsx +90 -0
- package/templates/directory/components.json +20 -0
- package/templates/directory/functions/approveSubmission.ts +45 -0
- package/templates/directory/functions/rejectSubmission.ts +20 -0
- package/templates/directory/functions/seedListings.ts +33 -0
- package/templates/directory/functions/submissionsForOwner.ts +29 -0
- package/templates/directory/functions/submitListing.ts +63 -0
- package/templates/directory/functions/upvote.ts +24 -0
- package/templates/directory/gitignore +10 -0
- package/templates/directory/lib/directory.ts +45 -0
- package/templates/directory/lib/owner.ts +26 -0
- package/templates/directory/lib/site.config.ts +130 -0
- package/templates/directory/lib/utils.ts +10 -0
- package/templates/directory/package.json +34 -0
- package/templates/directory/tsconfig.json +18 -0
- package/templates/local-service/.env.example +12 -0
- package/templates/local-service/AGENTS.md +61 -0
- package/templates/local-service/README.md +82 -0
- package/templates/local-service/app/auth-form.tsx +129 -0
- package/templates/local-service/app/booking-widget.tsx +399 -0
- package/templates/local-service/app/dashboard/dashboard-client.tsx +304 -0
- package/templates/local-service/app/dashboard/page.tsx +63 -0
- package/templates/local-service/app/error.tsx +26 -0
- package/templates/local-service/app/globals.css +148 -0
- package/templates/local-service/app/layout.tsx +151 -0
- package/templates/local-service/app/login/page.tsx +39 -0
- package/templates/local-service/app/not-found.tsx +19 -0
- package/templates/local-service/app/page.tsx +233 -0
- package/templates/local-service/app/robots.ts +12 -0
- package/templates/local-service/app/sitemap.ts +9 -0
- package/templates/local-service/app.ts +131 -0
- package/templates/local-service/components/marketing.tsx +162 -0
- package/templates/local-service/components/section-scroller.tsx +35 -0
- package/templates/local-service/components/ui/button.tsx +56 -0
- package/templates/local-service/components/ui/card.tsx +90 -0
- package/templates/local-service/components.json +20 -0
- package/templates/local-service/functions/bookingsForOwner.ts +30 -0
- package/templates/local-service/functions/cancelBooking.ts +27 -0
- package/templates/local-service/functions/confirmBooking.ts +18 -0
- package/templates/local-service/functions/createBooking.ts +98 -0
- package/templates/local-service/gitignore +10 -0
- package/templates/local-service/lib/booking.ts +24 -0
- package/templates/local-service/lib/owner.ts +26 -0
- package/templates/local-service/lib/site.config.ts +232 -0
- package/templates/local-service/lib/slots.ts +97 -0
- package/templates/local-service/lib/utils.ts +10 -0
- package/templates/local-service/package.json +34 -0
- package/templates/local-service/tsconfig.json +18 -0
- package/templates/marketplace/.env.example +9 -0
- package/templates/marketplace/AGENTS.md +61 -0
- package/templates/marketplace/README.md +78 -0
- package/templates/marketplace/app/_components/CategoryIcon.tsx +40 -0
- package/templates/marketplace/app/error.tsx +26 -0
- package/templates/marketplace/app/globals.css +64 -0
- package/templates/marketplace/app/layout.tsx +60 -0
- package/templates/marketplace/app/listing/[id]/page.tsx +163 -0
- package/templates/marketplace/app/me/page.tsx +15 -0
- package/templates/marketplace/app/not-found.tsx +20 -0
- package/templates/marketplace/app/page.tsx +159 -0
- package/templates/marketplace/app/robots.ts +12 -0
- package/templates/marketplace/app/sell/page.tsx +26 -0
- package/templates/marketplace/app/sitemap.ts +14 -0
- package/templates/marketplace/app.ts +190 -0
- package/templates/marketplace/client/AuthNav.tsx +46 -0
- package/templates/marketplace/client/LiveTicker.tsx +104 -0
- package/templates/marketplace/client/LoginCard.tsx +130 -0
- package/templates/marketplace/client/MarketProvider.tsx +148 -0
- package/templates/marketplace/client/MyMarket.tsx +180 -0
- package/templates/marketplace/client/OfferPanel.tsx +355 -0
- package/templates/marketplace/client/SeedOnEmpty.tsx +26 -0
- package/templates/marketplace/client/SellForm.tsx +160 -0
- package/templates/marketplace/client/WatchButton.tsx +88 -0
- package/templates/marketplace/client/market.ts +341 -0
- package/templates/marketplace/functions/buyNow.ts +78 -0
- package/templates/marketplace/functions/makeOffer.ts +65 -0
- package/templates/marketplace/functions/respondToOffer.ts +62 -0
- package/templates/marketplace/functions/seedMarket.ts +90 -0
- package/templates/marketplace/gitignore +10 -0
- package/templates/marketplace/package.json +35 -0
- package/templates/marketplace/tsconfig.json +14 -0
- package/templates/marketplace/ui/badge.tsx +30 -0
- package/templates/marketplace/ui/button.tsx +49 -0
- package/templates/marketplace/ui/card.tsx +48 -0
- package/templates/marketplace/ui/input.tsx +17 -0
- package/templates/marketplace/ui/label.tsx +18 -0
- package/templates/marketplace/ui/textarea.tsx +17 -0
- package/templates/marketplace/ui/tokens.css +32 -0
- package/templates/marketplace/ui/utils.ts +6 -0
- package/templates/restaurant/.env.example +12 -0
- package/templates/restaurant/AGENTS.md +61 -0
- package/templates/restaurant/README.md +77 -0
- package/templates/restaurant/app/auth-form.tsx +129 -0
- package/templates/restaurant/app/dashboard/dashboard-client.tsx +263 -0
- package/templates/restaurant/app/dashboard/page.tsx +59 -0
- package/templates/restaurant/app/error.tsx +26 -0
- package/templates/restaurant/app/globals.css +148 -0
- package/templates/restaurant/app/layout.tsx +151 -0
- package/templates/restaurant/app/login/page.tsx +39 -0
- package/templates/restaurant/app/not-found.tsx +19 -0
- package/templates/restaurant/app/page.tsx +194 -0
- package/templates/restaurant/app/reservation-widget.tsx +359 -0
- package/templates/restaurant/app/robots.ts +12 -0
- package/templates/restaurant/app/sitemap.ts +9 -0
- package/templates/restaurant/app.ts +115 -0
- package/templates/restaurant/components/marketing.tsx +162 -0
- package/templates/restaurant/components/section-scroller.tsx +35 -0
- package/templates/restaurant/components/ui/button.tsx +56 -0
- package/templates/restaurant/components/ui/card.tsx +90 -0
- package/templates/restaurant/components.json +20 -0
- package/templates/restaurant/functions/cancelReservation.ts +26 -0
- package/templates/restaurant/functions/confirmReservation.ts +17 -0
- package/templates/restaurant/functions/createReservation.ts +92 -0
- package/templates/restaurant/functions/reservationsForOwner.ts +28 -0
- package/templates/restaurant/gitignore +10 -0
- package/templates/restaurant/lib/owner.ts +26 -0
- package/templates/restaurant/lib/reservation.ts +22 -0
- package/templates/restaurant/lib/site.config.ts +218 -0
- package/templates/restaurant/lib/slots.ts +55 -0
- package/templates/restaurant/lib/utils.ts +10 -0
- package/templates/restaurant/package.json +34 -0
- package/templates/restaurant/tsconfig.json +18 -0
- package/templates/shop/.env.example +32 -0
- package/templates/shop/AGENTS.md +61 -0
- package/templates/shop/README.md +102 -0
- package/templates/shop/app/auth-form.tsx +129 -0
- package/templates/shop/app/dashboard/dashboard-client.tsx +264 -0
- package/templates/shop/app/dashboard/page.tsx +59 -0
- package/templates/shop/app/error.tsx +26 -0
- package/templates/shop/app/globals.css +148 -0
- package/templates/shop/app/layout.tsx +160 -0
- package/templates/shop/app/login/page.tsx +39 -0
- package/templates/shop/app/not-found.tsx +19 -0
- package/templates/shop/app/page.tsx +95 -0
- package/templates/shop/app/robots.ts +12 -0
- package/templates/shop/app/shop-client.tsx +436 -0
- package/templates/shop/app/sitemap.ts +9 -0
- package/templates/shop/app/success/page.tsx +33 -0
- package/templates/shop/app.ts +134 -0
- package/templates/shop/components/marketing.tsx +96 -0
- package/templates/shop/components/section-scroller.tsx +35 -0
- package/templates/shop/components/ui/button.tsx +56 -0
- package/templates/shop/components/ui/card.tsx +90 -0
- package/templates/shop/components.json +20 -0
- package/templates/shop/functions/cancelOrder.ts +33 -0
- package/templates/shop/functions/checkout.ts +130 -0
- package/templates/shop/functions/fulfillOrder.ts +17 -0
- package/templates/shop/functions/markGroupPaid.ts +26 -0
- package/templates/shop/functions/ordersForOwner.ts +28 -0
- package/templates/shop/functions/releaseGroup.ts +36 -0
- package/templates/shop/functions/reserveCart.ts +87 -0
- package/templates/shop/functions/restockProduct.ts +23 -0
- package/templates/shop/functions/seedProducts.ts +30 -0
- package/templates/shop/functions/stripeWebhook.ts +72 -0
- package/templates/shop/gitignore +10 -0
- package/templates/shop/lib/owner.ts +26 -0
- package/templates/shop/lib/shop.ts +45 -0
- package/templates/shop/lib/site.config.ts +198 -0
- package/templates/shop/lib/utils.ts +10 -0
- package/templates/shop/package.json +35 -0
- package/templates/shop/tsconfig.json +18 -0
- package/templates/waitlist/.env.example +12 -0
- package/templates/waitlist/AGENTS.md +61 -0
- package/templates/waitlist/README.md +81 -0
- package/templates/waitlist/app/auth-form.tsx +129 -0
- package/templates/waitlist/app/dashboard/dashboard-client.tsx +297 -0
- package/templates/waitlist/app/dashboard/page.tsx +70 -0
- package/templates/waitlist/app/error.tsx +26 -0
- package/templates/waitlist/app/globals.css +148 -0
- package/templates/waitlist/app/layout.tsx +158 -0
- package/templates/waitlist/app/login/page.tsx +39 -0
- package/templates/waitlist/app/not-found.tsx +19 -0
- package/templates/waitlist/app/page.tsx +119 -0
- package/templates/waitlist/app/robots.ts +12 -0
- package/templates/waitlist/app/sitemap.ts +9 -0
- package/templates/waitlist/app/waitlist-hero.tsx +219 -0
- package/templates/waitlist/app.ts +134 -0
- package/templates/waitlist/components/marketing.tsx +96 -0
- package/templates/waitlist/components/ui/button.tsx +56 -0
- package/templates/waitlist/components/ui/card.tsx +90 -0
- package/templates/waitlist/components.json +20 -0
- package/templates/waitlist/functions/joinWaitlist.ts +82 -0
- package/templates/waitlist/functions/waitlistStats.ts +75 -0
- package/templates/waitlist/gitignore +10 -0
- package/templates/waitlist/lib/owner.ts +26 -0
- package/templates/waitlist/lib/site.config.ts +178 -0
- package/templates/waitlist/lib/stats.ts +30 -0
- package/templates/waitlist/lib/utils.ts +10 -0
- package/templates/waitlist/package.json +34 -0
- package/templates/waitlist/tsconfig.json +18 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// THE single source of truth for everything personal/business-specific on this
|
|
2
|
+
// creator site. Rebrand the whole page by editing this ONE file — the landing
|
|
3
|
+
// page and layout read from here and stay generic. The create-pylon scaffolder
|
|
4
|
+
// and Mast target this file too.
|
|
5
|
+
//
|
|
6
|
+
// Colors live here (applied as CSS variables on <html> in app/layout.tsx).
|
|
7
|
+
// Fictional demo copy — replace the values, keep the shape.
|
|
8
|
+
|
|
9
|
+
/* ----------------------------- types ----------------------------- */
|
|
10
|
+
|
|
11
|
+
export type Social = { label: string; href: string; path: string };
|
|
12
|
+
|
|
13
|
+
export type BaseConfig = {
|
|
14
|
+
brand: {
|
|
15
|
+
name: string;
|
|
16
|
+
letter: string; // monogram
|
|
17
|
+
domain: string;
|
|
18
|
+
email: string;
|
|
19
|
+
footerBlurb: string;
|
|
20
|
+
copyrightName: string;
|
|
21
|
+
socials: Social[];
|
|
22
|
+
};
|
|
23
|
+
colors: { brand: string; brandSoft: string; paper: string };
|
|
24
|
+
seo: { title: string; description: string };
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type Offering = { title: string; body: string; price?: string };
|
|
28
|
+
export type Testimonial = { quote: string; name: string; role: string };
|
|
29
|
+
export type LinkItem = { label: string; href: string; note?: string };
|
|
30
|
+
|
|
31
|
+
export type CreatorConfig = BaseConfig & {
|
|
32
|
+
hero: {
|
|
33
|
+
badge: string;
|
|
34
|
+
name: string; // the person / personal brand
|
|
35
|
+
tagline: string; // one-line "what you do"
|
|
36
|
+
intro: string; // a short paragraph
|
|
37
|
+
};
|
|
38
|
+
about: { eyebrow: string; headline: string; paragraphs: string[] };
|
|
39
|
+
offerings: { eyebrow: string; headline: string; items: Offering[] };
|
|
40
|
+
testimonials?: { eyebrow: string; headline: string; items: Testimonial[] };
|
|
41
|
+
// The realtime feature: a live newsletter subscriber count.
|
|
42
|
+
newsletter: {
|
|
43
|
+
eyebrow: string;
|
|
44
|
+
headline: string;
|
|
45
|
+
subcopy: string;
|
|
46
|
+
emailPlaceholder: string;
|
|
47
|
+
ctaLabel: string;
|
|
48
|
+
successMessage: string;
|
|
49
|
+
counterLabel: string; // e.g. "readers subscribed"
|
|
50
|
+
seedCount?: number; // vanity baseline added to the real live count
|
|
51
|
+
};
|
|
52
|
+
links?: { eyebrow: string; headline: string; items: LinkItem[] };
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/* ----------------------------- config ---------------------------- */
|
|
56
|
+
|
|
57
|
+
export const siteConfig: CreatorConfig = {
|
|
58
|
+
brand: {
|
|
59
|
+
name: "Maya Rivera",
|
|
60
|
+
letter: "M",
|
|
61
|
+
domain: "mayarivera.co",
|
|
62
|
+
email: "hello@mayarivera.example",
|
|
63
|
+
footerBlurb:
|
|
64
|
+
"Product design coach and writer. I help designers do braver work — through 1:1 coaching, portfolio reviews, and a weekly newsletter.",
|
|
65
|
+
copyrightName: "Maya Rivera",
|
|
66
|
+
socials: [
|
|
67
|
+
{
|
|
68
|
+
label: "X",
|
|
69
|
+
href: "https://x.com/pylonsync",
|
|
70
|
+
path: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
label: "GitHub",
|
|
74
|
+
href: "https://github.com/pylonsync/pylon",
|
|
75
|
+
path: "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12",
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
colors: { brand: "#0d9488", brandSoft: "#ccfbf1", paper: "#fafafa" },
|
|
81
|
+
|
|
82
|
+
seo: {
|
|
83
|
+
title: "Maya Rivera — product design coach & writer",
|
|
84
|
+
description:
|
|
85
|
+
"Product design coaching, portfolio reviews, and a weekly newsletter for designers who want to do braver work.",
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
hero: {
|
|
89
|
+
badge: "Now coaching · 2 spots open",
|
|
90
|
+
name: "Maya Rivera",
|
|
91
|
+
tagline: "Product design coach & writer.",
|
|
92
|
+
intro:
|
|
93
|
+
"I help product designers get unstuck, sharpen their portfolios, and do the bravest work of their careers. Fifteen years in the room; now I spend it in yours.",
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
about: {
|
|
97
|
+
eyebrow: "About",
|
|
98
|
+
headline: "Hi, I'm Maya.",
|
|
99
|
+
paragraphs: [
|
|
100
|
+
"I've led design at two startups and a public company, shipped products to millions, and mentored designers who now lead teams of their own.",
|
|
101
|
+
"These days I coach one-on-one, review portfolios, and write a weekly newsletter about the craft and the career. No fluff, no hustle — just the things that actually move your work forward.",
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
offerings: {
|
|
106
|
+
eyebrow: "Work with me",
|
|
107
|
+
headline: "Three ways I can help.",
|
|
108
|
+
items: [
|
|
109
|
+
{
|
|
110
|
+
title: "1:1 coaching",
|
|
111
|
+
body: "Monthly sessions on whatever's in your way — craft, career, confidence. We build a plan and I hold you to it.",
|
|
112
|
+
price: "from $400/mo",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
title: "Portfolio review",
|
|
116
|
+
body: "A deep, honest teardown of your portfolio and a recorded walkthrough with everything I'd change.",
|
|
117
|
+
price: "$250",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
title: "Team workshops",
|
|
121
|
+
body: "Half-day workshops on critique, design systems, and shipping faster without lowering the bar.",
|
|
122
|
+
price: "let's talk",
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
testimonials: {
|
|
128
|
+
eyebrow: "Kind words",
|
|
129
|
+
headline: "From people I've worked with.",
|
|
130
|
+
items: [
|
|
131
|
+
{
|
|
132
|
+
quote:
|
|
133
|
+
"Maya helped me land a senior role in three months. The portfolio review alone was worth ten times the price.",
|
|
134
|
+
name: "Daniel Reyes",
|
|
135
|
+
role: "Senior Product Designer",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
quote:
|
|
139
|
+
"Our whole team got sharper after Maya's critique workshop. Calmer feedback, better work, less ego.",
|
|
140
|
+
name: "Hannah Brooks",
|
|
141
|
+
role: "Design Manager",
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
quote:
|
|
145
|
+
"The newsletter is the only one I actually read every week. It's like a coaching session in my inbox.",
|
|
146
|
+
name: "Marcus Bell",
|
|
147
|
+
role: "Product Designer",
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
newsletter: {
|
|
153
|
+
eyebrow: "The Studio Notes",
|
|
154
|
+
headline: "A weekly letter on the craft and the career.",
|
|
155
|
+
subcopy:
|
|
156
|
+
"One short, useful email every Sunday — on design, taste, and doing brave work. No spam, unsubscribe anytime.",
|
|
157
|
+
emailPlaceholder: "you@email.com",
|
|
158
|
+
ctaLabel: "Subscribe",
|
|
159
|
+
successMessage: "You're in — watch your inbox this Sunday.",
|
|
160
|
+
counterLabel: "designers reading",
|
|
161
|
+
seedCount: 2400,
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
links: {
|
|
165
|
+
eyebrow: "Elsewhere",
|
|
166
|
+
headline: "Find me around the web.",
|
|
167
|
+
items: [
|
|
168
|
+
{ label: "Portfolio", href: "#", note: "Selected work, 2010–today" },
|
|
169
|
+
{ label: "Read the archive", href: "#", note: "Every past issue of The Studio Notes" },
|
|
170
|
+
{ label: "Book a free intro call", href: "#", note: "15 minutes, no pitch" },
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Shape of the owner dashboard's data, shared by the server query
|
|
2
|
+
// (functions/subscriberStats.ts) that produces it and the client view
|
|
3
|
+
// (app/dashboard/dashboard-client.tsx) that renders it. Keeping it here means
|
|
4
|
+
// the client never imports server code — just the type.
|
|
5
|
+
|
|
6
|
+
export interface SubscriberRow {
|
|
7
|
+
id: string;
|
|
8
|
+
email: string;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SubscriberStatsData {
|
|
13
|
+
total: number;
|
|
14
|
+
today: number;
|
|
15
|
+
last7: number;
|
|
16
|
+
/** Last 30 days, ascending — continuous (zero-filled) for the chart. */
|
|
17
|
+
daily: { date: string; count: number }[];
|
|
18
|
+
/** Every subscriber, newest first — powers the list + CSV export. */
|
|
19
|
+
subscribers: SubscriberRow[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// subscriberStats returns a DISCRIMINATED result rather than throwing on a
|
|
23
|
+
// non-owner: a query handler has no `ctx.error`, and a plain `throw` reaches
|
|
24
|
+
// the client as a generic, message-stripped HANDLER_ERROR — useless for telling
|
|
25
|
+
// "you're not the owner" apart from a real failure. So a non-owner gets
|
|
26
|
+
// `{ authorized: false }` (and crucially, NO subscriber data); the owner gets the
|
|
27
|
+
// stats. The client switches on `authorized`.
|
|
28
|
+
export type SubscriberStatsResult =
|
|
29
|
+
| ({ authorized: true } & SubscriberStatsData)
|
|
30
|
+
| { authorized: false };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ClassValue, clsx } from "clsx";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
// `cn` — the shadcn class merger. clsx resolves conditional/array class
|
|
5
|
+
// inputs; tailwind-merge then dedupes conflicting Tailwind utilities so
|
|
6
|
+
// the last one wins (e.g. `cn("px-2", "px-4")` → "px-4"). Every shadcn
|
|
7
|
+
// component routes its className through this.
|
|
8
|
+
export function cn(...inputs: ClassValue[]) {
|
|
9
|
+
return twMerge(clsx(inputs));
|
|
10
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__APP_NAME_KEBAB__",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "pylon dev",
|
|
8
|
+
"deploy": "pylon deploy",
|
|
9
|
+
"check": "tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@pylonsync/react": "^__PYLON_VERSION__",
|
|
13
|
+
"@pylonsync/sdk": "^__PYLON_VERSION__",
|
|
14
|
+
"@pylonsync/functions": "^__PYLON_VERSION__",
|
|
15
|
+
"@pylonsync/client": "^__PYLON_VERSION__",
|
|
16
|
+
"react": "^19.0.0",
|
|
17
|
+
"react-dom": "^19.0.0",
|
|
18
|
+
"tailwindcss": "^4.3.0",
|
|
19
|
+
"@tailwindcss/cli": "^4.3.0",
|
|
20
|
+
"tw-animate-css": "^1.2.0",
|
|
21
|
+
"class-variance-authority": "^0.7.1",
|
|
22
|
+
"clsx": "^2.1.1",
|
|
23
|
+
"tailwind-merge": "^2.5.0",
|
|
24
|
+
"lucide-react": "^0.460.0",
|
|
25
|
+
"@radix-ui/react-slot": "^1.1.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@pylonsync/cli": "^__PYLON_VERSION__",
|
|
29
|
+
"@types/node": "^22.0.0",
|
|
30
|
+
"@types/react": "^19.0.0",
|
|
31
|
+
"@types/react-dom": "^19.0.0",
|
|
32
|
+
"typescript": "^5.6.0"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"jsx": "react",
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"strict": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"lib": ["ES2022", "DOM"],
|
|
11
|
+
"types": ["react", "react-dom", "node"],
|
|
12
|
+
"baseUrl": ".",
|
|
13
|
+
"paths": {
|
|
14
|
+
"@/*": ["./*"]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"include": ["app.ts", "app/**/*", "components/**/*", "lib/**/*", "functions/**/*"]
|
|
18
|
+
}
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { Link, type PageAuth } from "@pylonsync/react";
|
|
3
3
|
import { PRODUCTS } from "@/lib/products";
|
|
4
4
|
import { SOLUTIONS, RESOURCES, COMPANY, COMPARISONS } from "@/lib/site";
|
|
5
|
+
import { siteConfig } from "@/lib/site.config";
|
|
5
6
|
|
|
6
7
|
// A layout receives the page props plus `children`. `auth.user_id` is null for
|
|
7
8
|
// anonymous visitors and the signed-in user's id otherwise — resolved
|
|
@@ -27,11 +28,11 @@ const PRODUCT_MENU: MenuItem[] = PRODUCTS.map((p) => ({
|
|
|
27
28
|
}));
|
|
28
29
|
|
|
29
30
|
const RESOURCES_MENU: MenuItem[] = [
|
|
30
|
-
{ icon: "▢", title: "Docs", desc:
|
|
31
|
+
{ icon: "▢", title: "Docs", desc: `Set up and use ${siteConfig.brand.name}.`, href: "/resources/docs" },
|
|
31
32
|
{ icon: "✎", title: "Guides", desc: "Playbooks and walkthroughs.", href: "/resources/guides" },
|
|
32
|
-
{ icon: "✦", title: "Changelog", desc:
|
|
33
|
-
{ icon: "⌘", title: "API reference", desc:
|
|
34
|
-
{ icon: "◈", title: "Compare", desc:
|
|
33
|
+
{ icon: "✦", title: "Changelog", desc: `What's new in ${siteConfig.brand.name}.`, href: "/resources/changelog" },
|
|
34
|
+
{ icon: "⌘", title: "API reference", desc: `Build on the ${siteConfig.brand.name} API.`, href: "/resources/api" },
|
|
35
|
+
{ icon: "◈", title: "Compare", desc: `See how ${siteConfig.brand.name} stacks up.`, href: `/compare/${COMPARISONS[0].slug}` },
|
|
35
36
|
];
|
|
36
37
|
|
|
37
38
|
// A hover/focus dropdown — pure CSS via `group`, so the nav stays a server
|
|
@@ -184,7 +185,19 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
|
|
|
184
185
|
const BARE_PREFIXES = ["/login", "/signup", "/onboarding", "/dashboard"];
|
|
185
186
|
const isBare = BARE_PREFIXES.some((p) => path === p || path.startsWith(p + "/"));
|
|
186
187
|
return (
|
|
187
|
-
<html
|
|
188
|
+
<html
|
|
189
|
+
lang="en"
|
|
190
|
+
// Marketing theme colors come from the single site config (lib/site.config.ts).
|
|
191
|
+
// Set as inline CSS vars on <html> so they override globals.css defaults and
|
|
192
|
+
// the whole site re-themes from one place — no CSS edit needed.
|
|
193
|
+
style={
|
|
194
|
+
{
|
|
195
|
+
"--brand": siteConfig.colors.brand,
|
|
196
|
+
"--brand-soft": siteConfig.colors.brandSoft,
|
|
197
|
+
"--paper": siteConfig.colors.paper,
|
|
198
|
+
} as React.CSSProperties
|
|
199
|
+
}
|
|
200
|
+
>
|
|
188
201
|
<head>
|
|
189
202
|
<meta charSet="utf-8" />
|
|
190
203
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
@@ -217,10 +230,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
|
|
|
217
230
|
<div className="flex items-center gap-8">
|
|
218
231
|
<Link href="/" className="flex items-center gap-2">
|
|
219
232
|
<span className="flex size-6 items-center justify-center rounded-[7px] bg-zinc-900 text-[13px] font-bold text-white">
|
|
220
|
-
|
|
233
|
+
{siteConfig.brand.letter}
|
|
221
234
|
</span>
|
|
222
235
|
<span className="text-[15px] font-semibold tracking-tight text-zinc-900">
|
|
223
|
-
|
|
236
|
+
{siteConfig.brand.name}
|
|
224
237
|
</span>
|
|
225
238
|
</Link>
|
|
226
239
|
<nav className="hidden items-center gap-6 md:flex">
|
|
@@ -369,19 +382,6 @@ function FooterGroup({
|
|
|
369
382
|
);
|
|
370
383
|
}
|
|
371
384
|
|
|
372
|
-
const SOCIALS = [
|
|
373
|
-
{
|
|
374
|
-
label: "X",
|
|
375
|
-
href: "https://x.com/pylonsync",
|
|
376
|
-
path: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z",
|
|
377
|
-
},
|
|
378
|
-
{
|
|
379
|
-
label: "GitHub",
|
|
380
|
-
href: "https://github.com/pylonsync/pylon",
|
|
381
|
-
path: "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12",
|
|
382
|
-
},
|
|
383
|
-
];
|
|
384
|
-
|
|
385
385
|
function SiteFooter() {
|
|
386
386
|
return (
|
|
387
387
|
<footer className="border-t border-zinc-200/70 bg-white">
|
|
@@ -390,18 +390,17 @@ function SiteFooter() {
|
|
|
390
390
|
<div className="max-w-xs">
|
|
391
391
|
<Link href="/" className="inline-flex items-center gap-2">
|
|
392
392
|
<span className="flex size-7 items-center justify-center rounded-lg bg-zinc-900 text-sm font-bold text-white">
|
|
393
|
-
|
|
393
|
+
{siteConfig.brand.letter}
|
|
394
394
|
</span>
|
|
395
395
|
<span className="text-[15px] font-semibold tracking-tight text-zinc-900">
|
|
396
|
-
|
|
396
|
+
{siteConfig.brand.name}
|
|
397
397
|
</span>
|
|
398
398
|
</Link>
|
|
399
399
|
<p className="mt-4 text-[13px] leading-relaxed text-zinc-500">
|
|
400
|
-
|
|
401
|
-
projects, docs, and automation in one place.
|
|
400
|
+
{siteConfig.brand.footerBlurb}
|
|
402
401
|
</p>
|
|
403
402
|
<div className="mt-5 flex items-center gap-4">
|
|
404
|
-
{
|
|
403
|
+
{siteConfig.brand.socials.map((s) => (
|
|
405
404
|
<a
|
|
406
405
|
key={s.label}
|
|
407
406
|
href={s.href}
|
|
@@ -414,7 +413,7 @@ function SiteFooter() {
|
|
|
414
413
|
</a>
|
|
415
414
|
))}
|
|
416
415
|
<a
|
|
417
|
-
href=
|
|
416
|
+
href={`mailto:${siteConfig.brand.email}`}
|
|
418
417
|
aria-label="Email"
|
|
419
418
|
className="text-zinc-400 transition-colors hover:text-zinc-900"
|
|
420
419
|
>
|
|
@@ -449,7 +448,7 @@ function SiteFooter() {
|
|
|
449
448
|
</div>
|
|
450
449
|
|
|
451
450
|
<div className="mt-14 flex flex-col items-start justify-between gap-3 border-t border-zinc-200/70 pt-6 text-[12px] text-zinc-400 sm:flex-row sm:items-center">
|
|
452
|
-
<span>© {new Date().getFullYear()}
|
|
451
|
+
<span>© {new Date().getFullYear()} {siteConfig.brand.copyrightName}</span>
|
|
453
452
|
<span>
|
|
454
453
|
Built with{" "}
|
|
455
454
|
<a
|