@ardly/bunext 1.0.6 → 1.0.7
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.
- package/LICENSE +21 -0
- package/README.md +33 -16
- package/cli.mjs +126 -0
- package/package.json +14 -58
- package/.eslintrc.json +0 -8
- package/.prettierignore +0 -4
- package/STRUCTURE.md +0 -77
- package/bin/cli.mjs +0 -126
- package/components.json +0 -21
- package/next.config.ts +0 -22
- package/postcss.config.mjs +0 -8
- package/prettier.config.js +0 -7
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/favicon.svg +0 -1
- package/public/loading-dots.gif +0 -0
- package/public/logo.svg +0 -1
- package/public/ogImage.webp +0 -0
- package/public/site.webmanifest +0 -19
- package/src/actions/placeholder.ts +0 -30
- package/src/actions/sampleAction.ts +0 -39
- package/src/app/(index)/intr/TestCard.tsx +0 -31
- package/src/app/(index)/intr/page.tsx +0 -17
- package/src/app/(index)/page.tsx +0 -156
- package/src/app/(index)/pagetr/page.tsx +0 -37
- package/src/app/error-wrapper.tsx +0 -32
- package/src/app/global-error.tsx +0 -53
- package/src/app/layout.tsx +0 -56
- package/src/app/loading.tsx +0 -11
- package/src/app/not-found.tsx +0 -45
- package/src/app/sitemap.ts +0 -14
- package/src/components/Providers/root-provider.tsx +0 -22
- package/src/components/Providers/theme-provider.tsx +0 -27
- package/src/components/TestComp.tsx +0 -11
- package/src/components/brand.tsx +0 -35
- package/src/components/navigation/footer.tsx +0 -32
- package/src/components/navigation/main-nav.tsx +0 -55
- package/src/components/navigation/mobile-nav.tsx +0 -154
- package/src/components/navigation/site-header.tsx +0 -67
- package/src/components/ui/avatar.tsx +0 -50
- package/src/components/ui/badge.tsx +0 -36
- package/src/components/ui/button.tsx +0 -56
- package/src/components/ui/card.tsx +0 -79
- package/src/components/ui/command.tsx +0 -153
- package/src/components/ui/dialog.tsx +0 -122
- package/src/components/ui/drawer.tsx +0 -118
- package/src/components/ui/dropdown-menu.tsx +0 -200
- package/src/components/ui/input.tsx +0 -22
- package/src/components/ui/label.tsx +0 -26
- package/src/components/ui/multi-select.tsx +0 -380
- package/src/components/ui/origin/multiselect.tsx +0 -645
- package/src/components/ui/popover.tsx +0 -31
- package/src/components/ui/radio-group.tsx +0 -44
- package/src/components/ui/separator.tsx +0 -31
- package/src/components/ui/skeleton.tsx +0 -15
- package/src/components/ui/themeSelector.tsx +0 -157
- package/src/components/ui/toast.tsx +0 -129
- package/src/components/ui/toaster.tsx +0 -31
- package/src/components/ui/tooltip.tsx +0 -39
- package/src/components/utils/ConditionalLink.tsx +0 -46
- package/src/components/utils/Image.tsx +0 -57
- package/src/components/utils/Img.tsx +0 -104
- package/src/components/utils/Spinner.tsx +0 -29
- package/src/components/utils/TopButton.tsx +0 -67
- package/src/components/utils/TransitionLink.tsx +0 -67
- package/src/components/utils/copy.tsx +0 -98
- package/src/components/utils/featureFlag.tsx +0 -22
- package/src/components/utils/icons.tsx +0 -155
- package/src/components/utils/share-modal.tsx +0 -159
- package/src/hooks/use-intersection.ts +0 -52
- package/src/hooks/use-lazy-load.ts +0 -33
- package/src/hooks/use-meta-color.ts +0 -25
- package/src/hooks/use-toast.ts +0 -191
- package/src/lib/config/featureflags.ts +0 -63
- package/src/lib/config/siteConfig.ts +0 -172
- package/src/lib/config/user.ts +0 -9
- package/src/lib/data/footer-data.ts +0 -85
- package/src/lib/data/nav-data.ts +0 -30
- package/src/lib/data/siteData.ts +0 -52
- package/src/lib/utils/index.ts +0 -190
- package/src/styles/customGlobal.css +0 -141
- package/src/styles/globals.css +0 -72
- package/src/styles/tailwind/base.ts +0 -46
- package/src/styles/tailwind/fonts/ClashDisplay-Bold.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Bold.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Bold.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Bold.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Extralight.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Extralight.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Extralight.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Extralight.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Light.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Light.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Light.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Light.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Medium.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Medium.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Medium.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Medium.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Regular.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Regular.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Regular.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Regular.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Semibold.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Semibold.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Semibold.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Semibold.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Variable.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Variable.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Variable.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Variable.woff2 +0 -0
- package/src/styles/tailwind/fonts/GeistMonoVF.woff +0 -0
- package/src/styles/tailwind/fonts/GeistVF.woff +0 -0
- package/src/styles/tailwind/fonts.ts +0 -51
- package/src/styles/tailwind/tailwindUtils.ts +0 -29
- package/src/types/index.ts +0 -80
- package/tailwind.config.ts +0 -104
- package/tsconfig.json +0 -28
- package/vercel.json +0 -6
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { useTheme } from 'next-themes'
|
|
2
|
-
import * as React from 'react'
|
|
3
|
-
|
|
4
|
-
import { siteData } from '@/lib/data/siteData'
|
|
5
|
-
const META_THEME_COLORS = siteData.metadata_color
|
|
6
|
-
export function useMetaColor() {
|
|
7
|
-
const { resolvedTheme } = useTheme()
|
|
8
|
-
|
|
9
|
-
const metaColor = React.useMemo(() => {
|
|
10
|
-
return resolvedTheme !== 'dark'
|
|
11
|
-
? META_THEME_COLORS.light
|
|
12
|
-
: META_THEME_COLORS.dark
|
|
13
|
-
}, [resolvedTheme])
|
|
14
|
-
|
|
15
|
-
const setMetaColor = React.useCallback((color: string) => {
|
|
16
|
-
document
|
|
17
|
-
.querySelector('meta[name="theme-color"]')
|
|
18
|
-
?.setAttribute('content', color)
|
|
19
|
-
}, [])
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
metaColor,
|
|
23
|
-
setMetaColor,
|
|
24
|
-
}
|
|
25
|
-
}
|
package/src/hooks/use-toast.ts
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
// Inspired by react-hot-toast library
|
|
4
|
-
import * as React from 'react'
|
|
5
|
-
|
|
6
|
-
import type { ToastActionElement, ToastProps } from '@/components/ui/toast'
|
|
7
|
-
|
|
8
|
-
const TOAST_LIMIT = 1
|
|
9
|
-
const TOAST_REMOVE_DELAY = 1000000
|
|
10
|
-
|
|
11
|
-
type ToasterToast = ToastProps & {
|
|
12
|
-
id: string
|
|
13
|
-
title?: React.ReactNode
|
|
14
|
-
description?: React.ReactNode
|
|
15
|
-
action?: ToastActionElement
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const actionTypes = {
|
|
19
|
-
ADD_TOAST: 'ADD_TOAST',
|
|
20
|
-
UPDATE_TOAST: 'UPDATE_TOAST',
|
|
21
|
-
DISMISS_TOAST: 'DISMISS_TOAST',
|
|
22
|
-
REMOVE_TOAST: 'REMOVE_TOAST',
|
|
23
|
-
} as const
|
|
24
|
-
|
|
25
|
-
let count = 0
|
|
26
|
-
|
|
27
|
-
function genId() {
|
|
28
|
-
count = (count + 1) % Number.MAX_SAFE_INTEGER
|
|
29
|
-
return count.toString()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
type ActionType = typeof actionTypes
|
|
33
|
-
|
|
34
|
-
type Action =
|
|
35
|
-
| {
|
|
36
|
-
type: ActionType['ADD_TOAST']
|
|
37
|
-
toast: ToasterToast
|
|
38
|
-
}
|
|
39
|
-
| {
|
|
40
|
-
type: ActionType['UPDATE_TOAST']
|
|
41
|
-
toast: Partial<ToasterToast>
|
|
42
|
-
}
|
|
43
|
-
| {
|
|
44
|
-
type: ActionType['DISMISS_TOAST']
|
|
45
|
-
toastId?: ToasterToast['id']
|
|
46
|
-
}
|
|
47
|
-
| {
|
|
48
|
-
type: ActionType['REMOVE_TOAST']
|
|
49
|
-
toastId?: ToasterToast['id']
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
interface State {
|
|
53
|
-
toasts: ToasterToast[]
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
|
|
57
|
-
|
|
58
|
-
const addToRemoveQueue = (toastId: string) => {
|
|
59
|
-
if (toastTimeouts.has(toastId)) {
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const timeout = setTimeout(() => {
|
|
64
|
-
toastTimeouts.delete(toastId)
|
|
65
|
-
dispatch({
|
|
66
|
-
type: 'REMOVE_TOAST',
|
|
67
|
-
toastId: toastId,
|
|
68
|
-
})
|
|
69
|
-
}, TOAST_REMOVE_DELAY)
|
|
70
|
-
|
|
71
|
-
toastTimeouts.set(toastId, timeout)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export const reducer = (state: State, action: Action): State => {
|
|
75
|
-
switch (action.type) {
|
|
76
|
-
case 'ADD_TOAST':
|
|
77
|
-
return {
|
|
78
|
-
...state,
|
|
79
|
-
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
case 'UPDATE_TOAST':
|
|
83
|
-
return {
|
|
84
|
-
...state,
|
|
85
|
-
toasts: state.toasts.map((t) =>
|
|
86
|
-
t.id === action.toast.id ? { ...t, ...action.toast } : t
|
|
87
|
-
),
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
case 'DISMISS_TOAST': {
|
|
91
|
-
const { toastId } = action
|
|
92
|
-
|
|
93
|
-
// ! Side effects ! - This could be extracted into a dismissToast() action,
|
|
94
|
-
// but I'll keep it here for simplicity
|
|
95
|
-
if (toastId) {
|
|
96
|
-
addToRemoveQueue(toastId)
|
|
97
|
-
} else {
|
|
98
|
-
state.toasts.forEach((toast) => {
|
|
99
|
-
addToRemoveQueue(toast.id)
|
|
100
|
-
})
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
...state,
|
|
105
|
-
toasts: state.toasts.map((t) =>
|
|
106
|
-
t.id === toastId || toastId === undefined
|
|
107
|
-
? {
|
|
108
|
-
...t,
|
|
109
|
-
open: false,
|
|
110
|
-
}
|
|
111
|
-
: t
|
|
112
|
-
),
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
case 'REMOVE_TOAST':
|
|
116
|
-
if (action.toastId === undefined) {
|
|
117
|
-
return {
|
|
118
|
-
...state,
|
|
119
|
-
toasts: [],
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return {
|
|
123
|
-
...state,
|
|
124
|
-
toasts: state.toasts.filter((t) => t.id !== action.toastId),
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const listeners: Array<(state: State) => void> = []
|
|
130
|
-
|
|
131
|
-
let memoryState: State = { toasts: [] }
|
|
132
|
-
|
|
133
|
-
function dispatch(action: Action) {
|
|
134
|
-
memoryState = reducer(memoryState, action)
|
|
135
|
-
listeners.forEach((listener) => {
|
|
136
|
-
listener(memoryState)
|
|
137
|
-
})
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
type Toast = Omit<ToasterToast, 'id'>
|
|
141
|
-
|
|
142
|
-
function toast({ ...props }: Toast) {
|
|
143
|
-
const id = genId()
|
|
144
|
-
|
|
145
|
-
const update = (props: ToasterToast) =>
|
|
146
|
-
dispatch({
|
|
147
|
-
type: 'UPDATE_TOAST',
|
|
148
|
-
toast: { ...props, id },
|
|
149
|
-
})
|
|
150
|
-
const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id })
|
|
151
|
-
|
|
152
|
-
dispatch({
|
|
153
|
-
type: 'ADD_TOAST',
|
|
154
|
-
toast: {
|
|
155
|
-
...props,
|
|
156
|
-
id,
|
|
157
|
-
open: true,
|
|
158
|
-
onOpenChange: (open) => {
|
|
159
|
-
if (!open) dismiss()
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
id: id,
|
|
166
|
-
dismiss,
|
|
167
|
-
update,
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function useToast() {
|
|
172
|
-
const [state, setState] = React.useState<State>(memoryState)
|
|
173
|
-
|
|
174
|
-
React.useEffect(() => {
|
|
175
|
-
listeners.push(setState)
|
|
176
|
-
return () => {
|
|
177
|
-
const index = listeners.indexOf(setState)
|
|
178
|
-
if (index > -1) {
|
|
179
|
-
listeners.splice(index, 1)
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}, [state])
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
...state,
|
|
186
|
-
toast,
|
|
187
|
-
dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }),
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export { useToast, toast }
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { murmurhash } from '@/lib/utils'
|
|
2
|
-
import type { User, UserRole } from '@/lib/config/user'
|
|
3
|
-
|
|
4
|
-
export type FeatureFlagName = keyof typeof FEATURE_FLAGS
|
|
5
|
-
// type for multiple allowances
|
|
6
|
-
type FeatureFlagRule = {
|
|
7
|
-
percentageOfUsers?: number
|
|
8
|
-
userRoles?: UserRole[]
|
|
9
|
-
} & (
|
|
10
|
-
| {
|
|
11
|
-
percentageOfUsers: number
|
|
12
|
-
}
|
|
13
|
-
| { userRoles: UserRole[] }
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
export const FEATURE_FLAGS = {
|
|
17
|
-
NEXT_THEME: true,
|
|
18
|
-
THEME_BUTTON: true, //flase will remove the theme selector button thus not allowing the user to change the theme
|
|
19
|
-
DEFAULT_THEME: 'system', // "system | dark | light" only works if NEXT_THEME is true
|
|
20
|
-
|
|
21
|
-
// example of multiple allowances
|
|
22
|
-
// 25% of users can see this feature
|
|
23
|
-
SAMPLE_MULTIPLE_ALLOWANCES: [
|
|
24
|
-
{ percentageOfUsers: 0.25, userRoles: ['user'] },
|
|
25
|
-
{ userRoles: ['admin', 'tester'] },
|
|
26
|
-
],
|
|
27
|
-
} as const satisfies Record<string, FeatureFlagRule[] | boolean | string>
|
|
28
|
-
|
|
29
|
-
export function canViewFeature(featureName: FeatureFlagName, user: User) {
|
|
30
|
-
const rules = FEATURE_FLAGS[featureName]
|
|
31
|
-
if (typeof rules === 'boolean') return rules
|
|
32
|
-
if (typeof rules === 'string') return rules
|
|
33
|
-
return rules.some((rule) => checkRule(rule, featureName, user))
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function checkRule(
|
|
37
|
-
{ userRoles, percentageOfUsers }: FeatureFlagRule,
|
|
38
|
-
featureName: FeatureFlagName,
|
|
39
|
-
user: User
|
|
40
|
-
) {
|
|
41
|
-
return (
|
|
42
|
-
userHasValidRole(userRoles, user.role) &&
|
|
43
|
-
userIsWithinPercentage(featureName, percentageOfUsers, user.id)
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function userHasValidRole(
|
|
48
|
-
allowedRoles: UserRole[] | undefined,
|
|
49
|
-
userRole: UserRole
|
|
50
|
-
) {
|
|
51
|
-
return allowedRoles == null || allowedRoles.includes(userRole)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const MAX_UINT_32 = 4294967295
|
|
55
|
-
function userIsWithinPercentage(
|
|
56
|
-
featureName: FeatureFlagName,
|
|
57
|
-
allowedPercent: number | undefined,
|
|
58
|
-
flagId: string
|
|
59
|
-
) {
|
|
60
|
-
if (allowedPercent == null) return true
|
|
61
|
-
|
|
62
|
-
return murmurhash(`${featureName}-${flagId}`) / MAX_UINT_32 < allowedPercent
|
|
63
|
-
}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import type { Metadata, Viewport } from 'next'
|
|
2
|
-
import type { StaticImageData } from 'next/image'
|
|
3
|
-
|
|
4
|
-
import { icons, siteData, twitterMetaData as twData } from '@/lib/data/siteData'
|
|
5
|
-
import packageJson from '../../../package.json'
|
|
6
|
-
|
|
7
|
-
// gets the full remote url
|
|
8
|
-
export const remoteUrl = siteData.baseUrl?.startsWith('https://')
|
|
9
|
-
? siteData.baseUrl
|
|
10
|
-
: `https://${siteData.baseUrl?.toLowerCase()}`
|
|
11
|
-
|
|
12
|
-
export const viewportData: Viewport = {
|
|
13
|
-
themeColor: [
|
|
14
|
-
{
|
|
15
|
-
media: '(prefers-color-scheme: light)',
|
|
16
|
-
color: siteData.metadata_color.light,
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
media: '(prefers-color-scheme: dark)',
|
|
20
|
-
color: siteData.metadata_color.dark,
|
|
21
|
-
},
|
|
22
|
-
],
|
|
23
|
-
}
|
|
24
|
-
// Metadata
|
|
25
|
-
|
|
26
|
-
export const siteMetaData: Metadata = {
|
|
27
|
-
// title: {
|
|
28
|
-
// default: siteData.name,
|
|
29
|
-
// template: `%s / ${siteData.name}`,
|
|
30
|
-
// },
|
|
31
|
-
title: siteData.name,
|
|
32
|
-
description: siteData.description,
|
|
33
|
-
robots: siteData.robotsDefault, // { index: false, follow: false }
|
|
34
|
-
publisher: siteData.publisher,
|
|
35
|
-
metadataBase: new URL(remoteUrl),
|
|
36
|
-
keywords: siteData.keywords,
|
|
37
|
-
authors: [
|
|
38
|
-
{
|
|
39
|
-
name: siteData.author.name,
|
|
40
|
-
url: siteData.author.url,
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
creator: siteData.author.name,
|
|
44
|
-
// og metadata
|
|
45
|
-
openGraph: {
|
|
46
|
-
type: 'website',
|
|
47
|
-
locale: 'en_US',
|
|
48
|
-
url: remoteUrl,
|
|
49
|
-
siteName: siteData.baseUrl,
|
|
50
|
-
title: siteData.name,
|
|
51
|
-
description: siteData.description,
|
|
52
|
-
images: [
|
|
53
|
-
{
|
|
54
|
-
url: siteData.ogImage.src,
|
|
55
|
-
width: siteData.ogImage.width,
|
|
56
|
-
height: siteData.ogImage.height,
|
|
57
|
-
alt: siteData.ogImage.alt,
|
|
58
|
-
},
|
|
59
|
-
],
|
|
60
|
-
},
|
|
61
|
-
// twitter metadata
|
|
62
|
-
twitter: {
|
|
63
|
-
card: 'summary_large_image',
|
|
64
|
-
title: twData.title,
|
|
65
|
-
description: twData.description,
|
|
66
|
-
site: `@${siteData.publisher}`,
|
|
67
|
-
images: [twData.images],
|
|
68
|
-
creator: twData.creator,
|
|
69
|
-
},
|
|
70
|
-
alternates: {
|
|
71
|
-
canonical: remoteUrl,
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
icons: icons,
|
|
75
|
-
manifest: `${remoteUrl}/site.webmanifest`,
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
type TAuthor = {
|
|
79
|
-
name: string
|
|
80
|
-
url: string
|
|
81
|
-
}
|
|
82
|
-
type TgetCustomMetaData = {
|
|
83
|
-
title: string
|
|
84
|
-
description?: string
|
|
85
|
-
publisher?: string
|
|
86
|
-
url?: string
|
|
87
|
-
keywords?: string[]
|
|
88
|
-
authors?: TAuthor[]
|
|
89
|
-
creator?: string
|
|
90
|
-
twCreator?: string
|
|
91
|
-
titleSuffix?: boolean
|
|
92
|
-
shortSuffix?: boolean
|
|
93
|
-
ogTitleSuffix?: boolean
|
|
94
|
-
longogTitleSuffix?: boolean
|
|
95
|
-
ogImage?: string | StaticImageData
|
|
96
|
-
robots?: 'index, follow' | 'noindex, nofollow'
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// helpful for defining custom metadata for pages without clutter
|
|
100
|
-
export function getCustomMetaData({
|
|
101
|
-
title,
|
|
102
|
-
description,
|
|
103
|
-
publisher,
|
|
104
|
-
url,
|
|
105
|
-
keywords,
|
|
106
|
-
authors,
|
|
107
|
-
creator,
|
|
108
|
-
twCreator,
|
|
109
|
-
titleSuffix = true,
|
|
110
|
-
shortSuffix,
|
|
111
|
-
ogTitleSuffix = true,
|
|
112
|
-
longogTitleSuffix,
|
|
113
|
-
ogImage,
|
|
114
|
-
robots = 'index, follow',
|
|
115
|
-
}: TgetCustomMetaData) {
|
|
116
|
-
const suffix = shortSuffix ? siteData.shortName : siteData.name
|
|
117
|
-
const customTitle = titleSuffix ? `${title} / ${suffix}` : title
|
|
118
|
-
|
|
119
|
-
const ogSuffix = longogTitleSuffix ? siteData.name : siteData.shortName
|
|
120
|
-
const ogTitle = ogTitleSuffix ? `${title} / ${ogSuffix}` : title
|
|
121
|
-
|
|
122
|
-
const md: Metadata = {
|
|
123
|
-
title: customTitle,
|
|
124
|
-
description: description || siteData.description,
|
|
125
|
-
|
|
126
|
-
robots: robots || siteData.robotsDefault, // { index: false, follow: false }
|
|
127
|
-
publisher: publisher || siteData.publisher,
|
|
128
|
-
metadataBase: new URL(url || remoteUrl),
|
|
129
|
-
keywords: keywords || siteData.keywords,
|
|
130
|
-
authors: authors || [
|
|
131
|
-
{
|
|
132
|
-
name: siteData.author.name,
|
|
133
|
-
url: siteData.author.url,
|
|
134
|
-
},
|
|
135
|
-
],
|
|
136
|
-
creator: creator || siteData.author.name,
|
|
137
|
-
// og metadata
|
|
138
|
-
openGraph: {
|
|
139
|
-
type: 'website',
|
|
140
|
-
locale: 'en_US',
|
|
141
|
-
url: url || remoteUrl,
|
|
142
|
-
siteName: siteData.baseUrl,
|
|
143
|
-
title: ogTitle,
|
|
144
|
-
description: description || siteData.description,
|
|
145
|
-
images: {
|
|
146
|
-
url:
|
|
147
|
-
typeof ogImage === 'string'
|
|
148
|
-
? ogImage
|
|
149
|
-
: ogImage?.src || siteData.ogImage.src,
|
|
150
|
-
width: siteData.ogImage.width,
|
|
151
|
-
height: siteData.ogImage.height,
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
twitter: {
|
|
155
|
-
card: 'summary_large_image',
|
|
156
|
-
title: twData.title,
|
|
157
|
-
description: twData.description,
|
|
158
|
-
site: `@${publisher || siteData.publisher}`,
|
|
159
|
-
images:
|
|
160
|
-
typeof ogImage === 'string'
|
|
161
|
-
? ogImage
|
|
162
|
-
: ogImage?.src || siteData.ogImage.src,
|
|
163
|
-
creator: twCreator || twData.creator,
|
|
164
|
-
},
|
|
165
|
-
alternates: {
|
|
166
|
-
canonical: remoteUrl,
|
|
167
|
-
},
|
|
168
|
-
icons: icons,
|
|
169
|
-
manifest: `${remoteUrl}/site.webmanifest`,
|
|
170
|
-
}
|
|
171
|
-
return md
|
|
172
|
-
}
|
package/src/lib/config/user.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { Icons } from '@/components/utils/icons'
|
|
2
|
-
import type { TSimpleFooterData } from '@/types'
|
|
3
|
-
|
|
4
|
-
export const footerData = {
|
|
5
|
-
company: {
|
|
6
|
-
logo: '/fac',
|
|
7
|
-
name: 'Bunext',
|
|
8
|
-
description: '',
|
|
9
|
-
},
|
|
10
|
-
sections: [
|
|
11
|
-
{
|
|
12
|
-
title: 'Useful Links',
|
|
13
|
-
links: [
|
|
14
|
-
{ label: 'Privacy Policy', url: '/privacy-policy' },
|
|
15
|
-
{ label: 'Terms of Use', url: '/terms-of-use' },
|
|
16
|
-
{ label: 'Contact Us', url: '/contact' },
|
|
17
|
-
],
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
title: 'Contact info',
|
|
21
|
-
links: [
|
|
22
|
-
{ label: 'Email', url: 'mailto:support@zen.com' },
|
|
23
|
-
{ label: 'Phone', url: 'tel:+1234567890' },
|
|
24
|
-
{ label: 'Address', url: '1234 Main St, Anytown, USA' },
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
bottom: {
|
|
29
|
-
copyright: `© ${new Date().getFullYear()}`, // © 2024
|
|
30
|
-
copyrightLink: {
|
|
31
|
-
label: 'Zenetic Esports',
|
|
32
|
-
url: 'https://zeneticesports.com/',
|
|
33
|
-
},
|
|
34
|
-
otherLinks: [{ label: 'Privacy Policy', url: '/privacy-policy' }],
|
|
35
|
-
socialLinks: [
|
|
36
|
-
{
|
|
37
|
-
platform: 'Facebook',
|
|
38
|
-
icon: 'ri:facebook-fill',
|
|
39
|
-
url: 'https://www.facebook.com',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
platform: 'YouTube',
|
|
43
|
-
icon: 'basil:youtube-solid',
|
|
44
|
-
url: 'https://www.youtube.com',
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
platform: 'LinkedIn',
|
|
48
|
-
icon: 'basil:linkedin-solid',
|
|
49
|
-
url: 'https://www.linkedin.com',
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
platform: 'Instagram',
|
|
53
|
-
icon: 'basil:instagram-outline',
|
|
54
|
-
url: 'https://www.instagram.com',
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
platform: 'X (formerly Twitter)',
|
|
58
|
-
icon: 'hugeicons:new-twitter',
|
|
59
|
-
url: 'https://www.twitter.com',
|
|
60
|
-
},
|
|
61
|
-
],
|
|
62
|
-
},
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const simpleFooterData: TSimpleFooterData = {
|
|
66
|
-
texts: [
|
|
67
|
-
{
|
|
68
|
-
pretext: 'Built by',
|
|
69
|
-
label: 'Farhan Ashhab Nur (@darkidop)',
|
|
70
|
-
url: 'https://github.com/darkidop',
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
pretext: 'The source code is available on',
|
|
74
|
-
label: 'GitHub',
|
|
75
|
-
url: 'https://github.com/DarkidOP/Bunext',
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
socialLinks: [
|
|
79
|
-
{
|
|
80
|
-
label: 'Github',
|
|
81
|
-
Icon: Icons.gitHub,
|
|
82
|
-
href: 'https://github.com/darkidop',
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
}
|
package/src/lib/data/nav-data.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { TnavData } from '@/types'
|
|
2
|
-
import { Icons } from '@/components/utils/icons'
|
|
3
|
-
import { siteData } from '@/lib/data/siteData'
|
|
4
|
-
|
|
5
|
-
export const navData: TnavData = {
|
|
6
|
-
title: siteData.shortName,
|
|
7
|
-
showTitle: true,
|
|
8
|
-
logo: {
|
|
9
|
-
src: '/logo.svg',
|
|
10
|
-
alt: 'logo',
|
|
11
|
-
},
|
|
12
|
-
links: [
|
|
13
|
-
{
|
|
14
|
-
label: 'Home',
|
|
15
|
-
href: '/',
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
label: 'Docs',
|
|
19
|
-
href: 'https://github.com/DarkidOP/Bunext?tab=readme-ov-file#bunext',
|
|
20
|
-
external: true,
|
|
21
|
-
},
|
|
22
|
-
],
|
|
23
|
-
iconButtons: [
|
|
24
|
-
{
|
|
25
|
-
label: 'GitHub',
|
|
26
|
-
href: 'https://github.com/DarkidOP/Bunext',
|
|
27
|
-
Icon: Icons.gitHub,
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
}
|
package/src/lib/data/siteData.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { TSiteData, TtwitterMetaData, TMetadataIcons } from '@/types'
|
|
2
|
-
|
|
3
|
-
// edit the webmanifest file in /public to change the name, short_name, and icons in android
|
|
4
|
-
// in webmanifest, theme_color is the color of the app icon's background and
|
|
5
|
-
export const siteData: TSiteData = {
|
|
6
|
-
favicon: '/favicon.svg', // .svg / .ico / .png
|
|
7
|
-
name: 'BUNEXT - Next.js 15 Bun Starter',
|
|
8
|
-
shortName: 'BUNEXT',
|
|
9
|
-
publisher: 'bunext.ardastroid.com',
|
|
10
|
-
baseUrl: 'bunext.ardastroid.com',
|
|
11
|
-
description:
|
|
12
|
-
'BUNEXT is a Next.js 15 Bun Starter with Shadcn UI, Tailwind CSS, TypeScript, Zod, React Hook Form, React Email, Resend, and React Hot Toast.',
|
|
13
|
-
ogImage: { src: '/ogImage.webp', alt: 'Bunext', width: 1200, height: 630 },
|
|
14
|
-
metadata_color: {
|
|
15
|
-
light: '#fbf0df',
|
|
16
|
-
dark: '#fbf0df',
|
|
17
|
-
},
|
|
18
|
-
author: {
|
|
19
|
-
name: 'ardastroid',
|
|
20
|
-
url: 'https://ardastroid.com/',
|
|
21
|
-
},
|
|
22
|
-
keywords: [
|
|
23
|
-
'Next.js',
|
|
24
|
-
'React',
|
|
25
|
-
'Tailwind CSS',
|
|
26
|
-
'Bun',
|
|
27
|
-
'Shadcn UI',
|
|
28
|
-
'TypeScript',
|
|
29
|
-
'Zod',
|
|
30
|
-
'React Hook Form',
|
|
31
|
-
'React Email',
|
|
32
|
-
'Resend',
|
|
33
|
-
'React Hot To ast',
|
|
34
|
-
],
|
|
35
|
-
|
|
36
|
-
robotsDefault: 'index, follow', // { index: false, follow: false }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const twitterMetaData: TtwitterMetaData = {
|
|
40
|
-
card: 'summary_large_image',
|
|
41
|
-
title: siteData.name,
|
|
42
|
-
description: siteData.description,
|
|
43
|
-
images: siteData.ogImage.src,
|
|
44
|
-
creator: '@darkidop', //twitter username of author
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// By default, it uses the favicon mentioned at the top
|
|
48
|
-
export const icons: TMetadataIcons = {
|
|
49
|
-
icon: siteData.favicon, // "/favicon.svg",
|
|
50
|
-
shortcut: siteData.favicon, // "/favicon-16x16.png",
|
|
51
|
-
apple: siteData.favicon, // "/apple-touch-icon.png",
|
|
52
|
-
}
|