Conversation
WalkthroughAdds a complete Next.js Lamatic-powered travel planner template: project configs, Lamatic client and flow config, server orchestration, a full page UI, extensive shadcn/Radix UI component library, theme/styles, utilities, hooks, and documentation. Changes
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 39
♻️ Duplicate comments (5)
templates/agentic/travel-planner/components/ui/context-menu.tsx (5)
129-129: Duplicate: Invalidoutline-hiddenclass.Same issue as line 69 -
outline-hiddenshould beoutline-none.Apply this diff:
- "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
126-126: Duplicate: Data attribute issue withinsetprop.Same issue as line 67 - the attribute should be conditionally added only when inset is truthy.
Apply this diff:
<ContextMenuPrimitive.Item data-slot="context-menu-item" - data-inset={inset} + {...(inset && { "data-inset": true })} data-variant={variant} className={cn(
147-147: Duplicate: Invalidoutline-hiddenclass.Same issue as line 69 -
outline-hiddenshould beoutline-none.Apply this diff:
- "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
172-172: Duplicate: Invalidoutline-hiddenclass.Same issue as line 69 -
outline-hiddenshould beoutline-none.Apply this diff:
- "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
197-197: Duplicate: Data attribute issue withinsetprop.Same issue as line 67 - the attribute should be conditionally added only when inset is truthy.
Apply this diff:
<ContextMenuPrimitive.Label data-slot="context-menu-label" - data-inset={inset} + {...(inset && { "data-inset": true })} className={cn(
🧹 Nitpick comments (39)
templates/agentic/travel-planner/components/ui/skeleton.tsx (1)
3-11: Consider adding accessibility attributes for loading states.The component implementation is solid and follows React best practices. However, skeleton loaders should communicate loading state to assistive technologies.
Consider applying this diff to improve accessibility:
-function Skeleton({ className, ...props }: React.ComponentProps<"div">) { +function Skeleton({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="skeleton" className={cn("bg-accent animate-pulse rounded-md", className)} + role="status" + aria-live="polite" + aria-label="Loading..." {...props} /> ) }Optional: Add a display name for better debugging experience in React DevTools:
function Skeleton({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="skeleton" className={cn("bg-accent animate-pulse rounded-md", className)} {...props} /> ) } + +Skeleton.displayName = "Skeleton"templates/agentic/travel-planner/components/ui/radio-group.tsx (1)
45-45: LGTM! Clean exports.Both components are properly exported.
Optional: Consider adding display names to the components for improved debugging experience:
function RadioGroup({ className, ...props }: React.ComponentProps<typeof RadioGroupPrimitive.Root>) { return ( <RadioGroupPrimitive.Root data-slot="radio-group" className={cn("grid gap-3", className)} {...props} /> ) } +RadioGroup.displayName = "RadioGroup" function RadioGroupItem({ className, ...props }: React.ComponentProps<typeof RadioGroupPrimitive.Item>) { return ( <RadioGroupPrimitive.Item data-slot="radio-group-item" className={cn( "border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", className )} {...props} > <RadioGroupPrimitive.Indicator data-slot="radio-group-indicator" className="relative flex items-center justify-center" > <CircleIcon className="fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" /> </RadioGroupPrimitive.Indicator> </RadioGroupPrimitive.Item> ) } +RadioGroupItem.displayName = "RadioGroupItem"templates/agentic/travel-planner/components/ui/drawer.tsx (1)
54-54: Remove redundant data-slot prop.The
data-slot="drawer-portal"prop is redundant here sinceDrawerPortalalready sets this attribute internally (line 23). While functionally harmless, removing it improves code clarity.Apply this diff:
- <DrawerPortal data-slot="drawer-portal"> + <DrawerPortal>templates/agentic/travel-planner/components/ui/toggle.tsx (1)
9-29: Well-structured variant configuration.The toggleVariants CVA setup provides comprehensive styling with proper accessibility states (focus-visible, aria-invalid, disabled) and thoughtful SVG handling. The variant and size options are well-defined with sensible defaults.
For improved readability, the long base class string on line 10 could be split into multiple lines or grouped by concern (layout, interaction states, accessibility, SVG):
const toggleVariants = cva( - "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap", + [ + // Layout & typography + "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap", + // Interaction states + "hover:bg-muted hover:text-muted-foreground", + "disabled:pointer-events-none disabled:opacity-50", + "data-[state=on]:bg-accent data-[state=on]:text-accent-foreground", + // Focus & validation + "outline-none transition-[color,box-shadow]", + "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", + "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + // SVG styling + "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0", + ].join(" "), {templates/agentic/travel-planner/components/ui/use-mobile.tsx (2)
9-14: Use the matchMediamatchesproperty for consistency.The code creates a
MediaQueryListobject but doesn't leverage itsmatchesproperty in theonChangehandler. Instead, it recalculates usingwindow.innerWidth. While functional, this is inconsistent and slightly less efficient.Apply this diff to use the event's
matchesproperty:React.useEffect(() => { const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) - const onChange = () => { - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) + const onChange = (event: MediaQueryListEvent) => { + setIsMobile(event.matches) } mql.addEventListener("change", onChange) - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) + setIsMobile(mql.matches) return () => mql.removeEventListener("change", onChange) }, [])
5-6: Consider SSR hydration behavior.The hook initializes as
undefinedand returns!!isMobile(false on initial render). In a Next.js SSR context, this may cause a brief flash or hydration warning when the client is mobile. This is a common pattern, but consider whether a consistent default (always false) or a hydration suppression technique better fits the template's UX goals.Also applies to: 18-18
templates/agentic/travel-planner/components/ui/sidebar.tsx (5)
72-90: Persisted state: write-only cookie; add hydration + safer attributes.You set the cookie but never read it back, so “state persistence” doesn’t survive reloads. Also add SameSite and conditional Secure for hygiene.
Apply within this block:
const [_open, _setOpen] = React.useState(defaultOpen) const open = openProp ?? _open const setOpen = React.useCallback( (value: boolean | ((value: boolean) => boolean)) => { const openState = typeof value === "function" ? value(open) : value if (setOpenProp) { setOpenProp(openState) } else { _setOpen(openState) } // This sets the cookie to keep the sidebar state. - document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` + document.cookie = + `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}; SameSite=Lax` + + (typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "") }, [setOpenProp, open] ) + + // Hydrate from cookie on mount when uncontrolled + React.useEffect(() => { + if (openProp === undefined) { + const m = document.cookie.match(new RegExp(`(?:^|; )${SIDEBAR_COOKIE_NAME}=([^;]*)`)) + if (m) _setOpen(m[1] === "true") + } + }, [openProp])
96-110: Keyboard shortcut: guard typing contexts and avoid overriding Bold/Bookmarks.Currently Ctrl/Cmd+B will fire even in editors and prevents browser defaults. Guard inputs/contenteditable and don’t call preventDefault unless necessary.
React.useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { - if ( + const target = event.target as HTMLElement | null + const isTyping = + !!target && + (target.isContentEditable || + ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName)) + if ( event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey) ) { - event.preventDefault() - toggleSidebar() + if (!isTyping) { + // Avoid stealing Cmd/Ctrl+B from editors unless we’re outside inputs. + toggleSidebar() + } } }
408-413: Useoutline-noneinstead ofoutline-hidden(likely invalid).
outline-hiddenisn’t a standard Tailwind utility; useoutline-noneand rely onfocus-visible:ring-*for focus styles.Also applies to: 429-435, 564-575, 689-695
282-304: Rail a11y: confirm intended non-focusable behavior.The rail uses
tabIndex={-1}andtitleonly. If you intend it to be mouse-only, fine; otherwise addaria-pressed/focus handling for keyboard users.
183-206: Mobile cookie semantics.Toggling on mobile updates
openMobileonly (cookie tracks desktop state). If desired, persist a separate mobile preference to avoid surprising resets.templates/agentic/travel-planner/hooks/use-mobile.ts (2)
1-1: Mark as client module to prevent accidental server importThis hook touches window; add the client directive to avoid usage in Server Components.
+ "use client" + import * as React from "react"
8-16: Use event.matches and add Safari fallback for media query listenerUse the MediaQueryListEvent.matches value; also support addListener/removeListener for older Safari.
React.useEffect(() => { - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) - const onChange = () => { - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) - } - mql.addEventListener("change", onChange) - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) - return () => mql.removeEventListener("change", onChange) + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) + const onChange = (e: MediaQueryListEvent | MediaQueryList) => + setIsMobile('matches' in e ? e.matches : mql.matches) + // init + onChange(mql) + // modern + Safari fallback + mql.addEventListener?.("change", onChange as any) + mql.addListener?.(onChange as any) + return () => { + mql.removeEventListener?.("change", onChange as any) + mql.removeListener?.(onChange as any) + } }, [])templates/agentic/travel-planner/components/ui/switch.tsx (1)
8-29: Forward refs for accessibility and form libsExpose refs on Root to enable focus management (labels, RHF).
-import * as React from "react" +import * as React from "react" ... -function Switch({ - className, - ...props -}: React.ComponentProps<typeof SwitchPrimitive.Root>) { - return ( - <SwitchPrimitive.Root +const Switch = React.forwardRef< + React.ElementRef<typeof SwitchPrimitive.Root>, + React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root> +>(({ className, ...props }, ref) => { + return ( + <SwitchPrimitive.Root + ref={ref} data-slot="switch" className={cn( "peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", className )} {...props} > <SwitchPrimitive.Thumb ... - </SwitchPrimitive.Root> - ) -} + </SwitchPrimitive.Root> + ) +}) +Switch.displayName = "Switch"templates/agentic/travel-planner/components/ui/textarea.tsx (1)
5-16: Forward ref to support form libraries and focusForwarding the ref helps with react-hook-form, focusing, and accessibility.
-import * as React from "react" +import * as React from "react" ... -function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { - return ( - <textarea +const Textarea = React.forwardRef< + HTMLTextAreaElement, + React.ComponentPropsWithoutRef<"textarea"> +>(({ className, ...props }, ref) => { + return ( + <textarea + ref={ref} data-slot="textarea" className={cn( "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", className )} {...props} /> - ) -} + ) +}) +Textarea.displayName = "Textarea"templates/agentic/travel-planner/components/ui/tabs.tsx (1)
8-19: Forward refs on Radix wrappers for consistencyAdopt forwardRef for Root/List/Trigger/Content to mirror Radix primitives and allow imperative focus.
If you prefer minimal change, at least wrap TabsTrigger to enable focusing selected tab via ref.
Also applies to: 21-35, 37-51, 53-64
templates/agentic/travel-planner/components/ui/toast.tsx (1)
77-87: Replace nonstandard toast-close attribute; add accessible labelUnknown attribute toast-close="" is unnecessary. Prefer data attribute and an aria-label for screen readers.
- <ToastPrimitives.Close + <ToastPrimitives.Close ... - toast-close="" + data-toast-close + aria-label="Close" > <X className="h-4 w-4" /> </ToastPrimitives.Close>templates/agentic/travel-planner/tsconfig.json (1)
5-5: Consider using a more modern ES target.The target is set to "ES6" (ES2015), which lacks features like async/await. Modern Next.js projects typically use "ES2017" or higher for better language feature support.
Apply this diff to update to a more modern target:
- "target": "ES6", + "target": "ES2017",templates/agentic/travel-planner/components/theme-provider.tsx (1)
1-11: LGTM!Clean wrapper around next-themes provider with proper prop forwarding.
Note: This file uses single quotes while other files in the template use double quotes. For consistency, consider standardizing on double quotes throughout the codebase.
templates/agentic/travel-planner/components/ui/input.tsx (1)
5-19: Forward ref for focus/control and set a sensible default type.Forwarding refs improves integration with form libs and focus management. Also default to type="text" explicitly.
-function Input({ className, type, ...props }: React.ComponentProps<"input">) { - return ( - <input - type={type} +const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>( + ({ className, type = "text", ...props }, ref) => { + return ( + <input + ref={ref} + type={type} data-slot="input" className={cn( "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className )} {...props} /> - ) -} + ) + } +) + +Input.displayName = "Input"templates/agentic/travel-planner/components/ui/sonner.tsx (1)
6-23: Consider consolidating toast implementations.This Toaster wraps the Sonner library, while the codebase also includes another Toaster component in
toaster.tsx(based on Radix Toast primitives). Having two different toast systems can lead to:
- Confusion about which to use
- Inconsistent UX if both are used
- Unnecessary bundle size
Consider standardizing on one toast implementation across the application, or document when to use each if both are intentionally maintained.
templates/agentic/travel-planner/components/ui/button.tsx (1)
38-47: Forward refs for better interop (forms, focus, tooltips).Wrap Button with
React.forwardRef<HTMLButtonElement | HTMLAnchorElement, Props>so consumers can focus the element and compose with tooltips/popovers.I can provide a refactor if you want it included in this PR.
templates/agentic/travel-planner/components/ui/avatar.tsx (2)
24-35: Requirealton AvatarImage for accessibility.Ensure
alttext is provided (empty string for decorative). This prevents unlabeled images.Apply this diff to enforce at the type level:
-function AvatarImage({ - className, - ...props -}: React.ComponentProps<typeof AvatarPrimitive.Image>) { +function AvatarImage({ + className, + alt, + ...props +}: Omit<React.ComponentProps<typeof AvatarPrimitive.Image>, "alt"> & { + alt: string +}) { return ( <AvatarPrimitive.Image data-slot="avatar-image" - className={cn("aspect-square size-full", className)} - {...props} + className={cn("aspect-square size-full", className)} + alt={alt} + {...props} /> ) }
8-22: Optional: forward refs for Radix interop.Forward
refthrough Avatar, Image, and Fallback to keep parity with Radix primitives.templates/agentic/travel-planner/components/ui/collapsible.tsx (2)
11-19: Forward refs on CollapsibleTrigger.Radix triggers commonly rely on refs; forward them to avoid focus issues.
I can send a small forwardRef patch for
Collapsible,CollapsibleTrigger, andCollapsibleContent.
22-31: Forward refs on CollapsibleContent.Same reasoning as trigger; forward the ref for transitions/measurement.
templates/agentic/travel-planner/components/ui/alert.tsx (1)
22-35: LGTM — accessible alert surface.Solid defaults and CVA variant shape. Consider wiring
aria-labelledby/aria-describedbyusing the title/description IDs for stricter semantics.templates/agentic/travel-planner/app/page.tsx (1)
188-197: Remove unusedrawOutput(dead state).This memoized value isn’t rendered. Drop it to reduce cognitive load.
templates/agentic/travel-planner/components/ui/tooltip.tsx (1)
21-29: Consider allowing shared TooltipProvider usage.The
Tooltipcomponent always creates its ownTooltipProvider, which prevents users from sharing a provider across multiple tooltips (a common Radix UI pattern for managing delay and state). This means the exportedTooltipProvideris not usable in its intended role.Consider this alternative structure to enable provider sharing:
function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) { return ( - <TooltipProvider> - <TooltipPrimitive.Root data-slot="tooltip" {...props} /> - </TooltipProvider> + <TooltipPrimitive.Root data-slot="tooltip" {...props} /> ) }Users could then wrap multiple tooltips:
<TooltipProvider> <Tooltip>...</Tooltip> <Tooltip>...</Tooltip> </TooltipProvider>templates/agentic/travel-planner/components/ui/calendar.tsx (1)
183-186: Consider optimizing the useEffect dependency array.The
modifiersobject may be recreated on each render, causing this effect to run more frequently than necessary. Since you only needmodifiers.focused, extract it before the effect.Apply this diff to optimize:
function CalendarDayButton({ className, day, modifiers, ...props }: React.ComponentProps<typeof DayButton>) { const defaultClassNames = getDefaultClassNames() const ref = React.useRef<HTMLButtonElement>(null) + const isFocused = modifiers.focused React.useEffect(() => { - if (modifiers.focused) ref.current?.focus() - }, [modifiers.focused]) + if (isFocused) ref.current?.focus() + }, [isFocused])templates/agentic/travel-planner/components/ui/pagination.tsx (1)
102-117: Use explicit boolean value for aria-hidden.For clarity and consistency,
aria-hiddenshould be set to an explicit boolean value.Apply this diff:
return ( <span - aria-hidden + aria-hidden="true" data-slot="pagination-ellipsis" className={cn("flex size-9 items-center justify-center", className)} {...props} >templates/agentic/travel-planner/components/ui/chart.tsx (2)
186-221: Unstable React keys in tooltip items
key={item.dataKey}can be undefined or duplicated, causing key collisions. Use a stable composite fallback.- <div - key={item.dataKey} + <div + key={`${String(item.dataKey ?? item.name ?? "item")}-${index}`}Also applies to: 229-241
279-301: Legend key and color fallback
- Keying by
item.valuerisks duplicates. UsedataKeyor index fallback.- If
item.coloris missing, fall back to CSS var from ChartStyle.- {payload.map((item) => { + {payload.map((item, index) => { @@ - <div - key={item.value} + <div + key={String(item.dataKey ?? item.value ?? index)} @@ - <div - className="h-2 w-2 shrink-0 rounded-[2px]" - style={{ - backgroundColor: item.color, - }} - /> + <div + className="h-2 w-2 shrink-0 rounded-[2px]" + style={{ + backgroundColor: item.color ?? `var(--color-${String(item.dataKey ?? "value")})`, + }} + />templates/agentic/travel-planner/hooks/use-toast.ts (2)
77-130: Reducer lacks default branchAdd a default returning current state for robustness.
switch (action.type) { @@ - } + default: + return state + }
11-13: Hard-coded TOAST_LIMIT/TOAST_REMOVE_DELAYConsider making these configurable via props/env or export setters for UX tuning.
templates/agentic/travel-planner/components/ui/dialog.tsx (2)
33-47: Preserve ref forwarding on Radix wrappersWithout forwardRef, consumers cannot attach refs, breaking common patterns.
-function DialogOverlay({ - className, - ...props -}: React.ComponentProps<typeof DialogPrimitive.Overlay>) { - return ( - <DialogPrimitive.Overlay +const DialogOverlay = React.forwardRef< + React.ElementRef<typeof DialogPrimitive.Overlay>, + React.ComponentProps<typeof DialogPrimitive.Overlay> +>(({ className, ...props }, ref) => ( + <DialogPrimitive.Overlay data-slot="dialog-overlay" className={cn( "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", className )} - {...props} + ref={ref} + {...props} /> - ) -} +)) +DialogOverlay.displayName = "DialogOverlay"
49-81: Forward ref through DialogContent and align with Radix compositionEnables focus management and parent ref access.
-function DialogContent({ - className, - children, - showCloseButton = true, - ...props -}: React.ComponentProps<typeof DialogPrimitive.Content> & { - showCloseButton?: boolean -}) { - return ( +const DialogContent = React.forwardRef< + React.ElementRef<typeof DialogPrimitive.Content>, + React.ComponentProps<typeof DialogPrimitive.Content> & { showCloseButton?: boolean } +>(({ className, children, showCloseButton = true, ...props }, ref) => { + return ( <DialogPortal data-slot="dialog-portal"> <DialogOverlay /> <DialogPrimitive.Content data-slot="dialog-content" className={cn( "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg", className )} + ref={ref} {...props} > {children} {showCloseButton && ( <DialogPrimitive.Close data-slot="dialog-close" className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:not([class*='size-'])]:size-4" > <XIcon /> <span className="sr-only">Close</span> </DialogPrimitive.Close> )} </DialogPrimitive.Content> </DialogPortal> - ) -} + ) +}) +DialogContent.displayName = "DialogContent"templates/agentic/travel-planner/actions/orchestrate.ts (2)
404-421: embedHtml may be rendered later; sanitize at render timeVisualizationResource.embedHtml is carried through; ensure any UI that injects it sanitizes with DOMPurify (or avoid HTML injection). No change here, but add a TODO near the renderer.
Also applies to: 635-791
793-821: Add optional AbortSignal/timeout to flow callPrevents indefinite hangs if the external service stalls.
-export async function planTrip( - preferences: TravelPreferences -): Promise<PlanTripResponse> { +export async function planTrip( + preferences: TravelPreferences, + options?: { signal?: AbortSignal; timeoutMs?: number } +): Promise<PlanTripResponse> { try { @@ - const response = await lamaticClient.executeFlow( - travelPlannerFlow.workflowId, - payload - ); + const controller = + options?.signal ? null : new AbortController() + const timer = options?.timeoutMs + ? setTimeout(() => controller?.abort(), options.timeoutMs) + : undefined + const response = await lamaticClient.executeFlow( + travelPlannerFlow.workflowId, + payload, + { signal: options?.signal ?? controller?.signal } + ) + if (timer) clearTimeout(timer)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (3)
templates/agentic/travel-planner/app/icon.pngis excluded by!**/*.pngtemplates/agentic/travel-planner/public/lamatic-logo.pngis excluded by!**/*.pngtemplates/agentic/travel-planner/public/placeholder.svgis excluded by!**/*.svg
📒 Files selected for processing (73)
templates/agentic/travel-planner/.env.example(1 hunks)templates/agentic/travel-planner/.eslintrc.json(1 hunks)templates/agentic/travel-planner/.gitignore(1 hunks)templates/agentic/travel-planner/.npmrc(1 hunks)templates/agentic/travel-planner/LICENSE(1 hunks)templates/agentic/travel-planner/README.md(1 hunks)templates/agentic/travel-planner/actions/orchestrate.ts(1 hunks)templates/agentic/travel-planner/app/globals.css(1 hunks)templates/agentic/travel-planner/app/layout.tsx(1 hunks)templates/agentic/travel-planner/app/page.tsx(1 hunks)templates/agentic/travel-planner/components.json(1 hunks)templates/agentic/travel-planner/components/theme-provider.tsx(1 hunks)templates/agentic/travel-planner/components/ui/accordion.tsx(1 hunks)templates/agentic/travel-planner/components/ui/alert-dialog.tsx(1 hunks)templates/agentic/travel-planner/components/ui/alert.tsx(1 hunks)templates/agentic/travel-planner/components/ui/aspect-ratio.tsx(1 hunks)templates/agentic/travel-planner/components/ui/avatar.tsx(1 hunks)templates/agentic/travel-planner/components/ui/badge.tsx(1 hunks)templates/agentic/travel-planner/components/ui/breadcrumb.tsx(1 hunks)templates/agentic/travel-planner/components/ui/button.tsx(1 hunks)templates/agentic/travel-planner/components/ui/calendar.tsx(1 hunks)templates/agentic/travel-planner/components/ui/card.tsx(1 hunks)templates/agentic/travel-planner/components/ui/carousel.tsx(1 hunks)templates/agentic/travel-planner/components/ui/chart.tsx(1 hunks)templates/agentic/travel-planner/components/ui/checkbox.tsx(1 hunks)templates/agentic/travel-planner/components/ui/collapsible.tsx(1 hunks)templates/agentic/travel-planner/components/ui/command.tsx(1 hunks)templates/agentic/travel-planner/components/ui/context-menu.tsx(1 hunks)templates/agentic/travel-planner/components/ui/dialog.tsx(1 hunks)templates/agentic/travel-planner/components/ui/drawer.tsx(1 hunks)templates/agentic/travel-planner/components/ui/dropdown-menu.tsx(1 hunks)templates/agentic/travel-planner/components/ui/form.tsx(1 hunks)templates/agentic/travel-planner/components/ui/hover-card.tsx(1 hunks)templates/agentic/travel-planner/components/ui/input-otp.tsx(1 hunks)templates/agentic/travel-planner/components/ui/input.tsx(1 hunks)templates/agentic/travel-planner/components/ui/label.tsx(1 hunks)templates/agentic/travel-planner/components/ui/menubar.tsx(1 hunks)templates/agentic/travel-planner/components/ui/navigation-menu.tsx(1 hunks)templates/agentic/travel-planner/components/ui/pagination.tsx(1 hunks)templates/agentic/travel-planner/components/ui/popover.tsx(1 hunks)templates/agentic/travel-planner/components/ui/progress.tsx(1 hunks)templates/agentic/travel-planner/components/ui/radio-group.tsx(1 hunks)templates/agentic/travel-planner/components/ui/resizable.tsx(1 hunks)templates/agentic/travel-planner/components/ui/scroll-area.tsx(1 hunks)templates/agentic/travel-planner/components/ui/select.tsx(1 hunks)templates/agentic/travel-planner/components/ui/separator.tsx(1 hunks)templates/agentic/travel-planner/components/ui/sheet.tsx(1 hunks)templates/agentic/travel-planner/components/ui/sidebar.tsx(1 hunks)templates/agentic/travel-planner/components/ui/skeleton.tsx(1 hunks)templates/agentic/travel-planner/components/ui/slider.tsx(1 hunks)templates/agentic/travel-planner/components/ui/sonner.tsx(1 hunks)templates/agentic/travel-planner/components/ui/switch.tsx(1 hunks)templates/agentic/travel-planner/components/ui/table.tsx(1 hunks)templates/agentic/travel-planner/components/ui/tabs.tsx(1 hunks)templates/agentic/travel-planner/components/ui/textarea.tsx(1 hunks)templates/agentic/travel-planner/components/ui/toast.tsx(1 hunks)templates/agentic/travel-planner/components/ui/toaster.tsx(1 hunks)templates/agentic/travel-planner/components/ui/toggle-group.tsx(1 hunks)templates/agentic/travel-planner/components/ui/toggle.tsx(1 hunks)templates/agentic/travel-planner/components/ui/tooltip.tsx(1 hunks)templates/agentic/travel-planner/components/ui/use-mobile.tsx(1 hunks)templates/agentic/travel-planner/components/ui/use-toast.ts(1 hunks)templates/agentic/travel-planner/hooks/use-mobile.ts(1 hunks)templates/agentic/travel-planner/hooks/use-toast.ts(1 hunks)templates/agentic/travel-planner/lamatic-config.json(1 hunks)templates/agentic/travel-planner/lib/lamatic-client.ts(1 hunks)templates/agentic/travel-planner/lib/utils.ts(1 hunks)templates/agentic/travel-planner/next.config.mjs(1 hunks)templates/agentic/travel-planner/package.json(1 hunks)templates/agentic/travel-planner/postcss.config.mjs(1 hunks)templates/agentic/travel-planner/scripts/deploy.sh(1 hunks)templates/agentic/travel-planner/styles/globals.css(1 hunks)templates/agentic/travel-planner/tsconfig.json(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (11)
templates/agentic/travel-planner/hooks/use-mobile.ts (1)
templates/agentic/travel-planner/components/ui/use-mobile.tsx (1)
useIsMobile(5-19)
templates/agentic/travel-planner/components/ui/form.tsx (1)
templates/agentic/travel-planner/components/ui/label.tsx (1)
Label(24-24)
templates/agentic/travel-planner/components/ui/sonner.tsx (1)
templates/agentic/travel-planner/components/ui/toaster.tsx (1)
Toaster(13-35)
templates/agentic/travel-planner/components/ui/command.tsx (1)
templates/agentic/travel-planner/components/ui/dialog.tsx (5)
Dialog(133-133)DialogHeader(138-138)DialogTitle(141-141)DialogDescription(136-136)DialogContent(135-135)
templates/agentic/travel-planner/components/ui/toaster.tsx (2)
templates/agentic/travel-planner/hooks/use-toast.ts (1)
useToast(194-194)templates/agentic/travel-planner/components/ui/toast.tsx (6)
ToastProvider(122-122)Toast(124-124)ToastTitle(125-125)ToastDescription(126-126)ToastClose(127-127)ToastViewport(123-123)
templates/agentic/travel-planner/components/ui/sidebar.tsx (1)
templates/agentic/travel-planner/hooks/use-mobile.ts (1)
useIsMobile(5-19)
templates/agentic/travel-planner/app/page.tsx (1)
templates/agentic/travel-planner/actions/orchestrate.ts (3)
NormalizedTravelPlan(124-141)planTrip(793-852)FlightLeg(113-117)
templates/agentic/travel-planner/hooks/use-toast.ts (1)
templates/agentic/travel-planner/components/ui/toast.tsx (3)
ToastProps(120-120)ToastActionElement(121-121)Toast(124-124)
templates/agentic/travel-planner/components/ui/use-toast.ts (1)
templates/agentic/travel-planner/components/ui/toast.tsx (3)
ToastProps(120-120)ToastActionElement(121-121)Toast(124-124)
templates/agentic/travel-planner/actions/orchestrate.ts (2)
templates/assistant/grammar-extension/sidepanel.js (1)
response(130-138)templates/agentic/travel-planner/lib/lamatic-client.ts (1)
lamaticClient(10-14)
templates/agentic/travel-planner/components/ui/alert-dialog.tsx (1)
templates/agentic/travel-planner/components/ui/button.tsx (1)
buttonVariants(59-59)
🪛 ast-grep (0.39.6)
templates/agentic/travel-planner/components/ui/chart.tsx
[warning] 82-82: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html
(react-unsafe-html-injection)
templates/agentic/travel-planner/app/page.tsx
[warning] 1422-1422: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html
(react-unsafe-html-injection)
🪛 Biome (2.1.2)
templates/agentic/travel-planner/components/ui/chart.tsx
[error] 83-83: Avoid passing content using the dangerouslySetInnerHTML prop.
Setting content using code can expose users to cross-site scripting (XSS) attacks
(lint/security/noDangerouslySetInnerHtml)
templates/agentic/travel-planner/app/page.tsx
[error] 1423-1424: Avoid passing content using the dangerouslySetInnerHTML prop.
Setting content using code can expose users to cross-site scripting (XSS) attacks
(lint/security/noDangerouslySetInnerHtml)
🔇 Additional comments (49)
templates/agentic/travel-planner/components/ui/aspect-ratio.tsx (1)
1-11: LGTM! Clean wrapper implementation.The AspectRatio component is a well-structured wrapper around Radix UI's primitive. The type safety, prop forwarding, and
data-slotattribute follow the established pattern for UI components in this codebase.templates/agentic/travel-planner/components/ui/skeleton.tsx (2)
1-2: LGTM!The import is clean and follows standard patterns for className merging utilities.
13-13: LGTM!The named export follows standard patterns for component libraries.
templates/agentic/travel-planner/components/ui/radio-group.tsx (3)
1-8: LGTM! Clean imports and proper Next.js client directive.The imports are well-organized, and the "use client" directive is correctly placed for this interactive component.
9-20: LGTM! Well-structured RadioGroup wrapper.The component properly forwards all props (including refs) and provides sensible default styling with the grid layout.
22-43: LGTM! Comprehensive styling with excellent accessibility.The RadioGroupItem component includes proper focus states, invalid states, disabled states, and dark mode support. The CircleIcon indicator is correctly centered.
templates/agentic/travel-planner/components/ui/drawer.tsx (1)
1-135: LGTM! Well-structured drawer component wrapper.The implementation follows established UI component patterns and properly wraps the vaul library primitives with consistent styling, data-slot attributes, and TypeScript typing. The directional styling logic correctly handles all four drawer directions (top, bottom, left, right), and the handle indicator appropriately displays only for bottom drawers.
templates/agentic/travel-planner/components/ui/toggle.tsx (2)
1-8: LGTM! Clean setup with proper directives.The imports and "use client" directive are correctly structured for a Next.js client component using Radix UI primitives.
31-47: LGTM! Correct export of both component and variants.The Toggle component properly wraps the Radix primitive and exports toggleVariants, which is essential for the ToggleGroup component to maintain consistent styling.
templates/agentic/travel-planner/components/ui/toggle-group.tsx (3)
1-15: LGTM! Well-designed context for variant inheritance.The ToggleGroupContext with default values enables child items to inherit variant and size from the parent group, promoting consistent styling and reducing prop duplication.
17-41: LGTM! Clean provider implementation.The ToggleGroup properly wraps children in a context provider and applies appropriate data attributes for styling hooks. The
group/toggle-groupclass enables group-based styling of descendants.
43-73: LGTM! Context consumption with proper fallback.The ToggleGroupItem correctly consumes context values with fallback to explicit props, enabling flexible usage. The styling on line 63 effectively creates a visually connected toggle group with:
- Collapsed borders between items (
border-l-0withfirst:border-l)- Selective rounding (
first:rounded-l-md,last:rounded-r-md)- Proper focus layering (
focus:z-10)The consistent fallback pattern (
context.variant || variant) across data attributes and variant application ensures predictable behavior.templates/agentic/travel-planner/components/ui/carousel.tsx (1)
174-232: Navigation buttons are well-implemented.Both CarouselPrevious and CarouselNext correctly consume context, adjust positioning based on orientation, respect scroll boundaries via the disabled state, and include accessible sr-only labels.
templates/agentic/travel-planner/components/ui/menubar.tsx (1)
114-138: No changes required. The review comment is incorrect.Both
outline-hiddenandrounded-xsare valid standard utilities in Tailwind CSS v4.1.9 (the version in use):
outline-hiddenintentionally preserves outlines in forced-colors/accessibility mode while hiding them visually, making it more accessible thanoutline-none(which completely removes outlines).rounded-xsis a standard v4 utility applying 0.125rem border-radius, not a custom class.The code is correct as written.
Likely an incorrect or invalid review comment.
templates/agentic/travel-planner/components/ui/context-menu.tsx (1)
236-252: LGTM!All components are properly exported and the export structure is clean.
templates/agentic/travel-planner/components/ui/sidebar.tsx (2)
264-278: Ensure the trigger doesn’t submit forms.If your
Buttoncomponent doesn’t default totype="button", clicking this inside a form will submit it. Consider explicitly setting the type.- <Button + <Button + type="button"
173-176: Based on my verification of the codebase and Tailwind v4 documentation:Tailwind CSS v4 exposes CSS variables and allows consuming them with syntax like
bg-(--color-primary), confirming thatw-(--sidebar-width)andmax-w-(--skeleton-width)are native Tailwind v4 features, not nonstandard or requiring custom plugins.The search results showed these patterns used consistently across many template files—not hypothetical edge cases. The w-(--gutter-width) syntax is documented Tailwind v4 for arbitrary CSS custom property values.
The other mentioned patterns (
[[data-*]]compound selectors,in-data-variants, and complex data attribute selectors) appear throughout the codebase in actual use, and Tailwind v4 supports data- prefixed variants likedata-selected:bg-emerald-600. The absence of visible build errors or style failures across multiple templates suggests these patterns are working as intended.No issues found. These are intentional Tailwind v4 syntax choices, not nonstandard patterns requiring verification.
templates/agentic/travel-planner/.eslintrc.json (1)
1-6: LGTM!The ESLint configuration correctly extends Next.js core web vitals and TypeScript rules, which is the recommended setup for Next.js projects with TypeScript.
templates/agentic/travel-planner/LICENSE (1)
1-21: LGTM!Standard MIT License with appropriate copyright notice for 2025.
templates/agentic/travel-planner/README.md (1)
1-107: LGTM! Excellent documentation.The README provides comprehensive, well-organized documentation covering setup, architecture, customization, and validation. The inclusion of specific workflow details, file path references, and a validation checklist makes this template immediately usable.
templates/agentic/travel-planner/components.json (1)
1-21: LGTM!The shadcn/ui configuration is properly set up with React Server Components, TypeScript, Tailwind CSS variables, and appropriate path aliases that align with the project structure.
templates/agentic/travel-planner/components/ui/label.tsx (1)
1-24: LGTM!Well-structured Label component following best practices:
- Proper "use client" directive for client-side interactivity
- Type-safe prop forwarding using Radix UI's component props
- Comprehensive accessibility styling including disabled and peer states
- Clean composition pattern using the cn utility
templates/agentic/travel-planner/.gitignore (1)
36-37: Verify the lamatic config filename.The
.gitignoreignoresconfig.json, but the README and other documentation consistently referencelamatic-config.json. Please verify:
- If
config.jsonis a different file that should be ignored- Or if this should be
lamatic-config.jsoninsteadGiven that the README instructs users to include
lamatic-config.jsonin their deployments and states it should be "uploaded to Vercel," this discrepancy could lead to confusion or accidental commits of the wrong file.If this should ignore
lamatic-config.json, apply this diff:#lamatic -config.json +lamatic-config.jsontemplates/agentic/travel-planner/components/ui/separator.tsx (1)
1-28: LGTM!Well-implemented Separator component with:
- Proper client directive for Radix UI
- Sensible defaults (
decorative=true,orientation="horizontal")- Data-attribute-based styling for both orientations
- Clean prop forwarding pattern
templates/agentic/travel-planner/postcss.config.mjs (1)
1-6: No changes needed—configuration is correct for Tailwind v4The template specifies Tailwind CSS v4.1.9, and the postcss.config.mjs correctly uses
'@tailwindcss/postcss'as the plugin. For Tailwind CSS v4, the PostCSS plugin is the separate package "@tailwindcss/postcss". The code is already properly configured.templates/agentic/travel-planner/components/ui/popover.tsx (1)
1-48: LGTM!Clean implementation of Radix UI Popover primitives with proper prop forwarding, Portal rendering, and consistent styling patterns.
templates/agentic/travel-planner/.env.example (1)
1-1: LGTM!Appropriate environment variable placeholder for Lamatic API integration.
templates/agentic/travel-planner/components/ui/checkbox.tsx (1)
1-32: LGTM!Well-structured Radix UI Checkbox wrapper with comprehensive state styling (checked, disabled, focus, invalid) and proper accessibility attributes.
templates/agentic/travel-planner/lib/utils.ts (1)
1-6: LGTM!Standard utility for merging Tailwind CSS classes using clsx and tailwind-merge. This pattern properly handles conditional classes and resolves Tailwind class conflicts.
templates/agentic/travel-planner/components/ui/toaster.tsx (1)
13-35: LGTM — toast mapping and provider/viewport wiring look correct.templates/agentic/travel-planner/styles/globals.css (1)
2-2: Now let me verify the Tailwind version being used:Remove the review comment; current animation import is correct for Tailwind v4.
tw-animate-css is a replacement for tailwindcss-animate that embraces the new CSS-first architecture. The correct usage for Tailwind v4 is
@import "tw-animate-css", which matches the current code exactly. shadcn/ui deprecated tailwindcss-animate in favor of tw-animate-css, with new projects defaulting to tw-animate-css. The original suggestion to use@plugin "tailwindcss-animate"is the legacy JavaScript configuration approach, not compatible with Tailwind v4's CSS-first model.templates/agentic/travel-planner/components/ui/progress.tsx (1)
8-29: LGTM!Clean implementation of a Radix UI Progress component. The transform calculation correctly positions the indicator based on the value prop, and the component properly forwards all standard ProgressRoot props.
templates/agentic/travel-planner/lamatic-config.json (1)
1-29: LGTM!Well-structured Lamatic configuration that properly defines the travel planner workflow schema. The workflowId matches the one referenced in the PR description, and the input/output schemas are comprehensive.
templates/agentic/travel-planner/app/globals.css (1)
1-125: Well-structured theme system.The CSS establishes a comprehensive design system with proper light/dark mode support and Tailwind integration. The theme token mapping is clean and maintainable.
templates/agentic/travel-planner/app/layout.tsx (1)
15-27: LGTM!Clean root layout implementation with proper font configuration, Suspense boundary, and analytics integration.
templates/agentic/travel-planner/components/ui/slider.tsx (1)
8-61: LGTM!Well-implemented Slider component that properly handles both single and multi-value scenarios. The
useMemooptimization for_valuesis appropriate, and the dynamic thumb rendering based on array length is clean.templates/agentic/travel-planner/components/ui/badge.tsx (1)
7-44: LGTM!Clean Badge component implementation with well-defined variants using
class-variance-authority. TheasChildprop support enables flexible composition, and the variant styles are comprehensive.templates/agentic/travel-planner/app/page.tsx (1)
6-13: The API key is properly protected; the current server action pattern is safe.The concern in the review is technically incorrect. While
page.tsxis a client component, it correctly importsplanTripas a server action (which has"use server"at the top oforchestrate.ts). In Next.js, when a client component calls a server action, the action's dependencies—includinglamatic-client.ts—execute only on the server.process.env.LAMATIC_API_KEYis never exposed to the browser.That said, adding explicit
"use server"or"server-only"tolib/lamatic-client.tsis a best practice to prevent accidental client-side bundling:"use server"; import { Lamatic } from "lamatic"; import config from "@/lamatic-config.json"; // ... rest of fileThis clarifies intent and hardens the boundary without changing runtime behavior.
Likely an incorrect or invalid review comment.
templates/agentic/travel-planner/components/ui/resizable.tsx (1)
1-56: LGTM!The resizable components correctly wrap the react-resizable-panels primitives with consistent data-slot attributes and className composition. The ResizableHandle's orientation-aware styling and optional grip icon are well implemented.
templates/agentic/travel-planner/components/ui/accordion.tsx (1)
1-66: LGTM!The accordion components correctly implement the Radix UI primitives with appropriate semantic structure, ARIA attributes, and animation states. The trigger includes accessible focus indicators and the chevron rotation enhances user experience.
templates/agentic/travel-planner/components/ui/dropdown-menu.tsx (1)
1-257: LGTM!The dropdown menu components provide a comprehensive and well-structured API surface. All wrappers correctly forward props to Radix UI primitives, apply consistent data-slot attributes, and include appropriate indicators (checkmarks, radio dots, chevrons). The variant system and inset support add useful flexibility.
templates/agentic/travel-planner/components/ui/table.tsx (1)
1-116: LGTM!The table components correctly wrap semantic HTML table elements with appropriate styling. The overflow container in the
Tablecomponent ensures responsive behavior, and the checkbox-aware selectors inTableHeadandTableCelldemonstrate thoughtful design for common use cases.templates/agentic/travel-planner/components/ui/input-otp.tsx (1)
1-77: LGTM!The OTP input components correctly integrate with the input-otp library. The
InputOTPSlotimplementation includes proper defensive coding with optional chaining (line 47) and comprehensive state-aware styling for active and invalid states. The visual caret indicator enhances user experience.templates/agentic/travel-planner/components/ui/card.tsx (1)
1-92: LGTM!The card component structure is well-organized with consistent use of data-slot attributes and proper prop forwarding. All seven card components follow the established patterns in the UI library.
templates/agentic/travel-planner/components/ui/select.tsx (1)
1-185: LGTM!The select component suite is comprehensive and well-implemented. It properly wraps Radix UI primitives with consistent styling, includes size variants, and maintains good accessibility with keyboard navigation and screen reader support.
templates/agentic/travel-planner/components/ui/navigation-menu.tsx (1)
1-168: LGTM!The navigation menu implementation is comprehensive and follows best practices. It includes proper animations, keyboard navigation support, and a flexible API with optional viewport rendering. The use of
cvafor styling variants maintains consistency across the component.templates/agentic/travel-planner/components/ui/alert-dialog.tsx (1)
1-157: LGTM with minor suggestion for consistency.The alert dialog implementation is solid and follows the established patterns. All components properly wrap Radix UI primitives with appropriate styling and accessibility features.
For consistency, consider adding
data-slotattributes toAlertDialogActionandAlertDialogCancel(lines 121-143) to match the pattern used by other components in this file:function AlertDialogAction({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Action>) { return ( <AlertDialogPrimitive.Action + data-slot="alert-dialog-action" className={cn(buttonVariants(), className)} {...props} /> ) } function AlertDialogCancel({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) { return ( <AlertDialogPrimitive.Cancel + data-slot="alert-dialog-cancel" className={cn(buttonVariants({ variant: "outline" }), className)} {...props} /> ) }templates/agentic/travel-planner/actions/orchestrate.ts (1)
6-11: Config structure matches code expectations—no issues foundThe code at lines 6-11 correctly extracts
travelPlannerFlowfromconfig.flows.travelPlannerwith proper error handling. Verification confirms thelamatic-config.jsoncontainsflows.travelPlanner.workflowIdas expected, and theplanTripfunction correctly accesses this key at line 819.templates/agentic/travel-planner/components/ui/dialog.tsx (1)
71-76: Review comment is incorrect — both utilities are valid Tailwind v4 standards.The utilities
rounded-xsandoutline-hiddenare not non-standard. Both are core Tailwind utilities:
rounded-xsis the standard name for the smallest border-radius in Tailwind v4 (previouslyrounded-smin v3). It's a native utility.outline-hiddenis a standard Tailwind utility that outputs a transparent outline with offset, preserving accessibility for forced-colors mode while visually removing the default outline.The code at lines 71–76 in
templates/agentic/travel-planner/components/ui/dialog.tsxcorrectly uses these supported utilities.Likely an incorrect or invalid review comment.
| @@ -0,0 +1 @@ | |||
| force=true No newline at end of file | |||
There was a problem hiding this comment.
Remove force=true to prevent dependency conflicts.
The force=true flag forces npm to overwrite files and ignore conflicts, which can mask version mismatches and make builds less reproducible. This is particularly problematic in CI/CD environments and can lead to hard-to-debug issues.
Remove this line unless there's a specific, documented reason for forcing installations:
-force=true📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| force=true |
🤖 Prompt for AI Agents
In templates/agentic/travel-planner/.npmrc around lines 1 to 1, remove the
"force=true" setting because it forces npm to overwrite files and mask
dependency/version conflicts; delete that line (or comment it out) so installs
use default conflict handling and add a brief comment in the file if there was a
previous reason so future maintainers know why it was removed.
| } catch (error) { | ||
| console.error( | ||
| "[travel-planner] Failed to execute travel planner flow", | ||
| error | ||
| ); | ||
| const message = | ||
| error instanceof Error | ||
| ? error.message | ||
| : "Unexpected error while executing travel planner workflow."; | ||
|
|
||
| return { | ||
| success: false, | ||
| error: message, | ||
| }; | ||
| } |
There was a problem hiding this comment.
Log hygiene: avoid dumping full error objects (risk of sensitive data)
Remote client errors can include request/headers. Log minimal message and a safe code instead.
- console.error(
- "[travel-planner] Failed to execute travel planner flow",
- error
- );
+ const msg =
+ error instanceof Error ? error.message : "Unknown error"
+ console.error("[travel-planner] Failed to execute travel planner flow:", msg)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } catch (error) { | |
| console.error( | |
| "[travel-planner] Failed to execute travel planner flow", | |
| error | |
| ); | |
| const message = | |
| error instanceof Error | |
| ? error.message | |
| : "Unexpected error while executing travel planner workflow."; | |
| return { | |
| success: false, | |
| error: message, | |
| }; | |
| } | |
| } catch (error) { | |
| const msg = | |
| error instanceof Error ? error.message : "Unknown error" | |
| console.error("[travel-planner] Failed to execute travel planner flow:", msg) | |
| const message = | |
| error instanceof Error | |
| ? error.message | |
| : "Unexpected error while executing travel planner workflow."; | |
| return { | |
| success: false, | |
| error: message, | |
| }; | |
| } |
🤖 Prompt for AI Agents
templates/agentic/travel-planner/actions/orchestrate.ts around lines 837 to 851:
current catch block prints the full error object and returns the raw error
message; change it to log only a minimal, non-sensitive message (e.g.,
console.error("[travel-planner] Failed to execute travel planner flow:",
error?.message || "unknown error")) and do NOT log stack, request headers, or
the full error object; return a safe error code/string (for example success:
false, errorCode: "TRAVEL_PLANNER_EXECUTION_FAILED") and optionally include a
non-sensitive short message for users (e.g., "An internal error occurred"); if
you need to preserve specific error types, map known errors to distinct safe
codes instead of returning raw error text.
| --destructive: oklch(0.577 0.245 27.325); | ||
| --destructive-foreground: oklch(0.577 0.245 27.325); |
There was a problem hiding this comment.
Fix contrast issue: destructive foreground color.
The --destructive and --destructive-foreground are set to the same color value in light mode, which would result in insufficient contrast (text would be invisible on destructive buttons/alerts). The dark mode correctly uses different values (lines 57-58).
Apply this diff to fix the contrast:
--destructive: oklch(0.577 0.245 27.325);
- --destructive-foreground: oklch(0.577 0.245 27.325);
+ --destructive-foreground: oklch(0.985 0 0);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| --destructive: oklch(0.577 0.245 27.325); | |
| --destructive-foreground: oklch(0.577 0.245 27.325); | |
| --destructive: oklch(0.577 0.245 27.325); | |
| --destructive-foreground: oklch(0.985 0 0); |
🤖 Prompt for AI Agents
In templates/agentic/travel-planner/app/globals.css around lines 21-22, the
light-mode CSS variables set --destructive and --destructive-foreground to the
exact same oklch value which yields insufficient contrast; change
--destructive-foreground to a contrasting color (use a much darker oklch
lightness or the same foreground value used for dark mode at lines 57-58) so
text on destructive elements meets contrast requirements.
| export const metadata: Metadata = { | ||
| title: "Agent Kit Reasoning", | ||
| description: "AI-powered search and chat interface by Lamatic.ai", | ||
| generator: "v0.app", | ||
| } |
There was a problem hiding this comment.
Update metadata to reflect the travel planner purpose.
The metadata describes a "search and chat interface" with title "Agent Kit Reasoning", but this PR introduces a multi-agent travel planner. The metadata should accurately reflect the application's purpose for SEO and user clarity.
Apply this diff to update the metadata:
export const metadata: Metadata = {
- title: "Agent Kit Reasoning",
- description: "AI-powered search and chat interface by Lamatic.ai",
+ title: "Agent Kit Travel Planner",
+ description: "Multi-agent travel researcher and booking assistant by Lamatic.ai",
generator: "v0.app",
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const metadata: Metadata = { | |
| title: "Agent Kit Reasoning", | |
| description: "AI-powered search and chat interface by Lamatic.ai", | |
| generator: "v0.app", | |
| } | |
| export const metadata: Metadata = { | |
| title: "Agent Kit Travel Planner", | |
| description: "Multi-agent travel researcher and booking assistant by Lamatic.ai", | |
| generator: "v0.app", | |
| } |
🤖 Prompt for AI Agents
In templates/agentic/travel-planner/app/layout.tsx around lines 9 to 13, the
exported metadata currently references "Agent Kit Reasoning" and a generic
"search and chat interface"; update the metadata to reflect this app as a travel
planner by changing the title to something like "Travel Planner — Agentic
Multi‑Agent Planner" and the description to "AI-powered multi-agent travel
planner by Lamatic.ai" (leave generator unchanged), so replace the existing
title and description strings with these travel-planner-specific values.
| const today = useMemo(() => new Date().toISOString().split("T")[0], []); | ||
|
|
||
| const endDateMin = useMemo(() => { | ||
| if (form.startDate) { | ||
| return form.startDate > today ? form.startDate : today; | ||
| } | ||
| return today; | ||
| }, [form.startDate, today]); |
There was a problem hiding this comment.
Fix off‑by‑one dates: compute “today” in local time, not UTC.
toISOString().split("T")[0] uses UTC; in US time zones this can shift to tomorrow and block selecting the correct date.
Apply this diff:
- const today = useMemo(() => new Date().toISOString().split("T")[0], []);
+ const today = useMemo(() => {
+ const d = new Date();
+ const y = d.getFullYear();
+ const m = String(d.getMonth() + 1).padStart(2, "0");
+ const day = String(d.getDate()).padStart(2, "0");
+ return `${y}-${m}-${day}`;
+ }, []);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const today = useMemo(() => new Date().toISOString().split("T")[0], []); | |
| const endDateMin = useMemo(() => { | |
| if (form.startDate) { | |
| return form.startDate > today ? form.startDate : today; | |
| } | |
| return today; | |
| }, [form.startDate, today]); | |
| const today = useMemo(() => { | |
| const d = new Date(); | |
| const y = d.getFullYear(); | |
| const m = String(d.getMonth() + 1).padStart(2, "0"); | |
| const day = String(d.getDate()).padStart(2, "0"); | |
| return `${y}-${m}-${day}`; | |
| }, []); | |
| const endDateMin = useMemo(() => { | |
| if (form.startDate) { | |
| return form.startDate > today ? form.startDate : today; | |
| } | |
| return today; | |
| }, [form.startDate, today]); |
🤖 Prompt for AI Agents
In templates/agentic/travel-planner/app/page.tsx around lines 172 to 179,
replace the UTC-based today computation that uses toISOString().split("T")[0]
with a local-date string built from new Date() using getFullYear(), getMonth()+1
and getDate() with zero-padding to produce YYYY-MM-DD; keep it memoized the same
way and ensure endDateMin logic remains unchanged but uses this local today
value so dates in local timezones (e.g. US) don't shift to the wrong day.
| if (!process.env.LAMATIC_API_KEY) { | ||
| throw new Error( | ||
| "LAMATIC_API_KEY environment variable is not set. Please add it to your .env.local file." | ||
| ); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
Harden server-only usage and fix apiKey typing; avoid client-bundle hazards.
- Add server-only guard to prevent accidental client imports.
- Narrow env var to a string via a local const to satisfy TS strict.
Apply within this file:
import { Lamatic } from "lamatic";
import config from "@/lamatic-config.json";
-if (!process.env.LAMATIC_API_KEY) {
- throw new Error(
- "LAMATIC_API_KEY environment variable is not set. Please add it to your .env.local file."
- );
-}
+const apiKey = process.env.LAMATIC_API_KEY;
+if (!apiKey) {
+ throw new Error(
+ "LAMATIC_API_KEY environment variable is not set. Please add it to your .env.local file."
+ );
+}
export const lamaticClient = new Lamatic({
endpoint: config.api.endpoint,
projectId: config.api.projectId,
- apiKey: process.env.LAMATIC_API_KEY,
+ apiKey,
});Also add at the very top (outside the ranges above):
import "server-only"Run to ensure no client components import this module:
- Add LAMATIC_API_KEY to the Vercel project env (Production/Preview/Development).
- Include it in templates/agentic/travel-planner/.env.example for DX.
Also applies to: 10-14
🏁 Script executed:
#!/bin/bash
# Find "use client" files that import lamatic-client
rg -nP -C2 '^"use client"' templates/agentic/travel-planner | awk -F: '{print $1}' | sort -u | while read f; do
rg -n 'lamatic-client' "$f" && echo "Potential client import -> $f"
doneLength of output: 0
I need to gather more information about the codebase structure and verify the claims more thoroughly. Let me run targeted verification scripts.
---
🏁 Script executed:
```shell
#!/bin/bash
# 1. Check if the file exists and show its content
echo "=== Checking lamatic-client.ts existence ==="
if [ -f "templates/agentic/travel-planner/lib/lamatic-client.ts" ]; then
echo "File exists. Content:"
cat "templates/agentic/travel-planner/lib/lamatic-client.ts"
else
echo "File not found"
fi
echo ""
echo "=== Checking for 'use client' files in travel-planner ==="
fd -e ts -e tsx "." "templates/agentic/travel-planner" | while read f; do
head -1 "$f" | grep -q '"use client"' && echo "$f"
done
echo ""
echo "=== All imports of lamatic-client in travel-planner ==="
rg -n "lamatic-client" "templates/agentic/travel-planner" -g "*.ts" -g "*.tsx"
Length of output: 368
The specified directory and file don't exist. Let me search more broadly to locate them.
---
🏁 Script executed:
```shell
#!/bin/bash
# Search for lamatic-client file anywhere
echo "=== Searching for lamatic-client file ==="
find . -name "*lamatic-client*" -type f 2>/dev/null
echo ""
echo "=== Searching for travel-planner directory ==="
find . -name "travel-planner" -type d 2>/dev/null
echo ""
echo "=== Checking what's in templates/agentic if it exists ==="
if [ -d "templates/agentic" ]; then
ls -la "templates/agentic"
else
echo "templates/agentic does not exist"
fi
echo ""
echo "=== Top-level directory structure ==="
ls -la | head -20
Length of output: 1751
Now let me inspect the actual file content and verify the claims.
---
🏁 Script executed:
```shell
#!/bin/bash
echo "=== Content of travel-planner lamatic-client.ts ==="
cat "./templates/agentic/travel-planner/lib/lamatic-client.ts"
echo ""
echo "=== Checking if server-only is imported ==="
grep -n "server-only" "./templates/agentic/travel-planner/lib/lamatic-client.ts" || echo "Not found"
echo ""
echo "=== Checking tsconfig or similar for strict mode ==="
find "./templates/agentic/travel-planner" -name "tsconfig.json" -o -name "tsconfig.*.json" | head -1 | xargs cat 2>/dev/null || echo "No tsconfig found"
Length of output: 1146
Let me verify if this file is imported by client components and check the Next.js context.
---
🏁 Script executed:
```shell
#!/bin/bash
echo "=== Searching for imports of lamatic-client in travel-planner ==="
rg -n "lamatic-client" "./templates/agentic/travel-planner" --type ts --type tsx
echo ""
echo "=== Checking for 'use client' directives ==="
rg -n '"use client"' "./templates/agentic/travel-planner" --type ts --type tsx
echo ""
echo "=== Verifying if this is a Next.js project ==="
if [ -f "./templates/agentic/travel-planner/package.json" ]; then
echo "Found package.json:"
grep -E '"next"|"react"' "./templates/agentic/travel-planner/package.json" | head -5
else
echo "No package.json in travel-planner"
fi
echo ""
echo "=== Checking directory structure ==="
ls -la "./templates/agentic/travel-planner/app" 2>/dev/null || echo "No app directory"
ls -la "./templates/agentic/travel-planner/pages" 2>/dev/null || echo "No pages directory"
Length of output: 699
Let me retry the search with proper file glob patterns.
---
🏁 Script executed:
```shell
#!/bin/bash
echo "=== Searching for imports of lamatic-client ==="
rg -n "lamatic-client" "./templates/agentic/travel-planner" -g "*.ts" -g "*.tsx"
echo ""
echo "=== Checking page.tsx for 'use client' ==="
head -5 "./templates/agentic/travel-planner/app/page.tsx"
echo ""
echo "=== Checking layout.tsx for 'use client' ==="
head -5 "./templates/agentic/travel-planner/app/layout.tsx"
echo ""
echo "=== Full search for lamatic imports with context ==="
rg -n -B2 -A2 "lamatic-client" "./templates/agentic/travel-planner" -g "*.ts" -g "*.tsx"
Length of output: 1073
Type narrowing is essential with strict mode; server-only is defensive but actual client-import risk is already mitigated.
The concern about TypeScript typing is valid: with strict: true enabled, passing process.env.LAMATIC_API_KEY (typed as string | undefined) to the Lamatic constructor creates a type safety issue. The narrowing via a local const is necessary.
However, the client-import risk is overstated: lamatic-client is currently imported only by actions/orchestrate.ts (a "use server" server action), not by any client components. Adding "server-only" is still good defensive practice to prevent future accidental misuse, but the architectural risk is already mitigated.
Apply this diff:
import { Lamatic } from "lamatic";
import config from "@/lamatic-config.json";
+import "server-only";
+
+const apiKey = process.env.LAMATIC_API_KEY;
-if (!process.env.LAMATIC_API_KEY) {
+if (!apiKey) {
throw new Error(
"LAMATIC_API_KEY environment variable is not set. Please add it to your .env.local file."
);
}
export const lamaticClient = new Lamatic({
endpoint: config.api.endpoint,
projectId: config.api.projectId,
- apiKey: process.env.LAMATIC_API_KEY,
+ apiKey,
});This satisfies TypeScript strict mode and adds the defensive boundary.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In templates/agentic/travel-planner/lib/lamatic-client.ts around lines 4–8,
narrow process.env.LAMATIC_API_KEY into a local const and add the defensive
server-only boundary: import "server-only"; const lamaticApiKey =
process.env.LAMATIC_API_KEY; if (!lamaticApiKey) { throw new
Error("LAMATIC_API_KEY environment variable is not set. Please add it to your
.env.local file."); } then pass lamaticApiKey (typed as string at runtime) to
the Lamatic constructor instead of using process.env.LAMATIC_API_KEY directly.
| eslint: { | ||
| ignoreDuringBuilds: true, | ||
| }, | ||
| typescript: { | ||
| ignoreBuildErrors: true, | ||
| }, | ||
| images: { | ||
| unoptimized: true, | ||
| }, | ||
| } |
There was a problem hiding this comment.
Don’t ship with lint/type errors ignored
Ignoring ESLint and TypeScript at build hides real defects and makes CI green when it shouldn’t. Gate these behind an env flag so templates dev fast locally but CI still protects main.
Apply:
/** @type {import('next').NextConfig} */
const nextConfig = {
- eslint: {
- ignoreDuringBuilds: true,
- },
- typescript: {
- ignoreBuildErrors: true,
- },
+ eslint: {
+ ignoreDuringBuilds: process.env.TEMPLATE_RELAXED_BUILD === "1",
+ },
+ typescript: {
+ ignoreBuildErrors: process.env.TEMPLATE_RELAXED_BUILD === "1",
+ },
images: {
unoptimized: true,
},
}Also ensure CI sets TEMPLATE_RELAXED_BUILD=0 (default).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| eslint: { | |
| ignoreDuringBuilds: true, | |
| }, | |
| typescript: { | |
| ignoreBuildErrors: true, | |
| }, | |
| images: { | |
| unoptimized: true, | |
| }, | |
| } | |
| eslint: { | |
| ignoreDuringBuilds: process.env.TEMPLATE_RELAXED_BUILD === "1", | |
| }, | |
| typescript: { | |
| ignoreBuildErrors: process.env.TEMPLATE_RELAXED_BUILD === "1", | |
| }, | |
| images: { | |
| unoptimized: true, | |
| }, | |
| } |
🤖 Prompt for AI Agents
In templates/agentic/travel-planner/next.config.mjs around lines 3 to 12, don’t
unconditionally disable ESLint and TypeScript build checks; instead read an env
var (e.g. TEMPLATE_RELAXED_BUILD) and only set eslint.ignoreDuringBuilds and
typescript.ignoreBuildErrors to true when that var explicitly enables relaxed
builds (true/1), otherwise keep them false so CI fails on lint/type errors;
ensure the default behavior is strict (env var off) and update CI to set
TEMPLATE_RELAXED_BUILD=0.
| "@radix-ui/react-toggle": "1.1.1", | ||
| "@radix-ui/react-toggle-group": "1.1.1", | ||
| "@radix-ui/react-tooltip": "1.1.6", | ||
| "@vercel/analytics": "latest", |
There was a problem hiding this comment.
🧩 Analysis chain
Pin dependency versions instead of using "latest".
Three dependencies use "latest" instead of specific versions, which can cause non-deterministic builds and unexpected breaking changes:
- Line 47:
@vercel/analytics - Line 54:
geist - Line 64:
react-markdown
Consider pinning to specific versions for reproducible builds:
- "@vercel/analytics": "latest",
+ "@vercel/analytics": "^1.4.1",- "geist": "latest",
+ "geist": "^1.3.1",- "react-markdown": "latest",
+ "react-markdown": "^9.0.1",Run this script to check the latest stable versions:
Also applies to: 54-54, 64-64
🏁 Script executed:
#!/bin/bash
# Check latest versions for the unpinned packages
npm view @vercel/analytics version
npm view geist version
npm view react-markdown versionLength of output: 18
I need to verify the current state of the package.json file to confirm the lines mentioned.
---
🏁 Script executed:
```shell
#!/bin/bash
# Check the current state of package.json at the specified lines
sed -n '45,50p;52,56p;62,66p' templates/agentic/travel-planner/package.json
Length of output: 526
Pin dependency versions instead of using "latest".
Three dependencies use "latest" instead of specific versions, which can cause non-deterministic builds and unexpected breaking changes:
- Line 47:
@vercel/analytics - Line 54:
geist - Line 64:
react-markdown
Consider pinning to specific versions for reproducible builds:
- "@vercel/analytics": "latest",
+ "@vercel/analytics": "^1.5.0",- "geist": "latest",
+ "geist": "^1.5.1",- "react-markdown": "latest",
+ "react-markdown": "^10.1.0",Also applies to: 54-54, 64-64
🤖 Prompt for AI Agents
In templates/agentic/travel-planner/package.json (lines 47, 54, 64) the
dependencies use "latest"; replace each "latest" with a specific semver version
string to ensure deterministic builds: determine the desired version by running
`npm view <package> version` (or checking your repo policy), update
@vercel/analytics, geist, and react-markdown to those exact version numbers in
package.json, then run your package manager to regenerate and commit the
lockfile (package-lock.json or yarn.lock) alongside the changes.
| #!/bin/bash | ||
|
|
||
| npm install | ||
|
|
||
| # Run the dev server | ||
| npm run dev No newline at end of file |
There was a problem hiding this comment.
Misleading script name for development server.
The script is named deploy.sh but runs the development server (npm run dev) rather than performing a production deployment. This naming could confuse users about the script's purpose.
Consider renaming to dev.sh or start-dev.sh, or alternatively, adjust the script to perform actual deployment tasks.
Additionally, consider adding error handling:
#!/bin/bash
+set -e
npm install
# Run the dev server
npm run dev🤖 Prompt for AI Agents
In templates/agentic/travel-planner/scripts/deploy.sh around lines 1 to 6, the
script name is misleading because it runs the development server (npm run dev)
instead of performing a production deploy; either rename the file to dev.sh or
start-dev.sh to reflect its purpose, or change its contents to perform
deployment steps (install dependencies, build, and start a production server or
create artifacts); also add basic error handling (exit on failure and check npm
commands' exit codes) so the script fails fast and surfaces errors.
| --destructive: oklch(0.577 0.245 27.325); | ||
| --destructive-foreground: oklch(0.577 0.245 27.325); |
There was a problem hiding this comment.
Destructive colors have no contrast in light theme.
--destructive and --destructive-foreground are identical, harming readability and a11y. Use a high-contrast foreground.
- --destructive: oklch(0.577 0.245 27.325);
- --destructive-foreground: oklch(0.577 0.245 27.325);
+ /* Red-ish background + near-white foreground for contrast (~WCAG AA on buttons) */
+ --destructive: oklch(0.6 0.25 27);
+ --destructive-foreground: oklch(0.98 0.02 27);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| --destructive: oklch(0.577 0.245 27.325); | |
| --destructive-foreground: oklch(0.577 0.245 27.325); | |
| /* Red-ish background + near-white foreground for contrast (~WCAG AA on buttons) */ | |
| --destructive: oklch(0.6 0.25 27); | |
| --destructive-foreground: oklch(0.98 0.02 27); |
🤖 Prompt for AI Agents
templates/agentic/travel-planner/styles/globals.css lines 21-22: the two CSS
variables --destructive and --destructive-foreground are identical which
provides no contrast and breaks accessibility; change --destructive-foreground
to a high-contrast value against --destructive (e.g., a light foreground if
--destructive is dark or a dark foreground if --destructive is light), ensure
the chosen foreground meets WCAG contrast ratios (>=4.5:1 for normal text), and
update any usages or comments to reflect the new semantic intent.
|
Thanks for your contribution @jeloskaisabel , reviewing it now. |
|
@amanintech @d-pamneja can you review my PR please? |
|
@jeloskaisabel we are in process to review it I'll get back to you shortly!! |
|
Hi @d-pamneja , just checking in to see if there are any updates on the review. Please let me know if there’s anything I can clarify or adjust on my side. Thanks again for your time! :) |
|
Hello @amanintech @d-pamneja any updates for this PR? |
|
Hi @jeloskaisabel |
|
@d-pamneja thanks. I'll review it and make the changes this week. |
|
Thanks for the contribution @jeloskaisabel !! |
|
Sounds good, @d-pamneja I'll reach out to you on Slack! |
|
Hi @jeloskaisabel |
|
Hi @jeloskaisabel! 👋 CodeRabbit has posted actionable review comments on this PR. Please review and address them before requesting a maintainer review. Once you've addressed the CodeRabbit feedback, please push your changes and we'll take another look. Thank you! 🙏 |
There was a problem hiding this comment.
Actionable comments posted: 23
♻️ Duplicate comments (12)
templates/agentic/travel-planner/scripts/deploy.sh (1)
1-6:⚠️ Potential issue | 🟠 MajorMission mismatch:
deploy.shis running development, not deployment.Line 6 executes
npm run dev, so this script is not a deploy path. Rename it to a dev-oriented script or change behavior to an actual deployment flow; current naming is operationally misleading.Proposed fix (if keeping this script as deploy)
#!/bin/bash +set -euo pipefail -npm install +npm install -# Run the dev server -npm run dev +# Build and run production server +npm run build +npm run startBased on learnings: "Bundles and templates do not have runnable apps and should not include web application code (Next.js app router, server actions, etc.)."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/scripts/deploy.sh` around lines 1 - 6, The script deploy.sh is misnamed because it runs the development server (npm run dev); either rename the file to dev.sh and keep the current contents, or change its behavior to a real deploy flow by replacing the dev command with a production build/start sequence (e.g., run npm install, then npm run build, then npm run start) so the script's name matches its behavior; update any callers or CI references accordingly (look for deploy.sh and the npm run dev invocation to modify).templates/agentic/travel-planner/.npmrc (1)
1-1:⚠️ Potential issue | 🟠 MajorMission-critical: remove forced npm behavior.
Line 1 (
force=true) makes installs bypass normal safeguards and can mask dependency conflicts in CI and local environments. Please remove it unless there is a documented, unavoidable reason.Proposed fix
-force=true🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/.npmrc` at line 1, Remove the forced npm behavior by deleting the "force=true" entry from the .npmrc in templates/agentic/travel-planner (the exact token to remove is "force=true"); update the commit to no longer include that setting and run a quick install check (npm ci or npm install) locally or in CI to ensure dependency resolution behaves normally without the forced flag.templates/agentic/travel-planner/components/ui/use-toast.ts (2)
12-12:⚠️ Potential issue | 🔴 CriticalAgent, your timing device appears miscalibrated—16.7 minutes is far too long for this operation.
TOAST_REMOVE_DELAY = 1000000means toasts linger for approximately 16.7 minutes before removal. This is almost certainly a typo; standard toast durations are 3-5 seconds (3000-5000ms).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/components/ui/use-toast.ts` at line 12, The TOAST_REMOVE_DELAY constant is set to 1000000 (≈16.7 minutes); change it to a realistic toast duration (e.g., 3000–5000 ms) by updating TOAST_REMOVE_DELAY in use-toast.ts (the constant name TOAST_REMOVE_DELAY) to a shorter value such as 4000 so toasts auto-remove after ~4 seconds.
177-185:⚠️ Potential issue | 🟠 MajorAgent, this surveillance setup re-establishes on every state change—compromising operational efficiency.
The
statein the dependency array causes the effect to unsubscribe and re-subscribe the listener on every state update.setStateis stable and doesn't require re-registration.🔧 Recommended fix
React.useEffect(() => { listeners.push(setState) return () => { const index = listeners.indexOf(setState) if (index > -1) { listeners.splice(index, 1) } } - }, [state]) + }, [])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/components/ui/use-toast.ts` around lines 177 - 185, The effect in use-toast.ts is re-registering the listener on every state change because React.useEffect lists state in its dependency array; stop this by using an empty dependency array (or [setState] if you prefer explicitness) so listeners.push(setState) runs only once and the cleanup removes that same setState; update the React.useEffect dependencies accordingly and keep the existing cleanup logic that finds and splices setState from listeners.templates/agentic/travel-planner/components/ui/scroll-area.tsx (1)
35-55:⚠️ Potential issue | 🔴 CriticalAgent, we have intel on this position—incorrect Radix primitive names will cause mission failure at runtime.
The Radix scroll-area package exports
ScrollbarandThumb, notScrollAreaScrollbarandScrollAreaThumb. This will crash when the component mounts.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/components/ui/scroll-area.tsx` around lines 35 - 55, The code is using incorrect Radix primitive names (ScrollAreaPrimitive.ScrollAreaScrollbar and ScrollAreaPrimitive.ScrollAreaThumb) which will crash; update the prop typing and JSX to use the actual exports ScrollAreaPrimitive.Scrollbar and ScrollAreaPrimitive.Thumb (e.g., change React.ComponentProps<typeof ScrollAreaPrimitive.Scrollbar> and replace <ScrollAreaPrimitive.ScrollAreaScrollbar> / <ScrollAreaPrimitive.ScrollAreaThumb> with <ScrollAreaPrimitive.Scrollbar> / <ScrollAreaPrimitive.Thumb>), preserving the existing props, classes and children spread.templates/agentic/travel-planner/components/ui/hover-card.tsx (1)
34-36:⚠️ Potential issue | 🟡 MinorAgent, the coordinates for transform-origin are in an unrecognized format—this will fail compilation.
The
origin-(--radix-hover-card-content-transform-origin)syntax is invalid in Tailwind. Use the bracketedvar()syntax for arbitrary CSS custom properties.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/components/ui/hover-card.tsx` around lines 34 - 36, The Tailwind class token origin-(--radix-hover-card-content-transform-origin) is invalid and causing compilation errors in the className passed to cn in the HoverCard component; replace that token with the bracketed var() syntax origin-[var(--radix-hover-card-content-transform-origin)] so Tailwind recognizes the arbitrary property (update the className string inside the cn(...) call in hover-card.tsx).templates/agentic/travel-planner/components/ui/carousel.tsx (2)
78-89:⚠️ Potential issue | 🟠 MajorMission fix: vertical carousels need vertical arrow keys.
This handler only listens for Left/Right, so
orientation="vertical"cannot be driven from the keyboard. Branch the key mapping byorientationand add it to the callback dependencies.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/components/ui/carousel.tsx` around lines 78 - 89, The handleKeyDown callback only handles ArrowLeft/ArrowRight so vertical carousels cannot be controlled by keyboard; update the handler (handleKeyDown) to branch on the component's orientation prop and map ArrowUp/ArrowDown to scrollPrev/scrollNext when orientation === "vertical", keep ArrowLeft/ArrowRight for horizontal, and add orientation to the React.useCallback dependency array alongside scrollPrev and scrollNext.
96-105:⚠️ Potential issue | 🔴 CriticalMission-critical: unregister
reIniton teardown too.The effect subscribes to both
"reInit"and"select", but cleanup removes only"select". That leaks listeners across re-inits and unmounts.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/components/ui/carousel.tsx` around lines 96 - 105, The effect currently subscribes to api events with api.on("reInit", onSelect) and api.on("select", onSelect) but only removes the "select" listener on teardown; update the cleanup in the React.useEffect to unregister both events (call api?.off("reInit", onSelect) and api?.off("select", onSelect)) so listeners aren’t leaked across re-inits/unmounts, keeping the initial onSelect(api) call and the existing dependency list intact.templates/agentic/travel-planner/components/ui/breadcrumb.tsx (1)
52-63:⚠️ Potential issue | 🟠 MajorMission accessibility: the current breadcrumb is not a link.
This is a non-interactive
<span>, sorole="link"advertises behavior it does not have.aria-current="page"is sufficient here. (w3.org)Suggested patch
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) { return ( <span data-slot="breadcrumb-page" - role="link" - aria-disabled="true" aria-current="page" className={cn("text-foreground font-normal", className)} {...props}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/components/ui/breadcrumb.tsx` around lines 52 - 63, BreadcrumbPage currently renders a non-interactive <span> but includes role="link" and aria-disabled="true", which misrepresents its behavior; either change the element to an interactive anchor/button if it should be clickable or (if it is purely the current page) remove role="link" and aria-disabled="true" and keep only aria-current="page". Update the BreadcrumbPage component to reflect one of these two options (remove the ARIA link/disabled attributes from the <span> in BreadcrumbPage or replace the <span> with an interactive element and handle href/onClick accordingly).templates/agentic/travel-planner/components/ui/sidebar.tsx (1)
476-489:⚠️ Potential issue | 🟠 MajorMission check: verify the Tailwind important syntax here.
If this template targets the current Tailwind syntax,
group-data-[collapsible=icon]:size-8!,...:p-2!, and...:p-0!will be ignored because the!modifier needs to prefix the utility. That leaves the collapsed icon/button overrides inactive.🛠️ Proposed fix
- "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", + "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", @@ - lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!", + lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0",Does Tailwind CSS support the important modifier as a suffix like `size-8!`, or must it prefix the utility as `!size-8`?🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/components/ui/sidebar.tsx` around lines 476 - 489, The Tailwind important modifier is used incorrectly as a suffix in the class tokens inside sidebarMenuButtonVariants (e.g., group-data-[collapsible=icon]:size-8!, group-data-[collapsible=icon]:p-2!, group-data-[collapsible=icon]:p-0!), so change those to prefix the utility with '!' (e.g., group-data-[collapsible=icon]:!size-8, group-data-[collapsible=icon]:!p-2, group-data-[collapsible=icon]:!p-0) in the cva definition and confirm the project Tailwind version supports the ! prefix syntax; update any other suffixed ! usages in sidebarMenuButtonVariants to the prefixed form.templates/agentic/travel-planner/components/ui/chart.tsx (1)
82-100:⚠️ Potential issue | 🟠 MajorMission-critical: lock down the injected stylesheet.
id, series keys, and color values are interpolated directly into a<style>tag viadangerouslySetInnerHTML. A crafted value can break the selector or inject arbitrary CSS/HTML into the page; escape selector/key fragments and only emit known-safe color formats.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/components/ui/chart.tsx` around lines 82 - 100, The injected stylesheet currently interpolates unescaped values (id, theme names, series keys and color strings) via dangerouslySetInnerHTML in the style block, allowing CSS injection; update the code that builds the CSS string (the block using THEMES, id, colorConfig and dangerouslySetInnerHTML) to escape selector fragments (use CSS.escape for id, theme and key fragments) and validate/sanitize colorConfig values to only emit known-safe color formats (e.g., whitelist hex, rgb(), rgba(), hsl(), hsla() via a strict regex) before emitting --color-... lines; drop any entries that fail validation and keep using join("\n") but only with escaped keys and safe colors so the generated CSS cannot break selectors or inject arbitrary content.templates/agentic/travel-planner/actions/orchestrate.ts (1)
837-850:⚠️ Potential issue | 🟠 MajorMission-critical: keep the failure path opaque.
This still logs the full SDK error object and returns
error.messageverbatim. That can leak upstream request metadata or internal diagnostics to logs and clients; log a minimal safe message/code and return a stable public error code instead.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@templates/agentic/travel-planner/actions/orchestrate.ts` around lines 837 - 850, The catch block in actions/orchestrate.ts currently logs the full SDK error and returns error.message; change it to avoid leaking internals by (1) replacing console.error(error) with a minimal safe log (e.g., "[travel-planner] execution failed" plus an internal trace id or error code only), (2) stop returning error.message and instead return a stable public error code/string (e.g., "TRAVEL_PLANNER_FAILURE") from the returned object, and (3) if you need internal diagnostics, capture the original Error in an internal-only logger or attach it to a monitored trace but do not emit it to stdout or client responses — update the catch handling around the error variable and the returned { success: false, error: message } accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@templates/agentic/travel-planner/actions/orchestrate.ts`:
- Around line 823-835: The current success branch unconditionally treats any
resolved response as successful; before calling normalizeTravelPlan(response)
and returning { success: true }, check the resolved status (the variable status
derived from response/status/result) against the explicit success statuses you
accept (e.g., "success", "completed", or similar) and only proceed to compute
rawResult and call normalizeTravelPlan when status is one of those allowed
values; otherwise return a failure object (e.g., { success: false, status,
error: ... } or propagate response) so failed/partial executions are not
normalized as a valid plan. Ensure you update the logic around the status,
rawResult, normalizeTravelPlan, and the returned object to gate success on the
explicit status set.
- Around line 1-10: The template currently hardcodes a Next.js server action by
using `"use server"` and importing lamatic-config.json into the top-level
variable travelPlannerFlow; remove the `"use server"` directive and the
lamatic-config.json import and instead read the workflow id from an environment
variable (e.g., process.env.TRAVEL_PLANNER_FLOW_ID) inside the orchestration
function, then call the Lamatic flow via the lamaticClient SDK (use
lamaticClient.invoke or the appropriate SDK method) using that env var; update
any references to travelPlannerFlow to use the env-derived id and ensure no
Next.js server-action patterns remain in actions/orchestrate.ts so the template
is SDK-driven and not bound to a checked-in workflow.
In `@templates/agentic/travel-planner/components/theme-provider.tsx`:
- Around line 9-10: The RootLayout in app/layout.tsx must mount the
ThemeProvider so useTheme consumers (e.g., components/ui/sonner.tsx) won't fail;
import the ThemeProvider from "@/components/theme-provider" and wrap the
layout's children (including the Suspense fallback and Analytics) inside
<ThemeProvider> in the RootLayout component, ensuring the provider encloses the
Suspense and Analytics nodes and preserves existing body classes and props.
In `@templates/agentic/travel-planner/components/ui/alert-dialog.tsx`:
- Around line 1-157: Summary: The UI components (e.g., AlertDialog,
AlertDialogTrigger, AlertDialogContent, AlertDialogAction, AlertDialogCancel)
are app code living under the templates subtree and must be removed or converted
to comply with the template contract. Fix: either relocate these components out
of templates into the real app/component library (update imports where
AlertDialog* symbols are used) or refactor this template to the "flow" template
shape by removing any runnable app surface (Next.js app router/server actions)
and replacing with template-only artifacts; ensure all references to the
exported symbols are updated and remove any Next.js-specific runtime code from
the templates subtree.
In `@templates/agentic/travel-planner/components/ui/aspect-ratio.tsx`:
- Around line 1-11: The component uses React.ComponentProps in the AspectRatio
function but never imports React; add an import for React (e.g., import React
from "react") at the top of the file so React.ComponentProps<typeof
AspectRatioPrimitive.Root> resolves correctly and the AspectRatio component can
compile when returning <AspectRatioPrimitive.Root ... />.
In `@templates/agentic/travel-planner/components/ui/calendar.tsx`:
- Line 193: The data-day attribute uses locale-dependent
day.date.toLocaleDateString(); change it to a stable ISO format (e.g.,
day.date.toISOString() or new Date(day.date).toISOString()) so scripts/tests see
consistent values; ensure the code handles cases where day.date might already be
a string by normalizing with new Date(day.date) before calling toISOString() and
update the JSX attribute reference for data-day accordingly.
In `@templates/agentic/travel-planner/components/ui/carousel.tsx`:
- Around line 183-197: The carousel previous/next controls use your Button
component (symbol: Button) which renders a native <button> when asChild is false
but doesn't set type, causing it to act like a submit button in forms; fix by
updating the Button implementation so that when rendering the native <button> it
sets the button type to the provided prop or defaults to "button" (e.g., use
type={props.type ?? "button"}), ensuring callers like the carousel Buttons
(data-slot="carousel-previous"/"carousel-next", props including onClick,
disabled, scrollPrev/scrollNext, canScrollPrev/canScrollNext) remain unchanged.
In `@templates/agentic/travel-planner/components/ui/chart.tsx`:
- Around line 235-237: The tooltip JSX currently uses a truthy check "item.value
&&" which filters out legitimate zero values; change the conditional to
explicitly test for null/undefined (e.g., "item.value != null" or "item.value
!== null && item.value !== undefined") so 0 is rendered; update the conditional
that wraps the <span className="text-foreground font-mono font-medium
tabular-nums"> block that displays {item.value.toLocaleString()} to use this
explicit null/undefined check.
In `@templates/agentic/travel-planner/components/ui/command.tsx`:
- Around line 101-109: The CommandEmpty component currently spreads {...props}
after a hard-coded className, allowing a caller's className to override instead
of extend the defaults; update CommandEmpty (rendering CommandPrimitive.Empty)
to merge the default classes ("py-6 text-center text-sm") with any
props.className (e.g., using a classNames/clsx helper or template literal) and
then spread the rest of props so caller classes are appended rather than
replacing the defaults.
In `@templates/agentic/travel-planner/components/ui/dropdown-menu.tsx`:
- Around line 232-234: The className in the DropdownMenuSubContent component
uses invalid Tailwind "origin-(--radix-dropdown-menu-content-transform-origin)"
syntax; update it to the correct bracketed CSS var form
"origin-[var(--radix-dropdown-menu-content-transform-origin)]" so the
transform-origin variable is applied. Locate the DropdownMenuSubContent (or the
sub-content component) and replace the
origin-(--radix-dropdown-menu-content-transform-origin) token in its className
with origin-[var(--radix-dropdown-menu-content-transform-origin)] to match the
fix used for the main DropdownMenuContent.
- Around line 44-46: The Tailwind arbitrary value syntax in the className for
the dropdown content is invalid; update the two problematic tokens in the
className string inside the DropdownMenuContent component (the cn(...) call) by
replacing max-h-(--radix-dropdown-menu-content-available-height) with
max-h-[var(--radix-dropdown-menu-content-available-height)] and
origin-(--radix-dropdown-menu-content-transform-origin) with
origin-[var(--radix-dropdown-menu-content-transform-origin)] so Tailwind
recognizes the CSS variable arbitrary values while keeping the rest of the
className and the appended className prop unchanged.
In `@templates/agentic/travel-planner/components/ui/input-otp.tsx`:
- Around line 46-47: The access inputOTPContext?.slots[index] can be
out-of-bounds; guard against missing context or invalid index by first checking
OTPInputContext / inputOTPContext and that inputOTPContext.slots is an array and
index is within 0 <= index < slots.length, then extract { char, hasFakeCaret,
isActive } from a safe fallback (e.g., an empty slot object) or clamp/throw as
appropriate; update the code around inputOTPContext, OTPInputContext, slots and
index to perform this defensive validation before using the extracted values.
In `@templates/agentic/travel-planner/components/ui/radio-group.tsx`:
- Line 1: The file
templates/agentic/travel-planner/components/ui/radio-group.tsx contains a
top-level "use client" directive which makes it a runnable Next.js client
component and violates template constraints; remove the "use client" directive
and any client-only APIs from the RadioGroup component (or move this component
into the app/ or components/ folder outside templates if it must remain a client
component), converting it to a server-safe React component (e.g., pure
functions, no browser-only hooks like useState/useEffect or event handlers
requiring client runtime) so the template bundle contains no runnable Next.js
client code.
In `@templates/agentic/travel-planner/components/ui/select.tsx`:
- Around line 63-65: The className string in the Select component uses invalid
Tailwind arbitrary syntax for CSS variables; update the occurrences inside the
cn(...) call (in the file containing the Select component where className is
built and where position === "popper" is checked) to use bracketed var() syntax:
replace max-h-(--radix-select-content-available-height) with
max-h-[var(--radix-select-content-available-height)] and
origin-(--radix-select-content-transform-origin) with
origin-[var(--radix-select-content-transform-origin)] so Tailwind recognizes the
custom property values.
In `@templates/agentic/travel-planner/components/ui/sidebar.tsx`:
- Around line 74-89: The component writes the sidebar state cookie but never
reads it, so _open always starts from defaultOpen; hydrate the initial state
from the SIDEBAR_COOKIE_NAME cookie when uncontrolled. Change the useState
initializer for [_open, _setOpen] (and/or add a useEffect) to parse
document.cookie for SIDEBAR_COOKIE_NAME and use that boolean if present (falling
back to defaultOpen), and ensure this only applies when openProp is undefined so
controlled usage still works; continue to use SIDEBAR_COOKIE_NAME and
SIDEBAR_COOKIE_MAX_AGE when writing the cookie in setOpen.
In `@templates/agentic/travel-planner/components/ui/toast.tsx`:
- Around line 73-89: ToastClose renders an icon-only ToastPrimitives.Close
without an accessible name; update the ToastClose component (the forwardRef
returning ToastPrimitives.Close) to provide an accessible label by adding
aria-label="Close" to the ToastPrimitives.Close element or by including
visually-hidden screen-reader text alongside the <X> icon (ensuring the label
text is not visible but present for assistive tech), keeping the existing props
spread ({...props}) and ref usage intact so nothing else changes.
In `@templates/agentic/travel-planner/components/ui/tooltip.tsx`:
- Around line 48-50: Replace the invalid Tailwind origin syntax in the cn(...)
call inside the Tooltip component: the token
"origin-(--radix-tooltip-content-transform-origin)" should be changed to the
bracketed variable form "origin-[var(--radix-tooltip-content-transform-origin)]"
so Tailwind recognizes the CSS variable; update the className string passed to
the cn(...) invocation (the className prop construction) accordingly.
In `@templates/agentic/travel-planner/hooks/use-mobile.ts`:
- Around line 10-12: The onChange handler for the MediaQueryList change listener
should use the event's matches property instead of reading window.innerWidth;
update the onChange signature to accept the MediaQueryListEvent (or event) and
call setIsMobile(event.matches) so the value comes directly from the media query
change, keeping MOBILE_BREAKPOINT logic in the media query setup and removing
the redundant global window access.
In `@templates/agentic/travel-planner/lib/lamatic-client.ts`:
- Around line 10-13: Replace the hardcoded config usage when constructing
lamaticClient: add the "server-only" module directive at top, read
process.env.LAMATIC_API_URL, process.env.LAMATIC_PROJECT_ID and
process.env.LAMATIC_API_KEY into local constants at module load, validate all
three are present (throw or log and exit if missing) and then pass those env
vars into the new Lamatic(...) call instead of
config.api.endpoint/config.api.projectId and process.env.LAMATIC_API_KEY; update
.env.example to include LAMATIC_API_URL, LAMATIC_PROJECT_ID and LAMATIC_API_KEY
placeholders.
In `@templates/agentic/travel-planner/README.md`:
- Around line 23-27: Add a blank line before the fenced code block inside the
first list item in templates/agentic/travel-planner/README.md so the markdown
linter stops flagging it; specifically, in the list item that starts with "1.
**Install dependencies**" insert an empty line before the ```bash block to
separate the paragraph from the code fence.
- Line 12: The README currently hardcodes the deployment-specific flow ID
"3cc791a2-ca33-4e27-8791-ff386cef14b2" for the "Multi-Agent Travel Planner"
flow; update the text to reference the user's lamatic-config.json instead of a
fixed UUID so docs work across deployments—specifically, replace the literal ID
in the "Lamatic orchestration" description with an instruction pointing readers
to the "Multi-Agent Travel Planner" flow entry in lamatic-config.json (or the
config key that holds the flowId), and mention that they should use their
configured flowId rather than the hardcoded value.
- Line 3: The README exposes a hardcoded Lamatic project ID
("bee05145-3d20-4d4b-a965-75ec69cc4a65") in the travel-planner template; replace
that literal with a clear placeholder (e.g., <PROJECT_ID>) and a one-line note
explaining it’s an example and instructing users to use their own project ID
from Lamatic Studio (or show how to find it). Update the sentence that currently
mentions the project ID so it reads generically and add the brief guidance
immediately after it.
In `@templates/agentic/travel-planner/styles/globals.css`:
- Around line 1-125: This stylesheet is a byte-for-byte duplicate (contains
`@import` 'tailwindcss'; `@theme` inline; :root and .dark variable sets and `@layer`
base) that is unused—remove the duplicate file containing those symbols to
eliminate confusion; after deletion, verify the layout still imports the
canonical globals.css (or consolidate by replacing the duplicate with an import
that re-exports the canonical file if you intentionally wanted separate
locations) or update any imports to point to the intended globals.css.
---
Duplicate comments:
In `@templates/agentic/travel-planner/.npmrc`:
- Line 1: Remove the forced npm behavior by deleting the "force=true" entry from
the .npmrc in templates/agentic/travel-planner (the exact token to remove is
"force=true"); update the commit to no longer include that setting and run a
quick install check (npm ci or npm install) locally or in CI to ensure
dependency resolution behaves normally without the forced flag.
In `@templates/agentic/travel-planner/actions/orchestrate.ts`:
- Around line 837-850: The catch block in actions/orchestrate.ts currently logs
the full SDK error and returns error.message; change it to avoid leaking
internals by (1) replacing console.error(error) with a minimal safe log (e.g.,
"[travel-planner] execution failed" plus an internal trace id or error code
only), (2) stop returning error.message and instead return a stable public error
code/string (e.g., "TRAVEL_PLANNER_FAILURE") from the returned object, and (3)
if you need internal diagnostics, capture the original Error in an internal-only
logger or attach it to a monitored trace but do not emit it to stdout or client
responses — update the catch handling around the error variable and the returned
{ success: false, error: message } accordingly.
In `@templates/agentic/travel-planner/components/ui/breadcrumb.tsx`:
- Around line 52-63: BreadcrumbPage currently renders a non-interactive <span>
but includes role="link" and aria-disabled="true", which misrepresents its
behavior; either change the element to an interactive anchor/button if it should
be clickable or (if it is purely the current page) remove role="link" and
aria-disabled="true" and keep only aria-current="page". Update the
BreadcrumbPage component to reflect one of these two options (remove the ARIA
link/disabled attributes from the <span> in BreadcrumbPage or replace the <span>
with an interactive element and handle href/onClick accordingly).
In `@templates/agentic/travel-planner/components/ui/carousel.tsx`:
- Around line 78-89: The handleKeyDown callback only handles
ArrowLeft/ArrowRight so vertical carousels cannot be controlled by keyboard;
update the handler (handleKeyDown) to branch on the component's orientation prop
and map ArrowUp/ArrowDown to scrollPrev/scrollNext when orientation ===
"vertical", keep ArrowLeft/ArrowRight for horizontal, and add orientation to the
React.useCallback dependency array alongside scrollPrev and scrollNext.
- Around line 96-105: The effect currently subscribes to api events with
api.on("reInit", onSelect) and api.on("select", onSelect) but only removes the
"select" listener on teardown; update the cleanup in the React.useEffect to
unregister both events (call api?.off("reInit", onSelect) and api?.off("select",
onSelect)) so listeners aren’t leaked across re-inits/unmounts, keeping the
initial onSelect(api) call and the existing dependency list intact.
In `@templates/agentic/travel-planner/components/ui/chart.tsx`:
- Around line 82-100: The injected stylesheet currently interpolates unescaped
values (id, theme names, series keys and color strings) via
dangerouslySetInnerHTML in the style block, allowing CSS injection; update the
code that builds the CSS string (the block using THEMES, id, colorConfig and
dangerouslySetInnerHTML) to escape selector fragments (use CSS.escape for id,
theme and key fragments) and validate/sanitize colorConfig values to only emit
known-safe color formats (e.g., whitelist hex, rgb(), rgba(), hsl(), hsla() via
a strict regex) before emitting --color-... lines; drop any entries that fail
validation and keep using join("\n") but only with escaped keys and safe colors
so the generated CSS cannot break selectors or inject arbitrary content.
In `@templates/agentic/travel-planner/components/ui/hover-card.tsx`:
- Around line 34-36: The Tailwind class token
origin-(--radix-hover-card-content-transform-origin) is invalid and causing
compilation errors in the className passed to cn in the HoverCard component;
replace that token with the bracketed var() syntax
origin-[var(--radix-hover-card-content-transform-origin)] so Tailwind recognizes
the arbitrary property (update the className string inside the cn(...) call in
hover-card.tsx).
In `@templates/agentic/travel-planner/components/ui/scroll-area.tsx`:
- Around line 35-55: The code is using incorrect Radix primitive names
(ScrollAreaPrimitive.ScrollAreaScrollbar and
ScrollAreaPrimitive.ScrollAreaThumb) which will crash; update the prop typing
and JSX to use the actual exports ScrollAreaPrimitive.Scrollbar and
ScrollAreaPrimitive.Thumb (e.g., change React.ComponentProps<typeof
ScrollAreaPrimitive.Scrollbar> and replace
<ScrollAreaPrimitive.ScrollAreaScrollbar> /
<ScrollAreaPrimitive.ScrollAreaThumb> with <ScrollAreaPrimitive.Scrollbar> /
<ScrollAreaPrimitive.Thumb>), preserving the existing props, classes and
children spread.
In `@templates/agentic/travel-planner/components/ui/sidebar.tsx`:
- Around line 476-489: The Tailwind important modifier is used incorrectly as a
suffix in the class tokens inside sidebarMenuButtonVariants (e.g.,
group-data-[collapsible=icon]:size-8!, group-data-[collapsible=icon]:p-2!,
group-data-[collapsible=icon]:p-0!), so change those to prefix the utility with
'!' (e.g., group-data-[collapsible=icon]:!size-8,
group-data-[collapsible=icon]:!p-2, group-data-[collapsible=icon]:!p-0) in the
cva definition and confirm the project Tailwind version supports the ! prefix
syntax; update any other suffixed ! usages in sidebarMenuButtonVariants to the
prefixed form.
In `@templates/agentic/travel-planner/components/ui/use-toast.ts`:
- Line 12: The TOAST_REMOVE_DELAY constant is set to 1000000 (≈16.7 minutes);
change it to a realistic toast duration (e.g., 3000–5000 ms) by updating
TOAST_REMOVE_DELAY in use-toast.ts (the constant name TOAST_REMOVE_DELAY) to a
shorter value such as 4000 so toasts auto-remove after ~4 seconds.
- Around line 177-185: The effect in use-toast.ts is re-registering the listener
on every state change because React.useEffect lists state in its dependency
array; stop this by using an empty dependency array (or [setState] if you prefer
explicitness) so listeners.push(setState) runs only once and the cleanup removes
that same setState; update the React.useEffect dependencies accordingly and keep
the existing cleanup logic that finds and splices setState from listeners.
In `@templates/agentic/travel-planner/scripts/deploy.sh`:
- Around line 1-6: The script deploy.sh is misnamed because it runs the
development server (npm run dev); either rename the file to dev.sh and keep the
current contents, or change its behavior to a real deploy flow by replacing the
dev command with a production build/start sequence (e.g., run npm install, then
npm run build, then npm run start) so the script's name matches its behavior;
update any callers or CI references accordingly (look for deploy.sh and the npm
run dev invocation to modify).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 8d2f0dc9-5b9a-49e5-940e-949523c40c68
⛔ Files ignored due to path filters (3)
templates/agentic/travel-planner/app/icon.pngis excluded by!**/*.pngtemplates/agentic/travel-planner/public/lamatic-logo.pngis excluded by!**/*.pngtemplates/agentic/travel-planner/public/placeholder.svgis excluded by!**/*.svg
📒 Files selected for processing (73)
templates/agentic/travel-planner/.env.exampletemplates/agentic/travel-planner/.eslintrc.jsontemplates/agentic/travel-planner/.gitignoretemplates/agentic/travel-planner/.npmrctemplates/agentic/travel-planner/LICENSEtemplates/agentic/travel-planner/README.mdtemplates/agentic/travel-planner/actions/orchestrate.tstemplates/agentic/travel-planner/app/globals.csstemplates/agentic/travel-planner/app/layout.tsxtemplates/agentic/travel-planner/app/page.tsxtemplates/agentic/travel-planner/components.jsontemplates/agentic/travel-planner/components/theme-provider.tsxtemplates/agentic/travel-planner/components/ui/accordion.tsxtemplates/agentic/travel-planner/components/ui/alert-dialog.tsxtemplates/agentic/travel-planner/components/ui/alert.tsxtemplates/agentic/travel-planner/components/ui/aspect-ratio.tsxtemplates/agentic/travel-planner/components/ui/avatar.tsxtemplates/agentic/travel-planner/components/ui/badge.tsxtemplates/agentic/travel-planner/components/ui/breadcrumb.tsxtemplates/agentic/travel-planner/components/ui/button.tsxtemplates/agentic/travel-planner/components/ui/calendar.tsxtemplates/agentic/travel-planner/components/ui/card.tsxtemplates/agentic/travel-planner/components/ui/carousel.tsxtemplates/agentic/travel-planner/components/ui/chart.tsxtemplates/agentic/travel-planner/components/ui/checkbox.tsxtemplates/agentic/travel-planner/components/ui/collapsible.tsxtemplates/agentic/travel-planner/components/ui/command.tsxtemplates/agentic/travel-planner/components/ui/context-menu.tsxtemplates/agentic/travel-planner/components/ui/dialog.tsxtemplates/agentic/travel-planner/components/ui/drawer.tsxtemplates/agentic/travel-planner/components/ui/dropdown-menu.tsxtemplates/agentic/travel-planner/components/ui/form.tsxtemplates/agentic/travel-planner/components/ui/hover-card.tsxtemplates/agentic/travel-planner/components/ui/input-otp.tsxtemplates/agentic/travel-planner/components/ui/input.tsxtemplates/agentic/travel-planner/components/ui/label.tsxtemplates/agentic/travel-planner/components/ui/menubar.tsxtemplates/agentic/travel-planner/components/ui/navigation-menu.tsxtemplates/agentic/travel-planner/components/ui/pagination.tsxtemplates/agentic/travel-planner/components/ui/popover.tsxtemplates/agentic/travel-planner/components/ui/progress.tsxtemplates/agentic/travel-planner/components/ui/radio-group.tsxtemplates/agentic/travel-planner/components/ui/resizable.tsxtemplates/agentic/travel-planner/components/ui/scroll-area.tsxtemplates/agentic/travel-planner/components/ui/select.tsxtemplates/agentic/travel-planner/components/ui/separator.tsxtemplates/agentic/travel-planner/components/ui/sheet.tsxtemplates/agentic/travel-planner/components/ui/sidebar.tsxtemplates/agentic/travel-planner/components/ui/skeleton.tsxtemplates/agentic/travel-planner/components/ui/slider.tsxtemplates/agentic/travel-planner/components/ui/sonner.tsxtemplates/agentic/travel-planner/components/ui/switch.tsxtemplates/agentic/travel-planner/components/ui/table.tsxtemplates/agentic/travel-planner/components/ui/tabs.tsxtemplates/agentic/travel-planner/components/ui/textarea.tsxtemplates/agentic/travel-planner/components/ui/toast.tsxtemplates/agentic/travel-planner/components/ui/toaster.tsxtemplates/agentic/travel-planner/components/ui/toggle-group.tsxtemplates/agentic/travel-planner/components/ui/toggle.tsxtemplates/agentic/travel-planner/components/ui/tooltip.tsxtemplates/agentic/travel-planner/components/ui/use-mobile.tsxtemplates/agentic/travel-planner/components/ui/use-toast.tstemplates/agentic/travel-planner/hooks/use-mobile.tstemplates/agentic/travel-planner/hooks/use-toast.tstemplates/agentic/travel-planner/lamatic-config.jsontemplates/agentic/travel-planner/lib/lamatic-client.tstemplates/agentic/travel-planner/lib/utils.tstemplates/agentic/travel-planner/next.config.mjstemplates/agentic/travel-planner/package.jsontemplates/agentic/travel-planner/postcss.config.mjstemplates/agentic/travel-planner/scripts/deploy.shtemplates/agentic/travel-planner/styles/globals.csstemplates/agentic/travel-planner/tsconfig.json
| "use server"; | ||
|
|
||
| import { lamaticClient } from "@/lib/lamatic-client"; | ||
| import config from "@/lamatic-config.json"; | ||
|
|
||
| const travelPlannerFlow = (config.flows as Record<string, any> | undefined) | ||
| ?.travelPlanner; | ||
|
|
||
| if (!travelPlannerFlow) { | ||
| throw new Error("travelPlanner flow not found in lamatic-config.json"); |
There was a problem hiding this comment.
Mission-critical: this template is still bound to a checked-in workflow and server action.
"use server" plus lamatic-config.json hardwire the kit to a runnable Next.js app and a single deployed Lamatic flow. That is the old template shape reviewers already asked to move away from; if an orchestration bridge remains, the workflow id needs to come from environment variables rather than source control. Based on learnings: Bundles and templates do not have runnable apps and should not include web application code (Next.js app router, server actions, etc.), and Kit server action files (e.g., actions/orchestrate.ts) must call Lamatic flows via the SDK and read flow IDs from environment variables.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/actions/orchestrate.ts` around lines 1 - 10,
The template currently hardcodes a Next.js server action by using `"use server"`
and importing lamatic-config.json into the top-level variable travelPlannerFlow;
remove the `"use server"` directive and the lamatic-config.json import and
instead read the workflow id from an environment variable (e.g.,
process.env.TRAVEL_PLANNER_FLOW_ID) inside the orchestration function, then call
the Lamatic flow via the lamaticClient SDK (use lamaticClient.invoke or the
appropriate SDK method) using that env var; update any references to
travelPlannerFlow to use the env-derived id and ensure no Next.js server-action
patterns remain in actions/orchestrate.ts so the template is SDK-driven and not
bound to a checked-in workflow.
| const status = response?.status ?? response?.result?.status ?? "unknown"; | ||
| const rawResult = | ||
| response?.result?.result ?? | ||
| response?.result?.data ?? | ||
| response?.result ?? | ||
| response; | ||
|
|
||
| const plan = normalizeTravelPlan(rawResult); | ||
|
|
||
| return { | ||
| success: true, | ||
| status, | ||
| plan, |
There was a problem hiding this comment.
Mission-critical: this success branch never consults the flow status.
Any resolved response with a non-success status still falls through here and returns { success: true }. That lets failed or partial executions get normalized and rendered as if they were a valid trip plan; gate this branch on the explicit statuses you consider successful before calling normalizeTravelPlan.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/actions/orchestrate.ts` around lines 823 -
835, The current success branch unconditionally treats any resolved response as
successful; before calling normalizeTravelPlan(response) and returning {
success: true }, check the resolved status (the variable status derived from
response/status/result) against the explicit success statuses you accept (e.g.,
"success", "completed", or similar) and only proceed to compute rawResult and
call normalizeTravelPlan when status is one of those allowed values; otherwise
return a failure object (e.g., { success: false, status, error: ... } or
propagate response) so failed/partial executions are not normalized as a valid
plan. Ensure you update the logic around the status, rawResult,
normalizeTravelPlan, and the returned object to gate success on the explicit
status set.
| export function ThemeProvider({ children, ...props }: ThemeProviderProps) { | ||
| return <NextThemesProvider {...props}>{children}</NextThemesProvider> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Layout files:"
fd -i '^layout\.tsx$' templates/agentic/travel-planner
echo
echo "ThemeProvider usage:"
rg -n -C3 'ThemeProvider|next-themes|useTheme' templates/agentic/travel-planner/app templates/agentic/travel-planner/componentsRepository: Lamatic/AgentKit
Length of output: 1905
🏁 Script executed:
cat -n templates/agentic/travel-planner/app/layout.tsxRepository: Lamatic/AgentKit
Length of output: 1002
Mission critical: Mount ThemeProvider in the app root.
ThemeProvider is defined in components/theme-provider.tsx, but app/layout.tsx does not wrap children with it. This causes useTheme() consumers (e.g., components/ui/sonner.tsx line 7) to fail at runtime. Add the import and wrap the children in app/layout.tsx:
import { ThemeProvider } from "@/components/theme-provider"
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<body className={`font-sans ${GeistSans.variable} ${GeistMono.variable}`}>
<ThemeProvider>
<Suspense fallback={null}>{children}</Suspense>
<Analytics />
</ThemeProvider>
</body>
</html>
)
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/components/theme-provider.tsx` around lines
9 - 10, The RootLayout in app/layout.tsx must mount the ThemeProvider so
useTheme consumers (e.g., components/ui/sonner.tsx) won't fail; import the
ThemeProvider from "@/components/theme-provider" and wrap the layout's children
(including the Suspense fallback and Analytics) inside <ThemeProvider> in the
RootLayout component, ensuring the provider encloses the Suspense and Analytics
nodes and preserves existing body classes and props.
| "use client" | ||
|
|
||
| import * as React from "react" | ||
| import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" | ||
|
|
||
| import { cn } from "@/lib/utils" | ||
| import { buttonVariants } from "@/components/ui/button" | ||
|
|
||
| function AlertDialog({ | ||
| ...props | ||
| }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) { | ||
| return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} /> | ||
| } | ||
|
|
||
| function AlertDialogTrigger({ | ||
| ...props | ||
| }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) { | ||
| return ( | ||
| <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} /> | ||
| ) | ||
| } | ||
|
|
||
| function AlertDialogPortal({ | ||
| ...props | ||
| }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) { | ||
| return ( | ||
| <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} /> | ||
| ) | ||
| } | ||
|
|
||
| function AlertDialogOverlay({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) { | ||
| return ( | ||
| <AlertDialogPrimitive.Overlay | ||
| data-slot="alert-dialog-overlay" | ||
| className={cn( | ||
| "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| function AlertDialogContent({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) { | ||
| return ( | ||
| <AlertDialogPortal> | ||
| <AlertDialogOverlay /> | ||
| <AlertDialogPrimitive.Content | ||
| data-slot="alert-dialog-content" | ||
| className={cn( | ||
| "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg", | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| </AlertDialogPortal> | ||
| ) | ||
| } | ||
|
|
||
| function AlertDialogHeader({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<"div">) { | ||
| return ( | ||
| <div | ||
| data-slot="alert-dialog-header" | ||
| className={cn("flex flex-col gap-2 text-center sm:text-left", className)} | ||
| {...props} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| function AlertDialogFooter({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<"div">) { | ||
| return ( | ||
| <div | ||
| data-slot="alert-dialog-footer" | ||
| className={cn( | ||
| "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| function AlertDialogTitle({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) { | ||
| return ( | ||
| <AlertDialogPrimitive.Title | ||
| data-slot="alert-dialog-title" | ||
| className={cn("text-lg font-semibold", className)} | ||
| {...props} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| function AlertDialogDescription({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) { | ||
| return ( | ||
| <AlertDialogPrimitive.Description | ||
| data-slot="alert-dialog-description" | ||
| className={cn("text-muted-foreground text-sm", className)} | ||
| {...props} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| function AlertDialogAction({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<typeof AlertDialogPrimitive.Action>) { | ||
| return ( | ||
| <AlertDialogPrimitive.Action | ||
| className={cn(buttonVariants(), className)} | ||
| {...props} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| function AlertDialogCancel({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) { | ||
| return ( | ||
| <AlertDialogPrimitive.Cancel | ||
| className={cn(buttonVariants({ variant: "outline" }), className)} | ||
| {...props} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| export { | ||
| AlertDialog, | ||
| AlertDialogPortal, | ||
| AlertDialogOverlay, | ||
| AlertDialogTrigger, | ||
| AlertDialogContent, | ||
| AlertDialogHeader, | ||
| AlertDialogFooter, | ||
| AlertDialogTitle, | ||
| AlertDialogDescription, | ||
| AlertDialogAction, | ||
| AlertDialogCancel, | ||
| } |
There was a problem hiding this comment.
Mission blocker: this whole templates/agentic/travel-planner/components/ui subtree is still app UI.
These wrappers keep the submission in runnable-web-app form under templates/, which conflicts with the template contract for this repo. Please move the UI/app surface out of templates/ or convert the submission to the current flow template before merge. Based on learnings: Bundles and templates do not have runnable apps and should not include web application code (Next.js app router, server actions, etc.).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/components/ui/alert-dialog.tsx` around lines
1 - 157, Summary: The UI components (e.g., AlertDialog, AlertDialogTrigger,
AlertDialogContent, AlertDialogAction, AlertDialogCancel) are app code living
under the templates subtree and must be removed or converted to comply with the
template contract. Fix: either relocate these components out of templates into
the real app/component library (update imports where AlertDialog* symbols are
used) or refactor this template to the "flow" template shape by removing any
runnable app surface (Next.js app router/server actions) and replacing with
template-only artifacts; ensure all references to the exported symbols are
updated and remove any Next.js-specific runtime code from the templates subtree.
| "use client" | ||
|
|
||
| import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" | ||
|
|
||
| function AspectRatio({ | ||
| ...props | ||
| }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) { | ||
| return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} /> | ||
| } | ||
|
|
||
| export { AspectRatio } |
There was a problem hiding this comment.
Agent, we have a situation: Missing React import.
The component references React.ComponentProps on line 7, but React is never imported. This will cause a compilation error. Your mission, should you choose to accept it: add the missing import.
🔧 Proposed fix
"use client"
+import * as React from "react"
import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "use client" | |
| import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" | |
| function AspectRatio({ | |
| ...props | |
| }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) { | |
| return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} /> | |
| } | |
| export { AspectRatio } | |
| "use client" | |
| import * as React from "react" | |
| import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" | |
| function AspectRatio({ | |
| ...props | |
| }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) { | |
| return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} /> | |
| } | |
| export { AspectRatio } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/components/ui/aspect-ratio.tsx` around lines
1 - 11, The component uses React.ComponentProps in the AspectRatio function but
never imports React; add an import for React (e.g., import React from "react")
at the top of the file so React.ComponentProps<typeof AspectRatioPrimitive.Root>
resolves correctly and the AspectRatio component can compile when returning
<AspectRatioPrimitive.Root ... />.
| export const lamaticClient = new Lamatic({ | ||
| endpoint: config.api.endpoint, | ||
| projectId: config.api.projectId, | ||
| apiKey: process.env.LAMATIC_API_KEY, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify client init and env placeholders are aligned after applying the fix
rg -n "LAMATIC_API_URL|LAMATIC_PROJECT_ID|LAMATIC_API_KEY|new Lamatic|endpoint:|projectId:" \
templates/agentic/travel-planner/lib/lamatic-client.ts \
templates/agentic/travel-planner/.env.exampleRepository: Lamatic/AgentKit
Length of output: 770
🏁 Script executed:
#!/bin/bash
# Check if lamatic-config.json exists in travel-planner template
fd -t f "lamatic-config.json" templates/agentic/travel-planner/Repository: Lamatic/AgentKit
Length of output: 112
🏁 Script executed:
#!/bin/bash
# View the full .env.example file
cat -n templates/agentic/travel-planner/.env.exampleRepository: Lamatic/AgentKit
Length of output: 103
🏁 Script executed:
#!/bin/bash
# View the complete lamatic-client.ts file with context
cat -n templates/agentic/travel-planner/lib/lamatic-client.tsRepository: Lamatic/AgentKit
Length of output: 548
🏁 Script executed:
#!/bin/bash
# Search for any other usages of 'config' or endpoint/projectId in the travel-planner template
rg -n "config\.|endpoint|projectId|lamatic-config" templates/agentic/travel-planner/ --type ts --type jsonRepository: Lamatic/AgentKit
Length of output: 1066
Decouple Lamatic client initialization from committed project configuration.
The template currently reads endpoint and projectId from lamatic-config.json (a committed file with hardcoded project-specific values), preventing reuse across different projects. Initialize Lamatic with environment variables LAMATIC_API_URL, LAMATIC_PROJECT_ID, and LAMATIC_API_KEY instead.
Update lib/lamatic-client.ts to:
- Add
"server-only"directive - Read all three credentials from environment variables at module load time
- Validate all three are present before creating the client
- Use env vars in the Lamatic constructor instead of
config.apiobject
Also update .env.example to include the new environment variable placeholders:
LAMATIC_API_URL=your_lamatic_api_url
LAMATIC_PROJECT_ID=your_lamatic_project_id
LAMATIC_API_KEY=your_lamatic_api_key
Proposed changes to lamatic-client.ts
import { Lamatic } from "lamatic";
import config from "@/lamatic-config.json";
+import "server-only";
-if (!process.env.LAMATIC_API_KEY) {
+const lamaticApiUrl = process.env.LAMATIC_API_URL;
+const lamaticProjectId = process.env.LAMATIC_PROJECT_ID;
+const lamaticApiKey = process.env.LAMATIC_API_KEY;
+
+if (!lamaticApiUrl || !lamaticProjectId || !lamaticApiKey) {
throw new Error(
- "LAMATIC_API_KEY environment variable is not set. Please add it to your .env.local file."
+ "LAMATIC_API_URL, LAMATIC_PROJECT_ID, and LAMATIC_API_KEY must be set in .env.local."
);
}
export const lamaticClient = new Lamatic({
- endpoint: config.api.endpoint,
- projectId: config.api.projectId,
- apiKey: process.env.LAMATIC_API_KEY,
+ endpoint: lamaticApiUrl,
+ projectId: lamaticProjectId,
+ apiKey: lamaticApiKey,
});🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/lib/lamatic-client.ts` around lines 10 - 13,
Replace the hardcoded config usage when constructing lamaticClient: add the
"server-only" module directive at top, read process.env.LAMATIC_API_URL,
process.env.LAMATIC_PROJECT_ID and process.env.LAMATIC_API_KEY into local
constants at module load, validate all three are present (throw or log and exit
if missing) and then pass those env vars into the new Lamatic(...) call instead
of config.api.endpoint/config.api.projectId and process.env.LAMATIC_API_KEY;
update .env.example to include LAMATIC_API_URL, LAMATIC_PROJECT_ID and
LAMATIC_API_KEY placeholders.
| @@ -0,0 +1,107 @@ | |||
| # Lamatic Multi-Agent Travel Planner | |||
|
|
|||
| Design flight-ready itineraries with Lamatic’s multi-agent coordination stack. This template wires the Lamatic workflow you deployed (project `bee05145-3d20-4d4b-a965-75ec69cc4a65`) into a polished Next.js front-end so travellers can collect flights, stays, activities, budgets, visualisations, and booking steps in one place. | |||
There was a problem hiding this comment.
Agent, sensitive operational details have been exposed in this document.
The hardcoded project ID (bee05145-3d20-4d4b-a965-75ec69cc4a65) is specific to your deployment. Users cloning this template will have their own project IDs from Lamatic Studio. Consider generalizing this reference or clarifying it's an example.
📝 Suggested revision
-Design flight-ready itineraries with Lamatic's multi-agent coordination stack. This template wires the Lamatic workflow you deployed (project `bee05145-3d20-4d4b-a965-75ec69cc4a65`) into a polished Next.js front-end so travellers can collect flights, stays, activities, budgets, visualisations, and booking steps in one place.
+Design flight-ready itineraries with Lamatic's multi-agent coordination stack. This template wires your Lamatic workflow deployment into a polished Next.js front-end so travellers can collect flights, stays, activities, budgets, visualisations, and booking steps in one place.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Design flight-ready itineraries with Lamatic’s multi-agent coordination stack. This template wires the Lamatic workflow you deployed (project `bee05145-3d20-4d4b-a965-75ec69cc4a65`) into a polished Next.js front-end so travellers can collect flights, stays, activities, budgets, visualisations, and booking steps in one place. | |
| Design flight-ready itineraries with Lamatic's multi-agent coordination stack. This template wires your Lamatic workflow deployment into a polished Next.js front-end so travellers can collect flights, stays, activities, budgets, visualisations, and booking steps in one place. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/README.md` at line 3, The README exposes a
hardcoded Lamatic project ID ("bee05145-3d20-4d4b-a965-75ec69cc4a65") in the
travel-planner template; replace that literal with a clear placeholder (e.g.,
<PROJECT_ID>) and a one-line note explaining it’s an example and instructing
users to use their own project ID from Lamatic Studio (or show how to find it).
Update the sentence that currently mentions the project ID so it reads
generically and add the brief guidance immediately after it.
| ## ✨ What’s inside | ||
|
|
||
| - **Preference capture UI** – guided form with origin/destination, dates, budget, travellers, cabin class, and up to three interests. | ||
| - **Lamatic orchestration** – calls the `Multi-Agent Travel Planner` flow (`3cc791a2-ca33-4e27-8791-ff386cef14b2`). The trigger node fans out to flight, hotel, and activity sub-flows and returns a structured brief. |
There was a problem hiding this comment.
Same operational security concern here, agent.
The flow ID 3cc791a2-ca33-4e27-8791-ff386cef14b2 is deployment-specific. Since users configure their own lamatic-config.json, reference the config file rather than hardcoding IDs that won't match their deployment.
📝 Suggested revision
-- **Lamatic orchestration** – calls the `Multi-Agent Travel Planner` flow (`3cc791a2-ca33-4e27-8791-ff386cef14b2`). The trigger node fans out to flight, hotel, and activity sub-flows and returns a structured brief.
+- **Lamatic orchestration** – calls the `Multi-Agent Travel Planner` flow (configured in `lamatic-config.json`). The trigger node fans out to flight, hotel, and activity sub-flows and returns a structured brief.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - **Lamatic orchestration** – calls the `Multi-Agent Travel Planner` flow (`3cc791a2-ca33-4e27-8791-ff386cef14b2`). The trigger node fans out to flight, hotel, and activity sub-flows and returns a structured brief. | |
| - **Lamatic orchestration** – calls the `Multi-Agent Travel Planner` flow (configured in `lamatic-config.json`). The trigger node fans out to flight, hotel, and activity sub-flows and returns a structured brief. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/README.md` at line 12, The README currently
hardcodes the deployment-specific flow ID "3cc791a2-ca33-4e27-8791-ff386cef14b2"
for the "Multi-Agent Travel Planner" flow; update the text to reference the
user's lamatic-config.json instead of a fixed UUID so docs work across
deployments—specifically, replace the literal ID in the "Lamatic orchestration"
description with an instruction pointing readers to the "Multi-Agent Travel
Planner" flow entry in lamatic-config.json (or the config key that holds the
flowId), and mention that they should use their configured flowId rather than
the hardcoded value.
| 1. **Install dependencies** | ||
| ```bash | ||
| cd templates/agentic/travel-planner | ||
| npm install | ||
| ``` |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Minor formatting intel, agent. Non-critical.
The markdown linter flags missing blank lines before fenced code blocks within list items. This is a stylistic preference and won't affect rendering in most viewers.
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)
[warning] 24-24: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/README.md` around lines 23 - 27, Add a blank
line before the fenced code block inside the first list item in
templates/agentic/travel-planner/README.md so the markdown linter stops flagging
it; specifically, in the list item that starts with "1. **Install
dependencies**" insert an empty line before the ```bash block to separate the
paragraph from the code fence.
| @import 'tailwindcss'; | ||
| @import 'tw-animate-css'; | ||
|
|
||
| @custom-variant dark (&:is(.dark *)); | ||
|
|
||
| :root { | ||
| --background: oklch(1 0 0); | ||
| --foreground: oklch(0.145 0 0); | ||
| --card: oklch(1 0 0); | ||
| --card-foreground: oklch(0.145 0 0); | ||
| --popover: oklch(1 0 0); | ||
| --popover-foreground: oklch(0.145 0 0); | ||
| --primary: oklch(0.205 0 0); | ||
| --primary-foreground: oklch(0.985 0 0); | ||
| --secondary: oklch(0.97 0 0); | ||
| --secondary-foreground: oklch(0.205 0 0); | ||
| --muted: oklch(0.97 0 0); | ||
| --muted-foreground: oklch(0.556 0 0); | ||
| --accent: oklch(0.97 0 0); | ||
| --accent-foreground: oklch(0.205 0 0); | ||
| --destructive: oklch(0.577 0.245 27.325); | ||
| --destructive-foreground: oklch(0.577 0.245 27.325); | ||
| --border: oklch(0.922 0 0); | ||
| --input: oklch(0.922 0 0); | ||
| --ring: oklch(0.708 0 0); | ||
| --chart-1: oklch(0.646 0.222 41.116); | ||
| --chart-2: oklch(0.6 0.118 184.704); | ||
| --chart-3: oklch(0.398 0.07 227.392); | ||
| --chart-4: oklch(0.828 0.189 84.429); | ||
| --chart-5: oklch(0.769 0.188 70.08); | ||
| --radius: 0.625rem; | ||
| --sidebar: oklch(0.985 0 0); | ||
| --sidebar-foreground: oklch(0.145 0 0); | ||
| --sidebar-primary: oklch(0.205 0 0); | ||
| --sidebar-primary-foreground: oklch(0.985 0 0); | ||
| --sidebar-accent: oklch(0.97 0 0); | ||
| --sidebar-accent-foreground: oklch(0.205 0 0); | ||
| --sidebar-border: oklch(0.922 0 0); | ||
| --sidebar-ring: oklch(0.708 0 0); | ||
| } | ||
|
|
||
| .dark { | ||
| --background: oklch(0.145 0 0); | ||
| --foreground: oklch(0.985 0 0); | ||
| --card: oklch(0.145 0 0); | ||
| --card-foreground: oklch(0.985 0 0); | ||
| --popover: oklch(0.145 0 0); | ||
| --popover-foreground: oklch(0.985 0 0); | ||
| --primary: oklch(0.985 0 0); | ||
| --primary-foreground: oklch(0.205 0 0); | ||
| --secondary: oklch(0.269 0 0); | ||
| --secondary-foreground: oklch(0.985 0 0); | ||
| --muted: oklch(0.269 0 0); | ||
| --muted-foreground: oklch(0.708 0 0); | ||
| --accent: oklch(0.269 0 0); | ||
| --accent-foreground: oklch(0.985 0 0); | ||
| --destructive: oklch(0.396 0.141 25.723); | ||
| --destructive-foreground: oklch(0.637 0.237 25.331); | ||
| --border: oklch(0.269 0 0); | ||
| --input: oklch(0.269 0 0); | ||
| --ring: oklch(0.439 0 0); | ||
| --chart-1: oklch(0.488 0.243 264.376); | ||
| --chart-2: oklch(0.696 0.17 162.48); | ||
| --chart-3: oklch(0.769 0.188 70.08); | ||
| --chart-4: oklch(0.627 0.265 303.9); | ||
| --chart-5: oklch(0.645 0.246 16.439); | ||
| --sidebar: oklch(0.205 0 0); | ||
| --sidebar-foreground: oklch(0.985 0 0); | ||
| --sidebar-primary: oklch(0.488 0.243 264.376); | ||
| --sidebar-primary-foreground: oklch(0.985 0 0); | ||
| --sidebar-accent: oklch(0.269 0 0); | ||
| --sidebar-accent-foreground: oklch(0.985 0 0); | ||
| --sidebar-border: oklch(0.269 0 0); | ||
| --sidebar-ring: oklch(0.439 0 0); | ||
| } | ||
|
|
||
| @theme inline { | ||
| --font-sans: var(--font-geist-sans); | ||
| --font-mono: var(--font-geist-mono); | ||
| --color-background: var(--background); | ||
| --color-foreground: var(--foreground); | ||
| --color-card: var(--card); | ||
| --color-card-foreground: var(--card-foreground); | ||
| --color-popover: var(--popover); | ||
| --color-popover-foreground: var(--popover-foreground); | ||
| --color-primary: var(--primary); | ||
| --color-primary-foreground: var(--primary-foreground); | ||
| --color-secondary: var(--secondary); | ||
| --color-secondary-foreground: var(--secondary-foreground); | ||
| --color-muted: var(--muted); | ||
| --color-muted-foreground: var(--muted-foreground); | ||
| --color-accent: var(--accent); | ||
| --color-accent-foreground: var(--accent-foreground); | ||
| --color-destructive: var(--destructive); | ||
| --color-destructive-foreground: var(--destructive-foreground); | ||
| --color-border: var(--border); | ||
| --color-input: var(--input); | ||
| --color-ring: var(--ring); | ||
| --color-chart-1: var(--chart-1); | ||
| --color-chart-2: var(--chart-2); | ||
| --color-chart-3: var(--chart-3); | ||
| --color-chart-4: var(--chart-4); | ||
| --color-chart-5: var(--chart-5); | ||
| --radius-sm: calc(var(--radius) - 4px); | ||
| --radius-md: calc(var(--radius) - 2px); | ||
| --radius-lg: var(--radius); | ||
| --radius-xl: calc(var(--radius) + 4px); | ||
| --color-sidebar: var(--sidebar); | ||
| --color-sidebar-foreground: var(--sidebar-foreground); | ||
| --color-sidebar-primary: var(--sidebar-primary); | ||
| --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); | ||
| --color-sidebar-accent: var(--sidebar-accent); | ||
| --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); | ||
| --color-sidebar-border: var(--sidebar-border); | ||
| --color-sidebar-ring: var(--sidebar-ring); | ||
| } | ||
|
|
||
| @layer base { | ||
| * { | ||
| @apply border-border outline-ring/50; | ||
| } | ||
| body { | ||
| @apply bg-background text-foreground; | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify if styles/globals.css is imported anywhere in the codebase
echo "=== Searching for imports of styles/globals.css ==="
rg -n "styles/globals" --type=ts --type=tsx --type=js --type=css
echo ""
echo "=== Searching for any globals.css imports ==="
rg -n "globals\.css" templates/agentic/travel-planner/Repository: Lamatic/AgentKit
Length of output: 357
🏁 Script executed:
#!/bin/bash
# Check if both files exist and compare their contents
echo "=== Checking if files exist ==="
ls -la templates/agentic/travel-planner/styles/globals.css 2>/dev/null && echo "styles/globals.css EXISTS" || echo "styles/globals.css NOT FOUND"
ls -la templates/agentic/travel-planner/app/globals.css 2>/dev/null && echo "app/globals.css EXISTS" || echo "app/globals.css NOT FOUND"
echo ""
echo "=== Comparing file contents (first 50 lines each) ==="
echo "--- app/globals.css ---"
head -50 templates/agentic/travel-planner/app/globals.css 2>/dev/null || echo "Cannot read app/globals.css"
echo ""
echo "--- styles/globals.css ---"
head -50 templates/agentic/travel-planner/styles/globals.css 2>/dev/null || echo "Cannot read styles/globals.css"
echo ""
echo "=== Checking file sizes ==="
wc -l templates/agentic/travel-planner/app/globals.css templates/agentic/travel-planner/styles/globals.css 2>/dev/nullRepository: Lamatic/AgentKit
Length of output: 3797
🏁 Script executed:
#!/bin/bash
# Full comparison of both files to confirm they are identical
echo "=== Full file diff ==="
diff templates/agentic/travel-planner/app/globals.css templates/agentic/travel-planner/styles/globals.css
if [ $? -eq 0 ]; then
echo "Files are IDENTICAL"
else
echo "Files have DIFFERENCES"
fiRepository: Lamatic/AgentKit
Length of output: 102
Mission briefing: Eliminate the doppelgänger stylesheet.
This styles/globals.css file is a dead drop—a perfect duplicate of app/globals.css that exists nowhere in your import chain. Your codebase only references app/globals.css (via app/layout.tsx), while styles/globals.css remains completely unused. Both files are byte-for-byte identical, creating redundancy and maintenance risk.
Your options:
- Delete
styles/globals.cssifapp/globals.cssis the canonical source (recommended) - Consolidate by having one file import the other if separation was intentional
- Update imports to use
styles/if that directory is the intended location
Remove the dead file to eliminate confusion about which version is authoritative.
🧰 Tools
🪛 Stylelint (17.5.0)
[error] 4-4: Unexpected unknown at-rule "@custom-variant" (scss/at-rule-no-unknown)
(scss/at-rule-no-unknown)
[error] 77-77: Unexpected unknown at-rule "@theme" (scss/at-rule-no-unknown)
(scss/at-rule-no-unknown)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@templates/agentic/travel-planner/styles/globals.css` around lines 1 - 125,
This stylesheet is a byte-for-byte duplicate (contains `@import` 'tailwindcss';
`@theme` inline; :root and .dark variable sets and `@layer` base) that is
unused—remove the duplicate file containing those symbols to eliminate
confusion; after deletion, verify the layout still imports the canonical
globals.css (or consolidate by replacing the duplicate with an import that
re-exports the canonical file if you intentionally wanted separate locations) or
update any imports to point to the intended globals.css.
|
Hi @jeloskaisabel! 👋 Before this PR can be reviewed by maintainers, please resolve all comments and requested changes from the CodeRabbit automated review. Steps to follow:
This helps keep the review process efficient for everyone. Thank you! 🙏 |
What: Introduces a multi-agent travel researcher and booking assistant that coordinates flight, hotel, and activity agents to deliver a shareable itinerary, budget, and booking checklist for any destination.
Prerequisites: Lamatic account with a valid LAMATIC_API_KEY.
Steps to run locally:
Live preview: https://agent-kit-vert.vercel.app/
Lamatic flow ID: 3cc791a2-ca33-4e27-8791-ff386cef14b2
Closes #31
Overview
Flow / node types (from lamatic-config.json + README hints)
Key added files (grouped)
How the flow is used by the template (high level)
Notes for reviewers