nitrostack 1.0.55 → 1.0.57

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 (222) hide show
  1. package/dist/cli/commands/init.d.ts.map +1 -1
  2. package/dist/cli/commands/init.js +14 -9
  3. package/dist/cli/commands/init.js.map +1 -1
  4. package/dist/widgets/hooks/index.d.ts +7 -0
  5. package/dist/widgets/hooks/index.d.ts.map +1 -0
  6. package/dist/widgets/hooks/index.js +7 -0
  7. package/dist/widgets/hooks/index.js.map +1 -0
  8. package/dist/widgets/hooks/use-display-mode.d.ts +11 -0
  9. package/dist/widgets/hooks/use-display-mode.d.ts.map +1 -0
  10. package/dist/widgets/hooks/use-display-mode.js +13 -0
  11. package/dist/widgets/hooks/use-display-mode.js.map +1 -0
  12. package/dist/widgets/hooks/use-max-height.d.ts +10 -0
  13. package/dist/widgets/hooks/use-max-height.d.ts.map +1 -0
  14. package/dist/widgets/hooks/use-max-height.js +13 -0
  15. package/dist/widgets/hooks/use-max-height.js.map +1 -0
  16. package/dist/widgets/hooks/use-openai-global.d.ts +12 -0
  17. package/dist/widgets/hooks/use-openai-global.d.ts.map +1 -0
  18. package/dist/widgets/hooks/use-openai-global.js +32 -0
  19. package/dist/widgets/hooks/use-openai-global.js.map +1 -0
  20. package/dist/widgets/hooks/use-theme.d.ts +10 -0
  21. package/dist/widgets/hooks/use-theme.d.ts.map +1 -0
  22. package/dist/widgets/hooks/use-theme.js +12 -0
  23. package/dist/widgets/hooks/use-theme.js.map +1 -0
  24. package/dist/widgets/hooks/use-widget-state.d.ts +18 -0
  25. package/dist/widgets/hooks/use-widget-state.d.ts.map +1 -0
  26. package/dist/widgets/hooks/use-widget-state.js +27 -0
  27. package/dist/widgets/hooks/use-widget-state.js.map +1 -0
  28. package/dist/widgets/hooks/useWidgetSDK.d.ts +47 -0
  29. package/dist/widgets/hooks/useWidgetSDK.d.ts.map +1 -0
  30. package/dist/widgets/hooks/useWidgetSDK.js +67 -0
  31. package/dist/widgets/hooks/useWidgetSDK.js.map +1 -0
  32. package/dist/widgets/index.d.ts +7 -1
  33. package/dist/widgets/index.d.ts.map +1 -1
  34. package/dist/widgets/index.js +11 -1
  35. package/dist/widgets/index.js.map +1 -1
  36. package/dist/widgets/runtime/WidgetLayout.d.ts +32 -0
  37. package/dist/widgets/runtime/WidgetLayout.d.ts.map +1 -0
  38. package/dist/widgets/runtime/WidgetLayout.js +143 -0
  39. package/dist/widgets/runtime/WidgetLayout.js.map +1 -0
  40. package/dist/widgets/runtime/widget-polyfill.d.ts +1 -0
  41. package/dist/widgets/runtime/widget-polyfill.d.ts.map +1 -0
  42. package/dist/widgets/runtime/widget-polyfill.js +28 -0
  43. package/dist/widgets/runtime/widget-polyfill.js.map +1 -0
  44. package/dist/widgets/sdk.d.ts +109 -0
  45. package/dist/widgets/sdk.d.ts.map +1 -0
  46. package/dist/widgets/sdk.js +221 -0
  47. package/dist/widgets/sdk.js.map +1 -0
  48. package/dist/widgets/types.d.ts +89 -0
  49. package/dist/widgets/types.d.ts.map +1 -0
  50. package/dist/widgets/types.js +8 -0
  51. package/dist/widgets/types.js.map +1 -0
  52. package/dist/widgets/utils/media-queries.d.ts +34 -0
  53. package/dist/widgets/utils/media-queries.d.ts.map +1 -0
  54. package/dist/widgets/utils/media-queries.js +42 -0
  55. package/dist/widgets/utils/media-queries.js.map +1 -0
  56. package/package.json +2 -2
  57. package/src/studio/app/chat/page.tsx +274 -137
  58. package/src/studio/app/globals.css +140 -64
  59. package/src/studio/branding.md +807 -0
  60. package/src/studio/components/WidgetRenderer.tsx +222 -16
  61. package/src/studio/lib/llm-service.ts +39 -39
  62. package/templates/typescript-oauth/{env.example → .env.example} +4 -10
  63. package/templates/typescript-oauth/README.md +226 -306
  64. package/templates/typescript-oauth/package-lock.json +4253 -0
  65. package/templates/typescript-oauth/package.json +10 -5
  66. package/templates/typescript-oauth/src/app.module.ts +39 -36
  67. package/templates/typescript-oauth/src/guards/oauth.guard.ts +0 -1
  68. package/templates/typescript-oauth/src/index.ts +22 -30
  69. package/templates/typescript-oauth/src/modules/flights/booking.tools.ts +323 -0
  70. package/templates/typescript-oauth/src/modules/flights/flights.module.ts +14 -0
  71. package/templates/typescript-oauth/src/modules/flights/flights.prompts.ts +231 -0
  72. package/templates/typescript-oauth/src/modules/flights/flights.resources.ts +215 -0
  73. package/templates/typescript-oauth/src/modules/flights/flights.tools.ts +457 -0
  74. package/templates/typescript-oauth/src/services/duffel.service.ts +285 -0
  75. package/templates/typescript-oauth/src/widgets/app/airport-search/page.tsx +270 -0
  76. package/templates/typescript-oauth/src/widgets/app/flight-details/page.tsx +261 -0
  77. package/templates/typescript-oauth/src/widgets/app/flight-search-results/page.tsx +378 -0
  78. package/templates/typescript-oauth/src/widgets/app/globals.css +167 -0
  79. package/templates/typescript-oauth/src/widgets/app/layout.tsx +6 -2
  80. package/templates/typescript-oauth/src/widgets/app/order-cancellation/page.tsx +207 -0
  81. package/templates/typescript-oauth/src/widgets/app/order-summary/page.tsx +245 -0
  82. package/templates/typescript-oauth/src/widgets/app/payment-confirmation/page.tsx +152 -0
  83. package/templates/typescript-oauth/src/widgets/app/seat-selection/page.tsx +486 -0
  84. package/templates/typescript-oauth/src/widgets/next-env.d.ts +5 -0
  85. package/templates/typescript-oauth/src/widgets/package-lock.json +155 -126
  86. package/templates/typescript-oauth/src/widgets/widget-manifest.json +374 -27
  87. package/templates/typescript-pizzaz/IMPLEMENTATION.md +98 -0
  88. package/templates/typescript-pizzaz/README.md +233 -0
  89. package/templates/typescript-pizzaz/package.json +31 -0
  90. package/templates/typescript-pizzaz/src/app.module.ts +28 -0
  91. package/templates/typescript-pizzaz/src/index.ts +30 -0
  92. package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.data.ts +106 -0
  93. package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.module.ts +11 -0
  94. package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.service.ts +60 -0
  95. package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.tools.ts +197 -0
  96. package/templates/typescript-pizzaz/src/widgets/app/layout.tsx +18 -0
  97. package/templates/typescript-pizzaz/src/widgets/app/pizza-list/page.tsx +272 -0
  98. package/templates/typescript-pizzaz/src/widgets/app/pizza-map/page.tsx +216 -0
  99. package/templates/typescript-pizzaz/src/widgets/app/pizza-shop/page.tsx +374 -0
  100. package/templates/typescript-pizzaz/src/widgets/components/CompactShopCard.tsx +144 -0
  101. package/templates/typescript-pizzaz/src/widgets/components/PizzaCard.tsx +191 -0
  102. package/templates/typescript-pizzaz/src/widgets/package.json +30 -0
  103. package/templates/typescript-pizzaz/src/widgets/widget-manifest.json +253 -0
  104. package/templates/typescript-pizzaz/tsconfig.json +30 -0
  105. package/templates/typescript-starter/src/modules/calculator/calculator.resources.ts +0 -1
  106. package/templates/typescript-starter/src/widgets/app/calculator-result/page.tsx +102 -56
  107. package/templates/typescript-starter/src/widgets/app/layout.tsx +6 -2
  108. package/templates/typescript-auth/AI_AGENT_CLI_REFERENCE.md +0 -702
  109. package/templates/typescript-auth/AI_AGENT_SDK_REFERENCE.md +0 -1260
  110. package/templates/typescript-auth/README.md +0 -402
  111. package/templates/typescript-auth/env.example +0 -25
  112. package/templates/typescript-auth/package.json +0 -36
  113. package/templates/typescript-auth/src/app.module.ts +0 -103
  114. package/templates/typescript-auth/src/db/database.ts +0 -160
  115. package/templates/typescript-auth/src/db/seed.ts +0 -374
  116. package/templates/typescript-auth/src/db/setup.ts +0 -87
  117. package/templates/typescript-auth/src/events/analytics.service.ts +0 -52
  118. package/templates/typescript-auth/src/events/notification.service.ts +0 -40
  119. package/templates/typescript-auth/src/filters/global-exception.filter.ts +0 -28
  120. package/templates/typescript-auth/src/guards/README.md +0 -75
  121. package/templates/typescript-auth/src/guards/jwt.guard.ts +0 -105
  122. package/templates/typescript-auth/src/health/database.health.ts +0 -41
  123. package/templates/typescript-auth/src/index.ts +0 -29
  124. package/templates/typescript-auth/src/interceptors/transform.interceptor.ts +0 -24
  125. package/templates/typescript-auth/src/middleware/logging.middleware.ts +0 -42
  126. package/templates/typescript-auth/src/modules/addresses/addresses.module.ts +0 -16
  127. package/templates/typescript-auth/src/modules/addresses/addresses.prompts.ts +0 -114
  128. package/templates/typescript-auth/src/modules/addresses/addresses.resources.ts +0 -40
  129. package/templates/typescript-auth/src/modules/addresses/addresses.tools.ts +0 -284
  130. package/templates/typescript-auth/src/modules/auth/auth.module.ts +0 -16
  131. package/templates/typescript-auth/src/modules/auth/auth.prompts.ts +0 -147
  132. package/templates/typescript-auth/src/modules/auth/auth.resources.ts +0 -84
  133. package/templates/typescript-auth/src/modules/auth/auth.tools.ts +0 -139
  134. package/templates/typescript-auth/src/modules/cart/cart.module.ts +0 -16
  135. package/templates/typescript-auth/src/modules/cart/cart.prompts.ts +0 -95
  136. package/templates/typescript-auth/src/modules/cart/cart.resources.ts +0 -44
  137. package/templates/typescript-auth/src/modules/cart/cart.tools.ts +0 -277
  138. package/templates/typescript-auth/src/modules/orders/orders.module.ts +0 -16
  139. package/templates/typescript-auth/src/modules/orders/orders.prompts.ts +0 -88
  140. package/templates/typescript-auth/src/modules/orders/orders.resources.ts +0 -48
  141. package/templates/typescript-auth/src/modules/orders/orders.tools.ts +0 -303
  142. package/templates/typescript-auth/src/modules/products/products.module.ts +0 -16
  143. package/templates/typescript-auth/src/modules/products/products.prompts.ts +0 -146
  144. package/templates/typescript-auth/src/modules/products/products.resources.ts +0 -98
  145. package/templates/typescript-auth/src/modules/products/products.tools.ts +0 -266
  146. package/templates/typescript-auth/src/pipes/validation.pipe.ts +0 -42
  147. package/templates/typescript-auth/src/services/database.service.ts +0 -90
  148. package/templates/typescript-auth/src/widgets/app/add-to-cart/page.tsx +0 -122
  149. package/templates/typescript-auth/src/widgets/app/address-added/page.tsx +0 -116
  150. package/templates/typescript-auth/src/widgets/app/address-deleted/page.tsx +0 -105
  151. package/templates/typescript-auth/src/widgets/app/address-list/page.tsx +0 -139
  152. package/templates/typescript-auth/src/widgets/app/address-updated/page.tsx +0 -153
  153. package/templates/typescript-auth/src/widgets/app/cart-cleared/page.tsx +0 -86
  154. package/templates/typescript-auth/src/widgets/app/cart-updated/page.tsx +0 -116
  155. package/templates/typescript-auth/src/widgets/app/categories/page.tsx +0 -134
  156. package/templates/typescript-auth/src/widgets/app/layout.tsx +0 -21
  157. package/templates/typescript-auth/src/widgets/app/login-result/page.tsx +0 -129
  158. package/templates/typescript-auth/src/widgets/app/order-confirmation/page.tsx +0 -231
  159. package/templates/typescript-auth/src/widgets/app/order-details/page.tsx +0 -225
  160. package/templates/typescript-auth/src/widgets/app/order-history/page.tsx +0 -218
  161. package/templates/typescript-auth/src/widgets/app/product-card/page.tsx +0 -121
  162. package/templates/typescript-auth/src/widgets/app/products-grid/page.tsx +0 -198
  163. package/templates/typescript-auth/src/widgets/app/shopping-cart/page.tsx +0 -187
  164. package/templates/typescript-auth/src/widgets/app/whoami/page.tsx +0 -165
  165. package/templates/typescript-auth/src/widgets/next.config.js +0 -38
  166. package/templates/typescript-auth/src/widgets/package.json +0 -18
  167. package/templates/typescript-auth/src/widgets/styles/ecommerce.ts +0 -169
  168. package/templates/typescript-auth/src/widgets/tsconfig.json +0 -28
  169. package/templates/typescript-auth/src/widgets/types/tool-data.ts +0 -141
  170. package/templates/typescript-auth/src/widgets/widget-manifest.json +0 -464
  171. package/templates/typescript-auth/tsconfig.json +0 -27
  172. package/templates/typescript-auth-api-key/AI_AGENT_CLI_REFERENCE.md +0 -701
  173. package/templates/typescript-auth-api-key/AI_AGENT_SDK_REFERENCE.md +0 -1260
  174. package/templates/typescript-auth-api-key/README.md +0 -485
  175. package/templates/typescript-auth-api-key/env.example +0 -17
  176. package/templates/typescript-auth-api-key/package.json +0 -21
  177. package/templates/typescript-auth-api-key/src/app.module.ts +0 -38
  178. package/templates/typescript-auth-api-key/src/guards/apikey.guard.ts +0 -47
  179. package/templates/typescript-auth-api-key/src/guards/multi-auth.guard.ts +0 -157
  180. package/templates/typescript-auth-api-key/src/index.ts +0 -47
  181. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.module.ts +0 -12
  182. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.prompts.ts +0 -73
  183. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.resources.ts +0 -60
  184. package/templates/typescript-auth-api-key/src/modules/calculator/calculator.tools.ts +0 -71
  185. package/templates/typescript-auth-api-key/src/modules/demo/demo.module.ts +0 -18
  186. package/templates/typescript-auth-api-key/src/modules/demo/demo.tools.ts +0 -155
  187. package/templates/typescript-auth-api-key/src/modules/demo/multi-auth.tools.ts +0 -123
  188. package/templates/typescript-auth-api-key/src/widgets/app/calculator-operations/page.tsx +0 -133
  189. package/templates/typescript-auth-api-key/src/widgets/app/calculator-result/page.tsx +0 -134
  190. package/templates/typescript-auth-api-key/src/widgets/app/layout.tsx +0 -14
  191. package/templates/typescript-auth-api-key/src/widgets/package.json +0 -24
  192. package/templates/typescript-auth-api-key/src/widgets/widget-manifest.json +0 -48
  193. package/templates/typescript-auth-api-key/tsconfig.json +0 -23
  194. package/templates/typescript-oauth/OAUTH_SETUP.md +0 -592
  195. package/templates/typescript-oauth/src/modules/demo/demo.module.ts +0 -16
  196. package/templates/typescript-oauth/src/modules/demo/demo.tools.ts +0 -190
  197. package/templates/typescript-oauth/src/widgets/app/calculator-operations/page.tsx +0 -133
  198. package/templates/typescript-oauth/src/widgets/app/calculator-result/page.tsx +0 -134
  199. package/templates/typescript-oauth/src/widgets/out/404.html +0 -1
  200. package/templates/typescript-oauth/src/widgets/out/_next/static/WU9THacVqL52RZbrZOLS1/_buildManifest.js +0 -1
  201. package/templates/typescript-oauth/src/widgets/out/_next/static/WU9THacVqL52RZbrZOLS1/_ssgManifest.js +0 -1
  202. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/117-eb57c7ef86f964a4.js +0 -2
  203. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/_not-found/page-dcb83ba3e4d0aafd.js +0 -1
  204. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/calculator-operations/page-b8913a740073ea8a.js +0 -1
  205. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/calculator-result/page-ddaaab2fce95dea2.js +0 -1
  206. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/layout-cbd3ebdc4ecc5247.js +0 -1
  207. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/fd9d1056-749e5812300142af.js +0 -1
  208. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/framework-f66176bb897dc684.js +0 -1
  209. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/main-76df43fcef3db344.js +0 -1
  210. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/main-app-f9c40224d04023c5.js +0 -1
  211. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/pages/_app-72b849fbd24ac258.js +0 -1
  212. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/pages/_error-7ba65e1336b92748.js +0 -1
  213. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  214. package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/webpack-100b9e646d9c912e.js +0 -1
  215. package/templates/typescript-oauth/src/widgets/out/calculator-operations.html +0 -1
  216. package/templates/typescript-oauth/src/widgets/out/calculator-operations.txt +0 -7
  217. package/templates/typescript-oauth/src/widgets/out/calculator-result.html +0 -1
  218. package/templates/typescript-oauth/src/widgets/out/calculator-result.txt +0 -7
  219. package/templates/typescript-starter/src/widgets/app/calculator-operations/page.tsx +0 -133
  220. /package/templates/{typescript-auth-api-key → typescript-oauth}/src/health/system.health.ts +0 -0
  221. /package/templates/{typescript-auth-api-key → typescript-pizzaz}/src/widgets/next.config.js +0 -0
  222. /package/templates/{typescript-auth-api-key → typescript-pizzaz}/src/widgets/tsconfig.json +0 -0
