diff --git a/website/components/ArticleCard.tsx b/website/components/ArticleCard.tsx new file mode 100644 index 00000000..e8bdfdac --- /dev/null +++ b/website/components/ArticleCard.tsx @@ -0,0 +1,138 @@ +import { Link, Flex, Box, chakra, Image, Button, Text } from "@chakra-ui/react"; +import { BlogPost } from "pages/blog"; +import { FC } from "react"; +import NavLink from "next/link"; + +const ArticleCard: FC = ({ + metadata: { + author, + author_avatar_url, + cover_image, + tags, + title, + summary, + date, + }, + slug, +}) => { + return ( + + Article + + + + {tags.map((tag, i) => { + return ( + + {tag} + + ); + })} + + + {title} + + + + {summary} + + + + + + + Avatar + + {author} + + + {date} + + + + + + + + + + ); +}; + +export default ArticleCard; diff --git a/website/components/DownloadButton.tsx b/website/components/DownloadButton.tsx index 17757ddb..add63569 100644 --- a/website/components/DownloadButton.tsx +++ b/website/components/DownloadButton.tsx @@ -10,26 +10,60 @@ import { } from "@chakra-ui/react"; import { Platform, usePlatform } from "hooks/usePlatform"; import React from "react"; -import { FaCaretDown } from "react-icons/fa"; +import { + FaApple, + FaCaretDown, + FaUbuntu, + FaLinux, + FaWindows, + FaAndroid, +} from "react-icons/fa"; const baseURL = "https://github.com/KRTirtho/spotube/releases/latest/download/"; const DownloadLinks = Object.freeze({ [Platform.linux]: [ - { name: "deb", url: baseURL + "Spotube-linux-x86_64.deb" }, - { name: "tar", url: baseURL + "Spotube-linux-x86_64.tar.xz" }, - { name: "AppImage", url: baseURL + "Spotube-linux-x86_64.AppImage" }, + { + name: "deb", + url: baseURL + "Spotube-linux-x86_64.deb", + icon: , + }, + { + name: "tar", + url: baseURL + "Spotube-linux-x86_64.tar.xz", + icon: , + }, + { + name: "AppImage", + url: baseURL + "Spotube-linux-x86_64.AppImage", + icon: , + }, ], [Platform.android]: [ { name: "apk", url: baseURL + "Spotube-android-all-arch.apk", + icon: , + }, + ], + [Platform.mac]: [ + { + name: "dmg", + url: baseURL + "Spotube-macos-x86_64.dmg", + icon: , }, ], - [Platform.mac]: [{ name: "dmg", url: baseURL + "Spotube-macos-x86_64.dmg" }], [Platform.windows]: [ - { name: "exe", url: baseURL + "Spotube-windows-x86_64-setup.exe" }, - { name: "nupkg", url: baseURL + "Spotube-windows-x86_64.nupkg " }, + { + name: "exe", + url: baseURL + "Spotube-windows-x86_64-setup.exe", + icon: , + }, + { + name: "nupkg", + url: baseURL + "Spotube-windows-x86_64.nupkg ", + icon: , + }, ], }); @@ -55,7 +89,7 @@ const DownloadButton = () => { href={currentPlatform.url} _hover={{ textDecoration: "none" }} > - Download for {platform} (.{currentPlatform.name}) Binary + Download for {platform} (.{currentPlatform.name}) { /> - {allPlatforms.map(({ name, url }) => { + {allPlatforms.map(({ name, url, icon }) => { return ( - + {name} ); diff --git a/website/components/Navbar.tsx b/website/components/Navbar.tsx index d74b9579..34ce9939 100644 --- a/website/components/Navbar.tsx +++ b/website/components/Navbar.tsx @@ -1,17 +1,29 @@ import { + Box, Button, ButtonGroup, + chakra, + CloseButton, + Flex, Heading, HStack, IconButton, + Link, useColorMode, + useColorModeValue, + useDisclosure, + VisuallyHidden, + VStack, } from "@chakra-ui/react"; import NavLink from "next/link"; import { GoLightBulb } from "react-icons/go"; -import { FiSun } from "react-icons/fi"; +import { FiGithub, FiSun } from "react-icons/fi"; import Image from "next/image"; +import React from "react"; +import { AiOutlineMenu } from "react-icons/ai"; +import { BsHeartFill } from "react-icons/bs"; -const Navbar = () => { +const ExNavbar = () => { const { colorMode, toggleColorMode } = useColorMode(); return ( @@ -34,6 +46,11 @@ const Navbar = () => { Downloads + + + + + + + + + + + + + + + } + onClick={mobileNav.onOpen} + /> + + + + + + + + + + + + + + + + + + + + ); +}; + export default Navbar; diff --git a/website/misc/MarkdownComponentDefs.tsx b/website/misc/MarkdownComponentDefs.tsx index 7e0ee614..f3c901ca 100644 --- a/website/misc/MarkdownComponentDefs.tsx +++ b/website/misc/MarkdownComponentDefs.tsx @@ -1,6 +1,16 @@ -import { Link as Anchor, Heading, Text, chakra } from "@chakra-ui/react"; +import { + Link as Anchor, + Heading, + Text, + chakra, + Code, + HStack, + Divider, + Box, +} from "@chakra-ui/react"; +import { Options } from "react-markdown"; -export const MarkdownComponentDefs = { +export const MarkdownComponentDefs: Options["components"] = { a: (props: any) => , h1: (props: any) => , h2: (props: any) => , @@ -10,4 +20,24 @@ export const MarkdownComponentDefs = { h6: (props: any) => , p: (props: any) => , li: (props: any) => , + code: (props) => ( + + ), + blockquote: (props) => { + return ( + + + + {props.children} + + + + ); + }, }; diff --git a/website/package.json b/website/package.json index 6e39a976..4c5ab9cc 100644 --- a/website/package.json +++ b/website/package.json @@ -18,6 +18,7 @@ "@octokit/rest": "^19.0.3", "@types/progress": "^2.0.5", "framer-motion": "^6", + "gray-matter": "^4.0.3", "next": "12.2.2", "nextjs-progressbar": "^0.0.14", "react": "18.2.0", @@ -32,6 +33,7 @@ "@types/node": "18.0.5", "@types/react": "18.0.15", "@types/react-dom": "18.0.6", + "@types/react-syntax-highlighter": "^15.5.3", "eslint": "8.20.0", "eslint-config-next": "12.2.2", "eslint-config-prettier": "^8.5.0", diff --git a/website/pages/api/hello.ts b/website/pages/api/hello.ts deleted file mode 100755 index f8bcc7e5..00000000 --- a/website/pages/api/hello.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from 'next' - -type Data = { - name: string -} - -export default function handler( - req: NextApiRequest, - res: NextApiResponse -) { - res.status(200).json({ name: 'John Doe' }) -} diff --git a/website/pages/blog/[slug].tsx b/website/pages/blog/[slug].tsx new file mode 100644 index 00000000..161b9503 --- /dev/null +++ b/website/pages/blog/[slug].tsx @@ -0,0 +1,105 @@ +import fs from "fs"; +import path from "path"; +import { GetStaticPaths, GetStaticProps, NextPage } from "next"; +import ReactMarkdown from "react-markdown"; +import matter from "gray-matter"; +import { BlogMetadata } from "."; +import gfm from "remark-gfm"; +import gemoji from "remark-gemoji"; +import { MarkdownComponentDefs } from "misc/MarkdownComponentDefs"; +import { + Box, + chakra, + Flex, + Heading, + Image, + Text, + VStack, +} from "@chakra-ui/react"; + +interface Props { + metadata: BlogMetadata; + content: string; +} + +const BlogPost: NextPage = ({ + content, + metadata: { author, author_avatar_url, cover_image, date, tags, title }, +}) => { + return ( + + + {title} + + + + Avatar + + + {author} + + + {date} + + + + {title} + + + {content} + + + + ); +}; + +export default BlogPost; + +export const getStaticPaths: GetStaticPaths = async () => { + const paths = fs.readdirSync("posts").map((file) => { + return { + params: { + slug: file.replace(".md", ""), + }, + }; + }); + return { + paths, + fallback: false, + }; +}; + +export const getStaticProps: GetStaticProps = async (ctx) => { + const { content, data } = matter( + fs.readFileSync(path.join("posts", `${ctx.params?.slug}.md`), "utf-8") + ); + return { + props: { + content, + metadata: data as BlogMetadata, + }, + }; +}; diff --git a/website/pages/blog/index.tsx b/website/pages/blog/index.tsx new file mode 100644 index 00000000..67034900 --- /dev/null +++ b/website/pages/blog/index.tsx @@ -0,0 +1,62 @@ +import fs from "fs"; +import path from "path"; +import { GetStaticProps, NextPage } from "next"; +import matter from "gray-matter"; +import ArticleCard from "components/ArticleCard"; +import { VStack } from "@chakra-ui/react"; + +export interface BlogMetadata { + title: string; + cover_image: string; + author: string; + date: string; + author_avatar_url: string; + tags: string[]; + summary: string; +} + +export interface BlogPost { + slug: string; + metadata: BlogMetadata; +} + +interface Props { + posts: BlogPost[]; +} + +const Blog: NextPage = ({ posts }) => { + return ( + + {posts.map((post) => { + return ( + + ); + })} + + ); +}; + +export default Blog; + +export const getStaticProps: GetStaticProps = async () => { + const posts = fs.readdirSync("posts").map((file) => { + return { + slug: file.replace(".md", ""), + metadata: matter(fs.readFileSync(path.join("posts", file))) + .data as BlogMetadata, + }; + }); + + return { + props: { + posts: posts.sort( + // @ts-ignore + (a, b) => new Date(b.metadata.date) - new Date(a.metadata.date) + ), + }, + }; +}; diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index ba63bb8f..e034573b 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -12,10 +12,12 @@ specifiers: '@types/progress': ^2.0.5 '@types/react': 18.0.15 '@types/react-dom': 18.0.6 + '@types/react-syntax-highlighter': ^15.5.3 eslint: 8.20.0 eslint-config-next: 12.2.2 eslint-config-prettier: ^8.5.0 framer-motion: ^6 + gray-matter: ^4.0.3 next: 12.2.2 nextjs-progressbar: ^0.0.14 react: 18.2.0 @@ -37,6 +39,7 @@ dependencies: '@octokit/rest': 19.0.3 '@types/progress': 2.0.5 framer-motion: 6.5.1_biqbaboplfbrettd7655fr4n2y + gray-matter: 4.0.3 next: 12.2.2_beenoklgwfttvph5dgxj7na7aq nextjs-progressbar: 0.0.14_next@12.2.2+react@18.2.0 react: 18.2.0 @@ -51,6 +54,7 @@ devDependencies: '@types/node': 18.0.5 '@types/react': 18.0.15 '@types/react-dom': 18.0.6 + '@types/react-syntax-highlighter': 15.5.3 eslint: 8.20.0 eslint-config-next: 12.2.2_he2ccbldppg44uulnyq4rwocfa eslint-config-prettier: 8.5.0_eslint@8.20.0 @@ -1662,6 +1666,12 @@ packages: '@types/react': 18.0.15 dev: true + /@types/react-syntax-highlighter/15.5.3: + resolution: {integrity: sha512-N5bgZxolo+wFuYnx4nOvIQO2P0E+KYHt3dDwb8ydUvZ96QN8Lpq60ReT+0W0JmXKZjp4udkYkIDYt9GIygBY1Q==} + dependencies: + '@types/react': 18.0.15 + dev: true + /@types/react/18.0.15: resolution: {integrity: sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==} dependencies: @@ -1784,6 +1794,12 @@ packages: color-convert: 2.0.1 dev: true + /argparse/1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + /argparse/2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true @@ -2441,6 +2457,12 @@ packages: eslint-visitor-keys: 3.3.0 dev: true + /esprima/4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: false + /esquery/1.4.0: resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} engines: {node: '>=0.10'} @@ -2465,6 +2487,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /extend-shallow/2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: false + /extend/3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: false @@ -2687,6 +2716,16 @@ packages: slash: 3.0.0 dev: true + /gray-matter/4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + dev: false + /has-bigints/1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true @@ -2826,6 +2865,11 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-extendable/0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: false + /is-extglob/2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2906,6 +2950,14 @@ packages: /js-tokens/4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + /js-yaml/3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: false + /js-yaml/4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2952,6 +3004,11 @@ packages: object.assign: 4.1.2 dev: true + /kind-of/6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: false + /kleur/4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} @@ -3955,6 +4012,14 @@ packages: loose-envify: 1.4.0 dev: false + /section-matter/1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + dev: false + /semver/6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true @@ -4006,6 +4071,10 @@ packages: resolution: {integrity: sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw==} dev: false + /sprintf-js/1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false + /string.prototype.matchall/4.0.7: resolution: {integrity: sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==} dependencies: @@ -4042,6 +4111,11 @@ packages: ansi-regex: 5.0.1 dev: true + /strip-bom-string/1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + dev: false + /strip-bom/3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} diff --git a/website/posts/getting-started-with-spotube.md b/website/posts/getting-started-with-spotube.md new file mode 100644 index 00000000..5731fab2 --- /dev/null +++ b/website/posts/getting-started-with-spotube.md @@ -0,0 +1,11 @@ +--- +title: Getting Started With Spotube +cover_image: https://github.com/KRTirtho/spotube/raw/master/assets/spotube-screenshot.jpg +date: "July 16, 2022" +author: Kingkor Roy Tirtho +author_avatar_url: https://avatars.githubusercontent.com/u/61944859?v=4 +tags: + - getting-started + - spotube +summary: You installed Spotube, don't know what to do now? Then don't worry we Gotchu covered here. We'll guide you through the basics of using Spotube & how you can use it to enrich your daily life with music. +--- \ No newline at end of file diff --git a/website/posts/improve-search-accuracy.md b/website/posts/improve-search-accuracy.md new file mode 100644 index 00000000..217a9294 --- /dev/null +++ b/website/posts/improve-search-accuracy.md @@ -0,0 +1,14 @@ +--- +title: Improve Search Accuracy +cover_image: https://github.com/KRTirtho/spotube/raw/master/assets/spotube_banner.png +date: "July 18, 2022" +author: Kingkor Roy Tirtho +author_avatar_url: https://avatars.githubusercontent.com/u/61944859?v=4 +tags: + - spotify + - music + - spotube +summary: Spotube has matches Spotify Song counterparts in YouTube. So there's a lot chance that sometimes you'll get the wrong song. This is where we'll help you improve the accuracy of your search for specific songs +--- + +# Improve Search Accuracy \ No newline at end of file