create-kuckit-app 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/package.json +1 -1
  2. package/templates/base/AGENTS.md +203 -0
  3. package/templates/base/apps/server/AGENTS.md +64 -8
  4. package/templates/base/apps/web/AGENTS.md +82 -8
  5. package/templates/base/apps/web/src/components/KuckitModuleRoute.tsx +119 -0
  6. package/templates/base/apps/web/src/components/dashboard/app-sidebar.tsx +120 -0
  7. package/templates/base/apps/web/src/components/dashboard/dashboard-layout.tsx +46 -0
  8. package/templates/base/apps/web/src/components/dashboard/dashboard-overview.tsx +24 -0
  9. package/templates/base/apps/web/src/components/dashboard/index.ts +2 -0
  10. package/templates/base/apps/web/src/components/dashboard/nav-user.tsx +77 -0
  11. package/templates/base/apps/web/src/components/ui/avatar.tsx +39 -0
  12. package/templates/base/apps/web/src/components/ui/breadcrumb.tsx +102 -0
  13. package/templates/base/apps/web/src/components/ui/collapsible.tsx +21 -0
  14. package/templates/base/apps/web/src/components/ui/separator.tsx +26 -0
  15. package/templates/base/apps/web/src/components/ui/sheet.tsx +130 -0
  16. package/templates/base/apps/web/src/components/ui/sidebar.tsx +694 -0
  17. package/templates/base/apps/web/src/components/ui/skeleton.tsx +13 -0
  18. package/templates/base/apps/web/src/components/ui/tooltip.tsx +55 -0
  19. package/templates/base/apps/web/src/hooks/use-mobile.ts +19 -0
  20. package/templates/base/apps/web/src/lib/utils.ts +6 -0
  21. package/templates/base/apps/web/src/modules.client.ts +4 -3
  22. package/templates/base/apps/web/src/providers/KuckitProvider.tsx +1 -25
  23. package/templates/base/apps/web/src/routes/$.tsx +14 -0
  24. package/templates/base/apps/web/src/routes/dashboard/$.tsx +9 -0
  25. package/templates/base/apps/web/src/routes/dashboard/index.tsx +6 -0
  26. package/templates/base/apps/web/src/routes/dashboard.tsx +25 -0
  27. package/templates/base/apps/web/tsconfig.json +5 -1
  28. package/templates/base/apps/web/vite.config.ts +6 -0
  29. package/templates/base/packages/api/AGENTS.md +44 -5
  30. package/templates/base/packages/auth/AGENTS.md +17 -1
  31. package/templates/base/packages/db/AGENTS.md +16 -1
  32. package/templates/base/packages/items-module/AGENTS.md +99 -1
  33. package/templates/base/packages/items-module/src/ui/ItemsPage.tsx +50 -68
  34. package/templates/base/apps/web/src/lib/kuckit-router.ts +0 -42