@@ -0,0 +1,233 @@
1
+ # 🍕 Pizzaz - Pizza Shop Finder
2
+
3
+ A comprehensive NitroStack template showcasing interactive pizza shop discovery with maps, lists, and detailed views. This template demonstrates the NitroStack Widget SDK for building interactive widgets.
4
+
5
+ ## Features
6
+
7
+ ### 🎨 **Widget SDK Features**
8
+ - ✅ `useTheme()` - Automatic dark mode support
9
+ - ✅ `useWidgetState()` - Persistent favorites and view preferences
10
+ - ✅ `useMaxHeight()` - Responsive height-aware layouts
11
+ - ✅ `useDisplayMode()` - Fullscreen mode adaptation
12
+ - ✅ `useWidgetSDK()` - Tool calling, navigation, and external links
13
+ - ✅ `<WidgetLayout>` - Automatic RPC setup
14
+
15
+ ### 🗺️ **Three Interactive Widgets**
16
+ 1. **Pizza Map** - Interactive Mapbox map with markers and shop selection
17
+ 2. **Pizza List** - Grid/list view with sorting, filtering, and favorites
18
+ 3. **Pizza Shop** - Detailed shop information with contact actions
19
+
20
+ ### 📊 **MCP Tools**
21
+ - `show_pizza_map` - Display shops on an interactive map
22
+ - `show_pizza_list` - Show filterable list of shops
23
+ - `show_pizza_shop` - Display detailed shop information
24
+
25
+ ## Quick Start
26
+
27
+ ### 1. Install Dependencies
28
+
29
+ ```bash
30
+ npm install
31
+ cd src/widgets && npm install && cd ../..
32
+ ```
33
+
34
+ ### 2. Configure Mapbox (Optional)
35
+
36
+ The map widget uses Mapbox GL. To use it:
37
+
38
+ 1. Get a free API key from [Mapbox](https://www.mapbox.com/)
39
+ 2. Create `.env` file:
40
+ ```bash
41
+ NEXT_PUBLIC_MAPBOX_TOKEN=your_mapbox_token_here
42
+ ```
43
+
44
+ > **Note**: The template works without Mapbox, but the map widget will show an error. You can still use the list and shop widgets.
45
+
46
+ ### 3. Run Development Server
47
+
48
+ ```bash
49
+ npm run dev
50
+ ```
51
+
52
+ The MCP server will start on `http://localhost:3000`
53
+
54
+ ### 4. Run Widget Dev Server
55
+
56
+ In a separate terminal:
57
+
58
+ ```bash
59
+ npm run widget dev
60
+ ```
61
+
62
+ Widgets will be available on `http://localhost:3001`
63
+
64
+ ### 5. Test in NitroStudio
65
+
66
+ 1. Open NitroStudio
67
+ 2. Connect to your MCP server
68
+ 3. Try these prompts:
69
+ - "Show me pizza shops on a map"
70
+ - "List all pizza shops"
71
+ - "Show me details for Tony's New York Pizza"
72
+
73
+ ## Project Structure
74
+
75
+ ```
76
+ typescript-pizzaz/
77
+ ├── src/
78
+ │ ├── index.ts # Main server entry
79
+ │ ├── app.module.ts # App module
80
+ │ └── modules/
81
+ │ └── pizzaz/
82
+ │ ├── pizzaz.data.ts # Pizza shop data
83
+ │ ├── pizzaz.service.ts # Business logic
84
+ │ ├── pizzaz.tools.ts # MCP tools
85
+ │ └── pizzaz.module.ts # Module definition
86
+ │ └── widgets/
87
+ │ ├── app/
88
+ │ │ ├── pizza-map/ # Map widget
89
+ │ │ ├── pizza-list/ # List widget
90
+ │ │ └── pizza-shop/ # Shop detail widget
91
+ │ └── components/
92
+ │ └── PizzaCard.tsx # Reusable card component
93
+ ├── package.json
94
+ └── README.md
95
+ ```
96
+
97
+ ## Widget Features
98
+
99
+ ### Pizza Map Widget
100
+ - **Interactive Mapbox map** with custom markers
101
+ - **Shop sidebar** with quick selection
102
+ - **Fullscreen mode** for better exploration
103
+ - **Persistent favorites** using `useWidgetState()`
104
+ - **Theme-aware** map styles (light/dark)
105
+
106
+ ### Pizza List Widget
107
+ - **Grid/List view toggle** with state persistence
108
+ - **Sorting** by rating, name, or price
109
+ - **Favorites tracking** across sessions
110
+ - **Responsive layout** using `useMaxHeight()`
111
+ - **Filter panel** for advanced search
112
+
113
+ ### Pizza Shop Widget
114
+ - **Hero image** with overlay information
115
+ - **Contact actions** (call, directions, website)
116
+ - **Specialties showcase**
117
+ - **Related shops** recommendations
118
+ - **External link handling** via `useWidgetSDK()`
119
+
120
+ ## Customization
121
+
122
+ ### Adding More Shops
123
+
124
+ Edit `src/modules/pizzaz/pizzaz.data.ts`:
125
+
126
+ ```typescript
127
+ export const PIZZA_SHOPS: PizzaShop[] = [
128
+ {
129
+ id: 'my-pizza-shop',
130
+ name: 'My Pizza Shop',
131
+ description: 'Amazing pizza!',
132
+ address: '123 Main St, City, State 12345',
133
+ coords: [-122.4194, 37.7749], // [lng, lat]
134
+ rating: 4.5,
135
+ reviews: 100,
136
+ priceLevel: 2,
137
+ cuisine: ['Italian', 'Pizza'],
138
+ hours: { open: '11:00 AM', close: '10:00 PM' },
139
+ phone: '(555) 123-4567',
140
+ website: 'https://example.com',
141
+ image: 'https://images.unsplash.com/photo-...',
142
+ specialties: ['Margherita', 'Pepperoni'],
143
+ openNow: true,
144
+ },
145
+ // ... more shops
146
+ ];
147
+ ```
148
+
149
+ ### Changing Map Style
150
+
151
+ Edit `src/widgets/app/pizza-map/page.tsx`:
152
+
153
+ ```typescript
154
+ style: isDark
155
+ ? 'mapbox://styles/mapbox/dark-v11' // Dark mode style
156
+ : 'mapbox://styles/mapbox/streets-v12' // Light mode style
157
+ ```
158
+
159
+ ### Adding New Filters
160
+
161
+ Edit `src/modules/pizzaz/pizzaz.service.ts` to add more filter options.
162
+
163
+ ## Deployment
164
+
165
+ ### Build for Production
166
+
167
+ ```bash
168
+ npm run build
169
+ ```
170
+
171
+ ### Deploy to OpenAI ChatGPT
172
+
173
+ 1. Build widgets:
174
+ ```bash
175
+ cd src/widgets && npm run build
176
+ ```
177
+
178
+ 2. Widget HTML files will be in `src/widgets/out/`
179
+
180
+ 3. Upload to your MCP server
181
+
182
+ 4. **Zero code changes needed!** Widgets work identically in OpenAI ChatGPT.
183
+
184
+ ## SDK Features Demonstrated
185
+
186
+ ### Theme Awareness
187
+ ```typescript
188
+ const theme = useTheme(); // 'light' | 'dark'
189
+ const bgColor = theme === 'dark' ? '#000' : '#fff';
190
+ ```
191
+
192
+ ### State Persistence
193
+ ```typescript
194
+ const [state, setState] = useWidgetState(() => ({
195
+ favorites: [],
196
+ viewMode: 'grid',
197
+ }));
198
+
199
+ // State persists across widget reloads
200
+ setState({ ...state, favorites: [...state.favorites, shopId] });
201
+ ```
202
+
203
+ ### Responsive Layouts
204
+ ```typescript
205
+ const maxHeight = useMaxHeight();
206
+ return <div style={{ maxHeight }}>{content}</div>;
207
+ ```
208
+
209
+ ### Display Mode Adaptation
210
+ ```typescript
211
+ const displayMode = useDisplayMode(); // 'inline' | 'pip' | 'fullscreen'
212
+ const showSidebar = displayMode === 'fullscreen';
213
+ ```
214
+
215
+ ### External Links
216
+ ```typescript
217
+ const { openExternal } = useWidgetSDK();
218
+ openExternal('https://example.com');
219
+ ```
220
+
221
+ ## Learn More
222
+
223
+ - [NitroStack Documentation](https://nitrostack.dev)
224
+ - [Widget Development Guide](../../WIDGET_DEVELOPMENT.md)
225
+ - [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/)
226
+
227
+ ## License
228
+
229
+ MIT
230
+
231
+ ---
232
+
233
+ **Built with ❤️ using NitroStack**
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "nitrostack-pizzaz",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "description": "Pizza shop finder with interactive map - NitroStack template showcasing Widget SDK features",
7
+ "scripts": {
8
+ "dev": "nitrostack dev",
9
+ "build": "nitrostack build",
10
+ "start": "npm run build && nitrostack start",
11
+ "start:prod": "nitrostack start",
12
+ "widget": "npm --prefix src/widgets"
13
+ },
14
+ "keywords": [
15
+ "nitrostack",
16
+ "mcp",
17
+ "pizza",
18
+ "map",
19
+ "widgets"
20
+ ],
21
+ "author": "",
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "nitrostack": "^1",
25
+ "zod": "^3.22.4",
26
+ "dotenv": "^16.3.1"
27
+ },
28
+ "devDependencies": {
29
+ "typescript": "^5.3.3"
30
+ }
31
+ }
@@ -0,0 +1,28 @@
1
+ import { McpApp, Module, ConfigModule } from 'nitrostack';
2
+ import { PizzazModule } from './modules/pizzaz/pizzaz.module.js';
3
+
4
+ /**
5
+ * Root Application Module
6
+ *
7
+ * Pizza shop finder with interactive maps.
8
+ * Showcases NitroStack Widget SDK features.
9
+ */
10
+ @McpApp({
11
+ module: AppModule,
12
+ server: {
13
+ name: 'pizzaz-finder',
14
+ version: '1.0.0'
15
+ },
16
+ logging: {
17
+ level: 'info'
18
+ }
19
+ })
20
+ @Module({
21
+ name: 'pizzaz',
22
+ description: 'Pizza shop finder with interactive maps',
23
+ imports: [
24
+ ConfigModule.forRoot(),
25
+ PizzazModule
26
+ ],
27
+ })
28
+ export class AppModule { }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Pizzaz MCP Server
3
+ *
4
+ * Pizza shop finder with interactive map widgets.
5
+ * Showcases NitroStack Widget SDK features including:
6
+ * - useTheme() for dark mode
7
+ * - useWidgetState() for persistent favorites
8
+ * - useDisplayMode() for fullscreen support
9
+ * - useMaxHeight() for responsive layouts
10
+ * - useWidgetSDK() for tool calling and navigation
11
+ */
12
+
13
+ import 'dotenv/config';
14
+ import { McpApplicationFactory } from 'nitrostack';
15
+ import { AppModule } from './app.module.js';
16
+
17
+ /**
18
+ * Bootstrap the application
19
+ */
20
+ async function bootstrap() {
21
+ // Create and start the MCP server
22
+ const server = await McpApplicationFactory.create(AppModule);
23
+ await server.start();
24
+ }
25
+
26
+ // Start the application
27
+ bootstrap().catch((error) => {
28
+ console.error('❌ Failed to start server:', error);
29
+ process.exit(1);
30
+ });
@@ -0,0 +1,106 @@
1
+ export interface PizzaShop {
2
+ id: string;
3
+ name: string;
4
+ description: string;
5
+ address: string;
6
+ coords: [number, number]; // [lng, lat]
7
+ rating: number;
8
+ reviews: number;
9
+ priceLevel: 1 | 2 | 3;
10
+ cuisine: string[];
11
+ hours: {
12
+ open: string;
13
+ close: string;
14
+ };
15
+ phone: string;
16
+ website?: string;
17
+ image: string;
18
+ specialties: string[];
19
+ openNow: boolean;
20
+ }
21
+
22
+ export const PIZZA_SHOPS: PizzaShop[] = [
23
+ {
24
+ id: 'tonys-pizza',
25
+ name: "Tony's New York Pizza",
26
+ description: "Authentic New York-style pizza with a crispy thin crust and fresh toppings",
27
+ address: "123 Main St, San Francisco, CA 94102",
28
+ coords: [-122.4194, 37.7749],
29
+ rating: 4.5,
30
+ reviews: 342,
31
+ priceLevel: 2,
32
+ cuisine: ['Italian', 'Pizza', 'New York Style'],
33
+ hours: { open: '11:00 AM', close: '10:00 PM' },
34
+ phone: '(415) 555-0123',
35
+ website: 'https://tonyspizza.example.com',
36
+ image: 'https://images.unsplash.com/photo-1513104890138-7c749659a591',
37
+ specialties: ['Margherita', 'Pepperoni', 'White Pizza'],
38
+ openNow: true,
39
+ },
40
+ {
41
+ id: 'bella-napoli',
42
+ name: 'Bella Napoli',
43
+ description: "Traditional Neapolitan pizza baked in a wood-fired oven",
44
+ address: "456 Market St, San Francisco, CA 94103",
45
+ coords: [-122.4089, 37.7858],
46
+ rating: 4.8,
47
+ reviews: 521,
48
+ priceLevel: 3,
49
+ cuisine: ['Italian', 'Pizza', 'Neapolitan'],
50
+ hours: { open: '12:00 PM', close: '11:00 PM' },
51
+ phone: '(415) 555-0456',
52
+ website: 'https://bellanapoli.example.com',
53
+ image: 'https://images.unsplash.com/photo-1574071318508-1cdbab80d002',
54
+ specialties: ['Marinara', 'Quattro Formaggi', 'Diavola'],
55
+ openNow: true,
56
+ },
57
+ {
58
+ id: 'slice-house',
59
+ name: 'The Slice House',
60
+ description: "Casual spot for creative pizza slices and craft beer",
61
+ address: "789 Valencia St, San Francisco, CA 94110",
62
+ coords: [-122.4216, 37.7599],
63
+ rating: 4.3,
64
+ reviews: 289,
65
+ priceLevel: 1,
66
+ cuisine: ['Pizza', 'American', 'Casual'],
67
+ hours: { open: '11:30 AM', close: '9:00 PM' },
68
+ phone: '(415) 555-0789',
69
+ image: 'https://images.unsplash.com/photo-1565299624946-b28f40a0ae38',
70
+ specialties: ['BBQ Chicken', 'Hawaiian', 'Veggie Supreme'],
71
+ openNow: true,
72
+ },
73
+ {
74
+ id: 'pizzeria-delfina',
75
+ name: 'Pizzeria Delfina',
76
+ description: "Upscale pizzeria with seasonal ingredients and house-made mozzarella",
77
+ address: "3611 18th St, San Francisco, CA 94110",
78
+ coords: [-122.4252, 37.7615],
79
+ rating: 4.6,
80
+ reviews: 678,
81
+ priceLevel: 3,
82
+ cuisine: ['Italian', 'Pizza', 'Fine Dining'],
83
+ hours: { open: '5:00 PM', close: '10:00 PM' },
84
+ phone: '(415) 555-3611',
85
+ website: 'https://pizzeriadelfina.example.com',
86
+ image: 'https://images.unsplash.com/photo-1571997478779-2adcbbe9ab2f',
87
+ specialties: ['Salsiccia', 'Funghi', 'Prosciutto e Rucola'],
88
+ openNow: false,
89
+ },
90
+ {
91
+ id: 'golden-boy',
92
+ name: 'Golden Boy Pizza',
93
+ description: "North Beach institution serving thick Sicilian-style squares",
94
+ address: "542 Green St, San Francisco, CA 94133",
95
+ coords: [-122.4102, 37.7999],
96
+ rating: 4.4,
97
+ reviews: 445,
98
+ priceLevel: 1,
99
+ cuisine: ['Pizza', 'Sicilian', 'Italian'],
100
+ hours: { open: '11:30 AM', close: '11:30 PM' },
101
+ phone: '(415) 555-0542',
102
+ image: 'https://images.unsplash.com/photo-1628840042765-356cda07504e',
103
+ specialties: ['Clam & Garlic', 'Pesto', 'Classic Cheese'],
104
+ openNow: true,
105
+ },
106
+ ];
@@ -0,0 +1,11 @@
1
+ import { Module } from 'nitrostack';
2
+ import { PizzazService } from './pizzaz.service.js';
3
+ import { PizzazTools } from './pizzaz.tools.js';
4
+
5
+ @Module({
6
+ name: 'pizzaz',
7
+ description: 'Pizza shop finder module',
8
+ controllers: [PizzazTools],
9
+ providers: [PizzazService],
10
+ })
11
+ export class PizzazModule { }
@@ -0,0 +1,60 @@
1
+ import { Injectable } from 'nitrostack';
2
+ import { PIZZA_SHOPS, type PizzaShop } from './pizzaz.data.js';
3
+
4
+ @Injectable()
5
+ export class PizzazService {
6
+ /**
7
+ * Get all pizza shops
8
+ */
9
+ getAllShops(): PizzaShop[] {
10
+ return PIZZA_SHOPS;
11
+ }
12
+
13
+ /**
14
+ * Get a specific pizza shop by ID
15
+ */
16
+ getShopById(id: string): PizzaShop | undefined {
17
+ return PIZZA_SHOPS.find(shop => shop.id === id);
18
+ }
19
+
20
+ /**
21
+ * Get pizza shops filtered by criteria
22
+ */
23
+ getShopsFiltered(filters: {
24
+ openNow?: boolean;
25
+ minRating?: number;
26
+ maxPrice?: number;
27
+ cuisine?: string;
28
+ }): PizzaShop[] {
29
+ let shops = [...PIZZA_SHOPS];
30
+
31
+ if (filters.openNow) {
32
+ shops = shops.filter(shop => shop.openNow);
33
+ }
34
+
35
+ if (filters.minRating !== undefined) {
36
+ shops = shops.filter(shop => shop.rating >= filters.minRating!);
37
+ }
38
+
39
+ if (filters.maxPrice !== undefined) {
40
+ shops = shops.filter(shop => shop.priceLevel <= filters.maxPrice!);
41
+ }
42
+
43
+ if (filters.cuisine) {
44
+ shops = shops.filter(shop =>
45
+ shop.cuisine.some(c => c.toLowerCase().includes(filters.cuisine!.toLowerCase()))
46
+ );
47
+ }
48
+
49
+ return shops;
50
+ }
51
+
52
+ /**
53
+ * Get shops sorted by rating
54
+ */
55
+ getTopRatedShops(limit: number = 5): PizzaShop[] {
56
+ return [...PIZZA_SHOPS]
57
+ .sort((a, b) => b.rating - a.rating)
58
+ .slice(0, limit);
59
+ }
60
+ }
@@ -0,0 +1,197 @@
1
+ import { ToolDecorator as Tool, Widget, ExecutionContext, Injectable, z } from 'nitrostack';
2
+ import { PizzazService } from './pizzaz.service.js';
3
+
4
+ const ShowMapSchema = z.object({
5
+ filter: z.enum(['open_now', 'top_rated', 'all']).optional().describe('Filter to apply'),
6
+ });
7
+
8
+ const ShowListSchema = z.object({
9
+ openNow: z.boolean().optional().describe('Show only shops that are currently open'),
10
+ minRating: z.number().min(1).max(5).optional().describe('Minimum rating (1-5)'),
11
+ maxPrice: z.number().min(1).max(3).optional().describe('Maximum price level (1-3)'),
12
+ });
13
+
14
+ const ShowShopSchema = z.object({
15
+ shopId: z.string().describe('ID of the pizza shop to display'),
16
+ });
17
+
18
+ @Injectable()
19
+ export class PizzazTools {
20
+ constructor(private readonly pizzazService: PizzazService) { }
21
+
22
+ @Tool({
23
+ name: 'show_pizza_map',
24
+ description: 'Display an interactive map of pizza shops in San Francisco',
25
+ inputSchema: ShowMapSchema,
26
+ examples: {
27
+ request: { filter: 'all' },
28
+ response: {
29
+ shops: [
30
+ {
31
+ id: 'tonys-pizza',
32
+ name: "Tony's New York Pizza",
33
+ description: "Authentic New York-style pizza with a crispy thin crust",
34
+ address: "123 Main St, San Francisco, CA 94102",
35
+ coords: [-122.4194, 37.7749],
36
+ rating: 4.5,
37
+ reviews: 342,
38
+ priceLevel: 2,
39
+ cuisine: ['Italian', 'Pizza'],
40
+ hours: { open: '11:00 AM', close: '10:00 PM' },
41
+ phone: '(415) 555-0123',
42
+ website: 'https://tonyspizza.example.com',
43
+ image: 'https://images.unsplash.com/photo-1513104890138-7c749659a591',
44
+ specialties: ['Margherita', 'Pepperoni'],
45
+ openNow: true
46
+ },
47
+ {
48
+ id: 'bella-napoli',
49
+ name: 'Bella Napoli',
50
+ description: "Traditional Neapolitan pizza baked in a wood-fired oven",
51
+ address: "456 Market St, San Francisco, CA 94103",
52
+ coords: [-122.4089, 37.7858],
53
+ rating: 4.8,
54
+ reviews: 521,
55
+ priceLevel: 3,
56
+ cuisine: ['Italian', 'Pizza'],
57
+ hours: { open: '12:00 PM', close: '11:00 PM' },
58
+ phone: '(415) 555-0456',
59
+ image: 'https://images.unsplash.com/photo-1574071318508-1cdbab80d002',
60
+ specialties: ['Marinara', 'Quattro Formaggi'],
61
+ openNow: true
62
+ }
63
+ ],
64
+ filter: 'all',
65
+ totalShops: 2
66
+ }
67
+ }
68
+ })
69
+ @Widget('pizza-map')
70
+ async showPizzaMap(args: z.infer<typeof ShowMapSchema>, ctx: ExecutionContext) {
71
+ let shops;
72
+
73
+ switch (args.filter) {
74
+ case 'open_now':
75
+ shops = this.pizzazService.getShopsFiltered({ openNow: true });
76
+ break;
77
+ case 'top_rated':
78
+ shops = this.pizzazService.getTopRatedShops();
79
+ break;
80
+ default:
81
+ shops = this.pizzazService.getAllShops();
82
+ }
83
+
84
+ ctx.logger.info('Showing pizza map', { filter: args.filter, totalShops: shops.length });
85
+
86
+ return {
87
+ shops,
88
+ filter: args.filter || 'all',
89
+ totalShops: shops.length,
90
+ };
91
+ }
92
+
93
+ @Tool({
94
+ name: 'show_pizza_list',
95
+ description: 'Display a list of pizza shops with filtering and sorting options',
96
+ inputSchema: ShowListSchema,
97
+ examples: {
98
+ request: { openNow: true },
99
+ response: {
100
+ shops: [
101
+ {
102
+ id: 'tonys-pizza',
103
+ name: "Tony's New York Pizza",
104
+ description: "Authentic New York-style pizza with a crispy thin crust",
105
+ address: "123 Main St, San Francisco, CA 94102",
106
+ coords: [-122.4194, 37.7749],
107
+ rating: 4.5,
108
+ reviews: 342,
109
+ priceLevel: 2,
110
+ cuisine: ['Italian', 'Pizza'],
111
+ hours: { open: '11:00 AM', close: '10:00 PM' },
112
+ phone: '(415) 555-0123',
113
+ website: 'https://tonyspizza.example.com',
114
+ image: 'https://images.unsplash.com/photo-1513104890138-7c749659a591',
115
+ specialties: ['Margherita', 'Pepperoni'],
116
+ openNow: true
117
+ }
118
+ ],
119
+ filters: { openNow: true },
120
+ totalShops: 1
121
+ }
122
+ }
123
+ })
124
+ @Widget('pizza-list')
125
+ async showPizzaList(args: z.infer<typeof ShowListSchema>, ctx: ExecutionContext) {
126
+ const shops = this.pizzazService.getShopsFiltered(args);
127
+
128
+ ctx.logger.info('Showing pizza list', { filters: args, totalShops: shops.length });
129
+
130
+ return {
131
+ shops,
132
+ filters: args,
133
+ totalShops: shops.length,
134
+ };
135
+ }
136
+
137
+ @Tool({
138
+ name: 'show_pizza_shop',
139
+ description: 'Display detailed information about a specific pizza shop',
140
+ inputSchema: ShowShopSchema,
141
+ examples: {
142
+ request: { shopId: 'tonys-pizza' },
143
+ response: {
144
+ shop: {
145
+ id: 'tonys-pizza',
146
+ name: "Tony's New York Pizza",
147
+ description: "Authentic New York-style pizza with a crispy thin crust and fresh toppings",
148
+ address: "123 Main St, San Francisco, CA 94102",
149
+ coords: [-122.4194, 37.7749],
150
+ rating: 4.5,
151
+ reviews: 342,
152
+ priceLevel: 2,
153
+ cuisine: ['Italian', 'Pizza', 'New York Style'],
154
+ hours: { open: '11:00 AM', close: '10:00 PM' },
155
+ phone: '(415) 555-0123',
156
+ website: 'https://tonyspizza.example.com',
157
+ image: 'https://images.unsplash.com/photo-1513104890138-7c749659a591',
158
+ specialties: ['Margherita', 'Pepperoni', 'White Pizza'],
159
+ openNow: true
160
+ },
161
+ relatedShops: [
162
+ {
163
+ id: 'bella-napoli',
164
+ name: 'Bella Napoli',
165
+ description: "Traditional Neapolitan pizza baked in a wood-fired oven",
166
+ address: "456 Market St, San Francisco, CA 94103",
167
+ coords: [-122.4089, 37.7858],
168
+ rating: 4.8,
169
+ reviews: 521,
170
+ priceLevel: 3,
171
+ cuisine: ['Italian', 'Pizza'],
172
+ hours: { open: '12:00 PM', close: '11:00 PM' },
173
+ phone: '(415) 555-0456',
174
+ image: 'https://images.unsplash.com/photo-1574071318508-1cdbab80d002',
175
+ specialties: ['Marinara', 'Quattro Formaggi'],
176
+ openNow: true
177
+ }
178
+ ]
179
+ }
180
+ }
181
+ })
182
+ @Widget('pizza-shop')
183
+ async showPizzaShop(args: z.infer<typeof ShowShopSchema>, ctx: ExecutionContext) {
184
+ const shop = this.pizzazService.getShopById(args.shopId);
185
+
186
+ if (!shop) {
187
+ throw new Error(`Pizza shop not found: ${args.shopId}`);
188
+ }
189
+
190
+ ctx.logger.info('Showing pizza shop', { shopId: args.shopId, shopName: shop.name });
191
+
192
+ return {
193
+ shop,
194
+ relatedShops: this.pizzazService.getTopRatedShops(3).filter(s => s.id !== shop.id),
195
+ };
196
+ }
197
+ }