@pylonsync/create-pylon 0.19.1 → 0.20.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/bin/create-pylon.js +30 -7
- package/package.json +1 -1
- package/templates/agency/.env.example +7 -0
- package/templates/agency/README.md +28 -3
- package/templates/agency/app/(marketing)/contact-form.tsx +20 -18
- package/templates/agency/app/(marketing)/page.tsx +3 -3
- package/templates/agency/app/(marketing)/work/page.tsx +3 -3
- package/templates/agency/app/auth-form.tsx +4 -4
- package/templates/agency/app/dashboard/dashboard-client.tsx +110 -64
- package/templates/agency/app/dashboard/page.tsx +14 -16
- package/templates/agency/app/icon.svg +3 -0
- package/templates/agency/app/login/page.tsx +12 -14
- package/templates/agency/components/marketing.tsx +12 -5
- package/templates/agency/functions/seedStudioBackoffice.ts +42 -11
- package/templates/agency/lib/agency.ts +22 -0
- package/templates/agency/lib/demo.ts +118 -0
- package/templates/agency/lib/site.config.ts +19 -13
- package/templates/agency/public/favicon.ico +0 -0
- package/templates/agency/tests/agency.test.ts +57 -0
- package/templates/ai-chat/.env.example +13 -27
- package/templates/ai-chat/README.md +53 -60
- package/templates/ai-chat/app/(chat)/c/[id]/page.tsx +19 -0
- package/templates/ai-chat/app/(chat)/chat-client.tsx +657 -622
- package/templates/ai-chat/app/(chat)/layout.tsx +6 -43
- package/templates/ai-chat/app/(chat)/not-found.tsx +6 -10
- package/templates/ai-chat/app/(chat)/page.tsx +7 -11
- package/templates/ai-chat/app/auth-form.tsx +45 -38
- package/templates/ai-chat/app/error.tsx +9 -12
- package/templates/ai-chat/app/globals.css +464 -102
- package/templates/ai-chat/app/layout.tsx +11 -19
- package/templates/ai-chat/app/login/page.tsx +39 -24
- package/templates/ai-chat/app.ts +118 -43
- package/templates/ai-chat/components/chat/composer.tsx +193 -0
- package/templates/ai-chat/components/chat/empty-state.tsx +65 -0
- package/templates/ai-chat/components/chat/icons.tsx +198 -0
- package/templates/ai-chat/components/chat/markdown.tsx +164 -0
- package/templates/ai-chat/components/chat/message.tsx +183 -0
- package/templates/ai-chat/components/chat/setup.tsx +71 -0
- package/templates/ai-chat/components/chat/sidebar.tsx +288 -0
- package/templates/ai-chat/functions/_beginTurn.ts +145 -0
- package/templates/ai-chat/functions/_finishTurn.ts +55 -0
- package/templates/ai-chat/functions/assistantStatus.ts +13 -0
- package/templates/ai-chat/functions/claimGuestHistory.ts +39 -0
- package/templates/ai-chat/functions/createConversation.ts +28 -0
- package/templates/ai-chat/functions/deleteConversation.ts +15 -20
- package/templates/ai-chat/functions/prepareGuestClaim.ts +32 -0
- package/templates/ai-chat/functions/renameConversation.ts +19 -0
- package/templates/ai-chat/functions/respond.ts +88 -0
- package/templates/ai-chat/functions/seedExamples.ts +46 -0
- package/templates/ai-chat/functions/stopResponse.ts +30 -0
- package/templates/ai-chat/lib/brand-icon.ts +7 -0
- package/templates/ai-chat/lib/chat.ts +277 -0
- package/templates/ai-chat/lib/claim.ts +15 -0
- package/templates/ai-chat/lib/examples.ts +179 -0
- package/templates/ai-chat/lib/highlight.ts +107 -0
- package/templates/ai-chat/lib/markdown.ts +317 -0
- package/templates/ai-chat/lib/provider.ts +38 -0
- package/templates/ai-chat/lib/site.config.ts +55 -39
- package/templates/ai-chat/tests/chat.test.ts +174 -0
- package/templates/ai-chat/tests/components.test.tsx +57 -0
- package/templates/ai-chat/tests/markdown.test.ts +88 -0
- package/templates/ai-chat/tests/provider.test.ts +32 -0
- package/templates/backend/consumer/apps/api/app/layout.tsx +33 -0
- package/templates/backend/consumer/apps/api/app/page.tsx +54 -0
- package/templates/backend/consumer/apps/api/app.ts +166 -0
- package/templates/backend/consumer/apps/api/functions/addComment.ts +24 -0
- package/templates/backend/consumer/apps/api/functions/createPost.ts +19 -36
- package/templates/backend/consumer/apps/api/functions/deletePost.ts +15 -13
- package/templates/backend/consumer/apps/api/functions/myProfile.ts +5 -8
- package/templates/backend/consumer/apps/api/functions/seedDemo.ts +95 -0
- package/templates/backend/consumer/apps/api/functions/setFollow.ts +36 -0
- package/templates/backend/consumer/apps/api/functions/setLike.ts +36 -0
- package/templates/backend/consumer/apps/api/functions/upsertProfile.ts +43 -37
- package/templates/backend/consumer/apps/api/lib/seed.ts +89 -0
- package/templates/backend/consumer/apps/api/lib/social.ts +50 -0
- package/templates/backend/consumer/apps/api/package.json +8 -2
- package/templates/backend/consumer/apps/api/public/images/posts/arch.jpg +0 -0
- package/templates/backend/consumer/apps/api/public/images/posts/coffee.jpg +0 -0
- package/templates/backend/consumer/apps/api/public/images/posts/dog.jpg +0 -0
- package/templates/backend/consumer/apps/api/public/images/posts/lisbon.jpg +0 -0
- package/templates/backend/consumer/apps/api/public/images/posts/ramen.jpg +0 -0
- package/templates/backend/consumer/apps/api/public/images/posts/run.jpg +0 -0
- package/templates/backend/consumer/apps/api/public/images/posts/sunset.jpg +0 -0
- package/templates/backend/consumer/apps/api/tsconfig.json +12 -2
- package/templates/chat/README.md +43 -21
- package/templates/chat/app/chat-client.tsx +495 -85
- package/templates/chat/app/error.tsx +1 -1
- package/templates/chat/app/globals.css +170 -54
- package/templates/chat/app/layout.tsx +12 -9
- package/templates/chat/app/not-found.tsx +4 -2
- package/templates/chat/app/page.tsx +9 -19
- package/templates/chat/app.ts +96 -17
- package/templates/chat/components/chat/avatar.tsx +45 -0
- package/templates/chat/components/chat/composer.tsx +110 -0
- package/templates/chat/components/chat/message-list.tsx +285 -0
- package/templates/chat/components/chat/sidebar.tsx +190 -0
- package/templates/chat/functions/joinChat.ts +83 -0
- package/templates/chat/functions/renameMember.ts +25 -0
- package/templates/chat/lib/chat.ts +188 -0
- package/templates/chat/lib/seed.ts +78 -0
- package/templates/chat/tests/chat.test.ts +159 -0
- package/templates/chat/tests/composer.test.tsx +54 -0
- package/templates/consumer/README.md +3 -3
- package/templates/consumer/app/globals.css +10 -3
- package/templates/consumer/app/icon.svg +1 -0
- package/templates/consumer/components/social/avatar.tsx +25 -11
- package/templates/consumer/functions/seedFeed.ts +3 -3
- package/templates/consumer/lib/seed.ts +43 -85
- package/templates/consumer/public/favicon.ico +0 -0
- package/templates/consumer/public/images/posts/arch.jpg +0 -0
- package/templates/consumer/public/images/posts/coffee.jpg +0 -0
- package/templates/consumer/public/images/posts/dog.jpg +0 -0
- package/templates/consumer/public/images/posts/lisbon.jpg +0 -0
- package/templates/consumer/public/images/posts/ramen.jpg +0 -0
- package/templates/consumer/public/images/posts/run.jpg +0 -0
- package/templates/consumer/public/images/posts/sunset.jpg +0 -0
- package/templates/consumer/tests/seed.test.ts +39 -0
- package/templates/creator/.env.example +7 -0
- package/templates/creator/README.md +24 -5
- package/templates/creator/app/(marketing)/newsletter-signup.tsx +33 -12
- package/templates/creator/app/auth-form.tsx +7 -7
- package/templates/creator/app/dashboard/dashboard-client.tsx +137 -100
- package/templates/creator/app/dashboard/page.tsx +18 -18
- package/templates/creator/app/icon.svg +2 -0
- package/templates/creator/app/login/page.tsx +14 -14
- package/templates/creator/app.ts +4 -4
- package/templates/creator/functions/seedDemo.ts +32 -0
- package/templates/creator/functions/subscribe.ts +4 -15
- package/templates/creator/lib/demo.ts +94 -0
- package/templates/creator/lib/site.config.ts +15 -10
- package/templates/creator/lib/stats.ts +35 -0
- package/templates/creator/public/favicon.ico +0 -0
- package/templates/creator/tests/counter.test.ts +92 -0
- package/templates/creator/tests/live-count.test.tsx +45 -0
- package/templates/crm/README.md +22 -1
- package/templates/crm/app/apple-icon.png +0 -0
- package/templates/crm/app/companies/companies-view.tsx +32 -14
- package/templates/crm/app/companies/page.tsx +2 -1
- package/templates/crm/app/contacts/contacts-view.tsx +34 -10
- package/templates/crm/app/contacts/page.tsx +2 -1
- package/templates/crm/app/deals/[id]/deal-view.tsx +137 -98
- package/templates/crm/app/deals/[id]/page.tsx +2 -1
- package/templates/crm/app/globals.css +29 -14
- package/templates/crm/app/icon.svg +1 -0
- package/templates/crm/app/layout.tsx +7 -5
- package/templates/crm/app/page.tsx +2 -1
- package/templates/crm/app/pipeline-view.tsx +5 -5
- package/templates/crm/app/workspace.tsx +29 -17
- package/templates/crm/app.ts +5 -5
- package/templates/crm/components/activity-timeline.tsx +14 -4
- package/templates/crm/components/app-shell.tsx +94 -0
- package/templates/crm/components/auth-form.tsx +35 -5
- package/templates/crm/components/avatar.tsx +5 -1
- package/templates/crm/components/board-skeleton.tsx +5 -5
- package/templates/crm/components/brand-mark.tsx +25 -0
- package/templates/crm/components/command-palette.tsx +17 -17
- package/templates/crm/components/data-table.tsx +97 -36
- package/templates/crm/components/deal-card.tsx +23 -27
- package/templates/crm/components/filter-tabs.tsx +101 -0
- package/templates/crm/components/metrics-bar.tsx +6 -6
- package/templates/crm/components/nav.tsx +15 -0
- package/templates/crm/components/page-header.tsx +43 -7
- package/templates/crm/components/pipeline-board.tsx +16 -10
- package/templates/crm/components/require-auth.tsx +24 -26
- package/templates/crm/components/sidebar.tsx +54 -49
- package/templates/crm/components/stage-badge.tsx +4 -2
- package/templates/crm/components/ui/button.tsx +5 -4
- package/templates/crm/components/ui/dialog.tsx +1 -1
- package/templates/crm/components/ui/input.tsx +1 -1
- package/templates/crm/components/ui/select.tsx +1 -1
- package/templates/crm/components/ui/textarea.tsx +1 -1
- package/templates/crm/functions/seedWorkspace.ts +32 -17
- package/templates/crm/lib/brand.ts +9 -0
- package/templates/crm/lib/demo-team.ts +51 -0
- package/templates/crm/lib/pipeline.ts +37 -0
- package/templates/crm/lib/search.ts +4 -3
- package/templates/crm/lib/seed.ts +53 -8
- package/templates/crm/public/favicon.ico +0 -0
- package/templates/crm/tests/components.test.tsx +5 -5
- package/templates/crm/tests/demo-team.test.ts +18 -0
- package/templates/crm/tests/pipeline.test.ts +59 -3
- package/templates/directory/.env.example +7 -0
- package/templates/directory/README.md +22 -3
- package/templates/directory/app/(marketing)/directory-browse.tsx +30 -12
- package/templates/directory/app/(marketing)/page.tsx +6 -4
- package/templates/directory/app/auth-form.tsx +4 -4
- package/templates/directory/app/dashboard/dashboard-client.tsx +177 -90
- package/templates/directory/app/dashboard/page.tsx +16 -14
- package/templates/directory/app/icon.svg +4 -0
- package/templates/directory/app/login/page.tsx +16 -15
- package/templates/directory/functions/seedDemo.ts +43 -0
- package/templates/directory/lib/demo.ts +145 -0
- package/templates/directory/lib/directory.ts +27 -0
- package/templates/directory/lib/site.config.ts +21 -16
- package/templates/directory/public/favicon.ico +0 -0
- package/templates/directory/tests/directory.test.ts +46 -0
- package/templates/expo/consumer/apps/expo/App.tsx +360 -288
- package/templates/expo/consumer/apps/expo/app.json +9 -1
- package/templates/expo/consumer/apps/expo/package.json +2 -1
- package/templates/helpdesk/README.md +21 -0
- package/templates/helpdesk/app/apple-icon.png +0 -0
- package/templates/helpdesk/app/customers/customers-view.tsx +23 -7
- package/templates/helpdesk/app/customers/page.tsx +2 -1
- package/templates/helpdesk/app/globals.css +29 -14
- package/templates/helpdesk/app/icon.svg +1 -0
- package/templates/helpdesk/app/inbox-view.tsx +66 -47
- package/templates/helpdesk/app/layout.tsx +7 -5
- package/templates/helpdesk/app/page.tsx +4 -7
- package/templates/helpdesk/app/tickets/[id]/page.tsx +2 -1
- package/templates/helpdesk/app/tickets/[id]/ticket-view.tsx +134 -97
- package/templates/helpdesk/app/workspace.tsx +33 -22
- package/templates/helpdesk/app.ts +2 -2
- package/templates/helpdesk/components/app-shell.tsx +94 -0
- package/templates/helpdesk/components/auth-form.tsx +35 -5
- package/templates/helpdesk/components/avatar.tsx +5 -1
- package/templates/helpdesk/components/brand-mark.tsx +28 -0
- package/templates/helpdesk/components/command-palette.tsx +17 -17
- package/templates/helpdesk/components/data-table.tsx +97 -36
- package/templates/helpdesk/components/filter-tabs.tsx +101 -0
- package/templates/helpdesk/components/nav.tsx +14 -0
- package/templates/helpdesk/components/page-header.tsx +43 -7
- package/templates/helpdesk/components/priority-badge.tsx +49 -6
- package/templates/helpdesk/components/require-auth.tsx +24 -26
- package/templates/helpdesk/components/sidebar.tsx +54 -48
- package/templates/helpdesk/components/sla-indicator.tsx +5 -8
- package/templates/helpdesk/components/thread.tsx +7 -7
- package/templates/helpdesk/components/ticket-list.tsx +79 -19
- package/templates/helpdesk/components/ui/button.tsx +5 -4
- package/templates/helpdesk/components/ui/dialog.tsx +1 -1
- package/templates/helpdesk/components/ui/input.tsx +1 -1
- package/templates/helpdesk/components/ui/select.tsx +1 -1
- package/templates/helpdesk/components/ui/textarea.tsx +1 -1
- package/templates/helpdesk/functions/seedWorkspace.ts +25 -15
- package/templates/helpdesk/lib/brand.ts +9 -0
- package/templates/helpdesk/lib/demo-team.ts +51 -0
- package/templates/helpdesk/lib/search.ts +4 -3
- package/templates/helpdesk/lib/seed.ts +43 -2
- package/templates/helpdesk/lib/tickets.ts +68 -20
- package/templates/helpdesk/public/favicon.ico +0 -0
- package/templates/helpdesk/tests/components.test.tsx +10 -0
- package/templates/helpdesk/tests/demo-team.test.ts +18 -0
- package/templates/helpdesk/tests/tickets.test.ts +70 -0
- package/templates/imessage/.env.example +49 -0
- package/templates/imessage/AGENTS.md +153 -0
- package/templates/imessage/CLAUDE.md +7 -0
- package/templates/imessage/README.md +187 -0
- package/templates/imessage/app/console.tsx +382 -0
- package/templates/imessage/app/contacts/page.tsx +13 -0
- package/templates/imessage/app/error.tsx +16 -0
- package/templates/imessage/app/gate.tsx +31 -0
- package/templates/imessage/app/globals.css +183 -0
- package/templates/imessage/app/layout.tsx +17 -0
- package/templates/imessage/app/login/login-form.tsx +115 -0
- package/templates/imessage/app/login/page.tsx +30 -0
- package/templates/imessage/app/not-found.tsx +13 -0
- package/templates/imessage/app/page.tsx +14 -0
- package/templates/imessage/app/robots.ts +6 -0
- package/templates/imessage/app/setup/page.tsx +13 -0
- package/templates/imessage/app/sign-out.tsx +20 -0
- package/templates/imessage/app.ts +299 -0
- package/templates/imessage/bunfig +4 -0
- package/templates/imessage/components/avatar.tsx +46 -0
- package/templates/imessage/components/contact-panel.tsx +263 -0
- package/templates/imessage/components/contacts-view.tsx +172 -0
- package/templates/imessage/components/conversation-list.tsx +129 -0
- package/templates/imessage/components/nav-rail.tsx +67 -0
- package/templates/imessage/components/setup-view.tsx +408 -0
- package/templates/imessage/components/thread.tsx +229 -0
- package/templates/imessage/components/ui/badge.tsx +37 -0
- package/templates/imessage/components/ui/button.tsx +56 -0
- package/templates/imessage/components/ui/card.tsx +90 -0
- package/templates/imessage/components/ui/dialog.tsx +110 -0
- package/templates/imessage/components/ui/input.tsx +30 -0
- package/templates/imessage/components/ui/label.tsx +21 -0
- package/templates/imessage/components/ui/select.tsx +39 -0
- package/templates/imessage/components/ui/table.tsx +124 -0
- package/templates/imessage/components/ui/textarea.tsx +24 -0
- package/templates/imessage/components.json +20 -0
- package/templates/imessage/functions/answerNow.ts +34 -0
- package/templates/imessage/functions/assistant.ts +96 -0
- package/templates/imessage/functions/beginTurn.ts +101 -0
- package/templates/imessage/functions/cancelReminder.ts +13 -0
- package/templates/imessage/functions/claimOutbound.ts +44 -0
- package/templates/imessage/functions/clearDemo.ts +18 -0
- package/templates/imessage/functions/deleteNote.ts +11 -0
- package/templates/imessage/functions/deliverOutbound.ts +55 -0
- package/templates/imessage/functions/finishTurn.ts +84 -0
- package/templates/imessage/functions/fireReminder.ts +42 -0
- package/templates/imessage/functions/ingestInbound.ts +22 -0
- package/templates/imessage/functions/ownerAccount.ts +13 -0
- package/templates/imessage/functions/processTurn.ts +74 -0
- package/templates/imessage/functions/relayApply.ts +102 -0
- package/templates/imessage/functions/relaySync.ts +63 -0
- package/templates/imessage/functions/releaseOutbound.ts +18 -0
- package/templates/imessage/functions/resolveTurn.ts +25 -0
- package/templates/imessage/functions/saveContact.ts +27 -0
- package/templates/imessage/functions/seedDemo.ts +70 -0
- package/templates/imessage/functions/sendOwnerMessage.ts +28 -0
- package/templates/imessage/functions/sendblueWebhook.ts +49 -0
- package/templates/imessage/functions/setContactStatus.ts +17 -0
- package/templates/imessage/functions/settleOutbound.ts +35 -0
- package/templates/imessage/functions/setupStatus.ts +33 -0
- package/templates/imessage/functions/sweep.ts +58 -0
- package/templates/imessage/functions/toolCancelReminder.ts +17 -0
- package/templates/imessage/functions/toolForgetNote.ts +15 -0
- package/templates/imessage/functions/toolListNotes.ts +16 -0
- package/templates/imessage/functions/toolListReminders.ts +17 -0
- package/templates/imessage/functions/toolSaveNote.ts +22 -0
- package/templates/imessage/functions/toolSetReminder.ts +55 -0
- package/templates/imessage/functions/updateSettings.ts +48 -0
- package/templates/imessage/gitignore +11 -0
- package/templates/imessage/lib/agent-call.ts +251 -0
- package/templates/imessage/lib/assistant.ts +74 -0
- package/templates/imessage/lib/chunk.ts +135 -0
- package/templates/imessage/lib/demo.ts +68 -0
- package/templates/imessage/lib/format.ts +170 -0
- package/templates/imessage/lib/gate.ts +104 -0
- package/templates/imessage/lib/handles.ts +67 -0
- package/templates/imessage/lib/provider.ts +38 -0
- package/templates/imessage/lib/relay-protocol.ts +95 -0
- package/templates/imessage/lib/reminders.ts +41 -0
- package/templates/imessage/lib/secrets.ts +59 -0
- package/templates/imessage/lib/sendblue.ts +173 -0
- package/templates/imessage/lib/store.ts +407 -0
- package/templates/imessage/lib/transport.ts +135 -0
- package/templates/imessage/lib/utils.ts +10 -0
- package/templates/imessage/package.json +40 -0
- package/templates/imessage/relay/.env.example +14 -0
- package/templates/imessage/relay/applescript.ts +70 -0
- package/templates/imessage/relay/chatdb.ts +165 -0
- package/templates/imessage/relay/client.ts +41 -0
- package/templates/imessage/relay/main.ts +137 -0
- package/templates/imessage/relay/state.ts +35 -0
- package/templates/imessage/tests/agent-call.test.ts +112 -0
- package/templates/imessage/tests/applescript.test.ts +88 -0
- package/templates/imessage/tests/chatdb.test.ts +139 -0
- package/templates/imessage/tests/chunk.test.ts +61 -0
- package/templates/imessage/tests/fake-ctx.ts +88 -0
- package/templates/imessage/tests/ingest.test.ts +141 -0
- package/templates/imessage/tests/lib.test.ts +99 -0
- package/templates/imessage/tests/review-fixes.test.ts +138 -0
- package/templates/imessage/tests/secrets.test.ts +36 -0
- package/templates/imessage/tests/sendblue.test.ts +143 -0
- package/templates/imessage/tests/setup.ts +5 -0
- package/templates/imessage/tsconfig.json +18 -0
- package/templates/inventory/README.md +21 -0
- package/templates/inventory/app/apple-icon.png +0 -0
- package/templates/inventory/app/globals.css +29 -14
- package/templates/inventory/app/icon.svg +1 -0
- package/templates/inventory/app/layout.tsx +7 -5
- package/templates/inventory/app/movements/movements-view.tsx +32 -10
- package/templates/inventory/app/movements/page.tsx +2 -1
- package/templates/inventory/app/page.tsx +4 -6
- package/templates/inventory/app/products/[id]/page.tsx +2 -1
- package/templates/inventory/app/products/[id]/product-view.tsx +55 -25
- package/templates/inventory/app/products-view.tsx +74 -33
- package/templates/inventory/app/workspace.tsx +34 -16
- package/templates/inventory/app.ts +10 -2
- package/templates/inventory/components/app-shell.tsx +94 -0
- package/templates/inventory/components/auth-form.tsx +35 -5
- package/templates/inventory/components/avatar.tsx +5 -1
- package/templates/inventory/components/brand-mark.tsx +25 -0
- package/templates/inventory/components/category-tile.tsx +49 -0
- package/templates/inventory/components/command-palette.tsx +17 -17
- package/templates/inventory/components/data-table.tsx +97 -36
- package/templates/inventory/components/filter-tabs.tsx +101 -0
- package/templates/inventory/components/nav.tsx +14 -0
- package/templates/inventory/components/page-header.tsx +43 -7
- package/templates/inventory/components/require-auth.tsx +24 -26
- package/templates/inventory/components/sidebar.tsx +54 -48
- package/templates/inventory/components/stock-level.tsx +30 -14
- package/templates/inventory/components/summary-bar.tsx +8 -15
- package/templates/inventory/components/ui/button.tsx +5 -4
- package/templates/inventory/components/ui/dialog.tsx +1 -1
- package/templates/inventory/components/ui/input.tsx +1 -1
- package/templates/inventory/components/ui/select.tsx +1 -1
- package/templates/inventory/components/ui/textarea.tsx +1 -1
- package/templates/inventory/functions/seedWorkspace.ts +18 -8
- package/templates/inventory/lib/brand.ts +9 -0
- package/templates/inventory/lib/demo-team.ts +51 -0
- package/templates/inventory/lib/search.ts +4 -3
- package/templates/inventory/lib/seed.ts +29 -2
- package/templates/inventory/lib/stock.ts +32 -0
- package/templates/inventory/public/favicon.ico +0 -0
- package/templates/inventory/tests/demo-team.test.ts +18 -0
- package/templates/inventory/tests/stock.test.ts +29 -0
- package/templates/invoices/README.md +16 -0
- package/templates/invoices/app/apple-icon.png +0 -0
- package/templates/invoices/app/clients/clients-view.tsx +18 -6
- package/templates/invoices/app/clients/page.tsx +2 -1
- package/templates/invoices/app/globals.css +29 -14
- package/templates/invoices/app/icon.svg +1 -0
- package/templates/invoices/app/invoices/[id]/invoice-view.tsx +72 -48
- package/templates/invoices/app/invoices/[id]/page.tsx +2 -1
- package/templates/invoices/app/invoices-view.tsx +81 -32
- package/templates/invoices/app/layout.tsx +7 -5
- package/templates/invoices/app/page.tsx +4 -6
- package/templates/invoices/app/workspace.tsx +26 -16
- package/templates/invoices/app.ts +2 -2
- package/templates/invoices/components/app-shell.tsx +94 -0
- package/templates/invoices/components/auth-form.tsx +35 -5
- package/templates/invoices/components/avatar.tsx +5 -1
- package/templates/invoices/components/brand-mark.tsx +26 -0
- package/templates/invoices/components/command-palette.tsx +17 -17
- package/templates/invoices/components/data-table.tsx +97 -36
- package/templates/invoices/components/filter-tabs.tsx +101 -0
- package/templates/invoices/components/line-items.tsx +19 -14
- package/templates/invoices/components/nav.tsx +14 -0
- package/templates/invoices/components/page-header.tsx +43 -7
- package/templates/invoices/components/require-auth.tsx +24 -26
- package/templates/invoices/components/sidebar.tsx +54 -48
- package/templates/invoices/components/status-badge.tsx +7 -7
- package/templates/invoices/components/summary-bar.tsx +5 -5
- package/templates/invoices/components/ui/button.tsx +5 -4
- package/templates/invoices/components/ui/dialog.tsx +1 -1
- package/templates/invoices/components/ui/input.tsx +1 -1
- package/templates/invoices/components/ui/select.tsx +1 -1
- package/templates/invoices/components/ui/textarea.tsx +1 -1
- package/templates/invoices/functions/recordPayment.ts +3 -0
- package/templates/invoices/lib/billing.ts +40 -0
- package/templates/invoices/lib/brand.ts +9 -0
- package/templates/invoices/lib/search.ts +4 -3
- package/templates/invoices/public/favicon.ico +0 -0
- package/templates/invoices/tests/billing.test.ts +27 -0
- package/templates/ios/consumer/apps/ios/Package.swift +4 -3
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ActivityView.swift +107 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/AppModel.swift +171 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/AuthView.swift +182 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/CommentsView.swift +136 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ComposeView.swift +152 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ExploreView.swift +117 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/FeedView.swift +175 -159
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/MainTabView.swift +54 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/Media.swift +271 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/Models.swift +101 -4
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/PostCard.swift +245 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ProfileEditorView.swift +208 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ProfileView.swift +183 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/RootView.swift +25 -31
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/SocialStore.swift +285 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/StoryViewer.swift +155 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/Theme.swift +82 -0
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/__APP_NAME_PASCAL__App.swift +4 -47
- package/templates/ios/consumer/apps/ios/project.yml +13 -9
- package/templates/local-service/.env.example +7 -0
- package/templates/local-service/README.md +26 -2
- package/templates/local-service/app/(marketing)/booking-widget.tsx +48 -9
- package/templates/local-service/app/(marketing)/page.tsx +66 -42
- package/templates/local-service/app/auth-form.tsx +8 -8
- package/templates/local-service/app/dashboard/dashboard-client.tsx +119 -92
- package/templates/local-service/app/dashboard/page.tsx +14 -14
- package/templates/local-service/app/icon.svg +2 -0
- package/templates/local-service/app/login/page.tsx +15 -15
- package/templates/local-service/functions/seedDemo.ts +49 -0
- package/templates/local-service/lib/demo.ts +135 -0
- package/templates/local-service/lib/hours.ts +44 -0
- package/templates/local-service/lib/site.config.ts +8 -3
- package/templates/local-service/lib/slots.ts +3 -0
- package/templates/local-service/public/favicon.ico +0 -0
- package/templates/local-service/tests/booking.test.ts +104 -0
- package/templates/marketplace/README.md +23 -15
- package/templates/marketplace/app/globals.css +172 -114
- package/templates/marketplace/app/layout.tsx +75 -30
- package/templates/marketplace/app/listing/[id]/page.tsx +210 -123
- package/templates/marketplace/app/me/page.tsx +4 -4
- package/templates/marketplace/app/page.tsx +221 -298
- package/templates/marketplace/app/sell/page.tsx +8 -11
- package/templates/marketplace/app.ts +32 -7
- package/templates/marketplace/client/ActivityFeed.tsx +311 -0
- package/templates/marketplace/client/AuthNav.tsx +24 -16
- package/templates/marketplace/client/ListingCard.tsx +118 -0
- package/templates/marketplace/client/LiveGrid.tsx +92 -0
- package/templates/marketplace/client/LiveListingStatus.tsx +32 -24
- package/templates/marketplace/client/LoginCard.tsx +114 -136
- package/templates/marketplace/client/MarketProvider.tsx +3 -5
- package/templates/marketplace/client/MyMarket.tsx +371 -185
- package/templates/marketplace/client/OfferPanel.tsx +421 -287
- package/templates/marketplace/client/SellForm.tsx +271 -192
- package/templates/marketplace/client/ThemeToggle.tsx +1 -0
- package/templates/marketplace/client/WatchButton.tsx +16 -16
- package/templates/marketplace/client/market.ts +61 -14
- package/templates/marketplace/functions/seedMarket.ts +143 -36
- package/templates/marketplace/functions/seedOffers.ts +101 -0
- package/templates/marketplace/lib/catalog.ts +72 -1
- package/templates/marketplace/public/images/listings/ceramic-lamp-640.webp +0 -0
- package/templates/marketplace/public/images/listings/ceramic-lamp.webp +0 -0
- package/templates/marketplace/public/images/listings/duffel-640.webp +0 -0
- package/templates/marketplace/public/images/listings/duffel.webp +0 -0
- package/templates/marketplace/public/images/listings/film-camera-640.webp +0 -0
- package/templates/marketplace/public/images/listings/film-camera.webp +0 -0
- package/templates/marketplace/public/images/listings/lounge-chair-640.webp +0 -0
- package/templates/marketplace/public/images/listings/lounge-chair.webp +0 -0
- package/templates/marketplace/public/images/listings/road-bike-640.webp +0 -0
- package/templates/marketplace/public/images/listings/road-bike.webp +0 -0
- package/templates/marketplace/public/images/listings/slipper-chair-640.webp +0 -0
- package/templates/marketplace/public/images/listings/slipper-chair.webp +0 -0
- package/templates/marketplace/public/images/listings/turntable-640.webp +0 -0
- package/templates/marketplace/public/images/listings/turntable.webp +0 -0
- package/templates/marketplace/public/images/listings/wardrobe-640.webp +0 -0
- package/templates/marketplace/public/images/listings/wardrobe.webp +0 -0
- package/templates/marketplace/public/images/listings/watch-640.webp +0 -0
- package/templates/marketplace/public/images/listings/watch.webp +0 -0
- package/templates/marketplace/public/images/listings/weekender-bag-640.webp +0 -0
- package/templates/marketplace/public/images/listings/weekender-bag.webp +0 -0
- package/templates/marketplace/tests/example.test.ts +64 -2
- package/templates/marketplace/tests/listing-card.test.tsx +61 -0
- package/templates/projects/README.md +24 -3
- package/templates/projects/app/apple-icon.png +0 -0
- package/templates/projects/app/clients/clients-view.tsx +20 -6
- package/templates/projects/app/clients/page.tsx +2 -1
- package/templates/projects/app/globals.css +29 -14
- package/templates/projects/app/icon.svg +1 -0
- package/templates/projects/app/layout.tsx +7 -5
- package/templates/projects/app/page.tsx +3 -5
- package/templates/projects/app/projects/[id]/page.tsx +2 -1
- package/templates/projects/app/projects/[id]/project-view.tsx +45 -30
- package/templates/projects/app/projects-view.tsx +105 -52
- package/templates/projects/app/workspace.tsx +41 -20
- package/templates/projects/app.ts +2 -2
- package/templates/projects/components/app-shell.tsx +94 -0
- package/templates/projects/components/auth-form.tsx +35 -5
- package/templates/projects/components/avatar.tsx +5 -1
- package/templates/projects/components/board-skeleton.tsx +3 -3
- package/templates/projects/components/brand-mark.tsx +25 -0
- package/templates/projects/components/command-palette.tsx +17 -17
- package/templates/projects/components/data-table.tsx +97 -36
- package/templates/projects/components/filter-tabs.tsx +101 -0
- package/templates/projects/components/meter.tsx +48 -0
- package/templates/projects/components/nav.tsx +14 -0
- package/templates/projects/components/page-header.tsx +43 -7
- package/templates/projects/components/require-auth.tsx +24 -26
- package/templates/projects/components/sidebar.tsx +54 -48
- package/templates/projects/components/summary-bar.tsx +49 -0
- package/templates/projects/components/task-board.tsx +10 -9
- package/templates/projects/components/time-dialog.tsx +29 -5
- package/templates/projects/components/ui/button.tsx +5 -4
- package/templates/projects/components/ui/dialog.tsx +1 -1
- package/templates/projects/components/ui/input.tsx +1 -1
- package/templates/projects/components/ui/select.tsx +1 -1
- package/templates/projects/components/ui/textarea.tsx +1 -1
- package/templates/projects/functions/seedWorkspace.ts +26 -12
- package/templates/projects/lib/brand.ts +9 -0
- package/templates/projects/lib/demo-team.ts +51 -0
- package/templates/projects/lib/search.ts +4 -3
- package/templates/projects/lib/seed.ts +35 -1
- package/templates/projects/lib/work.ts +63 -0
- package/templates/projects/public/favicon.ico +0 -0
- package/templates/projects/tests/demo-team.test.ts +18 -0
- package/templates/projects/tests/work.test.ts +65 -0
- package/templates/restaurant/.env.example +7 -0
- package/templates/restaurant/README.md +29 -3
- package/templates/restaurant/app/(marketing)/layout.tsx +4 -2
- package/templates/restaurant/app/(marketing)/page.tsx +47 -23
- package/templates/restaurant/app/(marketing)/reservation-widget.tsx +37 -7
- package/templates/restaurant/app/auth-form.tsx +8 -8
- package/templates/restaurant/app/dashboard/dashboard-client.tsx +241 -109
- package/templates/restaurant/app/dashboard/page.tsx +14 -14
- package/templates/restaurant/app/icon.svg +4 -0
- package/templates/restaurant/app/login/page.tsx +15 -15
- package/templates/restaurant/functions/seedDemo.ts +44 -0
- package/templates/restaurant/lib/demo.ts +144 -0
- package/templates/restaurant/lib/hours.ts +45 -0
- package/templates/restaurant/lib/site.config.ts +3 -3
- package/templates/restaurant/public/favicon.ico +0 -0
- package/templates/restaurant/tests/reservations.test.ts +67 -0
- package/templates/saas/README.md +54 -35
- package/templates/saas/app/(auth)/auth-form.tsx +25 -23
- package/templates/saas/app/(auth)/forgot-password/page.tsx +1 -1
- package/templates/saas/app/(auth)/layout.tsx +27 -33
- package/templates/saas/app/(auth)/login/page.tsx +1 -1
- package/templates/saas/app/(auth)/reset-password/page.tsx +1 -1
- package/templates/saas/app/(auth)/signup/page.tsx +1 -1
- package/templates/saas/app/(marketing)/layout.tsx +127 -253
- package/templates/saas/app/(marketing)/page.tsx +133 -372
- package/templates/saas/app/(marketing)/pricing/page.tsx +21 -19
- package/templates/saas/app/(marketing)/products/[slug]/page.tsx +40 -95
- package/templates/saas/app/dashboard/board-client.tsx +416 -0
- package/templates/saas/app/dashboard/dashboard-client.tsx +30 -615
- package/templates/saas/app/dashboard/layout.tsx +27 -13
- package/templates/saas/app/dashboard/overview-client.tsx +332 -0
- package/templates/saas/app/dashboard/page.tsx +29 -35
- package/templates/saas/app/dashboard/projects/[id]/page.tsx +29 -0
- package/templates/saas/app/dashboard/projects/page.tsx +11 -7
- package/templates/saas/app/dashboard/projects-client.tsx +398 -0
- package/templates/saas/app/globals.css +5 -4
- package/templates/saas/app/icon.svg +1 -0
- package/templates/saas/app/onboarding/onboarding-client.tsx +93 -26
- package/templates/saas/app/onboarding/page.tsx +6 -2
- package/templates/saas/app.ts +68 -13
- package/templates/saas/components/dashboard-shell.tsx +212 -132
- package/templates/saas/components/marketing.tsx +137 -274
- package/templates/saas/components/pricing-table.tsx +12 -11
- package/templates/saas/components/setup-checklist.tsx +31 -29
- package/templates/saas/components/task-ui.tsx +199 -0
- package/templates/saas/functions/createProject.ts +7 -13
- package/templates/saas/functions/createTask.ts +67 -0
- package/templates/saas/functions/deleteProject.ts +17 -0
- package/templates/saas/functions/deleteTask.ts +14 -0
- package/templates/saas/functions/seedWorkspace.ts +46 -0
- package/templates/saas/functions/setProjectStatus.ts +41 -0
- package/templates/saas/functions/updateProfile.ts +13 -0
- package/templates/saas/functions/updateProject.ts +4 -5
- package/templates/saas/functions/updateTask.ts +88 -0
- package/templates/saas/lib/members.ts +53 -0
- package/templates/saas/lib/names.ts +53 -0
- package/templates/saas/lib/plans.ts +11 -0
- package/templates/saas/lib/sample-workspace.ts +117 -0
- package/templates/saas/lib/site.config.ts +200 -463
- package/templates/saas/lib/tasks.ts +101 -0
- package/templates/saas/lib/use-live.ts +25 -0
- package/templates/saas/public/favicon.ico +0 -0
- package/templates/saas/public/screenshots/board.png +0 -0
- package/templates/saas/public/screenshots/members.png +0 -0
- package/templates/saas/public/screenshots/overview.png +0 -0
- package/templates/saas/public/screenshots/projects.png +0 -0
- package/templates/saas/scripts/capture-screenshots.mjs +156 -0
- package/templates/saas/tests/names.test.ts +35 -0
- package/templates/saas/tests/plans.test.ts +12 -0
- package/templates/saas/tests/sample-workspace.test.ts +46 -0
- package/templates/saas/tests/tasks.test.ts +81 -0
- package/templates/shop/README.md +25 -13
- package/templates/shop/app/(marketing)/layout.tsx +94 -67
- package/templates/shop/app/(marketing)/not-found.tsx +13 -12
- package/templates/shop/app/(marketing)/page.tsx +120 -59
- package/templates/shop/app/(marketing)/shop-client.tsx +364 -237
- package/templates/shop/app/(marketing)/success/page.tsx +75 -22
- package/templates/shop/app/globals.css +94 -1
- package/templates/shop/app/layout.tsx +4 -4
- package/templates/shop/app/login/page.tsx +4 -4
- package/templates/shop/app.ts +18 -6
- package/templates/shop/components/cart-button.tsx +33 -0
- package/templates/shop/components/marketing.tsx +17 -87
- package/templates/shop/components/shelf-count.tsx +36 -0
- package/templates/shop/functions/checkout.ts +17 -1
- package/templates/shop/lib/cart-store.ts +57 -0
- package/templates/shop/lib/shelf-store.ts +35 -0
- package/templates/shop/lib/shop.ts +27 -0
- package/templates/shop/lib/site.config.ts +108 -98
- package/templates/shop/public/images/hero.jpg +0 -0
- package/templates/shop/public/images/products/cedar-smoke.jpg +0 -0
- package/templates/shop/public/images/products/fig-leaf.jpg +0 -0
- package/templates/shop/public/images/products/linen.jpg +0 -0
- package/templates/shop/public/images/products/sea-salt.jpg +0 -0
- package/templates/shop/public/images/products/tobacco-oak.jpg +0 -0
- package/templates/shop/tests/shop.test.ts +64 -0
- package/templates/waitlist/.env.example +7 -0
- package/templates/waitlist/README.md +29 -13
- package/templates/waitlist/app/(marketing)/page.tsx +9 -7
- package/templates/waitlist/app/(marketing)/waitlist-hero.tsx +64 -31
- package/templates/waitlist/app/auth-form.tsx +8 -8
- package/templates/waitlist/app/dashboard/dashboard-client.tsx +132 -95
- package/templates/waitlist/app/dashboard/page.tsx +17 -16
- package/templates/waitlist/app/icon.svg +2 -0
- package/templates/waitlist/app/login/page.tsx +14 -14
- package/templates/waitlist/app.ts +6 -6
- package/templates/waitlist/functions/joinWaitlist.ts +6 -18
- package/templates/waitlist/functions/seedDemo.ts +32 -0
- package/templates/waitlist/lib/demo.ts +94 -0
- package/templates/waitlist/lib/launch.ts +19 -0
- package/templates/waitlist/lib/site.config.ts +14 -9
- package/templates/waitlist/lib/stats.ts +35 -0
- package/templates/waitlist/public/favicon.ico +0 -0
- package/templates/waitlist/tests/counter.test.ts +107 -0
- package/templates/waitlist/tests/live-count.test.tsx +48 -0
- package/templates/ai-chat/tests/example.test.ts +0 -12
- package/templates/backend/consumer/apps/api/functions/feed.ts +0 -57
- package/templates/backend/consumer/apps/api/functions/profilePosts.ts +0 -17
- package/templates/backend/consumer/apps/api/functions/toggleLike.ts +0 -48
- package/templates/backend/consumer/apps/api/schema.ts +0 -143
- package/templates/chat/functions/_keep.ts +0 -13
- package/templates/chat/tests/example.test.ts +0 -12
- package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ProfileSetupView.swift +0 -68
- package/templates/marketplace/client/LiveTicker.tsx +0 -116
- package/templates/marketplace/client/ScrollToListingsLink.tsx +0 -29
- package/templates/marketplace/public/images/marketplace-hero.webp +0 -0
|
@@ -12,7 +12,7 @@ export const metadata: Metadata = {
|
|
|
12
12
|
export default function SignupPage() {
|
|
13
13
|
return (
|
|
14
14
|
<>
|
|
15
|
-
<h1 className="mt-
|
|
15
|
+
<h1 className="mt-10 text-[26px] font-semibold tracking-[-0.025em] text-zinc-950">
|
|
16
16
|
Create an account
|
|
17
17
|
</h1>
|
|
18
18
|
<p className="mt-1 text-[13px] text-zinc-500">
|
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Link, type PageAuth } from "@pylonsync/react";
|
|
3
|
+
import { ChevronDown, Menu } from "lucide-react";
|
|
4
|
+
import type { LucideIcon } from "lucide-react";
|
|
3
5
|
import { PRODUCTS } from "@/lib/products";
|
|
4
6
|
import { SOLUTIONS, RESOURCES, COMPANY, COMPARISONS } from "@/lib/site";
|
|
5
7
|
import { siteConfig } from "@/lib/site.config";
|
|
6
8
|
|
|
7
9
|
// `(marketing)` is a ROUTE GROUP: the parens segment is stripped from every
|
|
8
10
|
// URL (so `(marketing)/page.tsx` still serves `/`), and this layout wraps
|
|
9
|
-
// only the pages inside the group
|
|
10
|
-
//
|
|
11
|
-
//
|
|
11
|
+
// only the pages inside the group with the marketing nav and footer. The
|
|
12
|
+
// other sections bring their own layouts: `(auth)` the split-screen frame,
|
|
13
|
+
// `dashboard/` the sidebar shell.
|
|
12
14
|
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// server-side from the session cookie before any HTML is sent, so the nav
|
|
16
|
-
// renders the right links on the first byte (no flash, no client fetch).
|
|
15
|
+
// `auth.user_id` is resolved on the server from the session cookie before any
|
|
16
|
+
// HTML is sent, so the nav renders the right buttons on the first byte.
|
|
17
17
|
interface LayoutProps {
|
|
18
18
|
children: React.ReactNode;
|
|
19
19
|
auth: PageAuth;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
// hrefs for real routes as you add pages.
|
|
24
|
-
type MenuItem = { icon: string; title: string; desc: string; href: string };
|
|
22
|
+
type MenuItem = { icon: LucideIcon; title: string; desc: string; href: string };
|
|
25
23
|
|
|
26
|
-
// Derived from the
|
|
27
|
-
//
|
|
24
|
+
// Derived from the product list, so the menu and the /products/[slug] pages
|
|
25
|
+
// can't drift.
|
|
28
26
|
const PRODUCT_MENU: MenuItem[] = PRODUCTS.map((p) => ({
|
|
29
27
|
icon: p.icon,
|
|
30
28
|
title: p.title,
|
|
@@ -32,46 +30,36 @@ const PRODUCT_MENU: MenuItem[] = PRODUCTS.map((p) => ({
|
|
|
32
30
|
href: `/products/${p.slug}`,
|
|
33
31
|
}));
|
|
34
32
|
|
|
35
|
-
const RESOURCES_MENU: MenuItem[] =
|
|
36
|
-
{ icon: "▢", title: "Docs", desc: `Set up and use ${siteConfig.brand.name}.`, href: "/resources/docs" },
|
|
37
|
-
{ icon: "✎", title: "Guides", desc: "Playbooks and walkthroughs.", href: "/resources/guides" },
|
|
38
|
-
{ icon: "✦", title: "Changelog", desc: `What's new in ${siteConfig.brand.name}.`, href: "/resources/changelog" },
|
|
39
|
-
{ icon: "⌘", title: "API reference", desc: `Build on the ${siteConfig.brand.name} API.`, href: "/resources/api" },
|
|
40
|
-
{ icon: "◈", title: "Compare", desc: `See how ${siteConfig.brand.name} stacks up.`, href: `/compare/${COMPARISONS[0].slug}` },
|
|
41
|
-
];
|
|
33
|
+
const RESOURCES_MENU: MenuItem[] = siteConfig.resourcesMenu;
|
|
42
34
|
|
|
43
|
-
// A hover/focus dropdown
|
|
44
|
-
// component
|
|
35
|
+
// A hover/focus dropdown in pure CSS (`group`), so the nav stays a server
|
|
36
|
+
// component with no client JS.
|
|
45
37
|
function NavDropdown({ label, items }: { label: string; items: MenuItem[] }) {
|
|
46
38
|
return (
|
|
47
39
|
<div className="group relative">
|
|
48
40
|
<button
|
|
49
41
|
type="button"
|
|
50
42
|
aria-haspopup="menu"
|
|
51
|
-
className="flex items-center gap-1 text-[13.5px] text-zinc-600 transition-colors hover:text-zinc-
|
|
43
|
+
className="flex items-center gap-1 rounded-full px-3 py-1.5 text-[13.5px] text-zinc-600 transition-colors hover:text-zinc-950 group-hover:text-zinc-950"
|
|
52
44
|
>
|
|
53
45
|
{label}
|
|
54
|
-
<
|
|
46
|
+
<ChevronDown className="size-3.5 text-zinc-400 transition-transform duration-200 group-hover:rotate-180" />
|
|
55
47
|
</button>
|
|
56
|
-
{/* `pt-
|
|
57
|
-
<div className="invisible absolute left-0 top-full z-40 w-[340px] translate-y-1 pt-
|
|
58
|
-
<div className="rounded-2xl
|
|
48
|
+
{/* `pt-2` (padding, not margin) bridges the gap so hover doesn't drop. */}
|
|
49
|
+
<div className="invisible absolute left-0 top-full z-40 w-[340px] translate-y-1 pt-2 opacity-0 transition-all duration-200 ease-[cubic-bezier(0.32,0.72,0,1)] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-within:visible group-focus-within:translate-y-0 group-focus-within:opacity-100">
|
|
50
|
+
<div className="rounded-2xl bg-white p-1.5 shadow-[0_0_0_1px_rgba(0,0,0,0.06),0_24px_60px_-20px_rgba(0,0,0,0.25)]">
|
|
59
51
|
{items.map((it) => (
|
|
60
52
|
<a
|
|
61
53
|
key={it.title}
|
|
62
54
|
href={it.href}
|
|
63
|
-
className="flex items-start gap-3 rounded-xl p-
|
|
55
|
+
className="flex items-start gap-3 rounded-xl p-2.5 transition-colors hover:bg-zinc-50"
|
|
64
56
|
>
|
|
65
|
-
<span className="mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-lg bg-
|
|
66
|
-
|
|
57
|
+
<span className="mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-lg bg-white text-zinc-700 shadow-[0_0_0_1px_rgba(0,0,0,0.07)]">
|
|
58
|
+
<it.icon className="size-4" strokeWidth={1.75} />
|
|
67
59
|
</span>
|
|
68
60
|
<span className="min-w-0">
|
|
69
|
-
<span className="block text-[13.5px] font-medium text-zinc-900">
|
|
70
|
-
|
|
71
|
-
</span>
|
|
72
|
-
<span className="block text-[12.5px] leading-snug text-zinc-500">
|
|
73
|
-
{it.desc}
|
|
74
|
-
</span>
|
|
61
|
+
<span className="block text-[13.5px] font-medium text-zinc-900">{it.title}</span>
|
|
62
|
+
<span className="block text-[12.5px] leading-snug text-zinc-500">{it.desc}</span>
|
|
75
63
|
</span>
|
|
76
64
|
</a>
|
|
77
65
|
))}
|
|
@@ -81,68 +69,50 @@ function NavDropdown({ label, items }: { label: string; items: MenuItem[] }) {
|
|
|
81
69
|
);
|
|
82
70
|
}
|
|
83
71
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
width="10"
|
|
88
|
-
height="10"
|
|
89
|
-
viewBox="0 0 10 10"
|
|
90
|
-
fill="none"
|
|
91
|
-
aria-hidden
|
|
92
|
-
className="text-zinc-400 transition-transform duration-200 group-hover:rotate-180"
|
|
93
|
-
>
|
|
94
|
-
<path
|
|
95
|
-
d="M2 3.5L5 6.5L8 3.5"
|
|
96
|
-
stroke="currentColor"
|
|
97
|
-
strokeWidth="1.5"
|
|
98
|
-
strokeLinecap="round"
|
|
99
|
-
strokeLinejoin="round"
|
|
100
|
-
/>
|
|
101
|
-
</svg>
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Mobile menu — the desktop nav is `hidden md:flex`, so on phones this is the
|
|
106
|
-
// only way to reach Product / Resources / Pricing. Pure-CSS via native
|
|
107
|
-
// `<details>` (no client JS, same pattern as the FAQ + user menu); plain `<a>`
|
|
108
|
-
// links do a full navigation, which closes the open panel. md:hidden so it
|
|
109
|
-
// never shows alongside the desktop nav.
|
|
72
|
+
// Below md the desktop nav is hidden and this menu is the way to reach the
|
|
73
|
+
// pages. Native `<details>`, so it needs no client JS; a link click does a
|
|
74
|
+
// full navigation, which closes it.
|
|
110
75
|
function MobileNav({ signedIn }: { signedIn: boolean }) {
|
|
111
76
|
return (
|
|
112
77
|
<details className="md:hidden">
|
|
113
78
|
<summary
|
|
114
79
|
aria-label="Open menu"
|
|
115
|
-
className="flex size-9 cursor-pointer select-none list-none items-center justify-center rounded-
|
|
80
|
+
className="flex size-9 cursor-pointer select-none list-none items-center justify-center rounded-full text-zinc-700 transition-colors marker:hidden hover:bg-zinc-100 [&::-webkit-details-marker]:hidden"
|
|
116
81
|
>
|
|
117
|
-
<
|
|
118
|
-
<path d="M3 6h18M3 12h18M3 18h18" />
|
|
119
|
-
</svg>
|
|
82
|
+
<Menu className="size-[18px]" strokeWidth={1.75} />
|
|
120
83
|
</summary>
|
|
121
|
-
<div className="fixed inset-x-0 top-14 z-40 max-h-[calc(
|
|
122
|
-
<div className="mx-auto max-w-
|
|
84
|
+
<div className="fixed inset-x-0 top-14 z-40 max-h-[calc(100dvh-3.5rem)] overflow-y-auto border-b border-zinc-200 bg-white shadow-[0_24px_48px_-24px_rgba(0,0,0,0.25)]">
|
|
85
|
+
<div className="mx-auto max-w-6xl space-y-6 px-4 py-6">
|
|
123
86
|
<MobileGroup title="Product" items={PRODUCT_MENU} />
|
|
124
87
|
<MobileGroup title="Resources" items={RESOURCES_MENU} />
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
</a>
|
|
132
|
-
</div>
|
|
88
|
+
<a
|
|
89
|
+
href="/pricing"
|
|
90
|
+
className="block rounded-lg px-2 py-2 text-[15px] font-medium text-zinc-800 transition-colors hover:bg-zinc-50"
|
|
91
|
+
>
|
|
92
|
+
Pricing
|
|
93
|
+
</a>
|
|
133
94
|
<div className="flex flex-col gap-2 border-t border-zinc-100 pt-5">
|
|
134
95
|
{signedIn ? (
|
|
135
|
-
<a
|
|
96
|
+
<a
|
|
97
|
+
href="/dashboard"
|
|
98
|
+
className="inline-flex h-11 items-center justify-center rounded-full bg-zinc-950 text-[14px] font-medium text-white"
|
|
99
|
+
>
|
|
136
100
|
Open dashboard
|
|
137
101
|
</a>
|
|
138
102
|
) : (
|
|
139
103
|
<>
|
|
140
|
-
<a
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
104
|
+
<a
|
|
105
|
+
href="/signup"
|
|
106
|
+
className="inline-flex h-11 items-center justify-center rounded-full bg-zinc-950 text-[14px] font-medium text-white"
|
|
107
|
+
>
|
|
144
108
|
Get started
|
|
145
109
|
</a>
|
|
110
|
+
<a
|
|
111
|
+
href="/login"
|
|
112
|
+
className="inline-flex h-11 items-center justify-center rounded-full text-[14px] font-medium text-zinc-900 ring-1 ring-zinc-200"
|
|
113
|
+
>
|
|
114
|
+
Log in
|
|
115
|
+
</a>
|
|
146
116
|
</>
|
|
147
117
|
)}
|
|
148
118
|
</div>
|
|
@@ -155,19 +125,15 @@ function MobileNav({ signedIn }: { signedIn: boolean }) {
|
|
|
155
125
|
function MobileGroup({ title, items }: { title: string; items: MenuItem[] }) {
|
|
156
126
|
return (
|
|
157
127
|
<div>
|
|
158
|
-
<div className="mb-1
|
|
159
|
-
{title}
|
|
160
|
-
</div>
|
|
128
|
+
<div className="mb-1 px-2 text-[13px] font-medium text-zinc-400">{title}</div>
|
|
161
129
|
<div className="flex flex-col">
|
|
162
130
|
{items.map((it) => (
|
|
163
131
|
<a
|
|
164
132
|
key={it.href}
|
|
165
133
|
href={it.href}
|
|
166
|
-
className="flex items-center gap-3 rounded-lg px-2 py-2 text-[
|
|
134
|
+
className="flex items-center gap-3 rounded-lg px-2 py-2 text-[15px] text-zinc-800 transition-colors hover:bg-zinc-50"
|
|
167
135
|
>
|
|
168
|
-
<
|
|
169
|
-
{it.icon}
|
|
170
|
-
</span>
|
|
136
|
+
<it.icon className="size-4 text-zinc-500" strokeWidth={1.75} />
|
|
171
137
|
{it.title}
|
|
172
138
|
</a>
|
|
173
139
|
))}
|
|
@@ -176,66 +142,62 @@ function MobileGroup({ title, items }: { title: string; items: MenuItem[] }) {
|
|
|
176
142
|
);
|
|
177
143
|
}
|
|
178
144
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
145
|
+
function Logo() {
|
|
146
|
+
return (
|
|
147
|
+
<Link href="/" className="flex items-center gap-2">
|
|
148
|
+
<span className="flex size-6 items-center justify-center rounded-[7px] bg-zinc-950 text-[13px] font-bold text-white">
|
|
149
|
+
{siteConfig.brand.letter}
|
|
150
|
+
</span>
|
|
151
|
+
<span className="text-[15px] font-semibold tracking-tight text-zinc-950">{siteConfig.brand.name}</span>
|
|
152
|
+
</Link>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// `<main>` is full-bleed; each page owns its container.
|
|
182
157
|
export default function MarketingLayout({ children, auth }: LayoutProps) {
|
|
183
158
|
const signedIn = Boolean(auth?.user_id);
|
|
184
159
|
return (
|
|
185
160
|
<>
|
|
186
|
-
<header className="sticky top-0 z-30 bg-white/
|
|
187
|
-
<div className="mx-auto flex h-14 max-w-
|
|
188
|
-
<div className="flex items-center gap-
|
|
189
|
-
<
|
|
190
|
-
|
|
191
|
-
{siteConfig.brand.letter}
|
|
192
|
-
</span>
|
|
193
|
-
<span className="text-[15px] font-semibold tracking-tight text-zinc-900">
|
|
194
|
-
{siteConfig.brand.name}
|
|
195
|
-
</span>
|
|
196
|
-
</Link>
|
|
197
|
-
<nav className="hidden items-center gap-6 md:flex">
|
|
161
|
+
<header className="sticky top-0 z-30 border-b border-zinc-950/[0.06] bg-white/75 backdrop-blur-xl">
|
|
162
|
+
<div className="mx-auto flex h-14 max-w-6xl items-center justify-between px-4 sm:px-6">
|
|
163
|
+
<div className="flex items-center gap-6">
|
|
164
|
+
<Logo />
|
|
165
|
+
<nav className="hidden items-center md:flex">
|
|
198
166
|
<NavDropdown label="Product" items={PRODUCT_MENU} />
|
|
199
167
|
<NavDropdown label="Resources" items={RESOURCES_MENU} />
|
|
200
168
|
<Link
|
|
201
169
|
href="/pricing"
|
|
202
|
-
className="text-[13.5px] text-zinc-600 transition-colors hover:text-zinc-
|
|
170
|
+
className="rounded-full px-3 py-1.5 text-[13.5px] text-zinc-600 transition-colors hover:text-zinc-950"
|
|
203
171
|
>
|
|
204
172
|
Pricing
|
|
205
173
|
</Link>
|
|
206
|
-
<Link
|
|
207
|
-
href="/#customers"
|
|
208
|
-
className="text-[13.5px] text-zinc-600 transition-colors hover:text-zinc-900"
|
|
209
|
-
>
|
|
210
|
-
Customers
|
|
211
|
-
</Link>
|
|
212
174
|
</nav>
|
|
213
175
|
</div>
|
|
214
|
-
<nav className="flex items-center gap-
|
|
215
|
-
<MobileNav signedIn={signedIn} />
|
|
176
|
+
<nav className="flex items-center gap-1.5">
|
|
216
177
|
{signedIn ? (
|
|
217
178
|
<Link
|
|
218
179
|
href="/dashboard"
|
|
219
|
-
className="inline-flex items-center rounded-full bg-zinc-
|
|
180
|
+
className="inline-flex h-8 items-center rounded-full bg-zinc-950 px-3.5 text-[13px] font-medium text-white transition-colors hover:bg-zinc-800"
|
|
220
181
|
>
|
|
221
|
-
|
|
182
|
+
Open dashboard
|
|
222
183
|
</Link>
|
|
223
184
|
) : (
|
|
224
185
|
<>
|
|
225
186
|
<Link
|
|
226
187
|
href="/login"
|
|
227
|
-
className="hidden rounded-full px-3
|
|
188
|
+
className="hidden h-8 items-center rounded-full px-3 text-[13px] font-medium text-zinc-600 transition-colors hover:text-zinc-950 sm:inline-flex"
|
|
228
189
|
>
|
|
229
190
|
Log in
|
|
230
191
|
</Link>
|
|
231
192
|
<Link
|
|
232
193
|
href="/signup"
|
|
233
|
-
className="inline-flex items-center rounded-full bg-zinc-
|
|
194
|
+
className="inline-flex h-8 items-center rounded-full bg-zinc-950 px-3.5 text-[13px] font-medium text-white transition-colors hover:bg-zinc-800"
|
|
234
195
|
>
|
|
235
196
|
Get started
|
|
236
197
|
</Link>
|
|
237
198
|
</>
|
|
238
199
|
)}
|
|
200
|
+
<MobileNav signedIn={signedIn} />
|
|
239
201
|
</nav>
|
|
240
202
|
</div>
|
|
241
203
|
</header>
|
|
@@ -247,165 +209,77 @@ export default function MarketingLayout({ children, auth }: LayoutProps) {
|
|
|
247
209
|
);
|
|
248
210
|
}
|
|
249
211
|
|
|
250
|
-
// Footer link groups, derived from the same data the pages use so every
|
|
251
|
-
// resolves to a real route.
|
|
252
|
-
type
|
|
253
|
-
type FooterGroupData = { title: string; links: FooterLink[] };
|
|
254
|
-
|
|
255
|
-
const SOLUTION_ICONS = ["◆", "◈", "▣", "◎"];
|
|
256
|
-
const RESOURCE_ICONS: Record<string, string> = {
|
|
257
|
-
docs: "▢",
|
|
258
|
-
guides: "✎",
|
|
259
|
-
changelog: "✦",
|
|
260
|
-
api: "⌘",
|
|
261
|
-
status: "◉",
|
|
262
|
-
};
|
|
263
|
-
const COMPANY_ICONS = ["◍", "≣", "◆", "✉", "▢"];
|
|
212
|
+
// Footer link groups, derived from the same data the pages use, so every
|
|
213
|
+
// link resolves to a real route.
|
|
214
|
+
type FooterGroupData = { title: string; links: { label: string; href: string }[] };
|
|
264
215
|
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
label: p.title,
|
|
270
|
-
href:
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
icon: RESOURCE_ICONS[r.slug] ?? "▢",
|
|
290
|
-
})),
|
|
291
|
-
};
|
|
292
|
-
const COMPANY_GROUP: FooterGroupData = {
|
|
293
|
-
title: "Company",
|
|
294
|
-
links: COMPANY.map((c, i) => ({
|
|
295
|
-
label: c.navLabel,
|
|
296
|
-
href: `/company/${c.slug}`,
|
|
297
|
-
icon: COMPANY_ICONS[i] ?? "◍",
|
|
298
|
-
})),
|
|
299
|
-
};
|
|
300
|
-
const COMPARE_GROUP: FooterGroupData = {
|
|
301
|
-
title: "Compare",
|
|
302
|
-
links: COMPARISONS.map((c) => ({
|
|
303
|
-
label: c.navLabel,
|
|
304
|
-
href: `/compare/${c.slug}`,
|
|
305
|
-
})),
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
function FooterGroup({
|
|
309
|
-
group,
|
|
310
|
-
className = "",
|
|
311
|
-
}: {
|
|
312
|
-
group: FooterGroupData;
|
|
313
|
-
className?: string;
|
|
314
|
-
}) {
|
|
315
|
-
return (
|
|
316
|
-
<div className={className}>
|
|
317
|
-
<div className="text-[11px] font-semibold uppercase tracking-wider text-zinc-900">
|
|
318
|
-
{group.title}
|
|
319
|
-
</div>
|
|
320
|
-
<div className="mt-4 flex flex-col gap-2.5">
|
|
321
|
-
{group.links.map((l) => (
|
|
322
|
-
<Link
|
|
323
|
-
key={l.href}
|
|
324
|
-
href={l.href}
|
|
325
|
-
className="group flex items-center gap-2 text-[13px] text-zinc-500 transition-colors hover:text-zinc-900"
|
|
326
|
-
>
|
|
327
|
-
{l.icon ? (
|
|
328
|
-
<span className="flex w-3.5 justify-center text-[11px] text-zinc-400 transition-colors group-hover:text-zinc-600">
|
|
329
|
-
{l.icon}
|
|
330
|
-
</span>
|
|
331
|
-
) : null}
|
|
332
|
-
{l.label}
|
|
333
|
-
</Link>
|
|
334
|
-
))}
|
|
335
|
-
</div>
|
|
336
|
-
</div>
|
|
337
|
-
);
|
|
338
|
-
}
|
|
216
|
+
const FOOTER_GROUPS: FooterGroupData[] = [
|
|
217
|
+
{
|
|
218
|
+
title: "Product",
|
|
219
|
+
links: [
|
|
220
|
+
...PRODUCTS.map((p) => ({ label: p.title, href: `/products/${p.slug}` })),
|
|
221
|
+
{ label: "Pricing", href: "/pricing" },
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
title: "Solutions",
|
|
226
|
+
links: [
|
|
227
|
+
...SOLUTIONS.map((s) => ({ label: s.navLabel, href: `/solutions/${s.slug}` })),
|
|
228
|
+
...COMPARISONS.map((c) => ({ label: c.navLabel, href: `/compare/${c.slug}` })),
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
title: "Resources",
|
|
233
|
+
links: RESOURCES.map((r) => ({ label: r.navLabel, href: `/resources/${r.slug}` })),
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
title: "Company",
|
|
237
|
+
links: COMPANY.map((c) => ({ label: c.navLabel, href: `/company/${c.slug}` })),
|
|
238
|
+
},
|
|
239
|
+
];
|
|
339
240
|
|
|
340
241
|
function SiteFooter() {
|
|
341
242
|
return (
|
|
342
243
|
<footer className="border-t border-zinc-200/70 bg-white">
|
|
343
|
-
<div className="mx-auto max-w-
|
|
344
|
-
{/* Brand block */}
|
|
244
|
+
<div className="mx-auto grid max-w-6xl gap-12 px-4 py-14 sm:px-6 lg:grid-cols-[minmax(0,1fr)_minmax(0,2fr)]">
|
|
345
245
|
<div className="max-w-xs">
|
|
346
|
-
<
|
|
347
|
-
|
|
348
|
-
{siteConfig.brand.letter}
|
|
349
|
-
</span>
|
|
350
|
-
<span className="text-[15px] font-semibold tracking-tight text-zinc-900">
|
|
351
|
-
{siteConfig.brand.name}
|
|
352
|
-
</span>
|
|
353
|
-
</Link>
|
|
354
|
-
<p className="mt-4 text-[13px] leading-relaxed text-zinc-500">
|
|
355
|
-
{siteConfig.brand.footerBlurb}
|
|
356
|
-
</p>
|
|
246
|
+
<Logo />
|
|
247
|
+
<p className="mt-4 text-[13.5px] leading-relaxed text-zinc-500">{siteConfig.brand.footerBlurb}</p>
|
|
357
248
|
<div className="mt-5 flex items-center gap-4">
|
|
358
249
|
{siteConfig.brand.socials.map((s) => (
|
|
359
250
|
<a
|
|
360
251
|
key={s.label}
|
|
361
252
|
href={s.href}
|
|
362
253
|
aria-label={s.label}
|
|
363
|
-
className="text-zinc-400 transition-colors hover:text-zinc-
|
|
254
|
+
className="text-zinc-400 transition-colors hover:text-zinc-950"
|
|
364
255
|
>
|
|
365
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
256
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden>
|
|
366
257
|
<path d={s.path} />
|
|
367
258
|
</svg>
|
|
368
259
|
</a>
|
|
369
260
|
))}
|
|
370
|
-
<a
|
|
371
|
-
href={`mailto:${siteConfig.brand.email}`}
|
|
372
|
-
aria-label="Email"
|
|
373
|
-
className="text-zinc-400 transition-colors hover:text-zinc-900"
|
|
374
|
-
>
|
|
375
|
-
<svg
|
|
376
|
-
width="16"
|
|
377
|
-
height="16"
|
|
378
|
-
viewBox="0 0 24 24"
|
|
379
|
-
fill="none"
|
|
380
|
-
stroke="currentColor"
|
|
381
|
-
strokeWidth="2"
|
|
382
|
-
>
|
|
383
|
-
<rect x="3" y="5" width="18" height="14" rx="2" />
|
|
384
|
-
<path d="m3 7 9 6 9-6" />
|
|
385
|
-
</svg>
|
|
386
|
-
</a>
|
|
387
|
-
</div>
|
|
388
|
-
</div>
|
|
389
|
-
|
|
390
|
-
{/* Link columns */}
|
|
391
|
-
<div className="mt-12 grid gap-x-8 gap-y-12 sm:grid-cols-2 lg:grid-cols-3">
|
|
392
|
-
<div>
|
|
393
|
-
<FooterGroup group={PRODUCT_GROUP} />
|
|
394
|
-
<FooterGroup group={SOLUTIONS_GROUP} className="mt-10" />
|
|
395
|
-
</div>
|
|
396
|
-
<div>
|
|
397
|
-
<FooterGroup group={RESOURCES_GROUP} />
|
|
398
|
-
<FooterGroup group={COMPANY_GROUP} className="mt-10" />
|
|
399
|
-
</div>
|
|
400
|
-
<div>
|
|
401
|
-
<FooterGroup group={COMPARE_GROUP} />
|
|
402
261
|
</div>
|
|
403
262
|
</div>
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
263
|
+
<div className="grid grid-cols-2 gap-x-6 gap-y-10 sm:grid-cols-4">
|
|
264
|
+
{FOOTER_GROUPS.map((g) => (
|
|
265
|
+
<div key={g.title}>
|
|
266
|
+
<div className="text-[13px] font-medium text-zinc-950">{g.title}</div>
|
|
267
|
+
<ul className="mt-3.5 space-y-2.5">
|
|
268
|
+
{g.links.map((l) => (
|
|
269
|
+
<li key={l.href}>
|
|
270
|
+
<Link href={l.href} className="text-[13px] text-zinc-500 transition-colors hover:text-zinc-950">
|
|
271
|
+
{l.label}
|
|
272
|
+
</Link>
|
|
273
|
+
</li>
|
|
274
|
+
))}
|
|
275
|
+
</ul>
|
|
276
|
+
</div>
|
|
277
|
+
))}
|
|
407
278
|
</div>
|
|
408
279
|
</div>
|
|
280
|
+
<div className="mx-auto max-w-6xl border-t border-zinc-200/70 px-4 py-6 text-[12.5px] text-zinc-400 sm:px-6">
|
|
281
|
+
© {new Date().getFullYear()} {siteConfig.brand.copyrightName}
|
|
282
|
+
</div>
|
|
409
283
|
</footer>
|
|
410
284
|
);
|
|
411
285
|
}
|