diff --git a/apps/marketing/.eslintrc.js b/apps/marketing/.eslintrc.js
new file mode 100644
index 0000000..11aec8a
--- /dev/null
+++ b/apps/marketing/.eslintrc.js
@@ -0,0 +1,9 @@
+/** @type {import("eslint").Linter.Config} */
+module.exports = {
+ root: true,
+ extends: ["@unsend/eslint-config/next.js"],
+ parser: "@typescript-eslint/parser",
+ parserOptions: {
+ project: true,
+ },
+};
diff --git a/apps/marketing/.gitignore b/apps/marketing/.gitignore
new file mode 100644
index 0000000..fd3dbb5
--- /dev/null
+++ b/apps/marketing/.gitignore
@@ -0,0 +1,36 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/apps/marketing/README.md b/apps/marketing/README.md
new file mode 100644
index 0000000..c403366
--- /dev/null
+++ b/apps/marketing/README.md
@@ -0,0 +1,36 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+# or
+pnpm dev
+# or
+bun dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+
+This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/apps/marketing/next.config.mjs b/apps/marketing/next.config.mjs
new file mode 100644
index 0000000..4678774
--- /dev/null
+++ b/apps/marketing/next.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+export default nextConfig;
diff --git a/apps/marketing/package.json b/apps/marketing/package.json
new file mode 100644
index 0000000..08f4aa6
--- /dev/null
+++ b/apps/marketing/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "marketing",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev -p 3001",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "framer-motion": "^11.0.24",
+ "lucide-react": "^0.359.0",
+ "next": "14.1.4",
+ "react": "^18",
+ "react-dom": "^18"
+ },
+ "devDependencies": {
+ "@types/node": "^20",
+ "@types/react": "^18",
+ "@types/react-dom": "^18",
+ "@unsend/eslint-config": "workspace:*",
+ "@unsend/tailwind-config": "workspace:*",
+ "@unsend/ui": "workspace:*",
+ "autoprefixer": "^10.0.1",
+ "eslint": "^8",
+ "eslint-config-next": "14.1.4",
+ "postcss": "^8",
+ "tailwindcss": "^3.3.0",
+ "typescript": "^5"
+ }
+}
\ No newline at end of file
diff --git a/apps/marketing/postcss.config.js b/apps/marketing/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/apps/marketing/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/apps/marketing/public/next.svg b/apps/marketing/public/next.svg
new file mode 100644
index 0000000..5174b28
--- /dev/null
+++ b/apps/marketing/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/marketing/public/vercel.svg b/apps/marketing/public/vercel.svg
new file mode 100644
index 0000000..d2f8422
--- /dev/null
+++ b/apps/marketing/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/marketing/src/app/favicon.ico b/apps/marketing/src/app/favicon.ico
new file mode 100644
index 0000000..4570eb8
Binary files /dev/null and b/apps/marketing/src/app/favicon.ico differ
diff --git a/apps/marketing/src/app/globals.css b/apps/marketing/src/app/globals.css
new file mode 100644
index 0000000..875c01e
--- /dev/null
+++ b/apps/marketing/src/app/globals.css
@@ -0,0 +1,33 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ --foreground-rgb: 0, 0, 0;
+ --background-start-rgb: 214, 219, 220;
+ --background-end-rgb: 255, 255, 255;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --foreground-rgb: 255, 255, 255;
+ --background-start-rgb: 0, 0, 0;
+ --background-end-rgb: 0, 0, 0;
+ }
+}
+
+body {
+ color: rgb(var(--foreground-rgb));
+ background: linear-gradient(
+ to bottom,
+ transparent,
+ rgb(var(--background-end-rgb))
+ )
+ rgb(var(--background-start-rgb));
+}
+
+@layer utilities {
+ .text-balance {
+ text-wrap: balance;
+ }
+}
diff --git a/apps/marketing/src/app/layout.tsx b/apps/marketing/src/app/layout.tsx
new file mode 100644
index 0000000..9ec174b
--- /dev/null
+++ b/apps/marketing/src/app/layout.tsx
@@ -0,0 +1,25 @@
+import type { Metadata } from "next";
+import { Inter } from "next/font/google";
+import "@unsend/ui/styles/globals.css";
+import { ThemeProvider } from "@unsend/ui/theme-provider";
+
+const inter = Inter({ subsets: ["latin"] });
+
+export const metadata: Metadata = {
+ title: "Unsend",
+ description: "Open source sending infrastructure",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ return (
+
+
+ {children}
+
+
+ );
+}
diff --git a/apps/marketing/src/app/page.tsx b/apps/marketing/src/app/page.tsx
new file mode 100644
index 0000000..dd72e64
--- /dev/null
+++ b/apps/marketing/src/app/page.tsx
@@ -0,0 +1,47 @@
+import { ArrowRight, MoveRight, SendHorizonal } from "lucide-react";
+import Image from "next/image";
+import { BackgroundBeams } from "~/components/ui/background-beams";
+import { StyledInput } from "~/components/ui/styled-input";
+
+export default function Home() {
+ return (
+
+
+
+
+ Open source sending infrastructure for{" "}
+
+ developers
+
+
+
+
+ Send transactional, marketing emails, SMSes and push notifications
+ effortlessly.
+
+
+ Join the waitlist!
+
+
+
+
+
+
+
+
+ Join the waitlist
+
+
+
+
+ );
+}
diff --git a/apps/marketing/src/components/ui/background-beams.tsx b/apps/marketing/src/components/ui/background-beams.tsx
new file mode 100644
index 0000000..e7ce1a8
--- /dev/null
+++ b/apps/marketing/src/components/ui/background-beams.tsx
@@ -0,0 +1,149 @@
+"use client";
+import React from "react";
+import { motion } from "framer-motion";
+import { cn } from "@unsend/ui/lib/utils";
+
+export const BackgroundBeams = React.memo(
+ ({ className }: { className?: string }) => {
+ const paths = [
+ "M-380 -189C-380 -189 -312 216 152 343C616 470 684 875 684 875",
+ "M-373 -197C-373 -197 -305 208 159 335C623 462 691 867 691 867",
+ "M-366 -205C-366 -205 -298 200 166 327C630 454 698 859 698 859",
+ "M-359 -213C-359 -213 -291 192 173 319C637 446 705 851 705 851",
+ "M-352 -221C-352 -221 -284 184 180 311C644 438 712 843 712 843",
+ "M-345 -229C-345 -229 -277 176 187 303C651 430 719 835 719 835",
+ "M-338 -237C-338 -237 -270 168 194 295C658 422 726 827 726 827",
+ "M-331 -245C-331 -245 -263 160 201 287C665 414 733 819 733 819",
+ "M-324 -253C-324 -253 -256 152 208 279C672 406 740 811 740 811",
+ "M-317 -261C-317 -261 -249 144 215 271C679 398 747 803 747 803",
+ "M-310 -269C-310 -269 -242 136 222 263C686 390 754 795 754 795",
+ "M-303 -277C-303 -277 -235 128 229 255C693 382 761 787 761 787",
+ "M-296 -285C-296 -285 -228 120 236 247C700 374 768 779 768 779",
+ "M-289 -293C-289 -293 -221 112 243 239C707 366 775 771 775 771",
+ "M-282 -301C-282 -301 -214 104 250 231C714 358 782 763 782 763",
+ "M-275 -309C-275 -309 -207 96 257 223C721 350 789 755 789 755",
+ "M-268 -317C-268 -317 -200 88 264 215C728 342 796 747 796 747",
+ "M-261 -325C-261 -325 -193 80 271 207C735 334 803 739 803 739",
+ "M-254 -333C-254 -333 -186 72 278 199C742 326 810 731 810 731",
+ "M-247 -341C-247 -341 -179 64 285 191C749 318 817 723 817 723",
+ "M-240 -349C-240 -349 -172 56 292 183C756 310 824 715 824 715",
+ "M-233 -357C-233 -357 -165 48 299 175C763 302 831 707 831 707",
+ "M-226 -365C-226 -365 -158 40 306 167C770 294 838 699 838 699",
+ "M-219 -373C-219 -373 -151 32 313 159C777 286 845 691 845 691",
+ "M-212 -381C-212 -381 -144 24 320 151C784 278 852 683 852 683",
+ "M-205 -389C-205 -389 -137 16 327 143C791 270 859 675 859 675",
+ "M-198 -397C-198 -397 -130 8 334 135C798 262 866 667 866 667",
+ "M-191 -405C-191 -405 -123 0 341 127C805 254 873 659 873 659",
+ "M-184 -413C-184 -413 -116 -8 348 119C812 246 880 651 880 651",
+ "M-177 -421C-177 -421 -109 -16 355 111C819 238 887 643 887 643",
+ "M-170 -429C-170 -429 -102 -24 362 103C826 230 894 635 894 635",
+ "M-163 -437C-163 -437 -95 -32 369 95C833 222 901 627 901 627",
+ "M-156 -445C-156 -445 -88 -40 376 87C840 214 908 619 908 619",
+ "M-149 -453C-149 -453 -81 -48 383 79C847 206 915 611 915 611",
+ "M-142 -461C-142 -461 -74 -56 390 71C854 198 922 603 922 603",
+ "M-135 -469C-135 -469 -67 -64 397 63C861 190 929 595 929 595",
+ "M-128 -477C-128 -477 -60 -72 404 55C868 182 936 587 936 587",
+ "M-121 -485C-121 -485 -53 -80 411 47C875 174 943 579 943 579",
+ "M-114 -493C-114 -493 -46 -88 418 39C882 166 950 571 950 571",
+ "M-107 -501C-107 -501 -39 -96 425 31C889 158 957 563 957 563",
+ "M-100 -509C-100 -509 -32 -104 432 23C896 150 964 555 964 555",
+ "M-93 -517C-93 -517 -25 -112 439 15C903 142 971 547 971 547",
+ "M-86 -525C-86 -525 -18 -120 446 7C910 134 978 539 978 539",
+ "M-79 -533C-79 -533 -11 -128 453 -1C917 126 985 531 985 531",
+ "M-72 -541C-72 -541 -4 -136 460 -9C924 118 992 523 992 523",
+ "M-65 -549C-65 -549 3 -144 467 -17C931 110 999 515 999 515",
+ "M-58 -557C-58 -557 10 -152 474 -25C938 102 1006 507 1006 507",
+ "M-51 -565C-51 -565 17 -160 481 -33C945 94 1013 499 1013 499",
+ "M-44 -573C-44 -573 24 -168 488 -41C952 86 1020 491 1020 491",
+ "M-37 -581C-37 -581 31 -176 495 -49C959 78 1027 483 1027 483",
+ ];
+ return (
+
+
+
+ );
+ }
+);
+
+BackgroundBeams.displayName = "BackgroundBeams";
diff --git a/apps/marketing/src/components/ui/styled-input.tsx b/apps/marketing/src/components/ui/styled-input.tsx
new file mode 100644
index 0000000..d3eccd0
--- /dev/null
+++ b/apps/marketing/src/components/ui/styled-input.tsx
@@ -0,0 +1,61 @@
+// Input component extends from shadcnui - https://ui.shadcn.com/docs/components/input
+"use client";
+import * as React from "react";
+import { cn } from "@unsend/ui/lib/utils";
+import { useMotionTemplate, useMotionValue, motion } from "framer-motion";
+
+export interface InputProps
+ extends React.InputHTMLAttributes {}
+
+const StyledInput = React.forwardRef(
+ ({ className, type, ...props }, ref) => {
+ const radius = 100; // change this to increase the rdaius of the hover effect
+ const [visible, setVisible] = React.useState(false);
+
+ let mouseX = useMotionValue(0);
+ let mouseY = useMotionValue(0);
+
+ function handleMouseMove({ currentTarget, clientX, clientY }: any) {
+ let { left, top } = currentTarget.getBoundingClientRect();
+
+ mouseX.set(clientX - left);
+ mouseY.set(clientY - top);
+ }
+ return (
+ setVisible(true)}
+ onMouseLeave={() => setVisible(false)}
+ className="p-[2px] rounded-lg transition duration-300 group/input"
+ >
+
+
+ );
+ }
+);
+StyledInput.displayName = "Input";
+
+export { StyledInput };
diff --git a/apps/marketing/tailwind.config.ts b/apps/marketing/tailwind.config.ts
new file mode 100644
index 0000000..37212a9
--- /dev/null
+++ b/apps/marketing/tailwind.config.ts
@@ -0,0 +1,8 @@
+import { type Config } from "tailwindcss";
+import sharedConfig from "@unsend/tailwind-config/tailwind.config";
+import path from "path";
+
+export default {
+ ...sharedConfig,
+ content: ["./src/**/*.tsx"],
+} satisfies Config;
diff --git a/apps/marketing/tsconfig.json b/apps/marketing/tsconfig.json
new file mode 100644
index 0000000..7e53db7
--- /dev/null
+++ b/apps/marketing/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "extends": "@unsend/typescript-config/nextjs.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "~/*": ["./src/*"]
+ },
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "strictNullChecks": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ "**/*.cjs",
+ "**/*.js",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": ["node_modules"]
+}
diff --git a/apps/web/package.json b/apps/web/package.json
index 6580dd1..fa54891 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -4,7 +4,7 @@
"private": true,
"type": "module",
"scripts": {
- "dev": "next dev",
+ "dev": "next dev -p 3000",
"build": "next build",
"start": "next start",
"lint": "eslint . --max-warnings 0",
diff --git a/apps/web/public/unsend_white_logo.png b/apps/web/public/unsend_white_logo.png
new file mode 100644
index 0000000..0e773b5
Binary files /dev/null and b/apps/web/public/unsend_white_logo.png differ
diff --git a/apps/web/public/unsend_white_new.png b/apps/web/public/unsend_white_new.png
new file mode 100644
index 0000000..7f4a664
Binary files /dev/null and b/apps/web/public/unsend_white_new.png differ
diff --git a/apps/web/src/app/(dashboard)/dashboard/page.tsx b/apps/web/src/app/(dashboard)/dashboard/page.tsx
index 6ff7149..1cc08a0 100644
--- a/apps/web/src/app/(dashboard)/dashboard/page.tsx
+++ b/apps/web/src/app/(dashboard)/dashboard/page.tsx
@@ -1,5 +1,29 @@
-import type { Metadata } from "next";
+import Link from "next/link";
+import {
+ Bell,
+ CircleUser,
+ Home,
+ LineChart,
+ Menu,
+ Package,
+ Package2,
+ Search,
+ ShoppingCart,
+ Users,
+} from "lucide-react";
+import { Button } from "@unsend/ui/src/button";
-export default async function DashboardPage() {
- return Hello world
;
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@unsend/ui/src/dropdown-menu";
+import { Input } from "@unsend/ui/src/input";
+import { Sheet, SheetContent, SheetTrigger } from "@unsend/ui/src/sheet";
+
+export default function Dashboard() {
+ return Hello
;
}
diff --git a/apps/web/src/app/(dashboard)/layout.tsx b/apps/web/src/app/(dashboard)/layout.tsx
index 7c92a7f..a95f76e 100644
--- a/apps/web/src/app/(dashboard)/layout.tsx
+++ b/apps/web/src/app/(dashboard)/layout.tsx
@@ -1,7 +1,39 @@
import Link from "next/link";
import { redirect } from "next/navigation";
+import {
+ Bell,
+ CircleUser,
+ Globe,
+ Home,
+ KeyRound,
+ LayoutDashboard,
+ LineChart,
+ Mail,
+ Menu,
+ Package,
+ Package2,
+ Search,
+ ShoppingCart,
+ Users,
+} from "lucide-react";
+import { Button } from "@unsend/ui/src/button";
+
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@unsend/ui/src/dropdown-menu";
+import { Input } from "@unsend/ui/src/input";
+import { Sheet, SheetContent, SheetTrigger } from "@unsend/ui/src/sheet";
+
import { NextAuthProvider } from "~/providers/next-auth";
import { getServerAuthSession } from "~/server/auth";
+import Image from "next/image";
+import { useRouter } from "next/navigation";
+import { NavButton } from "./nav-button";
export const metadata = {
title: "Unsend",
@@ -22,19 +54,131 @@ export default async function AuthenticatedDashboardLayout({
return (
-
-