@create-lft-app/nextjs 1.0.2 → 3.0.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 (81) hide show
  1. package/package.json +9 -3
  2. package/template/CLAUDE.md +279 -0
  3. package/template/drizzle.config.ts +12 -0
  4. package/template/package.json +31 -6
  5. package/template/proxy.ts +12 -0
  6. package/template/src/app/(auth)/dashboard/dashboard-content.tsx +124 -0
  7. package/template/src/app/(auth)/dashboard/page.tsx +9 -0
  8. package/template/src/app/(auth)/layout.tsx +7 -0
  9. package/template/src/app/(auth)/users/page.tsx +9 -0
  10. package/template/src/app/(auth)/users/users-content.tsx +26 -0
  11. package/template/src/app/(public)/layout.tsx +7 -0
  12. package/template/src/app/(public)/login/page.tsx +17 -0
  13. package/template/src/app/api/webhooks/route.ts +20 -0
  14. package/template/src/app/layout.tsx +13 -12
  15. package/template/src/app/providers.tsx +27 -0
  16. package/template/src/components/layout/{midday-sidebar.tsx → sidebar.tsx} +2 -7
  17. package/template/src/components/tables/data-table-column-header.tsx +68 -0
  18. package/template/src/components/tables/data-table-pagination.tsx +99 -0
  19. package/template/src/components/tables/data-table-toolbar.tsx +50 -0
  20. package/template/src/components/tables/data-table-view-options.tsx +59 -0
  21. package/template/src/components/tables/data-table.tsx +128 -0
  22. package/template/src/components/tables/index.ts +5 -0
  23. package/template/src/components/ui/animations/index.ts +44 -0
  24. package/template/src/components/ui/button.tsx +50 -21
  25. package/template/src/components/ui/card.tsx +27 -3
  26. package/template/src/components/ui/dialog.tsx +38 -35
  27. package/template/src/components/ui/motion.tsx +197 -0
  28. package/template/src/components/ui/page-transition.tsx +166 -0
  29. package/template/src/components/ui/sheet.tsx +65 -41
  30. package/template/src/config/navigation.ts +69 -0
  31. package/template/src/config/site.ts +12 -0
  32. package/template/src/db/index.ts +12 -0
  33. package/template/src/db/schema/index.ts +1 -0
  34. package/template/src/db/schema/users.ts +16 -0
  35. package/template/src/db/seed.ts +39 -0
  36. package/template/src/hooks/index.ts +3 -0
  37. package/template/src/hooks/useDataTable.ts +82 -0
  38. package/template/src/hooks/useDebounce.ts +49 -0
  39. package/template/src/hooks/useMediaQuery.ts +36 -0
  40. package/template/src/lib/date/config.ts +34 -0
  41. package/template/src/lib/date/formatters.ts +120 -0
  42. package/template/src/lib/date/index.ts +19 -0
  43. package/template/src/lib/excel/exporter.ts +89 -0
  44. package/template/src/lib/excel/index.ts +14 -0
  45. package/template/src/lib/excel/parser.ts +96 -0
  46. package/template/src/lib/query-client.ts +35 -0
  47. package/template/src/lib/supabase/client.ts +5 -2
  48. package/template/src/lib/supabase/proxy.ts +67 -0
  49. package/template/src/lib/supabase/server.ts +6 -4
  50. package/template/src/lib/supabase/types.ts +53 -0
  51. package/template/src/lib/validations/common.ts +75 -0
  52. package/template/src/lib/validations/index.ts +20 -0
  53. package/template/src/modules/auth/actions/auth-actions.ts +51 -4
  54. package/template/src/modules/auth/components/login-form.tsx +68 -0
  55. package/template/src/modules/auth/hooks/useAuth.ts +38 -0
  56. package/template/src/modules/auth/hooks/useAuthMutations.ts +43 -0
  57. package/template/src/modules/auth/hooks/useAuthQueries.ts +43 -0
  58. package/template/src/modules/auth/index.ts +12 -0
  59. package/template/src/modules/auth/schemas/auth.schema.ts +32 -0
  60. package/template/src/modules/auth/stores/useAuthStore.ts +37 -0
  61. package/template/src/modules/users/actions/users-actions.ts +94 -0
  62. package/template/src/modules/users/columns.tsx +86 -0
  63. package/template/src/modules/users/components/users-list.tsx +22 -0
  64. package/template/src/modules/users/hooks/useUsers.ts +39 -0
  65. package/template/src/modules/users/hooks/useUsersMutations.ts +55 -0
  66. package/template/src/modules/users/hooks/useUsersQueries.ts +35 -0
  67. package/template/src/modules/users/index.ts +12 -0
  68. package/template/src/modules/users/schemas/users.schema.ts +23 -0
  69. package/template/src/modules/users/stores/useUsersStore.ts +60 -0
  70. package/template/src/stores/index.ts +1 -0
  71. package/template/src/stores/useUiStore.ts +55 -0
  72. package/template/src/types/api.ts +28 -0
  73. package/template/src/types/index.ts +2 -0
  74. package/template/src/types/table.ts +34 -0
  75. package/template/supabase/config.toml +94 -0
  76. package/template/tsconfig.json +2 -1
  77. package/template/tsconfig.tsbuildinfo +1 -0
  78. package/template/next-env.d.ts +0 -6
  79. package/template/package-lock.json +0 -8454
  80. package/template/src/app/dashboard/page.tsx +0 -111
  81. package/template/src/components/dashboard/widget.tsx +0 -113
