create-nymbal-app 0.0.0 → 0.2.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.
Files changed (159) hide show
  1. package/bin/create-nymbal-app.mjs +9 -0
  2. package/dist/index.d.ts +37 -0
  3. package/dist/index.js +419 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +41 -7
  6. package/scaffold/project/astro/src/pages/index.astro +57 -0
  7. package/scaffold/templates/astro/README.md +26 -0
  8. package/scaffold/templates/astro/_dot.env.example +6 -0
  9. package/scaffold/templates/astro/_dot.gitignore +16 -0
  10. package/scaffold/templates/astro/_dot.node-version +1 -0
  11. package/scaffold/templates/astro/_dot.npmrc +1 -0
  12. package/scaffold/templates/astro/astro.config.mjs +14 -0
  13. package/scaffold/templates/astro/package.json +59 -0
  14. package/scaffold/templates/astro/src/components/AddressForm.astro +107 -0
  15. package/scaffold/templates/astro/src/components/Breadcrumb.astro +20 -0
  16. package/scaffold/templates/astro/src/components/CategoryNav.astro +27 -0
  17. package/scaffold/templates/astro/src/components/CheckoutSteps.astro +29 -0
  18. package/scaffold/templates/astro/src/components/Footer.astro +108 -0
  19. package/scaffold/templates/astro/src/components/Header.astro +192 -0
  20. package/scaffold/templates/astro/src/components/HeroSection.astro +17 -0
  21. package/scaffold/templates/astro/src/components/ImageGallery.astro +42 -0
  22. package/scaffold/templates/astro/src/components/NewsletterSignup.astro +39 -0
  23. package/scaffold/templates/astro/src/components/OrderSummary.astro +53 -0
  24. package/scaffold/templates/astro/src/components/Pagination.astro +13 -0
  25. package/scaffold/templates/astro/src/components/PriceDisplay.astro +25 -0
  26. package/scaffold/templates/astro/src/components/ProductCard.astro +44 -0
  27. package/scaffold/templates/astro/src/components/RelatedProducts.astro +28 -0
  28. package/scaffold/templates/astro/src/components/ReviewForm.astro +100 -0
  29. package/scaffold/templates/astro/src/components/ReviewList.astro +41 -0
  30. package/scaffold/templates/astro/src/components/SkipNav.astro +3 -0
  31. package/scaffold/templates/astro/src/components/SortDropdown.astro +26 -0
  32. package/scaffold/templates/astro/src/components/StockBadge.astro +32 -0
  33. package/scaffold/templates/astro/src/env.d.ts +2 -0
  34. package/scaffold/templates/astro/src/layouts/AccountLayout.astro +168 -0
  35. package/scaffold/templates/astro/src/layouts/BaseLayout.astro +55 -0
  36. package/scaffold/templates/astro/src/lib/api.ts +89 -0
  37. package/scaffold/templates/astro/src/lib/client.ts +13 -0
  38. package/scaffold/templates/astro/src/lib/format.ts +17 -0
  39. package/scaffold/templates/astro/src/lib/order-status.ts +14 -0
  40. package/scaffold/templates/astro/src/lib/seo.ts +62 -0
  41. package/scaffold/templates/astro/src/pages/404.astro +18 -0
  42. package/scaffold/templates/astro/src/pages/500.astro +17 -0
  43. package/scaffold/templates/astro/src/pages/account/addresses.astro +110 -0
  44. package/scaffold/templates/astro/src/pages/account/index.astro +67 -0
  45. package/scaffold/templates/astro/src/pages/account/login.astro +55 -0
  46. package/scaffold/templates/astro/src/pages/account/orders/[orderNumber].astro +108 -0
  47. package/scaffold/templates/astro/src/pages/account/orders.astro +81 -0
  48. package/scaffold/templates/astro/src/pages/account/profile.astro +131 -0
  49. package/scaffold/templates/astro/src/pages/account/register.astro +94 -0
  50. package/scaffold/templates/astro/src/pages/cart.astro +16 -0
  51. package/scaffold/templates/astro/src/pages/category/[slug].astro +73 -0
  52. package/scaffold/templates/astro/src/pages/checkout.astro +100 -0
  53. package/scaffold/templates/astro/src/pages/fragments/footer.astro +5 -0
  54. package/scaffold/templates/astro/src/pages/fragments/header.astro +5 -0
  55. package/scaffold/templates/astro/src/pages/fragments/nav.astro +9 -0
  56. package/scaffold/templates/astro/src/pages/fragments/product/[slug].astro +14 -0
  57. package/scaffold/templates/astro/src/pages/index.astro +49 -0
  58. package/scaffold/templates/astro/src/pages/order/[orderNumber].astro +127 -0
  59. package/scaffold/templates/astro/src/pages/product/[slug].astro +107 -0
  60. package/scaffold/templates/astro/src/pages/products/index.astro +62 -0
  61. package/scaffold/templates/astro/src/pages/search.astro +37 -0
  62. package/scaffold/templates/astro/src/scripts/account-guard.ts +22 -0
  63. package/scaffold/templates/astro/src/scripts/auth-forms.ts +89 -0
  64. package/scaffold/templates/astro/src/scripts/cart-page.ts +143 -0
  65. package/scaffold/templates/astro/src/scripts/checkout.ts +277 -0
  66. package/scaffold/templates/astro/src/scripts/image-gallery.ts +22 -0
  67. package/scaffold/templates/astro/src/scripts/init-client.ts +16 -0
  68. package/scaffold/templates/astro/src/scripts/order-status.ts +27 -0
  69. package/scaffold/templates/astro/src/scripts/pdp.ts +67 -0
  70. package/scaffold/templates/astro/src/scripts/plp.ts +109 -0
  71. package/scaffold/templates/astro/src/scripts/search.ts +145 -0
  72. package/scaffold/templates/astro/src/styles/global.css +362 -0
  73. package/scaffold/templates/astro/src/styles/pages/account.css +331 -0
  74. package/scaffold/templates/astro/src/styles/pages/cart.css +243 -0
  75. package/scaffold/templates/astro/src/styles/pages/checkout.css +270 -0
  76. package/scaffold/templates/astro/src/styles/pages/confirmation.css +142 -0
  77. package/scaffold/templates/astro/src/styles/pages/error.css +69 -0
  78. package/scaffold/templates/astro/src/styles/pages/home.css +269 -0
  79. package/scaffold/templates/astro/src/styles/pages/pdp.css +272 -0
  80. package/scaffold/templates/astro/src/styles/pages/plp.css +213 -0
  81. package/scaffold/templates/astro/src/styles/pages/search.css +152 -0
  82. package/scaffold/templates/astro/tsconfig.json +3 -0
  83. package/scaffold/templates/nextjs/README.md +26 -0
  84. package/scaffold/templates/nextjs/_dot.env.example +6 -0
  85. package/scaffold/templates/nextjs/_dot.gitignore +17 -0
  86. package/scaffold/templates/nextjs/_dot.node-version +1 -0
  87. package/scaffold/templates/nextjs/_dot.npmrc +1 -0
  88. package/scaffold/templates/nextjs/app/account/addresses/page.tsx +10 -0
  89. package/scaffold/templates/nextjs/app/account/layout.tsx +57 -0
  90. package/scaffold/templates/nextjs/app/account/login/page.tsx +23 -0
  91. package/scaffold/templates/nextjs/app/account/orders/[orderNumber]/page.tsx +192 -0
  92. package/scaffold/templates/nextjs/app/account/orders/page.tsx +123 -0
  93. package/scaffold/templates/nextjs/app/account/page.tsx +59 -0
  94. package/scaffold/templates/nextjs/app/account/profile/page.tsx +10 -0
  95. package/scaffold/templates/nextjs/app/account/register/page.tsx +10 -0
  96. package/scaffold/templates/nextjs/app/cart/page.tsx +10 -0
  97. package/scaffold/templates/nextjs/app/category/[slug]/page.tsx +58 -0
  98. package/scaffold/templates/nextjs/app/checkout/page.tsx +10 -0
  99. package/scaffold/templates/nextjs/app/error.tsx +49 -0
  100. package/scaffold/templates/nextjs/app/globals.css +473 -0
  101. package/scaffold/templates/nextjs/app/layout.tsx +29 -0
  102. package/scaffold/templates/nextjs/app/not-found.tsx +38 -0
  103. package/scaffold/templates/nextjs/app/order/[orderNumber]/page.tsx +127 -0
  104. package/scaffold/templates/nextjs/app/page.tsx +63 -0
  105. package/scaffold/templates/nextjs/app/product/[slug]/page.tsx +111 -0
  106. package/scaffold/templates/nextjs/app/products/page.tsx +40 -0
  107. package/scaffold/templates/nextjs/app/search/page.tsx +24 -0
  108. package/scaffold/templates/nextjs/components/client/AddressManager.tsx +181 -0
  109. package/scaffold/templates/nextjs/components/client/AuthGuard.tsx +55 -0
  110. package/scaffold/templates/nextjs/components/client/CartDrawerToggle.tsx +39 -0
  111. package/scaffold/templates/nextjs/components/client/CartPage.tsx +120 -0
  112. package/scaffold/templates/nextjs/components/client/CheckoutForm.tsx +523 -0
  113. package/scaffold/templates/nextjs/components/client/ImageGallery.tsx +68 -0
  114. package/scaffold/templates/nextjs/components/client/LoginForm.tsx +89 -0
  115. package/scaffold/templates/nextjs/components/client/MiniCartWrapper.tsx +12 -0
  116. package/scaffold/templates/nextjs/components/client/NewsletterSignup.tsx +74 -0
  117. package/scaffold/templates/nextjs/components/client/NymbalSetup.tsx +24 -0
  118. package/scaffold/templates/nextjs/components/client/OrderStatusRefresh.tsx +48 -0
  119. package/scaffold/templates/nextjs/components/client/ProductGrid.tsx +148 -0
  120. package/scaffold/templates/nextjs/components/client/ProductInteractive.tsx +61 -0
  121. package/scaffold/templates/nextjs/components/client/ProfileForm.tsx +112 -0
  122. package/scaffold/templates/nextjs/components/client/RegisterForm.tsx +131 -0
  123. package/scaffold/templates/nextjs/components/client/ReviewForm.tsx +116 -0
  124. package/scaffold/templates/nextjs/components/client/SearchBarWrapper.tsx +27 -0
  125. package/scaffold/templates/nextjs/components/client/SearchResults.tsx +141 -0
  126. package/scaffold/templates/nextjs/components/client/SortDropdown.tsx +35 -0
  127. package/scaffold/templates/nextjs/components/server/Breadcrumb.tsx +36 -0
  128. package/scaffold/templates/nextjs/components/server/CategoryNav.tsx +29 -0
  129. package/scaffold/templates/nextjs/components/server/CheckoutSteps.tsx +60 -0
  130. package/scaffold/templates/nextjs/components/server/Footer.module.css +64 -0
  131. package/scaffold/templates/nextjs/components/server/Footer.tsx +79 -0
  132. package/scaffold/templates/nextjs/components/server/Header.module.css +147 -0
  133. package/scaffold/templates/nextjs/components/server/Header.tsx +102 -0
  134. package/scaffold/templates/nextjs/components/server/HeroSection.tsx +18 -0
  135. package/scaffold/templates/nextjs/components/server/OrderSummary.tsx +79 -0
  136. package/scaffold/templates/nextjs/components/server/PriceDisplay.tsx +31 -0
  137. package/scaffold/templates/nextjs/components/server/ProductCard.tsx +59 -0
  138. package/scaffold/templates/nextjs/components/server/RelatedProducts.tsx +31 -0
  139. package/scaffold/templates/nextjs/components/server/ReviewList.tsx +62 -0
  140. package/scaffold/templates/nextjs/components/server/SkipNav.tsx +7 -0
  141. package/scaffold/templates/nextjs/components/server/StockBadge.tsx +19 -0
  142. package/scaffold/templates/nextjs/lib/api.ts +89 -0
  143. package/scaffold/templates/nextjs/lib/client.ts +23 -0
  144. package/scaffold/templates/nextjs/lib/format.ts +7 -0
  145. package/scaffold/templates/nextjs/lib/order-status.ts +14 -0
  146. package/scaffold/templates/nextjs/lib/seo.ts +73 -0
  147. package/scaffold/templates/nextjs/next.config.mjs +9 -0
  148. package/scaffold/templates/nextjs/package.json +64 -0
  149. package/scaffold/templates/nextjs/styles/pages/account.module.css +377 -0
  150. package/scaffold/templates/nextjs/styles/pages/cart.module.css +240 -0
  151. package/scaffold/templates/nextjs/styles/pages/checkout.module.css +404 -0
  152. package/scaffold/templates/nextjs/styles/pages/confirmation.module.css +237 -0
  153. package/scaffold/templates/nextjs/styles/pages/error.module.css +132 -0
  154. package/scaffold/templates/nextjs/styles/pages/home.module.css +285 -0
  155. package/scaffold/templates/nextjs/styles/pages/pdp.module.css +319 -0
  156. package/scaffold/templates/nextjs/styles/pages/plp.module.css +280 -0
  157. package/scaffold/templates/nextjs/styles/pages/search.module.css +192 -0
  158. package/scaffold/templates/nextjs/tsconfig.json +41 -0
  159. package/README.md +0 -4
