@titas_mallick/wedding-site-gen 1.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 (141) hide show
  1. package/.eslintignore +20 -0
  2. package/.eslintrc.json +93 -0
  3. package/.recover +9 -0
  4. package/.vscode/settings.json +3 -0
  5. package/LICENSE +21 -0
  6. package/README.md +83 -0
  7. package/app/Neo-Lucentism/layout.tsx +7 -0
  8. package/app/Neo-Lucentism/page.tsx +259 -0
  9. package/app/couple/layout.tsx +7 -0
  10. package/app/couple/page.tsx +164 -0
  11. package/app/error.tsx +31 -0
  12. package/app/guestbook/page.tsx +470 -0
  13. package/app/invitation/[slug]/layout.tsx +36 -0
  14. package/app/invitation/[slug]/page.tsx +462 -0
  15. package/app/invitation/maker/auth.js +165 -0
  16. package/app/invitation/maker/dashboard.js +81 -0
  17. package/app/invitation/maker/guestAdder.js +204 -0
  18. package/app/invitation/maker/guestShower.js +287 -0
  19. package/app/invitation/maker/layout.tsx +11 -0
  20. package/app/invitation/maker/page.js +168 -0
  21. package/app/invitation/maker/rsvpViewer.js +122 -0
  22. package/app/layout.tsx +98 -0
  23. package/app/mark-the-dates/layout.tsx +7 -0
  24. package/app/mark-the-dates/page.tsx +196 -0
  25. package/app/memories/layout.tsx +7 -0
  26. package/app/memories/page.tsx +29 -0
  27. package/app/page.tsx +5 -0
  28. package/app/providers.tsx +33 -0
  29. package/app/sagun/layout.tsx +7 -0
  30. package/app/sagun/page.tsx +348 -0
  31. package/app/song-requests/page.tsx +354 -0
  32. package/app/sukanya/layout.tsx +7 -0
  33. package/app/sukanya/page.tsx +167 -0
  34. package/app/titas/layout.tsx +7 -0
  35. package/app/titas/page.tsx +175 -0
  36. package/app/travel-guide/page.tsx +400 -0
  37. package/app/updates/maker/page.js +323 -0
  38. package/app/updates/overlay/page.tsx +144 -0
  39. package/app/updates/page.js +207 -0
  40. package/cli.mjs +196 -0
  41. package/components/ConciergeBot.tsx +203 -0
  42. package/components/CountdownTimer.tsx +137 -0
  43. package/components/Gallery.tsx +372 -0
  44. package/components/LiveVideos.tsx +173 -0
  45. package/components/OurStory.tsx +160 -0
  46. package/components/certificate.jsx +300 -0
  47. package/components/counter.tsx +14 -0
  48. package/components/footer.tsx +89 -0
  49. package/components/hero.tsx +136 -0
  50. package/components/icons.tsx +283 -0
  51. package/components/importantNews.js +168 -0
  52. package/components/navbar.tsx +106 -0
  53. package/components/primitives.ts +53 -0
  54. package/components/sagun.js +22 -0
  55. package/components/theme-switch.tsx +81 -0
  56. package/components/updates.tsx +118 -0
  57. package/components/weddingcard.js +68 -0
  58. package/components/weddingcard2.js +58 -0
  59. package/config/firebase-admin.js +17 -0
  60. package/config/firebase.ts +36 -0
  61. package/config/fonts.ts +21 -0
  62. package/config/site.ts +74 -0
  63. package/next-env.d.ts +6 -0
  64. package/next.config.js +4 -0
  65. package/package.json +64 -0
  66. package/postcss.config.js +6 -0
  67. package/public/DCV.gif +0 -0
  68. package/public/DCV2.gif +0 -0
  69. package/public/DCV3.gif +0 -0
  70. package/public/Images/1.jpg +0 -0
  71. package/public/Images/11.jpg +0 -0
  72. package/public/Images/12.jpg +0 -0
  73. package/public/Images/13.jpg +0 -0
  74. package/public/Images/14.jpg +0 -0
  75. package/public/Images/15.jpg +0 -0
  76. package/public/Images/16.jpg +0 -0
  77. package/public/Images/17.jpg +0 -0
  78. package/public/Images/18.jpg +0 -0
  79. package/public/Images/19.jpg +0 -0
  80. package/public/Images/2.jpg +0 -0
  81. package/public/Images/20.jpg +0 -0
  82. package/public/Images/21.jpg +0 -0
  83. package/public/Images/22.jpg +0 -0
  84. package/public/Images/3.jpg +0 -0
  85. package/public/Images/4.jpg +0 -0
  86. package/public/Images/5.jpg +0 -0
  87. package/public/Images/6.jpg +0 -0
  88. package/public/Images/7.jpg +0 -0
  89. package/public/Images/8.jpg +0 -0
  90. package/public/Images/9.jpg +0 -0
  91. package/public/Images/9b.jpg +0 -0
  92. package/public/Images/Patipatra.jpeg +0 -0
  93. package/public/audio (1).mp3 +0 -0
  94. package/public/audio (2).mp3 +0 -0
  95. package/public/bride.jpg +0 -0
  96. package/public/corner1-01.svg +1 -0
  97. package/public/favicon.ico +0 -0
  98. package/public/groom.jpg +0 -0
  99. package/public/invite.png +0 -0
  100. package/public/love-birds.png +0 -0
  101. package/public/next.svg +1 -0
  102. package/public/pubqr.png +0 -0
  103. package/public/pw/001.jpg +0 -0
  104. package/public/pw/002.jpg +0 -0
  105. package/public/pw/003.jpg +0 -0
  106. package/public/pw/004.jpg +0 -0
  107. package/public/pw/005.jpg +0 -0
  108. package/public/pw/006.jpg +0 -0
  109. package/public/pw/007.jpg +0 -0
  110. package/public/pw/008.jpg +0 -0
  111. package/public/pw/009.jpg +0 -0
  112. package/public/pw/010.jpg +0 -0
  113. package/public/pw/011.jpg +0 -0
  114. package/public/pw/012.jpg +0 -0
  115. package/public/pw/013.jpg +0 -0
  116. package/public/pw/014.jpg +0 -0
  117. package/public/pw/015.jpg +0 -0
  118. package/public/pw/016.jpg +0 -0
  119. package/public/pw/017.jpg +0 -0
  120. package/public/pw/018.jpg +0 -0
  121. package/public/pw/019.jpg +0 -0
  122. package/public/pw/020.jpg +0 -0
  123. package/public/pw/021.jpg +0 -0
  124. package/public/pw/022.jpg +0 -0
  125. package/public/pw/023.jpg +0 -0
  126. package/public/pw/024.jpg +0 -0
  127. package/public/pw/025.jpg +0 -0
  128. package/public/pw/026.jpg +0 -0
  129. package/public/pw/027.jpg +0 -0
  130. package/public/pw/028.jpg +0 -0
  131. package/public/pw/029.jpg +0 -0
  132. package/public/pw/030.jpg +0 -0
  133. package/public/pw/031.jpg +0 -0
  134. package/public/pw/032.jpg +0 -0
  135. package/public/qr.png +0 -0
  136. package/public/vercel.svg +1 -0
  137. package/styles/globals.css +3 -0
  138. package/tailwind.config.js +51 -0
  139. package/tsconfig.json +45 -0
  140. package/tsconfig.tsbuildinfo +1 -0
  141. package/types/index.ts +5 -0