@@ -0,0 +1,86 @@
1
+ 'use client'
2
+
3
+ import { ColumnDef } from '@tanstack/react-table'
4
+ import { MoreHorizontal } from 'lucide-react'
5
+ import { Button } from '@/components/ui/button'
6
+ import {
7
+ DropdownMenu,
8
+ DropdownMenuContent,
9
+ DropdownMenuItem,
10
+ DropdownMenuLabel,
11
+ DropdownMenuSeparator,
12
+ DropdownMenuTrigger,
13
+ } from '@/components/ui/dropdown-menu'
14
+ import { DataTableColumnHeader } from '@/components/tables/data-table-column-header'
15
+ import type { User } from './schemas/users.schema'
16
+
17
+ export const columns: ColumnDef<User>[] = [
18
+ {
19
+ accessorKey: 'name',
20
+ header: ({ column }) => (
21
+ <DataTableColumnHeader column={column} title="Nombre" />
22
+ ),
23
+ },
24
+ {
25
+ accessorKey: 'email',
26
+ header: ({ column }) => (
27
+ <DataTableColumnHeader column={column} title="Email" />
28
+ ),
29
+ },
30
+ {
31
+ accessorKey: 'role',
32
+ header: ({ column }) => (
33
+ <DataTableColumnHeader column={column} title="Rol" />
34
+ ),
35
+ cell: ({ row }) => {
36
+ const role = row.getValue('role') as string
37
+ const labels: Record<string, string> = {
38
+ admin: 'Administrador',
39
+ user: 'Usuario',
40
+ viewer: 'Visualizador',
41
+ }
42
+ return labels[role] ?? role
43
+ },
44
+ },
45
+ {
46
+ accessorKey: 'created_at',
47
+ header: ({ column }) => (
48
+ <DataTableColumnHeader column={column} title="Creado" />
49
+ ),
50
+ cell: ({ row }) => {
51
+ const date = new Date(row.getValue('created_at'))
52
+ return date.toLocaleDateString('es-ES')
53
+ },
54
+ },
55
+ {
56
+ id: 'actions',
57
+ cell: ({ row }) => {
58
+ const user = row.original
59
+
60
+ return (
61
+ <DropdownMenu>
62
+ <DropdownMenuTrigger asChild>
63
+ <Button variant="ghost" className="h-8 w-8 p-0">
64
+ <span className="sr-only">Abrir menú</span>
65
+ <MoreHorizontal className="h-4 w-4" />
66
+ </Button>
67
+ </DropdownMenuTrigger>
68
+ <DropdownMenuContent align="end">
69
+ <DropdownMenuLabel>Acciones</DropdownMenuLabel>
70
+ <DropdownMenuItem
71
+ onClick={() => navigator.clipboard.writeText(user.id)}
72
+ >
73
+ Copiar ID
74
+ </DropdownMenuItem>
75
+ <DropdownMenuSeparator />
76
+ <DropdownMenuItem>Ver detalles</DropdownMenuItem>
77
+ <DropdownMenuItem>Editar</DropdownMenuItem>
78
+ <DropdownMenuItem className="text-destructive">
79
+ Eliminar
80
+ </DropdownMenuItem>
81
+ </DropdownMenuContent>
82
+ </DropdownMenu>
83
+ )
84
+ },
85
+ },
86
+ ]
@@ -0,0 +1,22 @@
1
+ 'use client'
2
+
3
+ import { DataTable } from '@/components/tables/data-table'
4
+ import { useUsers } from '../hooks/useUsers'
5
+ import { columns } from '../columns'
6
+
7
+ export function UsersList() {
8
+ const { users, isLoading } = useUsers()
9
+
10
+ if (isLoading) {
11
+ return <div>Cargando usuarios...</div>
12
+ }
13
+
14
+ return (
15
+ <DataTable
16
+ columns={columns}
17
+ data={users}
18
+ searchKey="name"
19
+ searchPlaceholder="Buscar por nombre..."
20
+ />
21
+ )
22
+ }
@@ -0,0 +1,39 @@
1
+ 'use client'
2
+
3
+ import { useShallow } from 'zustand/react/shallow'
4
+ import { useUsersStore } from '../stores/useUsersStore'
5
+ import { useUsersQueries } from './useUsersQueries'
6
+ import { useUsersMutations } from './useUsersMutations'
7
+
8
+ /**
9
+ * Hook unificado para usuarios.
10
+ * Los componentes SOLO deben importar este hook, nunca useUsersQueries o useUsersMutations directamente.
11
+ */
12
+ export function useUsers() {
13
+ const state = useUsersStore(useShallow((s) => s.state))
14
+ const actions = useUsersStore(useShallow((s) => s.actions))
15
+
16
+ const queries = useUsersQueries(state.selectedUserId ?? undefined)
17
+ const mutations = useUsersMutations()
18
+
19
+ return {
20
+ // State from store (UI state)
21
+ ...state,
22
+ ...actions,
23
+
24
+ // Queries
25
+ users: queries.users,
26
+ user: queries.user,
27
+ isLoading: queries.isLoading,
28
+ isLoadingUser: queries.isLoadingUser,
29
+ error: queries.error,
30
+
31
+ // Mutations
32
+ createUser: mutations.create,
33
+ updateUser: mutations.update,
34
+ deleteUser: mutations.delete,
35
+ isCreating: mutations.isCreating,
36
+ isUpdating: mutations.isUpdating,
37
+ isDeleting: mutations.isDeleting,
38
+ }
39
+ }
@@ -0,0 +1,55 @@
1
+ 'use client'
2
+
3
+ import { useMutation, useQueryClient } from '@tanstack/react-query'
4
+ import { toast } from 'sonner'
5
+ import { createUser, updateUser, deleteUser } from '../actions/users-actions'
6
+ import { usersKeys } from './useUsersQueries'
7
+ import type { CreateUserInput, UpdateUserInput } from '../schemas/users.schema'
8
+
9
+ export function useUsersMutations() {
10
+ const queryClient = useQueryClient()
11
+
12
+ const createMutation = useMutation({
13
+ mutationFn: (input: CreateUserInput) => createUser(input),
14
+ onSuccess: () => {
15
+ queryClient.invalidateQueries({ queryKey: usersKeys.lists() })
16
+ toast.success('Usuario creado correctamente')
17
+ },
18
+ onError: (error) => {
19
+ toast.error(error.message)
20
+ },
21
+ })
22
+
23
+ const updateMutation = useMutation({
24
+ mutationFn: ({ id, input }: { id: string; input: UpdateUserInput }) =>
25
+ updateUser(id, input),
26
+ onSuccess: (_, { id }) => {
27
+ queryClient.invalidateQueries({ queryKey: usersKeys.lists() })
28
+ queryClient.invalidateQueries({ queryKey: usersKeys.detail(id) })
29
+ toast.success('Usuario actualizado correctamente')
30
+ },
31
+ onError: (error) => {
32
+ toast.error(error.message)
33
+ },
34
+ })
35
+
36
+ const deleteMutation = useMutation({
37
+ mutationFn: (id: string) => deleteUser(id),
38
+ onSuccess: () => {
39
+ queryClient.invalidateQueries({ queryKey: usersKeys.lists() })
40
+ toast.success('Usuario eliminado correctamente')
41
+ },
42
+ onError: (error) => {
43
+ toast.error(error.message)
44
+ },
45
+ })
46
+
47
+ return {
48
+ create: createMutation.mutateAsync,
49
+ update: updateMutation.mutateAsync,
50
+ delete: deleteMutation.mutateAsync,
51
+ isCreating: createMutation.isPending,
52
+ isUpdating: updateMutation.isPending,
53
+ isDeleting: deleteMutation.isPending,
54
+ }
55
+ }
@@ -0,0 +1,35 @@
1
+ 'use client'
2
+
3
+ import { useQuery } from '@tanstack/react-query'
4
+ import { getUsers, getUserById } from '../actions/users-actions'
5
+
6
+ export const usersKeys = {
7
+ all: ['users'] as const,
8
+ lists: () => [...usersKeys.all, 'list'] as const,
9
+ list: (filters: Record<string, unknown>) => [...usersKeys.lists(), filters] as const,
10
+ details: () => [...usersKeys.all, 'detail'] as const,
11
+ detail: (id: string) => [...usersKeys.details(), id] as const,
12
+ }
13
+
14
+ export function useUsersQueries(userId?: string) {
15
+ const usersQuery = useQuery({
16
+ queryKey: usersKeys.lists(),
17
+ queryFn: () => getUsers(),
18
+ })
19
+
20
+ const userQuery = useQuery({
21
+ queryKey: usersKeys.detail(userId!),
22
+ queryFn: () => getUserById(userId!),
23
+ enabled: !!userId,
24
+ })
25
+
26
+ return {
27
+ users: usersQuery.data ?? [],
28
+ user: userQuery.data,
29
+ isLoading: usersQuery.isLoading,
30
+ isLoadingUser: userQuery.isLoading,
31
+ error: usersQuery.error,
32
+ usersQuery,
33
+ userQuery,
34
+ }
35
+ }
@@ -0,0 +1,12 @@
1
+ // Components
2
+ export { UsersList } from './components/users-list'
3
+
4
+ // Hooks - Solo exportar el hook unificado
5
+ export { useUsers } from './hooks/useUsers'
6
+
7
+ // Schemas
8
+ export { userSchema, createUserSchema, updateUserSchema } from './schemas/users.schema'
9
+ export type { User, CreateUserInput, UpdateUserInput } from './schemas/users.schema'
10
+
11
+ // Columns
12
+ export { columns as usersColumns } from './columns'
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod'
2
+
3
+ export const userSchema = z.object({
4
+ id: z.string().uuid(),
5
+ email: z.string().email(),
6
+ name: z.string().min(1, 'El nombre es requerido'),
7
+ role: z.enum(['admin', 'user', 'viewer']).default('user'),
8
+ avatar_url: z.string().url().nullable().optional(),
9
+ created_at: z.string().datetime(),
10
+ updated_at: z.string().datetime(),
11
+ })
12
+
13
+ export const createUserSchema = userSchema.omit({
14
+ id: true,
15
+ created_at: true,
16
+ updated_at: true,
17
+ })
18
+
19
+ export const updateUserSchema = createUserSchema.partial()
20
+
21
+ export type User = z.infer<typeof userSchema>
22
+ export type CreateUserInput = z.infer<typeof createUserSchema>
23
+ export type UpdateUserInput = z.infer<typeof updateUserSchema>
@@ -0,0 +1,60 @@
1
+ import { create } from 'zustand'
2
+
3
+ interface UsersState {
4
+ state: {
5
+ selectedUserId: string | null
6
+ isFormOpen: boolean
7
+ isDeleteDialogOpen: boolean
8
+ searchQuery: string
9
+ }
10
+ actions: {
11
+ setSelectedUserId: (id: string | null) => void
12
+ openForm: () => void
13
+ closeForm: () => void
14
+ openDeleteDialog: (id: string) => void
15
+ closeDeleteDialog: () => void
16
+ setSearchQuery: (query: string) => void
17
+ reset: () => void
18
+ }
19
+ }
20
+
21
+ const initialState = {
22
+ selectedUserId: null,
23
+ isFormOpen: false,
24
+ isDeleteDialogOpen: false,
25
+ searchQuery: '',
26
+ }
27
+
28
+ export const useUsersStore = create<UsersState>()((set) => ({
29
+ state: initialState,
30
+ actions: {
31
+ setSelectedUserId: (id) =>
32
+ set((state) => ({
33
+ state: { ...state.state, selectedUserId: id },
34
+ })),
35
+ openForm: () =>
36
+ set((state) => ({
37
+ state: { ...state.state, isFormOpen: true },
38
+ })),
39
+ closeForm: () =>
40
+ set((state) => ({
41
+ state: { ...state.state, isFormOpen: false, selectedUserId: null },
42
+ })),
43
+ openDeleteDialog: (id) =>
44
+ set((state) => ({
45
+ state: { ...state.state, isDeleteDialogOpen: true, selectedUserId: id },
46
+ })),
47
+ closeDeleteDialog: () =>
48
+ set((state) => ({
49
+ state: { ...state.state, isDeleteDialogOpen: false, selectedUserId: null },
50
+ })),
51
+ setSearchQuery: (query) =>
52
+ set((state) => ({
53
+ state: { ...state.state, searchQuery: query },
54
+ })),
55
+ reset: () =>
56
+ set(() => ({
57
+ state: initialState,
58
+ })),
59
+ },
60
+ }))
@@ -0,0 +1 @@
1
+ export { useUiStore } from './useUiStore'
@@ -0,0 +1,55 @@
1
+ import { create } from 'zustand'
2
+ import { persist } from 'zustand/middleware'
3
+
4
+ interface UiState {
5
+ state: {
6
+ sidebarOpen: boolean
7
+ sidebarCollapsed: boolean
8
+ theme: 'light' | 'dark' | 'system'
9
+ }
10
+ actions: {
11
+ toggleSidebar: () => void
12
+ setSidebarOpen: (open: boolean) => void
13
+ toggleSidebarCollapsed: () => void
14
+ setSidebarCollapsed: (collapsed: boolean) => void
15
+ setTheme: (theme: 'light' | 'dark' | 'system') => void
16
+ }
17
+ }
18
+
19
+ export const useUiStore = create<UiState>()(
20
+ persist(
21
+ (set) => ({
22
+ state: {
23
+ sidebarOpen: true,
24
+ sidebarCollapsed: false,
25
+ theme: 'system',
26
+ },
27
+ actions: {
28
+ toggleSidebar: () =>
29
+ set((state) => ({
30
+ state: { ...state.state, sidebarOpen: !state.state.sidebarOpen },
31
+ })),
32
+ setSidebarOpen: (open) =>
33
+ set((state) => ({
34
+ state: { ...state.state, sidebarOpen: open },
35
+ })),
36
+ toggleSidebarCollapsed: () =>
37
+ set((state) => ({
38
+ state: { ...state.state, sidebarCollapsed: !state.state.sidebarCollapsed },
39
+ })),
40
+ setSidebarCollapsed: (collapsed) =>
41
+ set((state) => ({
42
+ state: { ...state.state, sidebarCollapsed: collapsed },
43
+ })),
44
+ setTheme: (theme) =>
45
+ set((state) => ({
46
+ state: { ...state.state, theme },
47
+ })),
48
+ },
49
+ }),
50
+ {
51
+ name: 'ui-storage',
52
+ partialize: (state) => ({ state: state.state }),
53
+ }
54
+ )
55
+ )
@@ -0,0 +1,28 @@
1
+ export interface ApiResponse<T = unknown> {
2
+ data: T
3
+ success: boolean
4
+ message?: string
5
+ }
6
+
7
+ export interface ApiError {
8
+ message: string
9
+ code?: string
10
+ status?: number
11
+ details?: Record<string, unknown>
12
+ }
13
+
14
+ export interface PaginatedResponse<T> {
15
+ data: T[]
16
+ pagination: {
17
+ page: number
18
+ pageSize: number
19
+ total: number
20
+ totalPages: number
21
+ }
22
+ }
23
+
24
+ export interface ActionResult<T = void> {
25
+ success: boolean
26
+ data?: T
27
+ error?: string
28
+ }
@@ -0,0 +1,2 @@
1
+ export * from './api'
2
+ export * from './table'
@@ -0,0 +1,34 @@
1
+ import type { ColumnDef, Table, Row } from '@tanstack/react-table'
2
+
3
+ export type DataTableColumn<TData, TValue = unknown> = ColumnDef<TData, TValue>
4
+
5
+ export interface DataTableProps<TData, TValue> {
6
+ columns: DataTableColumn<TData, TValue>[]
7
+ data: TData[]
8
+ searchKey?: string
9
+ searchPlaceholder?: string
10
+ }
11
+
12
+ export interface DataTablePaginationProps<TData> {
13
+ table: Table<TData>
14
+ }
15
+
16
+ export interface DataTableToolbarProps<TData> {
17
+ table: Table<TData>
18
+ searchKey?: string
19
+ searchPlaceholder?: string
20
+ }
21
+
22
+ export interface DataTableRowActionsProps<TData> {
23
+ row: Row<TData>
24
+ }
25
+
26
+ export interface DataTableFacetedFilterProps<TData, TValue> {
27
+ column?: import('@tanstack/react-table').Column<TData, TValue>
28
+ title?: string
29
+ options: {
30
+ label: string
31
+ value: string
32
+ icon?: React.ComponentType<{ className?: string }>
33
+ }[]
34
+ }
@@ -0,0 +1,94 @@
1
+ # A string used to distinguish different Supabase projects on the same host. Defaults to the
2
+ # working directory name when running `supabase init`.
3
+ project_id = "lft-app"
4
+
5
+ [api]
6
+ enabled = true
7
+ # Port to use for the API URL.
8
+ port = 54321
9
+ # Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
10
+ # endpoints. public and storage are always included.
11
+ schemas = ["public", "storage", "graphql_public"]
12
+ # Extra schemas to add to the search_path of every request. public is always included.
13
+ extra_search_path = ["public", "extensions"]
14
+ # The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
15
+ # for accidental or malicious requests.
16
+ max_rows = 1000
17
+
18
+ [db]
19
+ # Port to use for the local database URL.
20
+ port = 54322
21
+ # Port used by db diff command to initialise the shadow database.
22
+ shadow_port = 54320
23
+ # The database major version to use. This has to be the same as your remote database's. Run `SHOW
24
+ # server_version;` on the remote database to check.
25
+ major_version = 15
26
+
27
+ [studio]
28
+ enabled = true
29
+ # Port to use for Supabase Studio.
30
+ port = 54323
31
+ # External URL of the API server that frontend connects to.
32
+ api_url = "http://localhost"
33
+
34
+ # Email testing server. Emails sent with the local dev setup are not actually sent - rather, they
35
+ # are monitored, and you can view the emails that would have been sent from the web interface.
36
+ [inbucket]
37
+ enabled = true
38
+ # Port to use for the email testing server web interface.
39
+ port = 54324
40
+ # Uncomment to expose additional ports for testing user applications that send emails.
41
+ # smtp_port = 54325
42
+ # pop3_port = 54326
43
+
44
+ [storage]
45
+ enabled = true
46
+ # The maximum file size allowed (e.g. "5MB", "500KB").
47
+ file_size_limit = "50MiB"
48
+
49
+ [auth]
50
+ enabled = true
51
+ # The base URL of your website. Used as an allow-list for redirects and for constructing URLs used
52
+ # in emails.
53
+ site_url = "http://localhost:3000"
54
+ # A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
55
+ additional_redirect_urls = ["https://localhost:3000"]
56
+ # How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week).
57
+ jwt_expiry = 3600
58
+ # If disabled, the refresh token will never expire.
59
+ enable_refresh_token_rotation = true
60
+ # Allows refresh tokens to be reused after expiry, up to the specified interval in seconds.
61
+ # Requires enable_refresh_token_rotation = true.
62
+ refresh_token_reuse_interval = 10
63
+ # Allow/disallow new user signups to your project.
64
+ enable_signup = true
65
+
66
+ [auth.email]
67
+ # Allow/disallow new user signups via email to your project.
68
+ enable_signup = true
69
+ # If enabled, a user will be required to confirm any email change on both the old, and new email
70
+ # addresses. If disabled, only the new email is required to confirm.
71
+ double_confirm_changes = true
72
+ # If enabled, users need to confirm their email address before signing in.
73
+ enable_confirmations = false
74
+
75
+ [auth.sms]
76
+ # Allow/disallow new user signups via SMS to your project.
77
+ enable_signup = true
78
+ # If enabled, users need to confirm their phone number before signing in.
79
+ enable_confirmations = false
80
+
81
+ # Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`.
82
+ [auth.sms.twilio]
83
+ enabled = false
84
+ account_sid = ""
85
+ message_service_sid = ""
86
+ # DO NOT commit your Twilio auth token to git. Use environment variable substitution instead:
87
+ auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)"
88
+
89
+ [analytics]
90
+ enabled = false
91
+ port = 54327
92
+ vector_port = 54328
93
+ # Configure one of the supported backends: `postgres`, `bigquery`.
94
+ backend = "postgres"
@@ -36,6 +36,7 @@
36
36
  ".next/dev/types/**/*.ts"
37
37
  ],
38
38
  "exclude": [
39
- "node_modules"
39
+ "node_modules",
40
+ "supabase/functions"
40
41
  ]
41
42
  }