@@ -0,0 +1,213 @@
1
+ /* ----------------------------------------------------------------
2
+ Product listing page (PLP) styles
3
+ ---------------------------------------------------------------- */
4
+
5
+ /* ---- Page layout ---- */
6
+
7
+ .plp-layout {
8
+ display: grid;
9
+ grid-template-columns: 1fr;
10
+ gap: var(--nymbal-spacing-lg, 1.5rem);
11
+ }
12
+
13
+ @media (min-width: 769px) {
14
+ .plp-layout {
15
+ grid-template-columns: 240px 1fr;
16
+ gap: var(--nymbal-spacing-xl, 2rem);
17
+ }
18
+ }
19
+
20
+ /* ---- Page header / breadcrumbs ---- */
21
+
22
+ .plp-header {
23
+ margin-bottom: var(--nymbal-spacing-md, 1rem);
24
+ }
25
+
26
+ .plp-title {
27
+ font-size: 1.75rem;
28
+ font-weight: var(--nymbal-font-weight-bold, 700);
29
+ color: var(--nymbal-color-primary, #18181b);
30
+ margin-bottom: var(--nymbal-spacing-xs, 0.25rem);
31
+ }
32
+
33
+ .plp-count {
34
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
35
+ color: var(--nymbal-color-text-muted, #71717a);
36
+ }
37
+
38
+ /* ---- Filter sidebar ---- */
39
+
40
+ .plp-sidebar {
41
+ display: none;
42
+ }
43
+
44
+ @media (min-width: 769px) {
45
+ .plp-sidebar {
46
+ display: block;
47
+ position: sticky;
48
+ top: 80px;
49
+ align-self: start;
50
+ max-height: calc(100vh - 100px);
51
+ overflow-y: auto;
52
+ }
53
+ }
54
+
55
+ .filter-section {
56
+ border-bottom: 1px solid var(--nymbal-color-border, #e4e4e7);
57
+ padding-bottom: var(--nymbal-spacing-md, 1rem);
58
+ margin-bottom: var(--nymbal-spacing-md, 1rem);
59
+ }
60
+
61
+ .filter-section:last-child {
62
+ border-bottom: none;
63
+ margin-bottom: 0;
64
+ }
65
+
66
+ .filter-heading {
67
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
68
+ font-weight: var(--nymbal-font-weight-bold, 700);
69
+ color: var(--nymbal-color-primary, #18181b);
70
+ margin-bottom: var(--nymbal-spacing-sm, 0.5rem);
71
+ text-transform: uppercase;
72
+ letter-spacing: 0.03em;
73
+ }
74
+
75
+ .filter-list {
76
+ display: flex;
77
+ flex-direction: column;
78
+ gap: var(--nymbal-spacing-xs, 0.25rem);
79
+ }
80
+
81
+ .filter-item {
82
+ display: flex;
83
+ align-items: center;
84
+ gap: var(--nymbal-spacing-sm, 0.5rem);
85
+ }
86
+
87
+ .filter-item label {
88
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
89
+ color: var(--nymbal-color-text, #18181b);
90
+ cursor: pointer;
91
+ margin-bottom: 0;
92
+ }
93
+
94
+ .filter-item input[type="checkbox"] {
95
+ width: 16px;
96
+ height: 16px;
97
+ accent-color: var(--nymbal-color-accent, #2563eb);
98
+ cursor: pointer;
99
+ }
100
+
101
+ .filter-link {
102
+ display: block;
103
+ padding: var(--nymbal-spacing-xs, 0.25rem) 0;
104
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
105
+ color: var(--nymbal-color-text, #18181b);
106
+ text-decoration: none;
107
+ transition: color var(--nymbal-transition-fast, 150ms) ease;
108
+ }
109
+
110
+ .filter-link:hover,
111
+ .filter-link[aria-current="page"] {
112
+ color: var(--nymbal-color-accent, #2563eb);
113
+ }
114
+
115
+ .filter-link[aria-current="page"] {
116
+ font-weight: var(--nymbal-font-weight-bold, 700);
117
+ }
118
+
119
+ /* Mobile filter toggle */
120
+
121
+ .plp-filter-toggle {
122
+ display: inline-flex;
123
+ align-items: center;
124
+ gap: var(--nymbal-spacing-xs, 0.25rem);
125
+ padding: var(--nymbal-spacing-sm, 0.5rem) var(--nymbal-spacing-md, 1rem);
126
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
127
+ font-weight: var(--nymbal-font-weight-medium, 500);
128
+ color: var(--nymbal-color-text, #18181b);
129
+ background: var(--nymbal-color-surface, #fff);
130
+ border: 1px solid var(--nymbal-color-border, #e4e4e7);
131
+ border-radius: var(--nymbal-radius-md, 0.5rem);
132
+ cursor: pointer;
133
+ }
134
+
135
+ @media (min-width: 769px) {
136
+ .plp-filter-toggle {
137
+ display: none;
138
+ }
139
+ }
140
+
141
+ /* ---- Sort bar ---- */
142
+
143
+ .plp-sort-bar {
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: space-between;
147
+ gap: var(--nymbal-spacing-sm, 0.5rem);
148
+ padding-bottom: var(--nymbal-spacing-md, 1rem);
149
+ border-bottom: 1px solid var(--nymbal-color-border, #e4e4e7);
150
+ margin-bottom: var(--nymbal-spacing-md, 1rem);
151
+ flex-wrap: wrap;
152
+ }
153
+
154
+ .plp-sort-bar label {
155
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
156
+ font-weight: var(--nymbal-font-weight-medium, 500);
157
+ color: var(--nymbal-color-text-muted, #71717a);
158
+ margin-bottom: 0;
159
+ }
160
+
161
+ .plp-sort-bar select {
162
+ width: auto;
163
+ min-width: 160px;
164
+ padding: var(--nymbal-spacing-xs, 0.25rem) var(--nymbal-spacing-sm, 0.5rem);
165
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
166
+ }
167
+
168
+ /* ---- Grid area ---- */
169
+
170
+ .plp-grid-area {
171
+ min-width: 0;
172
+ }
173
+
174
+ /* ---- Pagination ---- */
175
+
176
+ .plp-pagination {
177
+ display: flex;
178
+ justify-content: center;
179
+ gap: var(--nymbal-spacing-sm, 0.5rem);
180
+ margin-top: var(--nymbal-spacing-xl, 2rem);
181
+ padding-top: var(--nymbal-spacing-lg, 1.5rem);
182
+ border-top: 1px solid var(--nymbal-color-border, #e4e4e7);
183
+ }
184
+
185
+ .plp-pagination .btn {
186
+ min-width: 100px;
187
+ }
188
+
189
+ /* ---- Empty state ---- */
190
+
191
+ .plp-empty {
192
+ text-align: center;
193
+ padding: 4rem var(--nymbal-spacing-md, 1rem);
194
+ color: var(--nymbal-color-text-muted, #71717a);
195
+ }
196
+
197
+ .plp-empty-title {
198
+ font-size: var(--nymbal-font-size-lg, 1.125rem);
199
+ font-weight: var(--nymbal-font-weight-medium, 500);
200
+ color: var(--nymbal-color-text, #18181b);
201
+ margin-bottom: var(--nymbal-spacing-xs, 0.25rem);
202
+ }
203
+
204
+ .plp-empty-text {
205
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
206
+ }
207
+
208
+ /* ---- nymbal-product-filter integration ---- */
209
+
210
+ nymbal-product-filter {
211
+ display: block;
212
+ margin-bottom: var(--nymbal-spacing-md, 1rem);
213
+ }
@@ -0,0 +1,152 @@
1
+ /* ----------------------------------------------------------------
2
+ Search results page styles
3
+ ---------------------------------------------------------------- */
4
+
5
+ /* ---- Prominent search bar ---- */
6
+
7
+ .search-hero {
8
+ text-align: center;
9
+ padding: var(--nymbal-spacing-xl, 2rem) var(--nymbal-spacing-md, 1rem);
10
+ background-color: #fafafa;
11
+ border-bottom: 1px solid var(--nymbal-color-border, #e4e4e7);
12
+ }
13
+
14
+ .search-hero-title {
15
+ font-size: 1.5rem;
16
+ font-weight: var(--nymbal-font-weight-bold, 700);
17
+ color: var(--nymbal-color-primary, #18181b);
18
+ margin-bottom: var(--nymbal-spacing-md, 1rem);
19
+ }
20
+
21
+ .search-bar-wrapper {
22
+ max-width: 36rem;
23
+ margin-inline: auto;
24
+ }
25
+
26
+ .search-bar-wrapper nymbal-search-bar {
27
+ display: block;
28
+ }
29
+
30
+ .search-input-large {
31
+ width: 100%;
32
+ padding: var(--nymbal-spacing-md, 1rem) var(--nymbal-spacing-lg, 1.5rem);
33
+ font-size: var(--nymbal-font-size-lg, 1.125rem);
34
+ border: 2px solid var(--nymbal-color-border, #e4e4e7);
35
+ border-radius: var(--nymbal-radius-lg, 0.75rem);
36
+ background-color: var(--nymbal-color-surface, #fff);
37
+ transition: border-color var(--nymbal-transition-fast, 150ms) ease,
38
+ box-shadow var(--nymbal-transition-fast, 150ms) ease;
39
+ }
40
+
41
+ .search-input-large:focus {
42
+ outline: none;
43
+ border-color: var(--nymbal-color-accent, #2563eb);
44
+ box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12);
45
+ }
46
+
47
+ /* ---- Results area ---- */
48
+
49
+ .search-results {
50
+ padding-top: var(--nymbal-spacing-lg, 1.5rem);
51
+ }
52
+
53
+ .search-results-header {
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: space-between;
57
+ margin-bottom: var(--nymbal-spacing-md, 1rem);
58
+ flex-wrap: wrap;
59
+ gap: var(--nymbal-spacing-sm, 0.5rem);
60
+ }
61
+
62
+ .search-query-label {
63
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
64
+ color: var(--nymbal-color-text-muted, #71717a);
65
+ }
66
+
67
+ .search-query-label strong {
68
+ color: var(--nymbal-color-text, #18181b);
69
+ font-weight: var(--nymbal-font-weight-bold, 700);
70
+ }
71
+
72
+ .search-result-count {
73
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
74
+ color: var(--nymbal-color-text-muted, #71717a);
75
+ }
76
+
77
+ /* ---- Results grid (uses .product-grid from global) ---- */
78
+
79
+ /* ---- Empty / no results ---- */
80
+
81
+ .search-empty {
82
+ text-align: center;
83
+ padding: 4rem var(--nymbal-spacing-md, 1rem);
84
+ }
85
+
86
+ .search-empty-icon {
87
+ font-size: 3rem;
88
+ margin-bottom: var(--nymbal-spacing-md, 1rem);
89
+ opacity: 0.3;
90
+ }
91
+
92
+ .search-empty-title {
93
+ font-size: var(--nymbal-font-size-lg, 1.125rem);
94
+ font-weight: var(--nymbal-font-weight-medium, 500);
95
+ color: var(--nymbal-color-text, #18181b);
96
+ margin-bottom: var(--nymbal-spacing-xs, 0.25rem);
97
+ }
98
+
99
+ .search-empty-text {
100
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
101
+ color: var(--nymbal-color-text-muted, #71717a);
102
+ max-width: 28ch;
103
+ margin-inline: auto;
104
+ }
105
+
106
+ /* ---- Suggestions ---- */
107
+
108
+ .search-suggestions {
109
+ margin-top: var(--nymbal-spacing-lg, 1.5rem);
110
+ }
111
+
112
+ .search-suggestions-title {
113
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
114
+ font-weight: var(--nymbal-font-weight-medium, 500);
115
+ color: var(--nymbal-color-text, #18181b);
116
+ margin-bottom: var(--nymbal-spacing-sm, 0.5rem);
117
+ }
118
+
119
+ .search-suggestions-list {
120
+ display: flex;
121
+ flex-wrap: wrap;
122
+ gap: var(--nymbal-spacing-sm, 0.5rem);
123
+ }
124
+
125
+ .search-suggestion {
126
+ display: inline-flex;
127
+ padding: var(--nymbal-spacing-xs, 0.25rem) var(--nymbal-spacing-md, 1rem);
128
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
129
+ color: var(--nymbal-color-text, #18181b);
130
+ background-color: var(--nymbal-color-surface, #fff);
131
+ border: 1px solid var(--nymbal-color-border, #e4e4e7);
132
+ border-radius: var(--nymbal-radius-full, 9999px);
133
+ text-decoration: none;
134
+ transition: border-color var(--nymbal-transition-fast, 150ms) ease,
135
+ background-color var(--nymbal-transition-fast, 150ms) ease;
136
+ }
137
+
138
+ .search-suggestion:hover {
139
+ border-color: var(--nymbal-color-accent, #2563eb);
140
+ background-color: rgba(37, 99, 235, 0.04);
141
+ }
142
+
143
+ /* ---- Loading ---- */
144
+
145
+ .search-loading {
146
+ display: flex;
147
+ align-items: center;
148
+ justify-content: center;
149
+ padding: 3rem;
150
+ color: var(--nymbal-color-text-muted, #71717a);
151
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
152
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "astro/tsconfigs/strict"
3
+ }
@@ -0,0 +1,26 @@
1
+ # Your Nymbal Store
2
+
3
+ A commerce project scaffolded with [create-nymbal-app](https://github.com/nymbal/nymbal).
4
+
5
+ ## Scripts
6
+
7
+ ```
8
+ pnpm dev # start Next.js dev server
9
+ pnpm build # production build
10
+ pnpm start # start production server
11
+ pnpm migrate # run database migrations
12
+ pnpm seed # re-seed demo content
13
+ ```
14
+
15
+ ## Configuration
16
+
17
+ All configuration lives in `nymbal.config.ts`. Adapters, template, security, and deployment
18
+ settings are centralized there — the CLI and every package reads from the same source of truth.
19
+
20
+ ## Swapping the command store
21
+
22
+ For local development you get SQLite out of the box. To move to Postgres:
23
+
24
+ 1. Set `DATABASE_URL=postgres://…` in `.env`.
25
+ 2. Change `infrastructure.commandStore` to `'postgres'` in `nymbal.config.ts`.
26
+ 3. Run `pnpm migrate`.
@@ -0,0 +1,6 @@
1
+ # Copy to .env and fill in as needed
2
+ NYMBAL_API_URL=http://localhost:3001
3
+ # DATABASE_URL=postgres://user:pass@localhost:5432/nymbal
4
+ # STRIPE_SECRET_KEY=
5
+ # STRIPE_WEBHOOK_SECRET=
6
+ # ANTHROPIC_API_KEY=
@@ -0,0 +1,17 @@
1
+ node_modules/
2
+ dist/
3
+ build/
4
+ .astro/
5
+ .next/
6
+ next-env.d.ts
7
+ coverage/
8
+ *.log
9
+ .DS_Store
10
+ .env
11
+ .env.local
12
+ .env.*.local
13
+ *.tsbuildinfo
14
+ nymbal.db
15
+ nymbal.db-journal
16
+ nymbal.db-shm
17
+ nymbal.db-wal
@@ -0,0 +1 @@
1
+ 22.23.3
@@ -0,0 +1 @@
1
+ engine-strict=true
@@ -0,0 +1,10 @@
1
+ import type { Metadata } from 'next'
2
+ import { AddressManager } from '@/components/client/AddressManager'
3
+
4
+ export const metadata: Metadata = {
5
+ title: 'Addresses',
6
+ }
7
+
8
+ export default function AddressesPage() {
9
+ return <AddressManager />
10
+ }
@@ -0,0 +1,57 @@
1
+ 'use client'
2
+
3
+ import type { ReactNode } from 'react'
4
+ import Link from 'next/link'
5
+ import { usePathname, useRouter } from 'next/navigation'
6
+ import { useAuth } from '@nymbalhq/react'
7
+ import { AuthGuard, PUBLIC_AUTH_PATHS } from '@/components/client/AuthGuard'
8
+ import styles from '@/styles/pages/account.module.css'
9
+
10
+ const NAV_LINKS = [
11
+ { href: '/account', label: 'Dashboard' },
12
+ { href: '/account/orders', label: 'Orders' },
13
+ { href: '/account/addresses', label: 'Addresses' },
14
+ { href: '/account/profile', label: 'Profile' },
15
+ ]
16
+
17
+ export default function AccountLayout({ children }: { children: ReactNode }) {
18
+ const pathname = usePathname()
19
+ const router = useRouter()
20
+ const { logout } = useAuth()
21
+
22
+ if (PUBLIC_AUTH_PATHS.includes(pathname)) {
23
+ return <>{children}</>
24
+ }
25
+
26
+ async function signOut() {
27
+ await logout()
28
+ router.push('/account/login')
29
+ }
30
+
31
+ return (
32
+ <AuthGuard>
33
+ <div className={`container ${styles.page}`}>
34
+ <div className={styles.layout}>
35
+ <aside className={styles.sidebar}>
36
+ <nav className={styles.sidebarNav} aria-label="Account navigation">
37
+ {NAV_LINKS.map((link) => (
38
+ <Link key={link.href} href={link.href} className={styles.sidebarLink}>
39
+ {link.label}
40
+ </Link>
41
+ ))}
42
+ <hr className={styles.sidebarDivider} />
43
+ <button
44
+ type="button"
45
+ onClick={signOut}
46
+ className={`${styles.sidebarLink} ${styles.logoutLink}`}
47
+ >
48
+ Sign Out
49
+ </button>
50
+ </nav>
51
+ </aside>
52
+ <div className={styles.content}>{children}</div>
53
+ </div>
54
+ </div>
55
+ </AuthGuard>
56
+ )
57
+ }
@@ -0,0 +1,23 @@
1
+ import type { Metadata } from 'next'
2
+ import { Suspense } from 'react'
3
+ import { LoginForm } from '@/components/client/LoginForm'
4
+
5
+ export const metadata: Metadata = {
6
+ title: 'Sign In',
7
+ }
8
+
9
+ export default function LoginPage() {
10
+ return (
11
+ <Suspense
12
+ fallback={
13
+ <div className="loading-center">
14
+ <div className="spinner spinner-lg" role="status">
15
+ <span className="visually-hidden">Loading...</span>
16
+ </div>
17
+ </div>
18
+ }
19
+ >
20
+ <LoginForm />
21
+ </Suspense>
22
+ )
23
+ }