@@ -0,0 +1,24 @@
1
+ import { useServices } from '@/providers/ServicesProvider'
2
+
3
+ export function DashboardOverview() {
4
+ const { authClient } = useServices()
5
+ const { data: session } = authClient.useSession()
6
+
7
+ return (
8
+ <div className="space-y-6">
9
+ <div>
10
+ <h1 className="text-3xl font-bold tracking-tight">Dashboard</h1>
11
+ <p className="text-muted-foreground">Welcome back, {session?.user?.name || 'User'}</p>
12
+ </div>
13
+
14
+ <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
15
+ <div className="rounded-lg border bg-card p-6">
16
+ <h3 className="font-semibold">Getting Started</h3>
17
+ <p className="text-sm text-muted-foreground">
18
+ Your Kuckit application is ready. Start building!
19
+ </p>
20
+ </div>
21
+ </div>
22
+ </div>
23
+ )
24
+ }
@@ -0,0 +1,2 @@
1
+ export { DashboardLayout } from './dashboard-layout'
2
+ export { DashboardOverview } from './dashboard-overview'
@@ -0,0 +1,77 @@
1
+ import { ChevronsUpDown, LogOut, User } from 'lucide-react'
2
+ import { useNavigate } from '@tanstack/react-router'
3
+ import { useServices } from '@/providers/ServicesProvider'
4
+ import {
5
+ DropdownMenu,
6
+ DropdownMenuContent,
7
+ DropdownMenuItem,
8
+ DropdownMenuSeparator,
9
+ DropdownMenuTrigger,
10
+ } from '@/components/ui/dropdown-menu'
11
+ import {
12
+ SidebarMenu,
13
+ SidebarMenuButton,
14
+ SidebarMenuItem,
15
+ useSidebar,
16
+ } from '@/components/ui/sidebar'
17
+ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
18
+
19
+ export function NavUser() {
20
+ const { isMobile } = useSidebar()
21
+ const navigate = useNavigate()
22
+ const { authClient } = useServices()
23
+ const { data: session } = authClient.useSession()
24
+
25
+ const user = session?.user
26
+ const initials =
27
+ user?.name
28
+ ?.split(' ')
29
+ .map((n) => n[0])
30
+ .join('')
31
+ .toUpperCase() || 'U'
32
+
33
+ const handleLogout = async () => {
34
+ await authClient.signOut()
35
+ navigate({ to: '/' })
36
+ }
37
+
38
+ return (
39
+ <SidebarMenu>
40
+ <SidebarMenuItem>
41
+ <DropdownMenu>
42
+ <DropdownMenuTrigger asChild>
43
+ <SidebarMenuButton size="lg" className="data-[state=open]:bg-sidebar-accent">
44
+ <Avatar className="h-8 w-8 rounded-lg">
45
+ <AvatarImage src={user?.image || undefined} alt={user?.name || ''} />
46
+ <AvatarFallback className="rounded-lg bg-gradient-to-br from-primary to-primary/80 text-primary-foreground">
47
+ {initials}
48
+ </AvatarFallback>
49
+ </Avatar>
50
+ <div className="grid flex-1 text-left text-sm leading-tight">
51
+ <span className="truncate font-semibold">{user?.name || 'User'}</span>
52
+ <span className="truncate text-xs text-muted-foreground">{user?.email || ''}</span>
53
+ </div>
54
+ <ChevronsUpDown className="ml-auto size-4" />
55
+ </SidebarMenuButton>
56
+ </DropdownMenuTrigger>
57
+ <DropdownMenuContent
58
+ className="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg"
59
+ side={isMobile ? 'bottom' : 'right'}
60
+ align="end"
61
+ sideOffset={4}
62
+ >
63
+ <DropdownMenuItem onClick={() => navigate({ to: '/dashboard/settings' })}>
64
+ <User className="mr-2 h-4 w-4" />
65
+ Settings
66
+ </DropdownMenuItem>
67
+ <DropdownMenuSeparator />
68
+ <DropdownMenuItem onClick={handleLogout}>
69
+ <LogOut className="mr-2 h-4 w-4" />
70
+ Log out
71
+ </DropdownMenuItem>
72
+ </DropdownMenuContent>
73
+ </DropdownMenu>
74
+ </SidebarMenuItem>
75
+ </SidebarMenu>
76
+ )
77
+ }
@@ -0,0 +1,39 @@
1
+ import * as React from 'react'
2
+ import * as AvatarPrimitive from '@radix-ui/react-avatar'
3
+
4
+ import { cn } from '@/lib/utils'
5
+
6
+ function Avatar({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
7
+ return (
8
+ <AvatarPrimitive.Root
9
+ data-slot="avatar"
10
+ className={cn('relative flex size-8 shrink-0 overflow-hidden rounded-full', className)}
11
+ {...props}
12
+ />
13
+ )
14
+ }
15
+
16
+ function AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
17
+ return (
18
+ <AvatarPrimitive.Image
19
+ data-slot="avatar-image"
20
+ className={cn('aspect-square size-full', className)}
21
+ {...props}
22
+ />
23
+ )
24
+ }
25
+
26
+ function AvatarFallback({
27
+ className,
28
+ ...props
29
+ }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
30
+ return (
31
+ <AvatarPrimitive.Fallback
32
+ data-slot="avatar-fallback"
33
+ className={cn('bg-muted flex size-full items-center justify-center rounded-full', className)}
34
+ {...props}
35
+ />
36
+ )
37
+ }
38
+
39
+ export { Avatar, AvatarImage, AvatarFallback }
@@ -0,0 +1,102 @@
1
+ import * as React from 'react'
2
+ import { Slot } from '@radix-ui/react-slot'
3
+ import { ChevronRight, MoreHorizontal } from 'lucide-react'
4
+
5
+ import { cn } from '@/lib/utils'
6
+
7
+ function Breadcrumb({ ...props }: React.ComponentProps<'nav'>) {
8
+ return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />
9
+ }
10
+
11
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<'ol'>) {
12
+ return (
13
+ <ol
14
+ data-slot="breadcrumb-list"
15
+ className={cn(
16
+ 'text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5',
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ )
22
+ }
23
+
24
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<'li'>) {
25
+ return (
26
+ <li
27
+ data-slot="breadcrumb-item"
28
+ className={cn('inline-flex items-center gap-1.5', className)}
29
+ {...props}
30
+ />
31
+ )
32
+ }
33
+
34
+ function BreadcrumbLink({
35
+ asChild,
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<'a'> & {
39
+ asChild?: boolean
40
+ }) {
41
+ const Comp = asChild ? Slot : 'a'
42
+
43
+ return (
44
+ <Comp
45
+ data-slot="breadcrumb-link"
46
+ className={cn('hover:text-foreground transition-colors', className)}
47
+ {...props}
48
+ />
49
+ )
50
+ }
51
+
52
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<'span'>) {
53
+ return (
54
+ <span
55
+ data-slot="breadcrumb-page"
56
+ role="link"
57
+ aria-disabled="true"
58
+ aria-current="page"
59
+ className={cn('text-foreground font-normal', className)}
60
+ {...props}
61
+ />
62
+ )
63
+ }
64
+
65
+ function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<'li'>) {
66
+ return (
67
+ <li
68
+ data-slot="breadcrumb-separator"
69
+ role="presentation"
70
+ aria-hidden="true"
71
+ className={cn('[&>svg]:size-3.5', className)}
72
+ {...props}
73
+ >
74
+ {children ?? <ChevronRight />}
75
+ </li>
76
+ )
77
+ }
78
+
79
+ function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<'span'>) {
80
+ return (
81
+ <span
82
+ data-slot="breadcrumb-ellipsis"
83
+ role="presentation"
84
+ aria-hidden="true"
85
+ className={cn('flex size-9 items-center justify-center', className)}
86
+ {...props}
87
+ >
88
+ <MoreHorizontal className="size-4" />
89
+ <span className="sr-only">More</span>
90
+ </span>
91
+ )
92
+ }
93
+
94
+ export {
95
+ Breadcrumb,
96
+ BreadcrumbList,
97
+ BreadcrumbItem,
98
+ BreadcrumbLink,
99
+ BreadcrumbPage,
100
+ BreadcrumbSeparator,
101
+ BreadcrumbEllipsis,
102
+ }
@@ -0,0 +1,21 @@
1
+ 'use client'
2
+
3
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'
4
+
5
+ function Collapsible({ ...props }: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
6
+ return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
7
+ }
8
+
9
+ function CollapsibleTrigger({
10
+ ...props
11
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
12
+ return <CollapsiblePrimitive.CollapsibleTrigger data-slot="collapsible-trigger" {...props} />
13
+ }
14
+
15
+ function CollapsibleContent({
16
+ ...props
17
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
18
+ return <CollapsiblePrimitive.CollapsibleContent data-slot="collapsible-content" {...props} />
19
+ }
20
+
21
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent }
@@ -0,0 +1,26 @@
1
+ import * as React from 'react'
2
+ import * as SeparatorPrimitive from '@radix-ui/react-separator'
3
+
4
+ import { cn } from '@/lib/utils'
5
+
6
+ function Separator({
7
+ className,
8
+ orientation = 'horizontal',
9
+ decorative = true,
10
+ ...props
11
+ }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
12
+ return (
13
+ <SeparatorPrimitive.Root
14
+ data-slot="separator"
15
+ decorative={decorative}
16
+ orientation={orientation}
17
+ className={cn(
18
+ 'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
19
+ className
20
+ )}
21
+ {...props}
22
+ />
23
+ )
24
+ }
25
+
26
+ export { Separator }
@@ -0,0 +1,130 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as SheetPrimitive from '@radix-ui/react-dialog'
5
+ import { XIcon } from 'lucide-react'
6
+
7
+ import { cn } from '@/lib/utils'
8
+
9
+ function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
10
+ return <SheetPrimitive.Root data-slot="sheet" {...props} />
11
+ }
12
+
13
+ function SheetTrigger({ ...props }: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
14
+ return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
15
+ }
16
+
17
+ function SheetClose({ ...props }: React.ComponentProps<typeof SheetPrimitive.Close>) {
18
+ return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
19
+ }
20
+
21
+ function SheetPortal({ ...props }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
22
+ return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
23
+ }
24
+
25
+ function SheetOverlay({
26
+ className,
27
+ ...props
28
+ }: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
29
+ return (
30
+ <SheetPrimitive.Overlay
31
+ data-slot="sheet-overlay"
32
+ className={cn(
33
+ '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',
34
+ className
35
+ )}
36
+ {...props}
37
+ />
38
+ )
39
+ }
40
+
41
+ function SheetContent({
42
+ className,
43
+ children,
44
+ side = 'right',
45
+ ...props
46
+ }: React.ComponentProps<typeof SheetPrimitive.Content> & {
47
+ side?: 'top' | 'right' | 'bottom' | 'left'
48
+ }) {
49
+ return (
50
+ <SheetPortal>
51
+ <SheetOverlay />
52
+ <SheetPrimitive.Content
53
+ data-slot="sheet-content"
54
+ className={cn(
55
+ 'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
56
+ side === 'right' &&
57
+ 'data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',
58
+ side === 'left' &&
59
+ 'data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
60
+ side === 'top' &&
61
+ 'data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b',
62
+ side === 'bottom' &&
63
+ 'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t',
64
+ className
65
+ )}
66
+ {...props}
67
+ >
68
+ {children}
69
+ <SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary 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">
70
+ <XIcon className="size-4" />
71
+ <span className="sr-only">Close</span>
72
+ </SheetPrimitive.Close>
73
+ </SheetPrimitive.Content>
74
+ </SheetPortal>
75
+ )
76
+ }
77
+
78
+ function SheetHeader({ className, ...props }: React.ComponentProps<'div'>) {
79
+ return (
80
+ <div
81
+ data-slot="sheet-header"
82
+ className={cn('flex flex-col gap-1.5 p-4', className)}
83
+ {...props}
84
+ />
85
+ )
86
+ }
87
+
88
+ function SheetFooter({ className, ...props }: React.ComponentProps<'div'>) {
89
+ return (
90
+ <div
91
+ data-slot="sheet-footer"
92
+ className={cn('mt-auto flex flex-col gap-2 p-4', className)}
93
+ {...props}
94
+ />
95
+ )
96
+ }
97
+
98
+ function SheetTitle({ className, ...props }: React.ComponentProps<typeof SheetPrimitive.Title>) {
99
+ return (
100
+ <SheetPrimitive.Title
101
+ data-slot="sheet-title"
102
+ className={cn('text-foreground font-semibold', className)}
103
+ {...props}
104
+ />
105
+ )
106
+ }
107
+
108
+ function SheetDescription({
109
+ className,
110
+ ...props
111
+ }: React.ComponentProps<typeof SheetPrimitive.Description>) {
112
+ return (
113
+ <SheetPrimitive.Description
114
+ data-slot="sheet-description"
115
+ className={cn('text-muted-foreground text-sm', className)}
116
+ {...props}
117
+ />
118
+ )
119
+ }
120
+
121
+ export {
122
+ Sheet,
123
+ SheetTrigger,
124
+ SheetClose,
125
+ SheetContent,
126
+ SheetHeader,
127
+ SheetFooter,
128
+ SheetTitle,
129
+ SheetDescription,
130
+ }