@@ -0,0 +1,53 @@
1
+ import { tv } from "tailwind-variants";
2
+
3
+ export const title = tv({
4
+ base: "tracking-tight inline font-semibold",
5
+ variants: {
6
+ color: {
7
+ violet: "from-[#FF1CF7] to-[#b249f8]",
8
+ yellow: "from-[#FF705B] to-[#FFB457]",
9
+ blue: "from-[#5EA2EF] to-[#0072F5]",
10
+ cyan: "from-[#00b7fa] to-[#01cfea]",
11
+ green: "from-[#6FEE8D] to-[#17c964]",
12
+ pink: "from-[#FF72E1] to-[#F54C7A]",
13
+ foreground: "dark:from-[#FFFFFF] dark:to-[#4B4B4B]",
14
+ },
15
+ size: {
16
+ sm: "text-3xl lg:text-4xl",
17
+ md: "text-[2.3rem] lg:text-5xl leading-9",
18
+ lg: "text-4xl lg:text-6xl",
19
+ },
20
+ fullWidth: {
21
+ true: "w-full block",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ size: "md",
26
+ },
27
+ compoundVariants: [
28
+ {
29
+ color: [
30
+ "violet",
31
+ "yellow",
32
+ "blue",
33
+ "cyan",
34
+ "green",
35
+ "pink",
36
+ "foreground",
37
+ ],
38
+ class: "bg-clip-text text-transparent bg-gradient-to-b",
39
+ },
40
+ ],
41
+ });
42
+
43
+ export const subtitle = tv({
44
+ base: "w-full md:w-1/2 my-2 text-lg lg:text-xl text-default-600 block max-w-full",
45
+ variants: {
46
+ fullWidth: {
47
+ true: "!w-full",
48
+ },
49
+ },
50
+ defaultVariants: {
51
+ fullWidth: true,
52
+ },
53
+ });
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ import { Button } from "@heroui/button";
3
+ import { Link } from "@heroui/link";
4
+ import { HeartFilledIcon } from "@/components/icons";
5
+ const Sagun = () => {
6
+ return (
7
+ <main>
8
+ <Button
9
+ isExternal
10
+ as={Link}
11
+ className="text-sm font-normal text-default-600 bg-default-100"
12
+ href={"/sagun"}
13
+ startContent={<HeartFilledIcon className="text-danger" />}
14
+ variant="flat"
15
+ >
16
+ Sagun
17
+ </Button>
18
+ </main>
19
+ );
20
+ };
21
+
22
+ export default Sagun;
@@ -0,0 +1,81 @@
1
+ "use client";
2
+
3
+ import { FC } from "react";
4
+ import { VisuallyHidden } from "@react-aria/visually-hidden";
5
+ import { SwitchProps, useSwitch } from "@heroui/switch";
6
+ import { useTheme } from "next-themes";
7
+ import { useIsSSR } from "@react-aria/ssr";
8
+ import clsx from "clsx";
9
+
10
+ import { SunFilledIcon, MoonFilledIcon } from "@/components/icons";
11
+
12
+ export interface ThemeSwitchProps {
13
+ className?: string;
14
+ classNames?: SwitchProps["classNames"];
15
+ }
16
+
17
+ export const ThemeSwitch: FC<ThemeSwitchProps> = ({
18
+ className,
19
+ classNames,
20
+ }) => {
21
+ const { theme, setTheme } = useTheme();
22
+ const isSSR = useIsSSR();
23
+
24
+ const onChange = () => {
25
+ theme === "light" ? setTheme("dark") : setTheme("light");
26
+ };
27
+
28
+ const {
29
+ Component,
30
+ slots,
31
+ isSelected,
32
+ getBaseProps,
33
+ getInputProps,
34
+ getWrapperProps,
35
+ } = useSwitch({
36
+ isSelected: theme === "light" || isSSR,
37
+ "aria-label": `Switch to ${theme === "light" || isSSR ? "dark" : "light"} mode`,
38
+ onChange,
39
+ });
40
+
41
+ return (
42
+ <Component
43
+ {...getBaseProps({
44
+ className: clsx(
45
+ "px-px transition-opacity hover:opacity-80 cursor-pointer",
46
+ className,
47
+ classNames?.base,
48
+ ),
49
+ })}
50
+ >
51
+ <VisuallyHidden>
52
+ <input {...getInputProps()} />
53
+ </VisuallyHidden>
54
+ <div
55
+ {...getWrapperProps()}
56
+ className={slots.wrapper({
57
+ class: clsx(
58
+ [
59
+ "w-auto h-auto",
60
+ "bg-transparent",
61
+ "rounded-lg",
62
+ "flex items-center justify-center",
63
+ "group-data-[selected=true]:bg-transparent",
64
+ "!text-default-500",
65
+ "pt-px",
66
+ "px-0",
67
+ "mx-0",
68
+ ],
69
+ classNames?.wrapper,
70
+ ),
71
+ })}
72
+ >
73
+ {!isSelected || isSSR ? (
74
+ <SunFilledIcon size={22} />
75
+ ) : (
76
+ <MoonFilledIcon size={22} />
77
+ )}
78
+ </div>
79
+ </Component>
80
+ );
81
+ };
@@ -0,0 +1,118 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+ import {
5
+ getFirestore,
6
+ collection,
7
+ onSnapshot,
8
+ query,
9
+ orderBy,
10
+ limit,
11
+ } from "firebase/firestore";
12
+ import { motion, AnimatePresence } from "framer-motion";
13
+ import Link from "next/link";
14
+ import { Chip } from "@heroui/react";
15
+
16
+ import firebaseApp from "@/config/firebase";
17
+ import { fontMono } from "@/config/fonts";
18
+ import { ClockIcon } from "./icons";
19
+
20
+ const db = getFirestore(firebaseApp());
21
+
22
+ const timeAgo = (timestamp: any) => {
23
+ if (!timestamp?.toDate) return "Just now";
24
+ const now = new Date();
25
+ const diff = (now.getTime() - timestamp.toDate().getTime()) / 1000;
26
+ if (diff < 60) return `${Math.floor(diff)}s ago`;
27
+ if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
28
+ if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
29
+ return `${Math.floor(diff / 86400)}d ago`;
30
+ };
31
+
32
+ const Updates = () => {
33
+ const [latestUpdate, setLatestUpdate] = useState<any>(null);
34
+ const [loading, setLoading] = useState(true);
35
+
36
+ useEffect(() => {
37
+ const q = query(
38
+ collection(db, "updates"),
39
+ orderBy("createdAt", "desc"),
40
+ limit(1)
41
+ );
42
+
43
+ const unsubscribe = onSnapshot(q, (snapshot) => {
44
+ if (!snapshot.empty) {
45
+ setLatestUpdate({
46
+ id: snapshot.docs[0].id,
47
+ ...snapshot.docs[0].data(),
48
+ });
49
+ }
50
+ setLoading(false);
51
+ });
52
+
53
+ return () => unsubscribe();
54
+ }, []);
55
+
56
+ if (loading || !latestUpdate) return null;
57
+
58
+ return (
59
+ <AnimatePresence>
60
+ <motion.div
61
+ initial={{ opacity: 0, y: -20 }}
62
+ animate={{ opacity: 1, y: 0 }}
63
+ exit={{ opacity: 0, y: -20 }}
64
+ className="w-full max-w-3xl mx-auto px-4 z-50"
65
+ >
66
+ <div className="relative group">
67
+ {/* Animated Background Glow */}
68
+ <div className="absolute -inset-0.5 bg-gradient-to-r from-wedding-pink-500 to-wedding-gold-500 rounded-full blur opacity-20 group-hover:opacity-40 transition duration-1000 group-hover:duration-200"></div>
69
+
70
+ <Link
71
+ href="/updates"
72
+ className="relative flex items-center gap-2 sm:gap-3 bg-white/90 dark:bg-zinc-900/90 backdrop-blur-xl border border-wedding-gold-200/50 dark:border-wedding-gold-800/50 p-1 sm:p-1.5 pr-4 sm:pr-6 rounded-full shadow-xl transition-all duration-300 group-hover:border-wedding-pink-400"
73
+ >
74
+ <div className="flex items-center bg-wedding-pink-500 text-white px-2 sm:px-3 py-1 rounded-full text-[9px] sm:text-[10px] font-black tracking-widest shadow-lg shadow-wedding-pink-500/20">
75
+ UPDATE
76
+ </div>
77
+
78
+ <p className="flex-1 text-xs sm:text-sm font-semibold text-zinc-800 dark:text-zinc-100 truncate">
79
+ {latestUpdate.text}
80
+ </p>
81
+
82
+ <div className="hidden sm:flex items-center gap-4">
83
+ <div className="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-zinc-400 font-mono whitespace-nowrap border-x border-default-200 dark:border-default-800 px-4">
84
+ <ClockIcon size={12} className="text-wedding-gold-500" />
85
+ {timeAgo(latestUpdate.createdAt)}
86
+ </div>
87
+
88
+ <div className="flex items-center gap-1 text-xs font-bold text-wedding-pink-500 whitespace-nowrap group-hover:translate-x-1 transition-transform">
89
+ View All
90
+ <svg
91
+ width="14"
92
+ height="14"
93
+ viewBox="0 0 24 24"
94
+ fill="none"
95
+ stroke="currentColor"
96
+ strokeWidth="3"
97
+ strokeLinecap="round"
98
+ strokeLinejoin="round"
99
+ >
100
+ <polyline points="9 18 15 12 9 6"></polyline>
101
+ </svg>
102
+ </div>
103
+ </div>
104
+
105
+ {/* Mobile Arrow */}
106
+ <div className="sm:hidden text-wedding-pink-500 flex-shrink-0">
107
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
108
+ <polyline points="9 18 15 12 9 6"></polyline>
109
+ </svg>
110
+ </div>
111
+ </Link>
112
+ </div>
113
+ </motion.div>
114
+ </AnimatePresence>
115
+ );
116
+ };
117
+
118
+ export default Updates;
@@ -0,0 +1,68 @@
1
+ "use client";
2
+
3
+ import {
4
+ Card,
5
+ CardFooter,
6
+ Image,
7
+ Button,
8
+ CardHeader,
9
+ CardBody,
10
+ Link,
11
+ } from "@heroui/react";
12
+
13
+ const WeddingCard = () => {
14
+ return (
15
+ <section className="relative w-full h-[500px] overflow-hidden rounded-2xl bg-black">
16
+ {/* Background Video */}
17
+ <div className="absolute inset-0 w-full h-full pointer-events-none">
18
+ <iframe
19
+ className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none border-none"
20
+ style={{
21
+ width: '100vw',
22
+ height: '56.25vw', /* 16:9 Aspect Ratio */
23
+ minHeight: '100%',
24
+ minWidth: '177.77vh', /* 100 / 9 * 16 */
25
+ transform: 'translate(-50%, -50%) scale(1.1)', /* Extra scale to ensure no edge bleed */
26
+ }}
27
+ src="https://www.youtube.com/embed/a_RV8HevyBE?autoplay=1&mute=1&loop=1&playlist=a_RV8HevyBE&controls=0&showinfo=0&modestbranding=1&rel=0"
28
+ title="Pre Wedding Video"
29
+ allow="autoplay; encrypted-media"
30
+ />
31
+ </div>
32
+
33
+ {/* Soft overlay */}
34
+ <div className="absolute inset-0 bg-black/30" />
35
+
36
+ {/* Card */}
37
+ <div className="relative z-10 flex items-center justify-center h-full">
38
+ <Card className="py-4">
39
+ <CardHeader className="pb-0 pt-2 px-4 flex-col items-start">
40
+ <p className="text-tiny uppercase font-bold">Social Marriage</p>
41
+ <small className="text-default-500">23 January, 2026</small>
42
+ <h4 className="font-bold text-large">
43
+ Anandamoyee Bhawan, Serampore
44
+ </h4>
45
+ </CardHeader>
46
+ <CardBody className="overflow-visible py-2">
47
+ <Image
48
+ alt="Card background"
49
+ className="object-cover rounded-xl"
50
+ src="/DCV2.gif"
51
+ width={320}
52
+ />
53
+ <Link
54
+ href="https://maps.app.goo.gl/G5R3bkcTwwa2d54R8"
55
+ showAnchorIcon
56
+ color="warning"
57
+ className="w-full mx-auto text-center mt-2"
58
+ >
59
+ Location
60
+ </Link>
61
+ </CardBody>
62
+ </Card>
63
+ </div>
64
+ </section>
65
+ );
66
+ };
67
+
68
+ export default WeddingCard;
@@ -0,0 +1,58 @@
1
+ "use client";
2
+
3
+ import { Card, CardFooter, Image, Button, CardHeader, CardBody, Link } from "@heroui/react";
4
+
5
+ const WeddingCard2 = () => {
6
+ return (
7
+ <section className="relative w-full h-[500px] overflow-hidden rounded-2xl bg-black">
8
+ {/* Background Video */}
9
+ <div className="absolute inset-0 w-full h-full pointer-events-none">
10
+ <iframe
11
+ className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none border-none"
12
+ style={{
13
+ width: '100vw',
14
+ height: '56.25vw', /* 16:9 Aspect Ratio */
15
+ minHeight: '100%',
16
+ minWidth: '177.77vh', /* 100 / 9 * 16 */
17
+ transform: 'translate(-50%, -50%) scale(1.1)', /* Extra scale to ensure no edge bleed */
18
+ }}
19
+ src="https://www.youtube.com/embed/a_RV8HevyBE?autoplay=1&mute=1&loop=1&playlist=a_RV8HevyBE&controls=0&showinfo=0&modestbranding=1&rel=0"
20
+ title="Pre Wedding Video"
21
+ allow="autoplay; encrypted-media"
22
+ />
23
+ </div>
24
+
25
+ {/* Soft overlay */}
26
+ <div className="absolute inset-0 bg-black/30" />
27
+
28
+ {/* Card */}
29
+ <div className="relative z-10 flex items-center justify-center h-full">
30
+ <Card className="py-4">
31
+ <CardHeader className="pb-0 pt-2 px-4 flex-col items-start">
32
+ <p className="text-tiny uppercase font-bold">Reception</p>
33
+ <small className="text-default-500">25 January, 2026</small>
34
+ <h4 className="font-bold text-large">Friend&apos;s Union Club, Konnagar</h4>
35
+ </CardHeader>
36
+ <CardBody className="overflow-visible py-2">
37
+ <Image
38
+ alt="Card background"
39
+ className="object-cover rounded-xl"
40
+ src="/DCV3.gif"
41
+ width={320}
42
+ />
43
+ <Link
44
+ href="https://maps.app.goo.gl/ubdTsy6tnYMsvSSXA"
45
+ showAnchorIcon
46
+ color="warning"
47
+ className="w-full mx-auto text-center mt-2"
48
+ >
49
+ Location
50
+ </Link>
51
+ </CardBody>
52
+ </Card>
53
+ </div>
54
+ </section>
55
+ );
56
+ };
57
+
58
+ export default WeddingCard2;
@@ -0,0 +1,17 @@
1
+ const adminCred = {
2
+ type: "service_account",
3
+ project_id: "wedding-forever-titas-sukanya",
4
+ private_key_id: "6d71529b4b898a03b0534024eb58ddabdc76548d",
5
+ private_key:
6
+ "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5hjvkXTkczAT3\nkoLvJdxeXt/1V4rAp0xpNb9xoJDME74ciig1oUUusZ/l6v0KD9Li4RInS8evb55W\n9OsPUwz0N5TUnKmmJ3Kz22pG6Cz13M9kOnlpkbrD14aU9M34OWUpmKwMpqc1wHHJ\nTRX7VQ11HQ/OGX6SsJkX0JDaaRenH4IMz1c2+Ci+6p2LpzMaM5yiw7l34aeHWWjV\nFffeFmqHMKhIcS0Ib1yTv8cjhm731ouYXztDYApAdu4DHENrZm2ygyFoAQYnp2L3\n/GimwDKPGDsBLZEOyucvPzYvWW6d/jqWfgFaxSX2hrtJ8dNwD340Wz8H+Zc1VRkM\n8mUwU+ExAgMBAAECggEABZScwevD8gfOW8a+cC8gB9QBbJcrh0wA/REu0bOAvNgY\nhIdAr7b1e8gVWox3prvUc2/4ZHzfuXk5YWg7QdoVA6uVqyeN5X+Tmwa4larE33MQ\nPKA9qAfy1D1Ba8L0Bx7C2j4gvr4B6ENXqN8hZXlTeaMG0gOWTmydePKUc4gXEWHQ\nxwQtQN1e6shlhMfYT0KFT+B0l6C1J1ZvVKZmZsvgUE9EcJrPu5wOhIk8mGu54BYb\nTeeYjKCGgSe6l8THFR5O5fwNk80nXL12kZfzWqGKvrkeIeILtzWMi95pKrwSYFoQ\n3Zzk+Way0nAXW2DtGltc3K0MV4lpgEXcmpg5fyXxmQKBgQDno3XFzVI4mnCk3PN0\n5pjWmVoqrPJMtDUZma3tWSdDwYtbBXgz0o3zuJ8qGHog7vmiqVG7/cwp199Bmrrf\nzdpx5B2NUijp95cmBt5nlX09DYoRatubhfsmdBH6pDqvDmNbV1aYgKFypaODgLHi\n5W3BBQO/UN1XB8FfjS3iEcyD6wKBgQDNCTcTklf2h27v9W3ovTyBrZZXolYEVMwA\n6iXvWk24MU/Xn7RGue78NwO5T5K3VU9wrkPOi3oEYNtoQKNVsMJDc6FI9TKEAQhz\nFjCq7+aUKYbzx/2Z8vXglFqMsBl/AhXSj99Nt0rjvI3LuUiI1QZwj8wRmnx5GSRG\nup35jDRUUwKBgEinkK02NW/joSlU1Ff6bD4DY7C3BljgvTcGaPNlX1d1QYyPLqCy\njiu/4MyHWOczjcFjcmuQs5T8TN569dp06uuGLW7CMmsQaaxXwzKiROH9eSz1Y2Ro\npdnt1iXTlUSLMsbXoiW7Uuhu49a/awxMAhzkwcQkTQibOiAKXDXod0l5AoGACgVQ\nRsmZOPhHiLzDAWP2SBQ2y9OoRo/qZIUNE5SjRcRLNaudgPNnZbY+nVjxP7qQpl4t\n/DM+5GXjc0Xtdaus4uUM1eb98Auo4Q8Nk90jtMwOx21XzKVeNPqrLkMRC+8LJ/5W\nGJNDurulZnaIv/9BUFEG1TlqqfR7nGVUgTTD/fcCgYEAwSo1mr03BIGOENuhxv7C\naSYSUjVEH6kdNo2nrK899ez2OxXHdfrvCg/I6Vpz2qFDQ7ZrENYeoljQzlFwYSzK\n2H6jZnt/6uZ7mXENZgxUXscrlu7znn0eQ1xo+acqIK03YTzvh5UnoBpvfy12bEiV\nlBOrdL+oEYBSHrhq38XQG80=\n-----END PRIVATE KEY-----\n",
7
+ client_email:
8
+ "firebase-adminsdk-fbsvc@wedding-forever-titas-sukanya.iam.gserviceaccount.com",
9
+ client_id: "108512120143007143022",
10
+ auth_uri: "https://accounts.google.com/o/oauth2/auth",
11
+ token_uri: "https://oauth2.googleapis.com/token",
12
+ auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
13
+ client_x509_cert_url:
14
+ "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fbsvc%40wedding-forever-titas-sukanya.iam.gserviceaccount.com",
15
+ universe_domain: "googleapis.com",
16
+ };
17
+ export default adminCred;
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ import { initializeApp, getApps, getApp, FirebaseApp } from "firebase/app";
3
+ import { getAnalytics } from "firebase/analytics";
4
+ import { initializeAppCheck, ReCaptchaV3Provider } from "firebase/app-check";
5
+
6
+ const firebaseConfig = {
7
+ apiKey: process.env.NEXT_PUBLIC_APIKEY,
8
+ authDomain: process.env.NEXT_PUBLIC_AUTHDOMAIN,
9
+ projectId: process.env.NEXT_PUBLIC_PROJECTID,
10
+ storageBucket: process.env.NEXT_PUBLIC_STORAGEBUCKET,
11
+ messagingSenderId: process.env.NEXT_PUBLIC_SENDERID,
12
+ appId: process.env.NEXT_PUBLIC_APPID,
13
+ measurementId: process.env.NEXT_PUBLIC_MEASUREMENTID,
14
+ };
15
+
16
+ const firebaseApp = (): FirebaseApp => {
17
+ let app: FirebaseApp;
18
+ if (!getApps().length) {
19
+ app = initializeApp(firebaseConfig);
20
+
21
+ if (typeof window !== "undefined") {
22
+ getAnalytics(app);
23
+ initializeAppCheck(app, {
24
+ provider: new ReCaptchaV3Provider(
25
+ process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY as string
26
+ ),
27
+ isTokenAutoRefreshEnabled: true,
28
+ });
29
+ }
30
+ } else {
31
+ app = getApp();
32
+ }
33
+ return app;
34
+ };
35
+
36
+ export default firebaseApp;
@@ -0,0 +1,21 @@
1
+ import {
2
+ Geist as FontSans,
3
+ Geist_Mono as FontMono,
4
+ Great_Vibes as FontCursive,
5
+ } from "next/font/google";
6
+
7
+ export const fontSans = FontSans({
8
+ subsets: ["latin"],
9
+ variable: "--font-sans",
10
+ });
11
+
12
+ export const fontMono = FontMono({
13
+ subsets: ["latin"],
14
+ variable: "--font-mono",
15
+ });
16
+
17
+ export const fontCursive = FontCursive({
18
+ subsets: ["latin"],
19
+ weight: "400", // Great Vibes only comes in 400
20
+ variable: "--font-cursive",
21
+ });
package/config/site.ts ADDED
@@ -0,0 +1,74 @@
1
+ export type SiteConfig = typeof siteConfig;
2
+
3
+ export const siteConfig = {
4
+ name: "Titas & Sukanya",
5
+ description:
6
+ "Join us in celebrating the wedding of Titas and Sukanya. Save the date and be part of our journey.",
7
+ navItems: [
8
+ {
9
+ label: "Home",
10
+ href: "/",
11
+ },
12
+ {
13
+ label: "Our Story",
14
+ href: "/couple",
15
+ },
16
+ {
17
+ label: "Events",
18
+ href: "/mark-the-dates",
19
+ },
20
+ {
21
+ label: "Guestbook",
22
+ href: "/guestbook",
23
+ },
24
+ {
25
+ label: "Songs",
26
+ href: "/song-requests",
27
+ },
28
+ {
29
+ label: "Travel Guide",
30
+ href: "/travel-guide",
31
+ },
32
+ {
33
+ label: "Gallery",
34
+ href: "/memories",
35
+ },
36
+ ],
37
+ navMenuItems: [
38
+ {
39
+ label: "Home",
40
+ href: "/",
41
+ },
42
+ {
43
+ label: "Our Story",
44
+ href: "/couple",
45
+ },
46
+ {
47
+ label: "Events",
48
+ href: "/mark-the-dates",
49
+ },
50
+ {
51
+ label: "Guestbook",
52
+ href: "/guestbook",
53
+ },
54
+ {
55
+ label: "Gallery",
56
+ href: "/memories",
57
+ },
58
+ {
59
+ label: "Song Requests",
60
+ href: "/song-requests",
61
+ },
62
+ {
63
+ label: "Travel Guide",
64
+ href: "/travel-guide",
65
+ },
66
+ {
67
+ label: "Send Wishes",
68
+ href: "/sagun",
69
+ },
70
+ ],
71
+ links: {
72
+ // Keep empty or relevant social links if needed later
73
+ },
74
+ };
package/next-env.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ import "./.next/dev/types/routes.d.ts";
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
package/next.config.js ADDED
@@ -0,0 +1,4 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {};
3
+
4
+ module.exports = nextConfig;
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@titas_mallick/wedding-site-gen",
3
+ "version": "1.0.0",
4
+ "bin": {
5
+ "create-wedding-site": "./cli.mjs"
6
+ },
7
+ "scripts": {
8
+ "dev": "next dev --turbopack",
9
+ "build": "next build --turbopack",
10
+ "start": "next start",
11
+ "lint": "eslint . --ext .ts,.tsx -c .eslintrc.json --fix"
12
+ },
13
+ "dependencies": {
14
+ "@heroui/button": "2.2.17",
15
+ "@heroui/code": "2.2.12",
16
+ "@heroui/input": "2.4.17",
17
+ "@heroui/kbd": "2.2.13",
18
+ "@heroui/link": "2.2.14",
19
+ "@heroui/listbox": "2.3.16",
20
+ "@heroui/navbar": "2.2.15",
21
+ "@heroui/react": "^2.7.8",
22
+ "@heroui/snippet": "2.2.18",
23
+ "@heroui/switch": "2.2.15",
24
+ "@heroui/system": "2.4.13",
25
+ "@heroui/theme": "2.4.13",
26
+ "@react-aria/ssr": "3.9.7",
27
+ "@react-aria/visually-hidden": "3.8.21",
28
+ "@vercel/analytics": "^1.6.1",
29
+ "clsx": "2.1.1",
30
+ "firebase": "^11.7.3",
31
+ "firebase-admin": "^13.4.0",
32
+ "framer-motion": "11.13.1",
33
+ "intl-messageformat": "^10.5.0",
34
+ "next": "^16.0.1",
35
+ "next-themes": "^0.4.4",
36
+ "react": "^18.3.1",
37
+ "react-dom": "^18.3.1"
38
+ },
39
+ "devDependencies": {
40
+ "@next/eslint-plugin-next": "15.0.4",
41
+ "@react-types/shared": "3.25.0",
42
+ "@types/node": "20.5.7",
43
+ "@types/react": "18.3.3",
44
+ "@types/react-dom": "18.3.0",
45
+ "@typescript-eslint/eslint-plugin": "8.11.0",
46
+ "@typescript-eslint/parser": "8.11.0",
47
+ "autoprefixer": "10.4.19",
48
+ "eslint": "^8.57.0",
49
+ "eslint-config-next": "^15.3.1",
50
+ "eslint-config-prettier": "9.1.0",
51
+ "eslint-plugin-import": "^2.26.0",
52
+ "eslint-plugin-jsx-a11y": "^6.4.1",
53
+ "eslint-plugin-node": "^11.1.0",
54
+ "eslint-plugin-prettier": "5.2.1",
55
+ "eslint-plugin-react": "^7.23.2",
56
+ "eslint-plugin-react-hooks": "^4.6.0",
57
+ "eslint-plugin-unused-imports": "4.1.4",
58
+ "postcss": "8.4.49",
59
+ "prettier": "3.3.3",
60
+ "tailwind-variants": "0.3.0",
61
+ "tailwindcss": "3.4.16",
62
+ "typescript": "5.6.3"
63
+ }
64
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
package/public/DCV.gif ADDED
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file