diff --git a/package-lock.json b/package-lock.json
index a39c00d..e961466 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,7 @@
"lucide-svelte": "^0.373.0",
"mode-watcher": "^0.3.0",
"svelte-markdown": "^0.4.1",
+ "svelte-motion": "^0.12.2",
"svelte-radix": "^1.1.0",
"svelte-sonner": "^0.3.22",
"sveltekit-superforms": "^2.12.6",
@@ -25,6 +26,7 @@
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
+ "@tabler/icons-svelte": "^3.3.0",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.32",
"postcss-load-config": "^5.0.2",
@@ -32,8 +34,11 @@
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.5.9",
"svelte": "^4.2.7",
+ "svelte-awesome-color-picker": "^3.0.6",
"svelte-check": "^3.6.0",
+ "svelte-legos": "^0.2.2",
"tailwindcss": "^3.3.6",
+ "timeago.js": "^4.0.2",
"typescript": "^5.0.0",
"vite": "^5.0.3"
}
@@ -937,6 +942,32 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@tabler/icons": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.3.0.tgz",
+ "integrity": "sha512-PLVe9d7b59sKytbx00KgeGhQG3N176Ezv8YMmsnSz4s0ifDzMWlp/h2wEfQZ0ZNe8e377GY2OW6kovUe3Rnd0g==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/codecalm"
+ }
+ },
+ "node_modules/@tabler/icons-svelte": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@tabler/icons-svelte/-/icons-svelte-3.3.0.tgz",
+ "integrity": "sha512-1NJvaT6w68j3y1c8lJSohRFKzpRT4LcTK7pPW1kGN7JXPJfh2efIw705dA0jxuwRClMrTxZt8BmEd6TRKQMqtA==",
+ "dev": true,
+ "dependencies": {
+ "@tabler/icons": "3.3.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/codecalm"
+ },
+ "peerDependencies": {
+ "svelte": ">=3 <5"
+ }
+ },
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
@@ -959,12 +990,26 @@
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-5.0.2.tgz",
"integrity": "sha512-OucS4KMHhFzhz27KxmWg7J+kIYqyqoW5kdIEI319hqARQQUTqhao3M/F+uFnDXD0Rg72iDDZxZNxq5gvctmLlg=="
},
+ "node_modules/@types/prop-types": {
+ "version": "15.7.12",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
+ "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
+ },
"node_modules/@types/pug": {
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz",
"integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==",
"dev": true
},
+ "node_modules/@types/react": {
+ "version": "18.3.2",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz",
+ "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/@types/validator": {
"version": "13.11.9",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz",
@@ -1280,6 +1325,16 @@
}
]
},
+ "node_modules/canvas-confetti": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.3.tgz",
+ "integrity": "sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==",
+ "dev": true,
+ "funding": {
+ "type": "donate",
+ "url": "https://www.paypal.me/kirilvatev"
+ }
+ },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -1339,6 +1394,12 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "node_modules/colord": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
+ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
+ "dev": true
+ },
"node_modules/commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
@@ -1397,6 +1458,11 @@
"node": ">=4"
}
},
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+ },
"node_modules/dayjs": {
"version": "1.11.10",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
@@ -1663,6 +1729,19 @@
"url": "https://github.com/sponsors/rawify"
}
},
+ "node_modules/framesync": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.1.2.tgz",
+ "integrity": "sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==",
+ "dependencies": {
+ "tslib": "2.4.0"
+ }
+ },
+ "node_modules/framesync/node_modules/tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -1748,6 +1827,11 @@
"node": ">= 0.4"
}
},
+ "node_modules/hey-listen": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
+ "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="
+ },
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -2254,6 +2338,22 @@
"node": ">= 6"
}
},
+ "node_modules/popmotion": {
+ "version": "11.0.5",
+ "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.5.tgz",
+ "integrity": "sha512-la8gPM1WYeFznb/JqF4GiTkRRPZsfaj2+kCxqQgr2MJylMmIKUwBfWW8Wa5fml/8gmtlD5yI01MP1QCZPWmppA==",
+ "dependencies": {
+ "framesync": "6.1.2",
+ "hey-listen": "^1.0.8",
+ "style-value-types": "5.1.2",
+ "tslib": "2.4.0"
+ }
+ },
+ "node_modules/popmotion/node_modules/tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
+ },
"node_modules/postcss": {
"version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
@@ -2484,6 +2584,21 @@
}
}
},
+ "node_modules/prism-svelte": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/prism-svelte/-/prism-svelte-0.5.0.tgz",
+ "integrity": "sha512-db91Bf3pRGKDPz1lAqLFSJXeW13mulUJxhycysFpfXV5MIK7RgWWK2E5aPAa71s8TCzQUXxF5JOV42/iOs6QkA==",
+ "dev": true
+ },
+ "node_modules/prismjs": {
+ "version": "1.29.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
+ "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/property-expr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
@@ -2850,6 +2965,20 @@
"node": ">=8"
}
},
+ "node_modules/style-value-types": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.1.2.tgz",
+ "integrity": "sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==",
+ "dependencies": {
+ "hey-listen": "^1.0.8",
+ "tslib": "2.4.0"
+ }
+ },
+ "node_modules/style-value-types/node_modules/tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
+ },
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
@@ -2958,6 +3087,28 @@
"node": ">=16"
}
},
+ "node_modules/svelte-awesome-color-picker": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/svelte-awesome-color-picker/-/svelte-awesome-color-picker-3.0.6.tgz",
+ "integrity": "sha512-lkyT9+78mpvzUm6yZLh2RKGHJn9U/XOZsc+WrCZVPaNTRnleled3dwR+EX0SgiAeFV7V/ieK3bu4wpgU0HRFlQ==",
+ "dev": true,
+ "dependencies": {
+ "colord": "^2.9.3",
+ "svelte-awesome-slider": "^1.1.0"
+ },
+ "peerDependencies": {
+ "svelte": "^3.55.1 || ^4.0.0"
+ }
+ },
+ "node_modules/svelte-awesome-slider": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/svelte-awesome-slider/-/svelte-awesome-slider-1.1.0.tgz",
+ "integrity": "sha512-MgY6ZdBON42HVZqNWNjq2HOgyDlC35q0TNbV/YO1l1/bcb5yhM8EE97h1AJ/7F6t6sLzXhQ3qPf5nGyCdDSnCg==",
+ "dev": true,
+ "peerDependencies": {
+ "svelte": "^3.54.0 || ^4.0.0"
+ }
+ },
"node_modules/svelte-check": {
"version": "3.6.9",
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.6.9.tgz",
@@ -2991,6 +3142,20 @@
"svelte": "^3.19.0 || ^4.0.0"
}
},
+ "node_modules/svelte-legos": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/svelte-legos/-/svelte-legos-0.2.2.tgz",
+ "integrity": "sha512-HTVkCIqhrxdy+OpXjxGr/4xIJEGv4d2cRQwTjm0SYfLw/YF1I1l/TQR59nb2WvjccnO8TNFNTvAWP5pgXQnU+w==",
+ "dev": true,
+ "dependencies": {
+ "canvas-confetti": "^1.6.0",
+ "prism-svelte": "^0.5.0",
+ "prismjs": "^1.29.0"
+ },
+ "peerDependencies": {
+ "svelte": "^4.0.0"
+ }
+ },
"node_modules/svelte-markdown": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/svelte-markdown/-/svelte-markdown-0.4.1.tgz",
@@ -3003,6 +3168,21 @@
"svelte": "^4.0.0"
}
},
+ "node_modules/svelte-motion": {
+ "version": "0.12.2",
+ "resolved": "https://registry.npmjs.org/svelte-motion/-/svelte-motion-0.12.2.tgz",
+ "integrity": "sha512-7RrdRz9iVP55B9HT/C0hYW3pyrKlF61kAby/AkDtOAP0uHFQDrfd0qQetDC81cEsK9b40jt+jfcqSAXcA7LPEw==",
+ "dependencies": {
+ "@types/react": "^18.2.42",
+ "framesync": "^6.1.2",
+ "popmotion": "^11.0.5",
+ "style-value-types": "5.1.2",
+ "tslib": "^2.6.2"
+ },
+ "peerDependencies": {
+ "svelte": ">=3.35.0 || ^4.0.0 || ^5.0.0 || ^5.0.0-next.0"
+ }
+ },
"node_modules/svelte-preprocess": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.4.tgz",
@@ -3313,6 +3493,12 @@
"node": ">=0.8"
}
},
+ "node_modules/timeago.js": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/timeago.js/-/timeago.js-4.0.2.tgz",
+ "integrity": "sha512-a7wPxPdVlQL7lqvitHGGRsofhdwtkoSXPGATFuSOA2i1ZNQEPLrGnj68vOp2sOJTCFAQVXPeNMX/GctBaO9L2w==",
+ "dev": true
+ },
"node_modules/tiny-case": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
diff --git a/package.json b/package.json
index 0060353..4d70210 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
+ "@tabler/icons-svelte": "^3.3.0",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.32",
"postcss-load-config": "^5.0.2",
@@ -22,8 +23,11 @@
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.5.9",
"svelte": "^4.2.7",
+ "svelte-awesome-color-picker": "^3.0.6",
"svelte-check": "^3.6.0",
+ "svelte-legos": "^0.2.2",
"tailwindcss": "^3.3.6",
+ "timeago.js": "^4.0.2",
"typescript": "^5.0.0",
"vite": "^5.0.3"
},
@@ -35,6 +39,7 @@
"lucide-svelte": "^0.373.0",
"mode-watcher": "^0.3.0",
"svelte-markdown": "^0.4.1",
+ "svelte-motion": "^0.12.2",
"svelte-radix": "^1.1.0",
"svelte-sonner": "^0.3.22",
"sveltekit-superforms": "^2.12.6",
diff --git a/src/app.html b/src/app.html
index 77a5ff5..009e878 100644
--- a/src/app.html
+++ b/src/app.html
@@ -6,7 +6,7 @@
%sveltekit.head%
-
+
%sveltekit.body%
diff --git a/src/lib/components/molecules/BackgroundBeams.svelte b/src/lib/components/molecules/BackgroundBeams.svelte
new file mode 100644
index 0000000..97bcef3
--- /dev/null
+++ b/src/lib/components/molecules/BackgroundBeams.svelte
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+ {#each paths as path, index (index)}
+
+
+
+ {/each}
+
+ {#each paths as path, index (`gradient-${index}`)}
+
+
+
+
+
+
+
+
+ {/each}
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/components/ui/pagination/index.js b/src/lib/components/ui/pagination/index.js
new file mode 100644
index 0000000..5641d52
--- /dev/null
+++ b/src/lib/components/ui/pagination/index.js
@@ -0,0 +1,24 @@
+import Root from "./pagination.svelte";
+import Content from "./pagination-content.svelte";
+import Item from "./pagination-item.svelte";
+import Link from "./pagination-link.svelte";
+import PrevButton from "./pagination-prev-button.svelte";
+import NextButton from "./pagination-next-button.svelte";
+import Ellipsis from "./pagination-ellipsis.svelte";
+export {
+ Root,
+ Content,
+ Item,
+ Link,
+ PrevButton,
+ NextButton,
+ Ellipsis,
+ //
+ Root as Pagination,
+ Content as PaginationContent,
+ Item as PaginationItem,
+ Link as PaginationLink,
+ PrevButton as PaginationPrevButton,
+ NextButton as PaginationNextButton,
+ Ellipsis as PaginationEllipsis,
+};
diff --git a/src/lib/components/ui/pagination/pagination-content.svelte b/src/lib/components/ui/pagination/pagination-content.svelte
new file mode 100644
index 0000000..4d21697
--- /dev/null
+++ b/src/lib/components/ui/pagination/pagination-content.svelte
@@ -0,0 +1,9 @@
+
+
+
diff --git a/src/lib/components/ui/pagination/pagination-ellipsis.svelte b/src/lib/components/ui/pagination/pagination-ellipsis.svelte
new file mode 100644
index 0000000..2cd6a80
--- /dev/null
+++ b/src/lib/components/ui/pagination/pagination-ellipsis.svelte
@@ -0,0 +1,15 @@
+
+
+
+
+ More pages
+
diff --git a/src/lib/components/ui/pagination/pagination-item.svelte b/src/lib/components/ui/pagination/pagination-item.svelte
new file mode 100644
index 0000000..70fdb98
--- /dev/null
+++ b/src/lib/components/ui/pagination/pagination-item.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/pagination/pagination-link.svelte b/src/lib/components/ui/pagination/pagination-link.svelte
new file mode 100644
index 0000000..22102b6
--- /dev/null
+++ b/src/lib/components/ui/pagination/pagination-link.svelte
@@ -0,0 +1,25 @@
+
+
+
+ {page.value}
+
diff --git a/src/lib/components/ui/pagination/pagination-next-button.svelte b/src/lib/components/ui/pagination/pagination-next-button.svelte
new file mode 100644
index 0000000..d7c746e
--- /dev/null
+++ b/src/lib/components/ui/pagination/pagination-next-button.svelte
@@ -0,0 +1,23 @@
+
+
+
+
+
+ Next
+
+
+
+
diff --git a/src/lib/components/ui/pagination/pagination-prev-button.svelte b/src/lib/components/ui/pagination/pagination-prev-button.svelte
new file mode 100644
index 0000000..db6c46c
--- /dev/null
+++ b/src/lib/components/ui/pagination/pagination-prev-button.svelte
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ Previous
+
+
+
diff --git a/src/lib/components/ui/pagination/pagination.svelte b/src/lib/components/ui/pagination/pagination.svelte
new file mode 100644
index 0000000..2122f6b
--- /dev/null
+++ b/src/lib/components/ui/pagination/pagination.svelte
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
diff --git a/src/lib/utils.js b/src/lib/utils.js
index 29aa840..1562a25 100644
--- a/src/lib/utils.js
+++ b/src/lib/utils.js
@@ -2,6 +2,11 @@ import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
import { cubicOut } from "svelte/easing";
+/**
+ *
+ * @param {import("clsx").ClassValue[]} inputs
+ * @returns
+ */
export function cn(...inputs) {
return twMerge(clsx(inputs));
}
diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte
deleted file mode 100644
index baa712c..0000000
--- a/src/routes/(app)/+page.svelte
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
-
-
-
- Total Articles
-
-
-
- 48
- 7 remaining this month
-
-
-
-
- Subscriptions
-
-
-
- +2350
- +180.1% from last month
-
-
-
-
- Emails collected
-
-
-
- +12,234
- +19% from last month
-
-
-
-
- Reads
-
-
-
- +573
- +201 since last hour
-
-
-
-
-
-
-
- Articles
- Recent articles written from your youtube videos.
-
-
- View All
-
-
-
-
-
-
-
- Customer
- Type
- Status
- Date
- Amount
-
-
-
-
-
- Liam Johnson
- liam@example.com
-
- Sale
-
- Approved
-
-
- 2023-06-23
-
- $250.00
-
-
-
- Olivia Smith
- olivia@example.com
-
- Refund
-
- Declined
-
-
- 2023-06-24
-
- $150.00
-
-
-
- Noah Williams
- noah@example.com
-
- Subscription
-
- Approved
-
-
- 2023-06-25
-
- $350.00
-
-
-
- Emma Brown
- emma@example.com
-
- Sale
-
- Approved
-
-
- 2023-06-26
-
- $450.00
-
-
-
- Liam Johnson
- liam@example.com
-
- Sale
-
- Approved
-
-
- 2023-06-27
-
- $550.00
-
-
-
-
-
-
-
- Recent Signups
-
-
-
-
-
- OM
-
-
-
Olivia Martin
-
olivia.martin@email.com
-
-
56 seconds ago
-
-
-
-
- JL
-
-
-
Jackson Lee
-
jackson.lee@email.com
-
-
2 minutes ago
-
-
-
-
- IN
-
-
-
Isabella Nguyen
-
isabella.nguyen@email.com
-
-
5 minutes ago
-
-
-
-
- WK
-
-
-
William Kim
-
will@email.com
-
-
9 minutes ago
-
-
-
-
- SD
-
-
-
Sofia Davis
-
sofia.davis@email.com
-
-
15 minutes ago
-
-
-
-
-
diff --git a/src/routes/(app)/articles/+page.svelte b/src/routes/(app)/articles/+page.svelte
deleted file mode 100644
index 7487691..0000000
--- a/src/routes/(app)/articles/+page.svelte
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
-
- A list of your recent articles.
-
-
- ID
- Title
- Source
- Actions
-
-
-
- {#each data.articles as article, i (i)}
-
- {i+1}
- {article.title}
- {"Youtube"}
-
- window.open("/site/" + data.site.id + "/" + article.seo_slug)}>
-
-
- editArticle(article.id)}>
-
-
-
-
-
-
-
- {/each}
-
-
-
-
-
-
-
diff --git a/src/routes/(app)/articles/createArticleDialog.svelte b/src/routes/(app)/articles/createArticleDialog.svelte
deleted file mode 100644
index 4161475..0000000
--- a/src/routes/(app)/articles/createArticleDialog.svelte
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
- Create Article
-
-
- Create Article
-
- Configure your article and let our AI do the writing!
-
-
-
-
-
-
-
-
Youtube video*
-
-
-
-
-
-
-
- {#each videos as video}
- {video.snippet.title}
- {/each}
-
-
-
-
-
-
-
Article length
-
-
-
-
-
-
- Short (~700 words)
- Medium (~1500 words)
- Long (~2500 words)
-
-
-
-
-
-
-
Format
-
-
-
-
-
-
- Summary
- Listicle
- Product Review
- News Report
- Tutorial
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Create
-
-
-
\ No newline at end of file
diff --git a/src/routes/(auth)/auth/+page.svelte b/src/routes/(auth)/auth/+page.svelte
deleted file mode 100644
index c3a4a4a..0000000
--- a/src/routes/(auth)/auth/+page.svelte
+++ /dev/null
@@ -1,6 +0,0 @@
-
-Log in here you fat bastard
\ No newline at end of file
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
new file mode 100644
index 0000000..eff402c
--- /dev/null
+++ b/src/routes/+page.svelte
@@ -0,0 +1,39 @@
+
+
+
+
+
+ Join the waitlist
+
+
+
+ Welcome to ExampleSaaS, the best solution for converting your video content into an engaging
+ blog website. Sign up to our waitlist to get notified when we launch and earn some free goodies as well.
+
+
+
+
+
+ Join Waitlist
+
+
+
+
+ {#if $isDesktop}
+
+ {/if}
+
diff --git a/src/routes/(app)/+layout.server.js b/src/routes/app/(app)/+layout.server.js
similarity index 75%
rename from src/routes/(app)/+layout.server.js
rename to src/routes/app/(app)/+layout.server.js
index 9a4f80e..13ff133 100644
--- a/src/routes/(app)/+layout.server.js
+++ b/src/routes/app/(app)/+layout.server.js
@@ -3,7 +3,10 @@ import { redirect } from "@sveltejs/kit";
/** @type {import("./$types").LayoutServerLoad} */
export const load = async ({fetch, cookies}) => {
- if(!cookies.get("token")) return redirect(302, "/auth")
+ if(!cookies.get("token")) {
+ console.log("ruh roh no token")
+ return redirect(302, "/auth")
+ }
const res = await fetch(config.api_url+"/me")
if(res.status > 399 && res.status < 499) {
cookies.delete("token", {
@@ -15,6 +18,6 @@ export const load = async ({fetch, cookies}) => {
const data = await res.json();
return {
- me: data
+ me: data.user
}
}
\ No newline at end of file
diff --git a/src/routes/(app)/+layout.svelte b/src/routes/app/(app)/+layout.svelte
similarity index 90%
rename from src/routes/(app)/+layout.svelte
rename to src/routes/app/(app)/+layout.svelte
index b248b00..5b04cc4 100644
--- a/src/routes/(app)/+layout.svelte
+++ b/src/routes/app/(app)/+layout.svelte
@@ -1,5 +1,5 @@
@@ -38,7 +43,7 @@
>
- {data.me.user.name}
+ {data.me.name}
{#each navs as nav}
{nav.name}
@@ -110,7 +115,7 @@
Settings
Support
- Logout
+ Logout
diff --git a/src/routes/app/(app)/+page.server.js b/src/routes/app/(app)/+page.server.js
new file mode 100644
index 0000000..85081e7
--- /dev/null
+++ b/src/routes/app/(app)/+page.server.js
@@ -0,0 +1,19 @@
+import { config } from "$lib"
+import { redirect } from "@sveltejs/kit";
+
+/** @type {import("./$types").PageServerLoad} */
+export const load = async ({fetch, cookies}) => {
+ const res = await fetch(config.api_url+"/dashboard")
+ if(res.status > 399 && res.status < 499) {
+ // cookies.delete("token", {
+ // path: "/"
+ // });
+
+ redirect(302, "/auth");
+ }
+ const data = await res.json();
+
+ return {
+ dashboard_info: data
+ }
+}
\ No newline at end of file
diff --git a/src/routes/app/(app)/+page.svelte b/src/routes/app/(app)/+page.svelte
new file mode 100644
index 0000000..ea18bf7
--- /dev/null
+++ b/src/routes/app/(app)/+page.svelte
@@ -0,0 +1,137 @@
+
+
+
+
+
+ Total Articles
+
+
+
+ 48
+ 7 remaining this month
+
+
+
+
+ Subscriptions
+
+
+
+ +2350
+ +180.1% from last month
+
+
+
+
+ Emails collected
+
+
+
+ +573
+ +19% from last month
+
+
+
+
+ Reads
+
+
+
+ +12,234
+ +201 since last hour
+
+
+
+
+
+
+
+ Articles
+ Recent articles written from your youtube videos.
+
+
+ View All
+
+
+
+
+
+
+
+ Title
+ Date
+ Views
+
+
+
+ {#each data.dashboard_info.recentArticles as article}
+
+
+ {article.title}
+
+
+ {new Date(article.created_at).toLocaleDateString()}
+ {article.views}
+
+ {/each}
+
+
+
+
+
+
+
+ Recent Signups
+
+
+
+ View All
+
+
+
+
+ {#each data.dashboard_info.recentSignups as signup}
+
+
+
+
{signup.created_at > 1000 * 60 * 60 * 24 * 7 ? new Date(signup.created_at).toLocaleDateString() : format(new Date(signup.created_at))}
+
+ {/each}
+
+
+
+
diff --git a/src/routes/(app)/articles/+page.server.js b/src/routes/app/(app)/articles/+page.server.js
similarity index 69%
rename from src/routes/(app)/articles/+page.server.js
rename to src/routes/app/(app)/articles/+page.server.js
index 8427e06..39f8674 100644
--- a/src/routes/(app)/articles/+page.server.js
+++ b/src/routes/app/(app)/articles/+page.server.js
@@ -1,23 +1,26 @@
import { config } from "$lib"
-import { message, superValidate } from "sveltekit-superforms";
+import { message, setError, superValidate, fail } from "sveltekit-superforms";
import { createFormSchema, editFormSchema } from "./schema";
import { zod } from "sveltekit-superforms/adapters";
-import { fail } from "@sveltejs/kit";
/** @type {import("./$types").PageServerLoad} */
-export const load = async ({ fetch }) => {
- const blogRes = await fetch(config.api_url + "/blog?mine=true", {
+export const load = async ({ fetch, url, request }) => {
+ const offset = (Number(url.searchParams.get("page") || 1) - 1) * 10;
+ // @ts-ignore
+ const blogRes = await fetch(config.api_url + "/blog?mine=true&offset=" + offset, {
credentials: 'include'
});
+ // const page = capPage(Number(url.searchParams.get("page")) || 1);
const videosRes = await fetch(config.api_url + "/videos", {
credentials: 'include'
});
-
+
const dataBlog = await blogRes.json();
const dataVideos = await videosRes.json();
return {
articles: dataBlog.articles,
+ total_articles: dataBlog.total_articles,
site: dataBlog.site,
videos: dataVideos.videos,
createForm: await superValidate(zod(createFormSchema)),
@@ -35,7 +38,9 @@ export const actions = {
form,
});
}
- const res = await event.fetch(config.api_url + "/blog/create", {
+
+ console.log(form.data);
+ const res = await event.fetch(config.api_url + "/dashboard/create", {
method: "POST",
body: JSON.stringify(form.data),
headers: {
@@ -43,6 +48,13 @@ export const actions = {
}
});
+ const resData = await res.json();
+
+ if(!resData.success) {
+ // console.log(resData)
+ return setError(form, resData.message);
+ }
+
return {
form,
};
@@ -55,7 +67,7 @@ export const actions = {
});
}
- const res = await event.fetch(config.api_url + "/blog/article", {
+ const res = await event.fetch(config.api_url + "/dashboard/article", {
method: "PUT",
body: JSON.stringify(form.data),
headers: {
@@ -75,4 +87,13 @@ export const actions = {
form
}
}
-};
\ No newline at end of file
+};
+
+/**
+ *
+ * @param {number} pageN
+ * @returns {number}
+ */
+function capPage(pageN) {
+ return pageN > 0 ? pageN : 1
+}
\ No newline at end of file
diff --git a/src/routes/app/(app)/articles/+page.svelte b/src/routes/app/(app)/articles/+page.svelte
new file mode 100644
index 0000000..bf54fc3
--- /dev/null
+++ b/src/routes/app/(app)/articles/+page.svelte
@@ -0,0 +1,165 @@
+
+
+
+
+ {#if data.articles.length > 0}
+ {#if isLoading}
+
+
+
+ {/if}
+
+
+
+ Visibility
+ Title
+ Source
+ Views
+ Actions
+
+
+
+ {#each data.articles as article, i (i)}
+
+
+ {#if article.is_public}
+
+ {:else}
+
+ {/if}
+
+ {article.id}
+ {'Youtube'}
+ {article.views}
+
+ window.open('/site/' + data.site.id + '/' + article.seo_slug)}
+ >
+
+
+ editArticle(article.id)}
+ >
+
+
+
+
+
+
+
+ {/each}
+
+
+
+
+
+
+
+
+ Previous
+
+
+ {#each pages as page (page.key)}
+ {#if page.type === 'ellipsis'}
+
+
+
+ {:else}
+
+ {
+ const pageQuery = new URLSearchParams(window.location.search);
+ if(pageQuery.get("page") == page.value.toString()) return;
+ console.log("fetching...")
+ pageQuery.set("page", page.value.toString())
+
+ window.location.search = pageQuery.toString();
+ isLoading = true
+ }}>
+ {page.value}
+
+
+ {/if}
+ {/each}
+
+
+ Next
+
+
+
+
+
+ {:else}
+
+ You don't have any articles yet. Start by making one!
+
+ {/if}
+
+
+
+
+
diff --git a/src/routes/app/(app)/articles/createArticleDialog.svelte b/src/routes/app/(app)/articles/createArticleDialog.svelte
new file mode 100644
index 0000000..b81029d
--- /dev/null
+++ b/src/routes/app/(app)/articles/createArticleDialog.svelte
@@ -0,0 +1,175 @@
+
+
+
+ Create Article
+
+
+ Create Article
+ Configure your article and let our AI do the writing!
+
+
+
+
+
+
+
Youtube video*
+
+
+
+
+
+
+
+ {#each videos as video}
+ {video.snippet.title}
+ {/each}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Article length
+
+
+
+
+
+
+ Short (~700 words)
+ Medium (~1500 words)
+ Long (~2500 words)
+
+
+
+
+
+
+
+
+
+
+
+
+
Format
+
+
+
+
+
+
+ Summary
+ Listicle
+ Product Review
+ News Report
+ Tutorial
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
diff --git a/src/routes/(app)/articles/editArticleDialog.svelte b/src/routes/app/(app)/articles/editArticleDialog.svelte
similarity index 100%
rename from src/routes/(app)/articles/editArticleDialog.svelte
rename to src/routes/app/(app)/articles/editArticleDialog.svelte
diff --git a/src/routes/(app)/articles/getArticleBody/+server.js b/src/routes/app/(app)/articles/getArticleBody/+server.js
similarity index 100%
rename from src/routes/(app)/articles/getArticleBody/+server.js
rename to src/routes/app/(app)/articles/getArticleBody/+server.js
diff --git a/src/routes/(app)/articles/schema.js b/src/routes/app/(app)/articles/schema.js
similarity index 100%
rename from src/routes/(app)/articles/schema.js
rename to src/routes/app/(app)/articles/schema.js
diff --git a/src/routes/(app)/emails/+page.server.js b/src/routes/app/(app)/emails/+page.server.js
similarity index 78%
rename from src/routes/(app)/emails/+page.server.js
rename to src/routes/app/(app)/emails/+page.server.js
index 2253af0..a820bac 100644
--- a/src/routes/(app)/emails/+page.server.js
+++ b/src/routes/app/(app)/emails/+page.server.js
@@ -2,7 +2,7 @@ import { config } from "$lib";
/** @type {import("./$types").PageServerLoad} */
export const load = async ({ fetch }) => {
- const signupsRes = await fetch(config.api_url + "/blog/signups", {
+ const signupsRes = await fetch(config.api_url + "/dashboard/signups", {
credentials: 'include'
});
diff --git a/src/routes/(app)/emails/+page.svelte b/src/routes/app/(app)/emails/+page.svelte
similarity index 56%
rename from src/routes/(app)/emails/+page.svelte
rename to src/routes/app/(app)/emails/+page.svelte
index 7c4f1ab..0ddb9c9 100644
--- a/src/routes/(app)/emails/+page.svelte
+++ b/src/routes/app/(app)/emails/+page.svelte
@@ -1,30 +1,59 @@
+
+ Export as CSV
+
+
A list of recent signups on your website.
Email
- Date
+ Date and Time
Actions
{#each data.signups as signup, i (i)}
-
+
{signup.email}
- {new Date(signup.created_at).toLocaleDateString()}
+ {new Date(signup.created_at).toLocaleString()}
- {/each}
-
-
+ {/each}
+
+
diff --git a/src/routes/app/(app)/emails/export/+server.js b/src/routes/app/(app)/emails/export/+server.js
new file mode 100644
index 0000000..2cc7505
--- /dev/null
+++ b/src/routes/app/(app)/emails/export/+server.js
@@ -0,0 +1,8 @@
+import { config } from '$lib';
+import { error, json, text } from '@sveltejs/kit';
+
+/** @type {import('./$types').RequestHandler} */
+export async function GET(event) {
+ const exportedCsv = await event.fetch(config.api_url + "/dashboard/signups/export").then(x=>x.json());
+ return new Response(exportedCsv.data);
+}
diff --git a/src/routes/app/(app)/website/+page.server.js b/src/routes/app/(app)/website/+page.server.js
new file mode 100644
index 0000000..f250971
--- /dev/null
+++ b/src/routes/app/(app)/website/+page.server.js
@@ -0,0 +1,54 @@
+import { config } from "$lib";
+import { fail, message, superValidate } from "sveltekit-superforms";
+import { schema } from "./schema";
+import { zod } from "sveltekit-superforms/adapters";
+
+/** @type {import("./$types").PageServerLoad} */
+export const load = async ({ fetch }) => {
+ const blogRes = await fetch(config.api_url + "/blog?mine=true", {
+ credentials: 'include'
+ });
+
+ const {site} = await blogRes.json();
+ site.primary_color_hex = "#" + site.primary_color_hex
+ site.secondary_color_hex = "#" + site.secondary_color_hex
+ site.text_color_hex = "#" + site.text_color_hex
+ return {
+ blog_info: site,
+ form: await superValidate(site, zod(schema))
+ }
+}
+
+/** @type {import("@sveltejs/kit").Actions} */
+export const actions = {
+ default: async (event) => {
+ const form = await superValidate(event, zod(schema));
+ if (!form.valid) {
+ return fail(400, {
+ form,
+ });
+ }
+
+ let data = structuredClone(form.data);
+ data.primary_color_hex = data.primary_color_hex.slice(1);
+ data.secondary_color_hex = data.secondary_color_hex.slice(1);
+ data.text_color_hex = data.text_color_hex.slice(1);
+
+ const res = await event.fetch(config.api_url + "/dashboard/website", {
+ method: "PUT",
+ body: JSON.stringify(data),
+ headers: {
+ "content-type": "application/json"
+ }
+ });
+ const res_data = await res.json();
+
+ if(!res_data.success) return fail(res.status, {
+ form
+ });
+
+ return {
+ form,
+ };
+ },
+}
\ No newline at end of file
diff --git a/src/routes/app/(app)/website/+page.svelte b/src/routes/app/(app)/website/+page.svelte
new file mode 100644
index 0000000..03e72a2
--- /dev/null
+++ b/src/routes/app/(app)/website/+page.svelte
@@ -0,0 +1,77 @@
+
+
+
+
+
+ Blog name
+
+
+
+
+
+
+
+ Primary color
+ {
+ if(e.detail.hex) $formData.primary_color_hex = e.detail.hex
+ }} hex={data.blog_info.primary_color_hex} {...attrs}/>
+
+
+
+
+
+
+ Secondary color
+ {
+ if(e.detail.hex) $formData.secondary_color_hex = e.detail.hex
+ }} hex={data.blog_info.secondary_color_hex} {...attrs}/>
+
+
+
+
+
+
+ Text color
+ {
+ if(e.detail.hex) $formData.text_color_hex = e.detail.hex
+ }} hex={data.blog_info.text_color_hex} {...attrs}/>
+
+
+
+
+
+ Submit
+
+
diff --git a/src/routes/app/(app)/website/schema.js b/src/routes/app/(app)/website/schema.js
new file mode 100644
index 0000000..7008cda
--- /dev/null
+++ b/src/routes/app/(app)/website/schema.js
@@ -0,0 +1,9 @@
+import { z } from "zod";
+
+export const schema = z.object({
+ id: z.string(),
+ name: z.string().min(4).max(16),
+ primary_color_hex: z.string().length(7),
+ secondary_color_hex: z.string().length(7),
+ text_color_hex: z.string().length(7),
+});
\ No newline at end of file
diff --git a/src/routes/(auth)/auth/+page.server.js b/src/routes/app/(auth)/auth/+page.server.js
similarity index 100%
rename from src/routes/(auth)/auth/+page.server.js
rename to src/routes/app/(auth)/auth/+page.server.js
diff --git a/src/routes/app/(auth)/auth/+page.svelte b/src/routes/app/(auth)/auth/+page.svelte
new file mode 100644
index 0000000..f2c17d6
--- /dev/null
+++ b/src/routes/app/(auth)/auth/+page.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/src/routes/app/(auth)/auth/logout/+server.js b/src/routes/app/(auth)/auth/logout/+server.js
new file mode 100644
index 0000000..c293af9
--- /dev/null
+++ b/src/routes/app/(auth)/auth/logout/+server.js
@@ -0,0 +1,8 @@
+/** @type {import('./$types').RequestHandler} */
+export function GET(event) {
+ event.cookies.delete("token", {
+ path: "/"
+ });
+
+ return new Response("success");
+}
\ No newline at end of file
diff --git a/src/routes/app/site/[site_id]/+layout.server.js b/src/routes/app/site/[site_id]/+layout.server.js
new file mode 100644
index 0000000..c16fd17
--- /dev/null
+++ b/src/routes/app/site/[site_id]/+layout.server.js
@@ -0,0 +1,20 @@
+import { config } from "$lib";
+import { error } from "@sveltejs/kit";
+import { articles } from "./store";
+import { fail, superValidate } from "sveltekit-superforms";
+import { zod } from "sveltekit-superforms/adapters";
+import { formSchema } from "./schema";
+
+/** @type {import("./$types").LayoutServerLoad} */
+export async function load(event) {
+ const data = await event.fetch(config.api_url + "/blog?mine=false&blog_id=" + event.params.site_id).then(x=>x.json());
+ if(!data.success) error(404);
+
+ articles.set(data.articles);
+
+ return {
+ articles: data.articles,
+ site: data.site,
+ root: event.url.origin + "/site/" + event.params.site_id
+ }
+}
\ No newline at end of file
diff --git a/src/routes/app/site/[site_id]/+layout.svelte b/src/routes/app/site/[site_id]/+layout.svelte
new file mode 100644
index 0000000..7797b72
--- /dev/null
+++ b/src/routes/app/site/[site_id]/+layout.svelte
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+ {#if is_subscribed}
+ Thank you for subscribing to our newsletter!
+ {:else}
+
+ {/if}
+
+
diff --git a/src/routes/site/[site_id]/+page.server.js b/src/routes/app/site/[site_id]/+page.server.js
similarity index 69%
rename from src/routes/site/[site_id]/+page.server.js
rename to src/routes/app/site/[site_id]/+page.server.js
index e971359..5cfea9d 100644
--- a/src/routes/site/[site_id]/+page.server.js
+++ b/src/routes/app/site/[site_id]/+page.server.js
@@ -6,18 +6,6 @@ import { zod } from "sveltekit-superforms/adapters";
import { formSchema } from "./schema";
-/** @type {import("./$types").PageServerLoad} */
-export async function load(event) {
- const data = await fetch(config.api_url + "/blog?mine=false&blog_id=" + event.params.site_id).then(x=>x.json());
- if(!data.success) error(404);
-
- articles.set(data.articles);
-
- return {
- ...{articles: data.articles, site: data.site}
- }
-}
-
/** @type {import("@sveltejs/kit").Actions} */
export const actions = {
default: async (event) => {
@@ -31,7 +19,8 @@ export const actions = {
method: "POST",
body: JSON.stringify({
email: form.data.email,
- site_id: event.params.site_id
+ site_id: event.params.site_id,
+ source: extractSlug(form.data.source)
}),
headers: {
"content-type": "application/json"
@@ -42,4 +31,13 @@ export const actions = {
form,
};
},
-};
\ No newline at end of file
+};
+
+/**
+ * @param {string | URL} url
+ */
+function extractSlug(url) {
+ const path = new URL(url).pathname;
+ const parts = path.split('/').filter(x=>x);
+ return parts[3]
+}
\ No newline at end of file
diff --git a/src/routes/app/site/[site_id]/+page.svelte b/src/routes/app/site/[site_id]/+page.svelte
new file mode 100644
index 0000000..c4a9ea3
--- /dev/null
+++ b/src/routes/app/site/[site_id]/+page.svelte
@@ -0,0 +1,19 @@
+
+
+
+ {#each data.articles as article}
+
+ {/each}
+
diff --git a/src/routes/site/[site_id]/[article_id]/+page.server.js b/src/routes/app/site/[site_id]/[article_id]/+page.server.js
similarity index 100%
rename from src/routes/site/[site_id]/[article_id]/+page.server.js
rename to src/routes/app/site/[site_id]/[article_id]/+page.server.js
diff --git a/src/routes/site/[site_id]/[article_id]/+page.svelte b/src/routes/app/site/[site_id]/[article_id]/+page.svelte
similarity index 82%
rename from src/routes/site/[site_id]/[article_id]/+page.svelte
rename to src/routes/app/site/[site_id]/[article_id]/+page.svelte
index 89b829d..563221b 100644
--- a/src/routes/site/[site_id]/[article_id]/+page.svelte
+++ b/src/routes/app/site/[site_id]/[article_id]/+page.svelte
@@ -1,8 +1,9 @@
-
+
{data.article.title}
diff --git a/src/routes/app/site/[site_id]/[article_id]/md-style.css b/src/routes/app/site/[site_id]/[article_id]/md-style.css
new file mode 100644
index 0000000..d48eb45
--- /dev/null
+++ b/src/routes/app/site/[site_id]/[article_id]/md-style.css
@@ -0,0 +1,9 @@
+h1 {
+ font-size: 1.8rem;
+ font-weight: 700;
+ margin-bottom: 1rem;
+}
+
+p {
+ margin-bottom: 1rem
+}
\ No newline at end of file
diff --git a/src/routes/site/[site_id]/schema.js b/src/routes/app/site/[site_id]/schema.js
similarity index 84%
rename from src/routes/site/[site_id]/schema.js
rename to src/routes/app/site/[site_id]/schema.js
index 550c0c8..cee02d9 100644
--- a/src/routes/site/[site_id]/schema.js
+++ b/src/routes/app/site/[site_id]/schema.js
@@ -2,6 +2,7 @@ import { z } from "zod";
export const formSchema = z.object({
email: z.string().email().min(1),
+ source: z.string().url()
});
/** @typedef {typeof formSchema} FormSchema */
\ No newline at end of file
diff --git a/src/routes/site/[site_id]/store.js b/src/routes/app/site/[site_id]/store.js
similarity index 100%
rename from src/routes/site/[site_id]/store.js
rename to src/routes/app/site/[site_id]/store.js
diff --git a/src/routes/site/[site_id]/+page.svelte b/src/routes/site/[site_id]/+page.svelte
deleted file mode 100644
index 13d1908..0000000
--- a/src/routes/site/[site_id]/+page.svelte
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-{data.site.name}
-
-
-
-
-
\ No newline at end of file
diff --git a/tailwind.config.js b/tailwind.config.js
index fa1cb36..ac21792 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,10 +1,14 @@
import { fontFamily } from "tailwindcss/defaultTheme";
+import flattenColorPalette from 'tailwindcss/lib/util/flattenColorPalette';
/** @type {import('tailwindcss').Config} */
const config = {
darkMode: ["class"],
content: ["./src/**/*.{html,js,svelte,ts}"],
safelist: ["dark"],
+ plugins: [
+ addVariablesForColors
+ ],
theme: {
container: {
center: true,
@@ -61,4 +65,15 @@ const config = {
},
};
+function addVariablesForColors({ addBase, theme }) {
+ let allColors = flattenColorPalette(theme('colors'));
+ let newVars = Object.fromEntries(
+ Object.entries(allColors).map(([key, val]) => [`--${key}`, val])
+ );
+
+ addBase({
+ ':root': newVars
+ });
+}
+
export default config;