├── .gitignore ├── .npmrc ├── .vscode └── settings.json ├── README.md ├── app.config.ts ├── app.vue ├── components ├── App │ ├── Changelog │ │ ├── Index.vue │ │ └── Timeline.vue │ ├── EmailDigest.vue │ └── ReportIssue.vue ├── EmptyState.vue ├── FeedColumn.vue ├── LogoFull.vue ├── Navbar.vue ├── NewFeed │ ├── Form.vue │ ├── GithubMeta.vue │ ├── ListItem.vue │ ├── RedditMeta.vue │ ├── RssFeedMeta.vue │ └── YoutubeMeta.vue ├── SocialLogin.vue ├── Spinner.vue └── global │ ├── Feed │ ├── Dribbble.vue │ ├── GithubTrending.vue │ ├── Hackernews.vue │ ├── Header.vue │ ├── Loading.vue │ ├── Producthunt.vue │ ├── Reddit.vue │ ├── RedditMeta.vue │ ├── Rss.vue │ └── Youtube.vue │ ├── GoogleNewsLogo.vue │ └── SubstackLogo.vue ├── constants ├── apple-pwa-links.json ├── feedtypes.ts ├── githubMeta.ts └── icons.json ├── lib ├── dribbbleFixtures.ts ├── getDribbblePosts.ts ├── getGithubTrendingRepos.ts ├── getHackernewsPosts.ts ├── getProducthuntPosts.ts ├── getRedditPosts.ts ├── getRssFeed.ts ├── getYoutubeFeed.ts ├── githubReposFixtures.ts ├── hnPostsFixtures.ts ├── phPostsFixtures.ts └── resend.ts ├── nuxt.config.ts ├── package.json ├── pages ├── auth │ ├── confirm.vue │ ├── login.vue │ └── register.vue └── index.vue ├── public ├── banner.png ├── envelope.svg ├── favicon.ico ├── logo-full.svg ├── logo-with-bg.svg ├── logo.svg ├── mailbox.webp ├── newspaper.png ├── newspaper.svg ├── pwa │ ├── android │ │ ├── android-launchericon-144-144.png │ │ ├── android-launchericon-192-192.png │ │ ├── android-launchericon-48-48.png │ │ ├── android-launchericon-512-512.png │ │ ├── android-launchericon-72-72.png │ │ └── android-launchericon-96-96.png │ ├── apple │ │ ├── apple-icon-180.png │ │ ├── apple-splash-1125-2436.jpg │ │ ├── apple-splash-1136-640.jpg │ │ ├── apple-splash-1170-2532.jpg │ │ ├── apple-splash-1179-2556.jpg │ │ ├── apple-splash-1242-2208.jpg │ │ ├── apple-splash-1242-2688.jpg │ │ ├── apple-splash-1284-2778.jpg │ │ ├── apple-splash-1290-2796.jpg │ │ ├── apple-splash-1334-750.jpg │ │ ├── apple-splash-1536-2048.jpg │ │ ├── apple-splash-1620-2160.jpg │ │ ├── apple-splash-1668-2224.jpg │ │ ├── apple-splash-1668-2388.jpg │ │ ├── apple-splash-1792-828.jpg │ │ ├── apple-splash-2048-1536.jpg │ │ ├── apple-splash-2048-2732.jpg │ │ ├── apple-splash-2160-1620.jpg │ │ ├── apple-splash-2208-1242.jpg │ │ ├── apple-splash-2224-1668.jpg │ │ ├── apple-splash-2388-1668.jpg │ │ ├── apple-splash-2436-1125.jpg │ │ ├── apple-splash-2532-1170.jpg │ │ ├── apple-splash-2556-1179.jpg │ │ ├── apple-splash-2688-1242.jpg │ │ ├── apple-splash-2732-2048.jpg │ │ ├── apple-splash-2778-1284.jpg │ │ ├── apple-splash-2796-1290.jpg │ │ ├── apple-splash-640-1136.jpg │ │ ├── apple-splash-750-1334.jpg │ │ ├── apple-splash-828-1792.jpg │ │ ├── manifest-icon-192.maskable.png │ │ └── manifest-icon-512.maskable.png │ ├── ios │ │ ├── 100.png │ │ ├── 1024.png │ │ ├── 114.png │ │ ├── 120.png │ │ ├── 128.png │ │ ├── 144.png │ │ ├── 152.png │ │ ├── 16.png │ │ ├── 167.png │ │ ├── 180.png │ │ ├── 192.png │ │ ├── 20.png │ │ ├── 256.png │ │ ├── 29.png │ │ ├── 32.png │ │ ├── 40.png │ │ ├── 50.png │ │ ├── 512.png │ │ ├── 57.png │ │ ├── 58.png │ │ ├── 60.png │ │ ├── 64.png │ │ ├── 72.png │ │ ├── 76.png │ │ ├── 80.png │ │ └── 87.png │ └── windows11 │ │ ├── LargeTile.scale-100.png │ │ ├── LargeTile.scale-125.png │ │ ├── LargeTile.scale-150.png │ │ ├── LargeTile.scale-200.png │ │ ├── LargeTile.scale-400.png │ │ ├── SmallTile.scale-100.png │ │ ├── SmallTile.scale-125.png │ │ ├── SmallTile.scale-150.png │ │ ├── SmallTile.scale-200.png │ │ ├── SmallTile.scale-400.png │ │ ├── SplashScreen.scale-100.png │ │ ├── SplashScreen.scale-125.png │ │ ├── SplashScreen.scale-150.png │ │ ├── SplashScreen.scale-200.png │ │ ├── SplashScreen.scale-400.png │ │ ├── Square150x150Logo.scale-100.png │ │ ├── Square150x150Logo.scale-125.png │ │ ├── Square150x150Logo.scale-150.png │ │ ├── Square150x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-400.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-20.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-30.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-36.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-40.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-44.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-48.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-60.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-64.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-72.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-80.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-96.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-20.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-24.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-30.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-36.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-40.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-44.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-60.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-64.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-72.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-80.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-96.png │ │ ├── Square44x44Logo.scale-100.png │ │ ├── Square44x44Logo.scale-125.png │ │ ├── Square44x44Logo.scale-150.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Square44x44Logo.scale-400.png │ │ ├── Square44x44Logo.targetsize-16.png │ │ ├── Square44x44Logo.targetsize-20.png │ │ ├── Square44x44Logo.targetsize-24.png │ │ ├── Square44x44Logo.targetsize-256.png │ │ ├── Square44x44Logo.targetsize-30.png │ │ ├── Square44x44Logo.targetsize-32.png │ │ ├── Square44x44Logo.targetsize-36.png │ │ ├── Square44x44Logo.targetsize-40.png │ │ ├── Square44x44Logo.targetsize-44.png │ │ ├── Square44x44Logo.targetsize-48.png │ │ ├── Square44x44Logo.targetsize-60.png │ │ ├── Square44x44Logo.targetsize-64.png │ │ ├── Square44x44Logo.targetsize-72.png │ │ ├── Square44x44Logo.targetsize-80.png │ │ ├── Square44x44Logo.targetsize-96.png │ │ ├── StoreLogo.scale-100.png │ │ ├── StoreLogo.scale-125.png │ │ ├── StoreLogo.scale-150.png │ │ ├── StoreLogo.scale-200.png │ │ ├── StoreLogo.scale-400.png │ │ ├── Wide310x150Logo.scale-100.png │ │ ├── Wide310x150Logo.scale-125.png │ │ ├── Wide310x150Logo.scale-150.png │ │ ├── Wide310x150Logo.scale-200.png │ │ └── Wide310x150Logo.scale-400.png └── spinner.svg ├── server └── api │ ├── feed │ ├── dribbble.ts │ ├── github-trending.ts │ ├── hackernews.ts │ ├── producthunt.ts │ ├── reddit.ts │ ├── rss.ts │ └── youtube.ts │ ├── report.post.ts │ └── youtube.ts ├── tailwind.config.ts ├── tsconfig.json ├── types ├── database.types.ts └── feed.d.ts ├── utils ├── getYoutubeChannelId.ts ├── index.ts └── rssparser.ts └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Nuxt dev/build outputs 2 | .output 3 | .data 4 | .nuxt 5 | .nitro 6 | .cache 7 | dist 8 | 9 | # Node dependencies 10 | node_modules 11 | 12 | # Logs 13 | logs 14 | *.log 15 | 16 | # Misc 17 | .DS_Store 18 | .fleet 19 | .idea 20 | 21 | # Local env files 22 | .env 23 | .env.* 24 | !.env.example 25 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.css": "tailwindcss" 4 | }, 5 | "editor.quickSuggestions": { 6 | "strings": true 7 | }, 8 | "tailwindCSS.experimental.configFile": "tailwind.config.ts", 9 | "tailwindCSS.experimental.classRegex": [ 10 | [ 11 | "ui:\\s*{([^)]*)\\s*}", 12 | "[\"'`]([^\"'`]*).*?[\"'`]" 13 | ], 14 | [ 15 | "/\\*ui\\*/\\s*{([^;]*)}", 16 | ":\\s*[\"'`]([^\"'`]*).*?[\"'`]" 17 | ] 18 | ], 19 | "tailwindCSS.classAttributes": [ 20 | "class", 21 | "className", 22 | "ngClass", 23 | "ui" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [](http://supersaas.dev?ref=github-feedful) 2 | 3 | 4 | # Feedful 5 | 6 | ![Feedful Banner](https://feedful.vercel.app/banner.png) 7 | 8 | **Feedful** is a tweetdeck-styled news reader designed for power users. Imagine having all your favorite news sources, blogs, and publications in one place, organized neatly into columns. Feedful allows you to do just that! 9 | 10 | ## Features 11 | 12 | - **Multiple Columns**: Add unlimited and infinite columns for different publications. 13 | - **Supported Platforms**: ProductHunt, HackerNews, GitHub Trending, Reddit, YouTube, Dribbble, RSS feeds, Google News, and more (Others WIP). 14 | - **User-Friendly**: Designed with a clean and intuitive interface. 15 | 16 | ## Getting Started 17 | 18 | To get started with Feedful, you can access the project at [feedful.vercel.app](https://feedful.vercel.app). 19 | 20 | 21 | ## A Note from the Creator 22 | 23 | Hi everyone! 24 | 25 | I initially created Feedful as a modern RSS reader for power readers. Due to various reasons(fulltime work, other projects etc), I kinda abandoned the project, and the user base eventually dwindled and I feel like there's no reason to renew the domain. 26 | 27 | However, I did not kill the project completely. I've decided to make the project open source so that the community can benefit from it or even take it forward. 28 | 29 | You can still access the project at [feedful.vercel.app](https://feedful.vercel.app). 30 | 31 | Happy reading! 32 | 33 | ## License 34 | 35 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 36 | 37 | --- 38 | 39 | Feel free to personalize this README according to your specific needs or preferences! 40 | 41 | Happy coding! 🛠️ 42 | 43 | ## Setup 44 | 45 | Make sure to install the dependencies: 46 | 47 | ```bash 48 | # npm 49 | npm install 50 | 51 | # pnpm 52 | pnpm install 53 | 54 | # yarn 55 | yarn install 56 | ``` 57 | 58 | ## Development Server 59 | 60 | Start the development server on `http://localhost:3000`: 61 | 62 | ```bash 63 | # npm 64 | npm run dev 65 | 66 | # pnpm 67 | pnpm run dev 68 | 69 | # yarn 70 | yarn dev 71 | ``` 72 | 73 | ## Production 74 | 75 | Build the application for production: 76 | 77 | ```bash 78 | # npm 79 | npm run build 80 | 81 | # pnpm 82 | pnpm run build 83 | 84 | # yarn 85 | yarn build 86 | ``` 87 | 88 | Locally preview production build: 89 | 90 | ```bash 91 | # npm 92 | npm run preview 93 | 94 | # pnpm 95 | pnpm run preview 96 | 97 | # yarn 98 | yarn preview 99 | ``` 100 | 101 | 102 | ## Contributions 103 | 104 | Feel free to fork this project, contribute, and open pull requests. All contributions are welcome! 105 | -------------------------------------------------------------------------------- /app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | ui: { 3 | primary: "sky", 4 | gray: "cool", 5 | formGroup: { 6 | help: "text-xs mt-1 text-gray-500 dark:text-gray-400", 7 | error: "text-xs mt-1 text-red-500 dark:text-red-400", 8 | label: { 9 | base: "text-sm block font-medium text-gray-700 dark:text-gray-200", 10 | }, 11 | }, 12 | modal: { 13 | overlay: { 14 | background: "bg-[rgba(0,8,47,.275)] saturate-50", 15 | }, 16 | }, 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /app.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | -------------------------------------------------------------------------------- /components/App/Changelog/Index.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 113 | -------------------------------------------------------------------------------- /components/App/Changelog/Timeline.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 40 | -------------------------------------------------------------------------------- /components/App/EmailDigest.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /components/App/ReportIssue.vue: -------------------------------------------------------------------------------- 1 | 77 | 78 | 134 | -------------------------------------------------------------------------------- /components/FeedColumn.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /components/LogoFull.vue: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 78 | 79 | 144 | -------------------------------------------------------------------------------- /components/NewFeed/Form.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | 349 | -------------------------------------------------------------------------------- /components/NewFeed/GithubMeta.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 37 | -------------------------------------------------------------------------------- /components/NewFeed/ListItem.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /components/NewFeed/RedditMeta.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 20 | -------------------------------------------------------------------------------- /components/NewFeed/RssFeedMeta.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 17 | -------------------------------------------------------------------------------- /components/NewFeed/YoutubeMeta.vue: -------------------------------------------------------------------------------- 1 | 61 | 62 | 107 | -------------------------------------------------------------------------------- /components/SocialLogin.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 61 | -------------------------------------------------------------------------------- /components/Spinner.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 45 | -------------------------------------------------------------------------------- /components/global/Feed/Dribbble.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 55 | -------------------------------------------------------------------------------- /components/global/Feed/GithubTrending.vue: -------------------------------------------------------------------------------- 1 | 34 | 57 | -------------------------------------------------------------------------------- /components/global/Feed/Hackernews.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 52 | -------------------------------------------------------------------------------- /components/global/Feed/Header.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 55 | -------------------------------------------------------------------------------- /components/global/Feed/Loading.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /components/global/Feed/Producthunt.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 60 | -------------------------------------------------------------------------------- /components/global/Feed/Reddit.vue: -------------------------------------------------------------------------------- 1 | 115 | 116 | 136 | -------------------------------------------------------------------------------- /components/global/Feed/RedditMeta.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 32 | -------------------------------------------------------------------------------- /components/global/Feed/Rss.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 61 | -------------------------------------------------------------------------------- /components/global/Feed/Youtube.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 51 | -------------------------------------------------------------------------------- /components/global/GoogleNewsLogo.vue: -------------------------------------------------------------------------------- 1 | 106 | -------------------------------------------------------------------------------- /components/global/SubstackLogo.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /constants/apple-pwa-links.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "rel": "apple-touch-startup-image", 4 | "href": "/pwa/apple/apple-splash-2048-2732.jpg", 5 | "media": "(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" 6 | }, 7 | { 8 | "rel": "apple-touch-startup-image", 9 | "href": "/pwa/apple/apple-splash-2732-2048.jpg", 10 | "media": "(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" 11 | }, 12 | { 13 | "rel": "apple-touch-startup-image", 14 | "href": "/pwa/apple/apple-splash-1668-2388.jpg", 15 | "media": "(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" 16 | }, 17 | { 18 | "rel": "apple-touch-startup-image", 19 | "href": "/pwa/apple/apple-splash-2388-1668.jpg", 20 | "media": "(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" 21 | }, 22 | { 23 | "rel": "apple-touch-startup-image", 24 | "href": "/pwa/apple/apple-splash-1536-2048.jpg", 25 | "media": "(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" 26 | }, 27 | { 28 | "rel": "apple-touch-startup-image", 29 | "href": "/pwa/apple/apple-splash-2048-1536.jpg", 30 | "media": "(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" 31 | }, 32 | { 33 | "rel": "apple-touch-startup-image", 34 | "href": "/pwa/apple/apple-splash-1668-2224.jpg", 35 | "media": "(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" 36 | }, 37 | { 38 | "rel": "apple-touch-startup-image", 39 | "href": "/pwa/apple/apple-splash-2224-1668.jpg", 40 | "media": "(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" 41 | }, 42 | { 43 | "rel": "apple-touch-startup-image", 44 | "href": "/pwa/apple/apple-splash-1620-2160.jpg", 45 | "media": "(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" 46 | }, 47 | { 48 | "rel": "apple-touch-startup-image", 49 | "href": "/pwa/apple/apple-splash-2160-1620.jpg", 50 | "media": "(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" 51 | }, 52 | { 53 | "rel": "apple-touch-startup-image", 54 | "href": "/pwa/apple/apple-splash-1290-2796.jpg", 55 | "media": "(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" 56 | }, 57 | { 58 | "rel": "apple-touch-startup-image", 59 | "href": "/pwa/apple/apple-splash-2796-1290.jpg", 60 | "media": "(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" 61 | }, 62 | { 63 | "rel": "apple-touch-startup-image", 64 | "href": "/pwa/apple/apple-splash-1179-2556.jpg", 65 | "media": "(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" 66 | }, 67 | { 68 | "rel": "apple-touch-startup-image", 69 | "href": "/pwa/apple/apple-splash-2556-1179.jpg", 70 | "media": "(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" 71 | }, 72 | { 73 | "rel": "apple-touch-startup-image", 74 | "href": "/pwa/apple/apple-splash-1284-2778.jpg", 75 | "media": "(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" 76 | }, 77 | { 78 | "rel": "apple-touch-startup-image", 79 | "href": "/pwa/apple/apple-splash-2778-1284.jpg", 80 | "media": "(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" 81 | }, 82 | { 83 | "rel": "apple-touch-startup-image", 84 | "href": "/pwa/apple/apple-splash-1170-2532.jpg", 85 | "media": "(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" 86 | }, 87 | { 88 | "rel": "apple-touch-startup-image", 89 | "href": "/pwa/apple/apple-splash-2532-1170.jpg", 90 | "media": "(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" 91 | }, 92 | { 93 | "rel": "apple-touch-startup-image", 94 | "href": "/pwa/apple/apple-splash-1125-2436.jpg", 95 | "media": "(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" 96 | }, 97 | { 98 | "rel": "apple-touch-startup-image", 99 | "href": "/pwa/apple/apple-splash-2436-1125.jpg", 100 | "media": "(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" 101 | }, 102 | { 103 | "rel": "apple-touch-startup-image", 104 | "href": "/pwa/apple/apple-splash-1242-2688.jpg", 105 | "media": "(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" 106 | }, 107 | { 108 | "rel": "apple-touch-startup-image", 109 | "href": "/pwa/apple/apple-splash-2688-1242.jpg", 110 | "media": "(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" 111 | }, 112 | { 113 | "rel": "apple-touch-startup-image", 114 | "href": "/pwa/apple/apple-splash-828-1792.jpg", 115 | "media": "(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" 116 | }, 117 | { 118 | "rel": "apple-touch-startup-image", 119 | "href": "/pwa/apple/apple-splash-1792-828.jpg", 120 | "media": "(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" 121 | }, 122 | { 123 | "rel": "apple-touch-startup-image", 124 | "href": "/pwa/apple/apple-splash-1242-2208.jpg", 125 | "media": "(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" 126 | }, 127 | { 128 | "rel": "apple-touch-startup-image", 129 | "href": "/pwa/apple/apple-splash-2208-1242.jpg", 130 | "media": "(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" 131 | }, 132 | { 133 | "rel": "apple-touch-startup-image", 134 | "href": "/pwa/apple/apple-splash-750-1334.jpg", 135 | "media": "(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" 136 | }, 137 | { 138 | "rel": "apple-touch-startup-image", 139 | "href": "/pwa/apple/apple-splash-1334-750.jpg", 140 | "media": "(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" 141 | }, 142 | { 143 | "rel": "apple-touch-startup-image", 144 | "href": "/pwa/apple/apple-splash-640-1136.jpg", 145 | "media": "(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" 146 | }, 147 | { 148 | "rel": "apple-touch-startup-image", 149 | "href": "/pwa/apple/apple-splash-1136-640.jpg", 150 | "media": "(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" 151 | } 152 | ] 153 | -------------------------------------------------------------------------------- /constants/feedtypes.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | type: "producthunt", 4 | name: "Producthunt", 5 | icon: "logos:producthunt", 6 | disabled: false, 7 | description: "Top products of the day", 8 | url: "https://www.producthunt.com/", 9 | }, 10 | { 11 | type: "hackernews", 12 | name: "Hackernews", 13 | icon: "logos:ycombinator", 14 | disabled: false, 15 | description: "Hackernews home page", 16 | url: "https://news.ycombinator.com/", 17 | }, 18 | { 19 | type: "github", 20 | name: "Github Trending", 21 | icon: "logos:github-icon", 22 | disabled: false, 23 | description: "Trending repositories on Github", 24 | url: "https://github.com/trending", 25 | }, 26 | { 27 | type: "youtube", 28 | name: "Youtube", 29 | icon: "logos:youtube-icon", 30 | disabled: false, 31 | description: "Latest videos from a channel", 32 | url: "https://www.youtube.com/", 33 | }, 34 | { 35 | type: "reddit", 36 | name: "Sub Reddit", 37 | icon: "logos:reddit-icon", 38 | disabled: false, 39 | description: "Top posts from a subreddit", 40 | }, 41 | { 42 | type: "dribbble", 43 | name: "Dribbble", 44 | icon: "logos:dribbble-icon", 45 | disabled: false, 46 | description: "Trending shots on Dribbble", 47 | url: "https://dribbble.com/", 48 | }, 49 | { 50 | type: "rss", 51 | name: "Publication or Blog (Beta)", 52 | icon: "ph:rss-simple-bold", 53 | disabled: false, 54 | description: "Subscribe via RSS feed", 55 | }, 56 | { 57 | type: "google-news", 58 | name: "Google news", 59 | icon: "GoogleNewsLogo", 60 | disabled: true, 61 | description: "Top news from Google news for your country", 62 | url: "https://news.google.com/", 63 | }, 64 | { 65 | type: "substack", 66 | name: "Substack publication", 67 | icon: "SubstackLogo", 68 | disabled: true, 69 | description: "Subscribe to a Substack publication", 70 | }, 71 | { 72 | type: "github-notifications", 73 | name: "Github notifications", 74 | icon: "logos:github-icon", 75 | disabled: true, 76 | description: "Get all your Github notifications in one place", 77 | }, 78 | { 79 | type: "github-issues", 80 | name: "Github issues", 81 | icon: "logos:github-icon", 82 | disabled: true, 83 | description: "Get all your Github issues", 84 | }, 85 | { 86 | type: "google-calendar", 87 | name: "Calendar events", 88 | icon: "logos:google-calendar", 89 | disabled: true, 90 | description: "List of all events today from your Google calendar", 91 | }, 92 | { 93 | type: "newsletter", 94 | name: "Newsletter", 95 | icon: "logos:google-gmail", 96 | disabled: true, 97 | description: "via Gmail (coming soon)", 98 | }, 99 | { 100 | type: "iframe", 101 | name: "iFrame", 102 | icon: "heroicons:computer-desktop", 103 | disabled: true, 104 | description: "Add any website via iFrame", 105 | }, 106 | { 107 | type: "linear", 108 | name: "Linear tickets", 109 | icon: "logos:linear-icon", 110 | disabled: true, 111 | description: "List of all your Linear tickets", 112 | }, 113 | { 114 | type: "notepad", 115 | name: "Notepad", 116 | icon: "heroicons:document-text", 117 | disabled: true, 118 | description: "Simple notepad to your dashboard", 119 | }, 120 | { 121 | type: "feedful-clips", 122 | name: "Feedful Clips", 123 | icon: "heroicons:bookmark", 124 | disabled: true, 125 | description: "Clips saved from the feedful browser extension", 126 | }, 127 | ]; 128 | -------------------------------------------------------------------------------- /constants/githubMeta.ts: -------------------------------------------------------------------------------- 1 | export const programmingLanguages = [ 2 | { 3 | language: "all", 4 | label: "All", 5 | }, 6 | { 7 | language: "c", 8 | label: "C", 9 | }, 10 | { 11 | language: "c%23", 12 | label: "C#", 13 | }, 14 | { 15 | language: "c++", 16 | label: "C++", 17 | }, 18 | { 19 | language: "css", 20 | label: "CSS", 21 | }, 22 | { 23 | language: "dart", 24 | label: "Dart", 25 | }, 26 | { 27 | language: "elixir", 28 | label: "Elixir", 29 | }, 30 | { 31 | language: "go", 32 | label: "Go", 33 | }, 34 | { 35 | language: "haskell", 36 | label: "Haskell", 37 | }, 38 | { 39 | language: "html", 40 | label: "HTML", 41 | }, 42 | { 43 | language: "java", 44 | label: "Java", 45 | }, 46 | { 47 | language: "javascript", 48 | label: "JavaScript", 49 | }, 50 | { 51 | language: "json", 52 | label: "JSON", 53 | }, 54 | { 55 | language: "julia", 56 | label: "Julia", 57 | }, 58 | { 59 | language: "jupyter-notebook", 60 | label: "Jupyter Notebook", 61 | }, 62 | { 63 | language: "kotlin", 64 | label: "Kotlin", 65 | }, 66 | { 67 | language: "lua", 68 | label: "Lua", 69 | }, 70 | { 71 | language: "objective-c", 72 | label: "Objective-C", 73 | }, 74 | { 75 | language: "python", 76 | label: "Python", 77 | }, 78 | { 79 | language: "r", 80 | label: "R", 81 | }, 82 | { 83 | language: "ruby", 84 | label: "Ruby", 85 | }, 86 | { 87 | language: "rust", 88 | label: "Rust", 89 | }, 90 | { 91 | language: "scala", 92 | label: "Scala", 93 | }, 94 | { 95 | language: "shell", 96 | label: "Shell", 97 | }, 98 | { 99 | language: "sql", 100 | label: "SQL", 101 | }, 102 | { 103 | language: "svelte", 104 | label: "Svelte", 105 | }, 106 | { 107 | language: "svg", 108 | label: "SVG", 109 | }, 110 | { 111 | language: "swift", 112 | label: "Swift", 113 | }, 114 | { 115 | language: "typescript", 116 | label: "TypeScript", 117 | }, 118 | { 119 | language: "v", 120 | label: "V", 121 | }, 122 | { 123 | language: "vue", 124 | label: "Vue", 125 | }, 126 | { 127 | language: "webassembly", 128 | label: "WebAssembly", 129 | }, 130 | { 131 | language: "yaml", 132 | label: "YAML", 133 | }, 134 | { 135 | language: "zig", 136 | label: "Zig", 137 | }, 138 | ]; 139 | 140 | export const githubFrequencyOptions = [ 141 | { label: "Daily", value: "daily" }, 142 | { label: "Weekly", value: "weekly" }, 143 | { label: "Monthly", value: "monthly" }, 144 | ]; 145 | -------------------------------------------------------------------------------- /lib/getDribbblePosts.ts: -------------------------------------------------------------------------------- 1 | import { load } from "cheerio"; 2 | import { sleep } from "@/utils"; 3 | import fixtures from "./dribbbleFixtures"; 4 | 5 | const DRIBBBLE_URL = "https://dribbble.com/shots"; 6 | 7 | export default async (): Promise => { 8 | try { 9 | if (process.env.NODE_ENV === "development") { 10 | await sleep(1000); 11 | return fixtures; 12 | } else { 13 | const response = await fetch(DRIBBBLE_URL); 14 | if (!response.ok) { 15 | throw new Error(`HTTP error: ${response.status}`); 16 | } 17 | const htmlString = await response.text(); 18 | const $ = load(htmlString); 19 | const posts: Dribbble[] = []; 20 | $(".shot-thumbnail-container").each((index, element) => { 21 | const post: Dribbble = { 22 | image: "", 23 | title: "", 24 | likes: "", 25 | views: "", 26 | author: "", 27 | authorAvatar: "", 28 | url: "", 29 | }; 30 | post.image = 31 | $(element) 32 | .find(".js-thumbnail-base .js-thumbnail-placeholder img[data-src]") 33 | .attr("data-src") || ""; 34 | post.title = $(element).find(".shot-title").text().trim(); 35 | post.likes = $(element) 36 | .find(".shot-statistic.js-shot-likes-container .js-shot-likes-count") 37 | .text() 38 | .trim(); 39 | post.views = $(element) 40 | .find(".shot-statistic.js-shot-views-container .js-shot-views-count") 41 | .text() 42 | .trim(); 43 | post.author = $(element) 44 | .find(".user-information .display-name") 45 | .text() 46 | .trim(); 47 | post.authorAvatar = 48 | $(element) 49 | .find(".user-information a img[data-src]") 50 | .attr("data-src") || ""; 51 | const url = $(element).find(".js-shot-link").attr("href"); 52 | post.url = `https://dribbble.com${url}`; 53 | posts.push(post); 54 | }); 55 | return posts; 56 | } 57 | } catch (error) { 58 | console.error(error); 59 | return []; 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /lib/getGithubTrendingRepos.ts: -------------------------------------------------------------------------------- 1 | import { sleep } from "@/utils"; 2 | import * as cheerio from "cheerio"; 3 | import { formatNumber } from "@/utils"; 4 | 5 | import fixtures from "./githubReposFixtures"; 6 | 7 | const GITHUB_TRENDING_BASE_URL = "https://github.com/trending"; 8 | 9 | export default async ( 10 | lang: string = "all", 11 | since: string = "daily" 12 | ): Promise => { 13 | try { 14 | if (lang === "all") { 15 | lang = ""; 16 | } 17 | 18 | const url = `${GITHUB_TRENDING_BASE_URL}/${lang}?since=${since}`; 19 | 20 | if (process.env.NODE_ENV === "development") { 21 | await sleep(1000); 22 | return fixtures; 23 | } else { 24 | const response = await fetch(url); 25 | if (!response.ok) { 26 | throw new Error(`HTTP error: ${response.status}`); 27 | } 28 | const htmlString = await response.text(); 29 | const $ = cheerio.load(htmlString); 30 | const repos: Github[] = []; 31 | $("article.Box-row").each((index, element) => { 32 | const repo: Github = { 33 | title: $(element).find("h2.h3.lh-condensed").text().trim(), 34 | description: $(element).find("p.col-9").text().trim(), 35 | url: `https://github.com${$(element) 36 | .find("h2.h3.lh-condensed a") 37 | .attr("href")}`, 38 | stars: formatNumber( 39 | parseInt( 40 | $(element) 41 | .find(`a[href*="/stargazers"]`) 42 | .text() 43 | .trim() 44 | .replace(/,/g, "") 45 | ) 46 | ), 47 | }; 48 | repos.push(repo); 49 | }); 50 | return repos; 51 | } 52 | } catch (error) { 53 | console.error(error); 54 | return []; 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /lib/getHackernewsPosts.ts: -------------------------------------------------------------------------------- 1 | import { sleep } from "@/utils"; 2 | import fixtures from "./hnPostsFixtures"; 3 | 4 | export default async () => { 5 | try { 6 | const URL = "https://api.hackerwebapp.com/news"; 7 | 8 | const options = { 9 | method: "GET", 10 | headers: { 11 | "Content-Type": "application/json", 12 | }, 13 | }; 14 | 15 | if (process.env.NODE_ENV === "development") { 16 | await sleep(1000); 17 | return fixtures; 18 | } else { 19 | const response: Response = await fetch(URL, options); 20 | if (!response.ok) { 21 | throw new Error(`HTTP error: ${response.status}`); 22 | } 23 | const posts: Hackernews[] = await response.json(); 24 | return posts; 25 | } 26 | } catch (error) { 27 | console.error(error); 28 | return []; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /lib/getProducthuntPosts.ts: -------------------------------------------------------------------------------- 1 | import { sleep } from "@/utils"; 2 | import fixtures from "./phPostsFixtures"; 3 | 4 | const fetchPosts = async (): Promise => { 5 | try { 6 | const URL: string = "https://api.producthunt.com/v2/api/graphql"; 7 | const afterDate = new Date( 8 | new Date(Date.now()).getTime() - 1000 * 60 * 60 * 1 * 24 9 | ).toUTCString(); 10 | const beforeDate = new Date(Date.now()).toUTCString(); 11 | 12 | const query: string = `query PostRanking { 13 | posts( 14 | postedAfter: "${afterDate}" 15 | order: RANKING 16 | first: 25 17 | postedBefore: "${beforeDate}" 18 | ) { 19 | edges { 20 | node { 21 | id 22 | name 23 | tagline 24 | description 25 | url 26 | votesCount 27 | thumbnail { 28 | type 29 | url 30 | } 31 | website 32 | reviewsRating 33 | } 34 | } 35 | } 36 | }`; 37 | 38 | const options: RequestInit = { 39 | method: "POST", 40 | headers: { 41 | "Content-Type": "application/json", 42 | Authorization: `Bearer ${process.env.PRODUCTHUNT_TOKEN}`, 43 | }, 44 | body: JSON.stringify({ query }), 45 | }; 46 | 47 | if (process.env.NODE_ENV === "development") { 48 | await sleep(1000); 49 | return fixtures; 50 | } else { 51 | const response: Response = await fetch(URL, options); 52 | if (!response.ok) { 53 | throw new Error(`HTTP error: ${response.status}`); 54 | } 55 | 56 | const { data }: { data: { posts: { edges: { node: Producthunt }[] } } } = 57 | await response.json(); 58 | if (!data?.posts?.edges?.length) { 59 | throw new Error("No data returned from API"); 60 | } 61 | 62 | const posts: Producthunt[] = data.posts.edges.map( 63 | (edge: { node: Producthunt }) => edge.node 64 | ); 65 | return posts; 66 | } 67 | } catch (error) { 68 | console.error("Error fetching posts:", error); 69 | return []; 70 | } 71 | }; 72 | 73 | export default fetchPosts; 74 | -------------------------------------------------------------------------------- /lib/getRedditPosts.ts: -------------------------------------------------------------------------------- 1 | // reddit url example - "https://www.reddit.com/r/popular/.json"; 2 | 3 | const EXCLUDE_IMAGE_TYPES = ["self", "nsfw", "default", "spoiler", "image"]; 4 | 5 | function cleanMediaUrl(url: string): string { 6 | if (!url || url === "self" || url === "nsfw") { 7 | return ""; 8 | } 9 | return url.replace(/&/g, "&"); 10 | } 11 | 12 | export default async function fetchRedditPosts( 13 | subreddit: string 14 | ): Promise { 15 | try { 16 | if (!subreddit) { 17 | return []; 18 | } 19 | 20 | const URL = `https://www.reddit.com/r/${subreddit}/.json`; 21 | const options = { 22 | method: "GET", 23 | headers: { 24 | "Content-Type": "application/json", 25 | }, 26 | }; 27 | 28 | const response = await fetch(URL, options); 29 | 30 | if (!response.ok) { 31 | throw new Error(`HTTP error: ${response.status}`); 32 | } 33 | 34 | const feed = await response.json(); 35 | const posts: RedditPost[] = feed.data.children 36 | .map((item: any) => { 37 | return { 38 | id: item.data.id, 39 | title: item.data.title, 40 | subreddit: item.data.subreddit_name_prefixed, 41 | author: item.data.author, 42 | votes: item.data.ups, 43 | text: item.data.selftext, 44 | nsfw: item.data.over_18, 45 | url: `https://reddit.com/${item.data.permalink}`, 46 | is_video: item.data.is_video, 47 | is_image: 48 | !EXCLUDE_IMAGE_TYPES.includes(item.data.thumbnail) && 49 | !item.data.is_video, 50 | thumbnail: cleanMediaUrl(item.data.thumbnail), 51 | video_url: item.data.media?.reddit_video?.fallback_url, 52 | comments: item.data.num_comments, 53 | created_at: item.data.created_utc, 54 | }; 55 | }) 56 | .filter( 57 | (post: RedditPost) => !post.author.toLowerCase().includes("moderator") 58 | ); 59 | 60 | return posts; 61 | } catch (error) { 62 | console.error(error); 63 | return []; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/getRssFeed.ts: -------------------------------------------------------------------------------- 1 | import { rssParser } from "@/utils"; 2 | 3 | export default async function getRssFeed(feedUrl: string): Promise<[]> { 4 | try { 5 | const feed = await rssParser(feedUrl); 6 | 7 | if (!feed || !feed.items || !Array.isArray(feed.items)) { 8 | console.error("Invalid feed structure:", feed); 9 | return []; 10 | } 11 | return { 12 | title: feed.title, 13 | icon: feed.icon, 14 | link: feed.link, 15 | items: feed.items, 16 | }; 17 | } catch (error) { 18 | console.error("Error fetching Rss feed:", error); 19 | return []; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/getYoutubeFeed.ts: -------------------------------------------------------------------------------- 1 | import { rssParser } from "@/utils"; 2 | 3 | export default async function fetchYoutubePosts( 4 | channelId: string 5 | ): Promise { 6 | try { 7 | const feed = await rssParser( 8 | `https://www.youtube.com/feeds/videos.xml?channel_id=${channelId}` 9 | ); 10 | 11 | if (!feed || !feed.items || !Array.isArray(feed.items)) { 12 | console.error("Invalid feed structure:", feed); 13 | return []; 14 | } 15 | 16 | return feed.items; 17 | } catch (error) { 18 | console.error("Error fetching YouTube posts:", error); 19 | return []; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/githubReposFixtures.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | title: "30-seconds /\n\n 30-seconds-of-code", 4 | description: "Short code snippets for all your development needs", 5 | url: "https://github.com/30-seconds/30-seconds-of-code", 6 | stars: "114.4k", 7 | }, 8 | { 9 | title: "github /\n\n docs", 10 | description: "The open-source repo for docs.github.com", 11 | url: "https://github.com/github/docs", 12 | stars: "14.1k", 13 | }, 14 | { 15 | title: "pot-app /\n\n pot-desktop", 16 | description: 17 | "🌈一个跨平台的划词翻译软件 | A cross-platform software for text translation.", 18 | url: "https://github.com/pot-app/pot-desktop", 19 | stars: "3.8k", 20 | }, 21 | { 22 | title: "iptv-org /\n\n iptv", 23 | description: 24 | "Collection of publicly available IPTV channels from all over the world", 25 | url: "https://github.com/iptv-org/iptv", 26 | stars: "67k", 27 | }, 28 | { 29 | title: "3Kmfi6HP /\n\n EDtunnel", 30 | description: "Some random description for you to read...", 31 | url: "https://github.com/3Kmfi6HP/EDtunnel", 32 | stars: 506, 33 | }, 34 | { 35 | title: "dev-lu /\n\n osint_toolkit", 36 | description: 37 | "A full stack web application that combines many tools and services for security analysts into a single tool.", 38 | url: "https://github.com/dev-lu/osint_toolkit", 39 | stars: 238, 40 | }, 41 | { 42 | title: "DIYgod /\n\n RSSHub", 43 | description: "🍰 Everything is RSSible", 44 | url: "https://github.com/DIYgod/RSSHub", 45 | stars: "25.4k", 46 | }, 47 | { 48 | title: "jonasschmedtmann /\n\n complete-javascript-course", 49 | description: 50 | "Starter files, final projects, and FAQ for my Complete JavaScript course", 51 | url: "https://github.com/jonasschmedtmann/complete-javascript-course", 52 | stars: "13.1k", 53 | }, 54 | { 55 | title: "chetannada /\n\n Namaste-React", 56 | description: 57 | "❤ Namaste React Live Course from Zero to Hero 🚀 by Akshay Saini(Founder of NamasteDev). This repository for Assignment & Class Notes taken during Namaste React Live Course #namaste #javascript #react", 58 | url: "https://github.com/chetannada/Namaste-React", 59 | stars: "1k", 60 | }, 61 | { 62 | title: "Asabeneh /\n\n 30-Days-Of-React", 63 | description: 64 | "30 Days of React challenge is a step by step guide to learn React in 30 days. These videos may help too: https://www.youtube.com/channel/UC7PNRuno1rzYPb1xLa4yktw", 65 | url: "https://github.com/Asabeneh/30-Days-Of-React", 66 | stars: "21.7k", 67 | }, 68 | { 69 | title: "Expensify /\n\n App", 70 | description: 71 | "Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.", 72 | url: "https://github.com/Expensify/App", 73 | stars: "1.5k", 74 | }, 75 | { 76 | title: "hakimel /\n\n reveal.js", 77 | description: "The HTML Presentation Framework", 78 | url: "https://github.com/hakimel/reveal.js", 79 | stars: "64.3k", 80 | }, 81 | { 82 | title: "janeczku /\n\n calibre-web", 83 | description: 84 | "📚 Web app for browsing, reading and downloading eBooks stored in a Calibre database", 85 | url: "https://github.com/janeczku/calibre-web", 86 | stars: "9.6k", 87 | }, 88 | { 89 | title: "Asabeneh /\n\n 30-Days-Of-JavaScript", 90 | description: 91 | "30 days of JavaScript programming challenge is a step-by-step guide to learn JavaScript programming language in 30 days. This challenge may take more than 100 days, please just follow your own pace. These videos may help too: https://www.youtube.com/channel/UC7PNRuno1rzYPb1xLa4yktw", 92 | url: "https://github.com/Asabeneh/30-Days-Of-JavaScript", 93 | stars: "37.5k", 94 | }, 95 | { 96 | title: "saiteja-madha /\n\n discord-js-bot", 97 | description: 98 | "🤖 Multipurpose discord bot built using discord.js v14 with moderation, music, ticketing, translation, and much more", 99 | url: "https://github.com/saiteja-madha/discord-js-bot", 100 | stars: 460, 101 | }, 102 | { 103 | title: "MetaMask /\n\n metamask-extension", 104 | description: 105 | "🌐 🔌 The MetaMask browser extension enables browsing Ethereum blockchain enabled websites", 106 | url: "https://github.com/MetaMask/metamask-extension", 107 | stars: "10.3k", 108 | }, 109 | { 110 | title: "pedroslopez /\n\n whatsapp-web.js", 111 | description: 112 | "A WhatsApp client library for NodeJS that connects through the WhatsApp Web browser app", 113 | url: "https://github.com/pedroslopez/whatsapp-web.js", 114 | stars: "10.8k", 115 | }, 116 | { 117 | title: "DarkMakerofc /\n\n QUEEN-ELISA-MD", 118 | description: 119 | "Queen Elisa Whatsapp is, It is a Project that can be called as a Whatsapp 3rd Party Application which you can get at a very good Bot Expirience", 120 | url: "https://github.com/DarkMakerofc/QUEEN-ELISA-MD", 121 | stars: 573, 122 | }, 123 | { 124 | title: "neetcode-gh /\n\n leetcode", 125 | description: "Leetcode solutions", 126 | url: "https://github.com/neetcode-gh/leetcode", 127 | stars: "3.6k", 128 | }, 129 | { 130 | title: "gaboolic /\n\n nodejs-proxy", 131 | description: "nodejs实现vless fork的同时帮我点点star", 132 | url: "https://github.com/gaboolic/nodejs-proxy", 133 | stars: 130, 134 | }, 135 | { 136 | title: "libccy /\n\n noname", 137 | description: "", 138 | url: "https://github.com/libccy/noname", 139 | stars: "1.2k", 140 | }, 141 | { 142 | title: "troyeguo /\n\n koodo-reader", 143 | description: 144 | "A modern ebook manager and reader with sync and backup capacities for Windows, macOS, Linux and Web", 145 | url: "https://github.com/troyeguo/koodo-reader", 146 | stars: "11.4k", 147 | }, 148 | { 149 | title: "shahriarsajeeb /\n\n Eshop-tutorial", 150 | description: "", 151 | url: "https://github.com/shahriarsajeeb/Eshop-tutorial", 152 | stars: 436, 153 | }, 154 | { 155 | title: "catvod /\n\n CatVodOpen", 156 | description: "Open version of catvod.", 157 | url: "https://github.com/catvod/CatVodOpen", 158 | stars: 247, 159 | }, 160 | { 161 | title: "popcorn-official /\n\n popcorn-desktop", 162 | description: 163 | "Popcorn Time is a multi-platform, free software BitTorrent client that includes an integrated media player ( Windows / Mac / Linux ) A Butter-Project Fork", 164 | url: "https://github.com/popcorn-official/popcorn-desktop", 165 | stars: "8.2k", 166 | }, 167 | ]; 168 | -------------------------------------------------------------------------------- /lib/hnPostsFixtures.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | id: 36928529, 4 | title: "Fighting for the Open Web [image]", 5 | points: 62, 6 | user: "pabs3", 7 | time: 1690699515, 8 | time_ago: "2 hours ago", 9 | comments_count: 30, 10 | type: "link", 11 | url: "https://www.davidrevoy.com/article982/fighting-for-the-open-web", 12 | domain: "davidrevoy.com", 13 | }, 14 | { 15 | id: 36927695, 16 | title: "Welcome to Wikifunctions", 17 | points: 126, 18 | user: "edward", 19 | time: 1690689752, 20 | time_ago: "4 hours ago", 21 | comments_count: 39, 22 | type: "link", 23 | url: "https://www.wikifunctions.org/wiki/Wikifunctions:Main_Page", 24 | domain: "wikifunctions.org", 25 | }, 26 | { 27 | id: 36905267, 28 | title: 29 | "Forced rhubarb, a vegetable deprived of sunlight, is having a renaissance (2019)", 30 | points: 73, 31 | user: "cellover", 32 | time: 1690542800, 33 | time_ago: "2 days ago", 34 | comments_count: 15, 35 | type: "link", 36 | url: "https://www.bbc.com/travel/article/20190424-the-english-vegetable-picked-by-candlelight", 37 | domain: "bbc.com", 38 | }, 39 | { 40 | id: 36926569, 41 | title: "Snowflake", 42 | points: 147, 43 | user: "bcg361", 44 | time: 1690678792, 45 | time_ago: "7 hours ago", 46 | comments_count: 18, 47 | type: "link", 48 | url: "https://snowflake.torproject.org/", 49 | domain: "snowflake.torproject.org", 50 | }, 51 | { 52 | id: 36917466, 53 | title: "Computer scientists discover limits of gradient descent", 54 | points: 51, 55 | user: "Anon84", 56 | time: 1690611728, 57 | time_ago: "a day ago", 58 | comments_count: 14, 59 | type: "link", 60 | url: "https://www.quantamagazine.org/computer-scientists-discover-limits-of-major-research-algorithm-20210817/", 61 | domain: "quantamagazine.org", 62 | }, 63 | { 64 | id: 36926228, 65 | title: "ASML EUV lithography machine could keep Moore’s Law on track", 66 | points: 133, 67 | user: "mfiguiere", 68 | time: 1690675633, 69 | time_ago: "8 hours ago", 70 | comments_count: 87, 71 | type: "link", 72 | url: "https://spectrum.ieee.org/high-na-euv", 73 | domain: "spectrum.ieee.org", 74 | }, 75 | { 76 | id: 36927971, 77 | title: "Comma 3X", 78 | points: 65, 79 | user: "Yenrabbit", 80 | time: 1690693189, 81 | time_ago: "3 hours ago", 82 | comments_count: 37, 83 | type: "link", 84 | url: "https://www.comma.ai/", 85 | domain: "comma.ai", 86 | }, 87 | { 88 | id: 36924267, 89 | title: "Show HN: Gogit – Just enough Git (in Go) to push itself to GitHub", 90 | points: 129, 91 | user: "benhoyt", 92 | time: 1690662866, 93 | time_ago: "12 hours ago", 94 | comments_count: 57, 95 | type: "link", 96 | url: "https://benhoyt.com/writings/gogit/", 97 | domain: "benhoyt.com", 98 | }, 99 | { 100 | id: 36928601, 101 | title: "PlayHT (YC W23) Is Hiring ML Engineers (LLMs, Generative AI)", 102 | points: null, 103 | user: null, 104 | time: 1690700446, 105 | time_ago: "an hour ago", 106 | comments_count: 0, 107 | type: "job", 108 | url: "https://www.ycombinator.com/companies/playht/jobs/G6vI660-senior-ml-engineer-large-language-models", 109 | domain: "ycombinator.com", 110 | }, 111 | { 112 | id: 36921446, 113 | title: "Functions are vectors", 114 | points: 201, 115 | user: "TheNumbat", 116 | time: 1690646091, 117 | time_ago: "17 hours ago", 118 | comments_count: 70, 119 | type: "link", 120 | url: "https://thenumb.at/Functions-are-Vectors/", 121 | domain: "thenumb.at", 122 | }, 123 | { 124 | id: 36927940, 125 | title: "Microbially produced protein that is much sweeter than sugar", 126 | points: 108, 127 | user: "walterbell", 128 | time: 1690692862, 129 | time_ago: "4 hours ago", 130 | comments_count: 65, 131 | type: "link", 132 | url: "https://www.nature.com/articles/s41587-023-01865-x", 133 | domain: "nature.com", 134 | }, 135 | { 136 | id: 36916982, 137 | title: "Blue iceberg", 138 | points: 29, 139 | user: "thunderbong", 140 | time: 1690605386, 141 | time_ago: "a day ago", 142 | comments_count: 6, 143 | type: "link", 144 | url: "https://en.wikipedia.org/wiki/Blue_iceberg", 145 | domain: "en.wikipedia.org", 146 | }, 147 | { 148 | id: 36926165, 149 | title: "Button Pushes You (2022)", 150 | points: 79, 151 | user: "john-doe", 152 | time: 1690675101, 153 | time_ago: "8 hours ago", 154 | comments_count: 20, 155 | type: "link", 156 | url: "https://despens.systems/2022/06/button-pushes-you/", 157 | domain: "despens.systems", 158 | }, 159 | { 160 | id: 36928485, 161 | title: "Why I use the D programming language for scripting (2021)", 162 | points: 25, 163 | user: "teleforce", 164 | time: 1690698979, 165 | time_ago: "2 hours ago", 166 | comments_count: 4, 167 | type: "link", 168 | url: "https://opensource.com/article/21/1/d-scripting", 169 | domain: "opensource.com", 170 | }, 171 | { 172 | id: 36922790, 173 | title: "Open Source Outdoor Air Quality Monitor", 174 | points: 175, 175 | user: "ahaucnx", 176 | time: 1690653544, 177 | time_ago: "14 hours ago", 178 | comments_count: 83, 179 | type: "link", 180 | url: "https://www.airgradient.com/open-air/", 181 | domain: "airgradient.com", 182 | }, 183 | { 184 | id: 36917552, 185 | title: "Code Duello: The Rules of Dueling (1963)", 186 | points: 13, 187 | user: "thunderbong", 188 | time: 1690612794, 189 | time_ago: "a day ago", 190 | comments_count: 3, 191 | type: "link", 192 | url: "https://www.pbs.org/wgbh/americanexperience/features/duel-code-duello-rules-dueling/", 193 | domain: "pbs.org", 194 | }, 195 | { 196 | id: 36922744, 197 | title: "How fast should you accelerate your kid in math?", 198 | points: 110, 199 | user: "sebg", 200 | time: 1690653238, 201 | time_ago: "15 hours ago", 202 | comments_count: 194, 203 | type: "link", 204 | url: "https://kidswholovemath.substack.com/p/how-fast-should-you-accelerate-your", 205 | domain: "kidswholovemath.substack.com", 206 | }, 207 | { 208 | id: 36922517, 209 | title: "US Army Field Manual on Leadership (1990) [pdf]", 210 | points: 197, 211 | user: "jtlicardo", 212 | time: 1690651962, 213 | time_ago: "15 hours ago", 214 | comments_count: 105, 215 | type: "link", 216 | url: "https://armyoe.files.wordpress.com/2018/03/1990-fm-22-100.pdf", 217 | domain: "armyoe.files.wordpress.com", 218 | }, 219 | { 220 | id: 36924832, 221 | title: "Red algae proteins grafted into tobacco double plant growth", 222 | points: 95, 223 | user: "geox", 224 | time: 1690666048, 225 | time_ago: "11 hours ago", 226 | comments_count: 57, 227 | type: "link", 228 | url: "https://news.cornell.edu/stories/2023/07/red-algae-proteins-grafted-tobacco-double-plant-growth", 229 | domain: "news.cornell.edu", 230 | }, 231 | { 232 | id: 36925688, 233 | title: "The papers were not ready for publication", 234 | points: 162, 235 | user: "Accujack", 236 | time: 1690671532, 237 | time_ago: "9 hours ago", 238 | comments_count: 87, 239 | type: "link", 240 | url: "https://twitter.com/8teAPi/status/1684385895565365248", 241 | domain: "twitter.com", 242 | }, 243 | { 244 | id: 36921785, 245 | title: "The Problem of Excess Genius (1997)", 246 | points: 15, 247 | user: "jseliger", 248 | time: 1690647930, 249 | time_ago: "16 hours ago", 250 | comments_count: 16, 251 | type: "link", 252 | url: "https://www.visakanv.com/archives/2021/02/14/the-problem-of-excess-genius-by-david-banks-1997/", 253 | domain: "visakanv.com", 254 | }, 255 | { 256 | id: 36928043, 257 | title: "What I Would Do If I Ran Tarsnap", 258 | points: 10, 259 | user: "reubano", 260 | time: 1690694036, 261 | time_ago: "3 hours ago", 262 | comments_count: 2, 263 | type: "link", 264 | url: "https://www.kalzumeus.com/2014/04/03/fantasy-tarsnap/", 265 | domain: "kalzumeus.com", 266 | }, 267 | { 268 | id: 36926852, 269 | title: "GNU Boot sent a cease and desist to Libreboot", 270 | points: 228, 271 | user: "codingcoyote", 272 | time: 1690681225, 273 | time_ago: "7 hours ago", 274 | comments_count: 145, 275 | type: "link", 276 | url: "https://libreboot.org/news/gnuboot.html#gnu-boot-cease-and-desist-email", 277 | domain: "libreboot.org", 278 | }, 279 | { 280 | id: 36908369, 281 | title: "The bigger the interface, the weaker the abstraction", 282 | points: 59, 283 | user: "zdw", 284 | time: 1690558267, 285 | time_ago: "2 days ago", 286 | comments_count: 39, 287 | type: "link", 288 | url: "https://functionallyimperative.com/p/the-bigger-the-interface-the-weaker", 289 | domain: "functionallyimperative.com", 290 | }, 291 | { 292 | id: 36927624, 293 | title: "Unsafe deserialization vulnerability in many Minecraft mods", 294 | points: 29, 295 | user: "davikr", 296 | time: 1690688773, 297 | time_ago: "5 hours ago", 298 | comments_count: 6, 299 | type: "link", 300 | url: "https://github.com/dogboy21/serializationisbad", 301 | domain: "github.com", 302 | }, 303 | { 304 | id: 36923562, 305 | title: "The Transformer Blueprint", 306 | points: 59, 307 | user: "nyandwi", 308 | time: 1690658515, 309 | time_ago: "13 hours ago", 310 | comments_count: 7, 311 | type: "link", 312 | url: "https://deeprevision.github.io/posts/001-transformer/", 313 | domain: "deeprevision.github.io", 314 | }, 315 | { 316 | id: 36917802, 317 | title: "Larne Craigyhill bonfire: 17000 pallets (2021)", 318 | points: 17, 319 | user: "daverol", 320 | time: 1690615770, 321 | time_ago: "a day ago", 322 | comments_count: 47, 323 | type: "link", 324 | url: "https://www.belfastlive.co.uk/news/larne-craigyhill-bonfire-more-17000-20989400", 325 | domain: "belfastlive.co.uk", 326 | }, 327 | { 328 | id: 36917290, 329 | title: "Birdga.me", 330 | points: 9, 331 | user: "dearwell", 332 | time: 1690609393, 333 | time_ago: "a day ago", 334 | comments_count: 3, 335 | type: "link", 336 | url: "https://birdga.me/harsh-division", 337 | domain: "birdga.me", 338 | }, 339 | { 340 | id: 36902351, 341 | title: "The Wrath of Goodreads", 342 | points: 49, 343 | user: "fortran77", 344 | time: 1690509397, 345 | time_ago: "2 days ago", 346 | comments_count: 65, 347 | type: "link", 348 | url: "https://www.theatlantic.com/ideas/archive/2023/07/goodreads-review-bombing-amazon-moderation/674811/", 349 | domain: "theatlantic.com", 350 | }, 351 | { 352 | id: 36919981, 353 | title: "The Hacker's Dictionary", 354 | points: 112, 355 | user: "derealized", 356 | time: 1690636439, 357 | time_ago: "19 hours ago", 358 | comments_count: 38, 359 | type: "link", 360 | url: "http://www.hackersdictionary.com/html/index.html", 361 | domain: "hackersdictionary.com", 362 | }, 363 | ]; 364 | -------------------------------------------------------------------------------- /lib/resend.ts: -------------------------------------------------------------------------------- 1 | import { Resend } from "resend"; 2 | const resend = new Resend(process.env.RESEND_KEY); 3 | export default resend; 4 | -------------------------------------------------------------------------------- /nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | devtools: { enabled: true }, 3 | modules: ["nuxt-icon", "@nuxtjs/supabase", "@vueuse/nuxt", "@nuxthq/ui"], 4 | ui: { 5 | icons: ["heroicons", "logos", "lucide"], 6 | }, 7 | colorMode: { 8 | preference: "light", 9 | }, 10 | supabase: { 11 | redirect: false, 12 | }, 13 | runtimeConfig: { 14 | public: { 15 | baseUrl: process.env.BASE_URL || "http://localhost:3000", 16 | }, 17 | }, 18 | app: { 19 | head: { 20 | script: [ 21 | { 22 | src: "https://analytics.umami.is/script.js", 23 | "data-website-id": "0e36663c-ef9c-42c5-a147-7c0d993ab160", 24 | async: true, 25 | }, 26 | ], 27 | }, 28 | }, 29 | }); 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-app", 3 | "private": true, 4 | "scripts": { 5 | "build": "nuxt build", 6 | "dev": "nuxt dev", 7 | "generate": "nuxt generate", 8 | "preview": "nuxt preview", 9 | "postinstall": "nuxt prepare" 10 | }, 11 | "devDependencies": { 12 | "@iconify-json/logos": "^1.1.37", 13 | "@nuxt/devtools": "^0.8.4", 14 | "@nuxtjs/supabase": "^1.1.0", 15 | "@tailwindcss/typography": "^0.5.10", 16 | "@types/cheerio": "^0.22.32", 17 | "@types/node": "^20.6.3", 18 | "@vueuse/core": "^10.4.1", 19 | "@vueuse/nuxt": "^10.4.1", 20 | "nuxt": "^3.7.3", 21 | "nuxt-icon": "^0.5.0", 22 | "yarn-upgrade-all": "^0.7.2" 23 | }, 24 | "dependencies": { 25 | "@iconify-json/lucide": "^1.1.128", 26 | "@nuxthq/ui": "^2.7.0", 27 | "@vercel/analytics": "^1.0.2", 28 | "cheerio": "^1.0.0-rc.12", 29 | "fast-xml-parser": "^4.3.0", 30 | "h3-zod": "^0.5.1", 31 | "resend": "^1.1.0", 32 | "zod": "^3.22.2" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pages/auth/confirm.vue: -------------------------------------------------------------------------------- 1 | 13 | 21 | 22 | 43 | -------------------------------------------------------------------------------- /pages/auth/login.vue: -------------------------------------------------------------------------------- 1 | 93 | 94 | 132 | -------------------------------------------------------------------------------- /pages/auth/register.vue: -------------------------------------------------------------------------------- 1 | 96 | 97 | 158 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 79 | 80 | 148 | -------------------------------------------------------------------------------- /public/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/banner.png -------------------------------------------------------------------------------- /public/envelope.svg: -------------------------------------------------------------------------------- 1 | Free Icons -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/favicon.ico -------------------------------------------------------------------------------- /public/logo-full.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/logo-with-bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /public/mailbox.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/mailbox.webp -------------------------------------------------------------------------------- /public/newspaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/newspaper.png -------------------------------------------------------------------------------- /public/pwa/android/android-launchericon-144-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/android/android-launchericon-144-144.png -------------------------------------------------------------------------------- /public/pwa/android/android-launchericon-192-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/android/android-launchericon-192-192.png -------------------------------------------------------------------------------- /public/pwa/android/android-launchericon-48-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/android/android-launchericon-48-48.png -------------------------------------------------------------------------------- /public/pwa/android/android-launchericon-512-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/android/android-launchericon-512-512.png -------------------------------------------------------------------------------- /public/pwa/android/android-launchericon-72-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/android/android-launchericon-72-72.png -------------------------------------------------------------------------------- /public/pwa/android/android-launchericon-96-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/android/android-launchericon-96-96.png -------------------------------------------------------------------------------- /public/pwa/apple/apple-icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-icon-180.png -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1125-2436.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1125-2436.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1136-640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1136-640.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1170-2532.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1170-2532.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1179-2556.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1179-2556.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1242-2208.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1242-2208.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1242-2688.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1242-2688.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1284-2778.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1284-2778.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1290-2796.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1290-2796.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1334-750.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1334-750.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1536-2048.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1536-2048.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1620-2160.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1620-2160.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1668-2224.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1668-2224.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1668-2388.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1668-2388.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-1792-828.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-1792-828.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2048-1536.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2048-1536.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2048-2732.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2048-2732.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2160-1620.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2160-1620.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2208-1242.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2208-1242.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2224-1668.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2224-1668.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2388-1668.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2388-1668.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2436-1125.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2436-1125.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2532-1170.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2532-1170.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2556-1179.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2556-1179.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2688-1242.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2688-1242.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2732-2048.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2732-2048.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2778-1284.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2778-1284.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-2796-1290.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-2796-1290.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-640-1136.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-640-1136.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-750-1334.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-750-1334.jpg -------------------------------------------------------------------------------- /public/pwa/apple/apple-splash-828-1792.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/apple-splash-828-1792.jpg -------------------------------------------------------------------------------- /public/pwa/apple/manifest-icon-192.maskable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/manifest-icon-192.maskable.png -------------------------------------------------------------------------------- /public/pwa/apple/manifest-icon-512.maskable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/apple/manifest-icon-512.maskable.png -------------------------------------------------------------------------------- /public/pwa/ios/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/100.png -------------------------------------------------------------------------------- /public/pwa/ios/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/1024.png -------------------------------------------------------------------------------- /public/pwa/ios/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/114.png -------------------------------------------------------------------------------- /public/pwa/ios/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/120.png -------------------------------------------------------------------------------- /public/pwa/ios/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/128.png -------------------------------------------------------------------------------- /public/pwa/ios/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/144.png -------------------------------------------------------------------------------- /public/pwa/ios/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/152.png -------------------------------------------------------------------------------- /public/pwa/ios/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/16.png -------------------------------------------------------------------------------- /public/pwa/ios/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/167.png -------------------------------------------------------------------------------- /public/pwa/ios/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/180.png -------------------------------------------------------------------------------- /public/pwa/ios/192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/192.png -------------------------------------------------------------------------------- /public/pwa/ios/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/20.png -------------------------------------------------------------------------------- /public/pwa/ios/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/256.png -------------------------------------------------------------------------------- /public/pwa/ios/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/29.png -------------------------------------------------------------------------------- /public/pwa/ios/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/32.png -------------------------------------------------------------------------------- /public/pwa/ios/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/40.png -------------------------------------------------------------------------------- /public/pwa/ios/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/50.png -------------------------------------------------------------------------------- /public/pwa/ios/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/512.png -------------------------------------------------------------------------------- /public/pwa/ios/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/57.png -------------------------------------------------------------------------------- /public/pwa/ios/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/58.png -------------------------------------------------------------------------------- /public/pwa/ios/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/60.png -------------------------------------------------------------------------------- /public/pwa/ios/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/64.png -------------------------------------------------------------------------------- /public/pwa/ios/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/72.png -------------------------------------------------------------------------------- /public/pwa/ios/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/76.png -------------------------------------------------------------------------------- /public/pwa/ios/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/80.png -------------------------------------------------------------------------------- /public/pwa/ios/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/ios/87.png -------------------------------------------------------------------------------- /public/pwa/windows11/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/LargeTile.scale-100.png -------------------------------------------------------------------------------- /public/pwa/windows11/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/LargeTile.scale-125.png -------------------------------------------------------------------------------- /public/pwa/windows11/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/LargeTile.scale-150.png -------------------------------------------------------------------------------- /public/pwa/windows11/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/LargeTile.scale-200.png -------------------------------------------------------------------------------- /public/pwa/windows11/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/LargeTile.scale-400.png -------------------------------------------------------------------------------- /public/pwa/windows11/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SmallTile.scale-100.png -------------------------------------------------------------------------------- /public/pwa/windows11/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SmallTile.scale-125.png -------------------------------------------------------------------------------- /public/pwa/windows11/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SmallTile.scale-150.png -------------------------------------------------------------------------------- /public/pwa/windows11/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SmallTile.scale-200.png -------------------------------------------------------------------------------- /public/pwa/windows11/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SmallTile.scale-400.png -------------------------------------------------------------------------------- /public/pwa/windows11/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /public/pwa/windows11/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /public/pwa/windows11/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /public/pwa/windows11/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /public/pwa/windows11/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-16.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-20.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-24.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-256.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-30.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-32.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-36.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-40.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-44.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-48.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-60.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-64.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-72.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-80.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-lightunplated_targetsize-96.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-20.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-24.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-30.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-36.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-40.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-44.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-60.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-64.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-72.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-80.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.altform-unplated_targetsize-96.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-20.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-30.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-36.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-40.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-44.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-60.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-64.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-72.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-80.png -------------------------------------------------------------------------------- /public/pwa/windows11/Square44x44Logo.targetsize-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Square44x44Logo.targetsize-96.png -------------------------------------------------------------------------------- /public/pwa/windows11/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /public/pwa/windows11/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /public/pwa/windows11/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /public/pwa/windows11/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /public/pwa/windows11/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /public/pwa/windows11/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /public/pwa/windows11/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /public/pwa/windows11/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /public/pwa/windows11/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /public/pwa/windows11/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fayazara/feedful/b07a7cf06a36fb677cdae153f86bf672e5f64d15/public/pwa/windows11/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /public/spinner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/api/feed/dribbble.ts: -------------------------------------------------------------------------------- 1 | import getDribbblePosts from "@/lib/getDribbblePosts"; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const posts = await getDribbblePosts(); 5 | return posts; 6 | }); 7 | -------------------------------------------------------------------------------- /server/api/feed/github-trending.ts: -------------------------------------------------------------------------------- 1 | import getGithubTrendingRepos from "@/lib/getGithubTrendingRepos"; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const { lang = "all", since = "daily" } = getQuery(event) as { 5 | lang: string; 6 | since: string; 7 | }; 8 | const posts = await getGithubTrendingRepos(lang, since); 9 | return posts; 10 | }); 11 | -------------------------------------------------------------------------------- /server/api/feed/hackernews.ts: -------------------------------------------------------------------------------- 1 | import getHackernewsPosts from "@/lib/getHackernewsPosts"; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const posts = await getHackernewsPosts(); 5 | return posts; 6 | }); 7 | -------------------------------------------------------------------------------- /server/api/feed/producthunt.ts: -------------------------------------------------------------------------------- 1 | import getProducthuntPosts from "@/lib/getProducthuntPosts"; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const posts = await getProducthuntPosts(); 5 | return posts; 6 | }); 7 | -------------------------------------------------------------------------------- /server/api/feed/reddit.ts: -------------------------------------------------------------------------------- 1 | import getRedditPosts from "@/lib/getRedditPosts"; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const { subreddit } = getQuery(event) as { subreddit: string }; 5 | if (!subreddit) { 6 | throw createError({ 7 | statusCode: 400, 8 | statusMessage: "Subreddit is required", 9 | }); 10 | return; 11 | } 12 | const posts: RedditPost[] = await getRedditPosts(subreddit); 13 | return posts; 14 | }); 15 | -------------------------------------------------------------------------------- /server/api/feed/rss.ts: -------------------------------------------------------------------------------- 1 | import getRssFeed from "~/lib/getRssFeed"; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const { feedUrl } = getQuery(event) as { feedUrl: string }; 5 | if (!feedUrl) { 6 | throw createError({ 7 | statusCode: 400, 8 | statusMessage: "feedUrl is required", 9 | }); 10 | return; 11 | } 12 | const posts = await getRssFeed(feedUrl); 13 | return posts; 14 | }); 15 | -------------------------------------------------------------------------------- /server/api/feed/youtube.ts: -------------------------------------------------------------------------------- 1 | import getYoutubeFeed from "@/lib/getYoutubeFeed"; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const { channel } = getQuery(event) as { channel: string }; 5 | if (!channel) { 6 | throw createError({ 7 | statusCode: 400, 8 | statusMessage: "Channel is required", 9 | }); 10 | return; 11 | } 12 | const posts = await getYoutubeFeed(channel); 13 | return posts; 14 | }); 15 | -------------------------------------------------------------------------------- /server/api/report.post.ts: -------------------------------------------------------------------------------- 1 | import resend from "@/lib/resend"; 2 | import { useValidatedBody, z } from "h3-zod"; 3 | 4 | export default defineEventHandler(async (event) => { 5 | try { 6 | const { message, type, email } = await useValidatedBody(event, { 7 | message: z.string(), 8 | type: z.enum(["Bug", "Feature", "Other"]), 9 | email: z.string().email().optional(), 10 | }); 11 | await resend.emails.send({ 12 | from: "Feedful Report ", 13 | to: ["hi@feedful.app"], 14 | subject: `Report: ${type}`, 15 | text: `Message: ${message}\nEmail: ${email}`, 16 | tags: [ 17 | { 18 | name: "type", 19 | value: "feedful-report", 20 | }, 21 | ], 22 | }); 23 | return { 24 | statusCode: 200, 25 | body: JSON.stringify({ 26 | message: "Report sent", 27 | }), 28 | }; 29 | } catch (error) { 30 | return { 31 | statusCode: 500, 32 | body: JSON.stringify({ 33 | error: "An error occurred while processing the report.", 34 | }), 35 | }; 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /server/api/youtube.ts: -------------------------------------------------------------------------------- 1 | const URL = `https://youtube.googleapis.com/youtube/v3/search`; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const { search } = getQuery(event); 5 | if (!search) { 6 | throw createError({ 7 | statusCode: 400, 8 | statusMessage: "Please provide a search query", 9 | }); 10 | } 11 | 12 | const data: YouTubeSearchResponse = await $fetch(URL, { 13 | params: { 14 | part: "snippet", 15 | q: search, 16 | type: "channel", 17 | key: process.env.YOUTUBE_KEY, 18 | }, 19 | }); 20 | 21 | const formattedData: YoutubeChannel[] = data.items.map( 22 | (item: YouTubeSearchItem) => ({ 23 | id: item.id.channelId, 24 | name: item.snippet.title, 25 | thumbnail: item.snippet.thumbnails.default.url, 26 | }) 27 | ); 28 | 29 | return formattedData; 30 | }); 31 | -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | module.exports = { 3 | content: [ 4 | "./components/**/*.{js,vue,ts}", 5 | "./layouts/**/*.vue", 6 | "./pages/**/*.vue", 7 | "./plugins/**/*.{js,ts}", 8 | "./nuxt.config.{js,ts}", 9 | "./app.vue", 10 | ], 11 | theme: { 12 | extend: { 13 | height: { 14 | screen: ["100vh", "100dvh"], 15 | }, 16 | minHeight: { 17 | screen: ["100vh", "100dvh"], 18 | }, 19 | colors: { 20 | peach: "#fbfaf8", 21 | }, 22 | screens: { 23 | pwa: { raw: "(display-mode: standalone)" }, 24 | }, 25 | }, 26 | }, 27 | plugins: [require("@tailwindcss/typography")], 28 | } satisfies Config; 29 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /types/database.types.ts: -------------------------------------------------------------------------------- 1 | export interface Database { 2 | public: { 3 | Tables: { 4 | feeds: { 5 | Row: { 6 | created_at: string 7 | description: string | null 8 | id: number 9 | icon: string | null 10 | meta: any | null 11 | name: string | null 12 | type: string 13 | url: string | null 14 | user_id: string | null 15 | } 16 | Insert: { 17 | created_at?: string 18 | description?: string | null 19 | id?: number 20 | icon?: string | null 21 | meta?: any | null 22 | name?: string | null 23 | type: string 24 | url?: string | null 25 | user_id?: string | null 26 | } 27 | Update: { 28 | created_at?: string 29 | description?: string | null 30 | id?: number 31 | icon?: string | null 32 | meta?: any | null 33 | name?: string | null 34 | type?: string 35 | url?: string | null 36 | user_id?: string | null 37 | } 38 | Relationships: [ 39 | { 40 | foreignKeyName: "feeds_user_id_fkey" 41 | columns: ["user_id"] 42 | referencedRelation: "users" 43 | referencedColumns: ["id"] 44 | } 45 | ] 46 | } 47 | } 48 | Views: { 49 | [_ in never]: never 50 | } 51 | Functions: { 52 | [_ in never]: never 53 | } 54 | Enums: { 55 | [_ in never]: never 56 | } 57 | CompositeTypes: { 58 | [_ in never]: never 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /types/feed.d.ts: -------------------------------------------------------------------------------- 1 | declare interface GithubFeedMeta { 2 | language: string; 3 | since: string; 4 | } 5 | 6 | declare interface YoutubeFeedMeta { 7 | channelId: string; 8 | } 9 | 10 | declare interface RedditFeedMeta { 11 | subreddit: string; 12 | } 13 | 14 | declare interface RssFeedMeta { 15 | feedUrl: string; 16 | } 17 | 18 | declare interface Feed { 19 | id?: number; 20 | name: string; 21 | type: string; 22 | icon?: string; 23 | url?: string; 24 | description?: string; 25 | meta?: GithubFeedMeta | YoutubeFeedMeta | RssFeedMeta | RedditFeedMeta; 26 | user_id?: string; 27 | created_at?: string; 28 | } 29 | 30 | declare interface RedditPost { 31 | id: string; 32 | title: string; 33 | subreddit: string; 34 | author: string; 35 | votes: number; 36 | text: string; 37 | nsfw: boolean; 38 | url: string; 39 | is_video: boolean; 40 | is_image: boolean; 41 | thumbnail: string; 42 | comments: number; 43 | video_url: string; 44 | created_at: number; 45 | } 46 | 47 | interface ProducthuntThumbnail { 48 | type: string; 49 | url: string; 50 | } 51 | declare interface Producthunt { 52 | id: string; 53 | name: string; 54 | tagline: string; 55 | description: string; 56 | url: string; 57 | votesCount: number; 58 | thumbnail: ProducthuntThumbnail; 59 | website: string; 60 | reviewsRating: number; 61 | } 62 | 63 | declare interface Hackernews { 64 | id: number; 65 | title: string; 66 | points: number; 67 | user: string; 68 | time: number; 69 | time_ago: string; 70 | comments_count: number; 71 | type: string; 72 | url: string; 73 | domain: string; 74 | } 75 | 76 | declare interface Github { 77 | title: string; 78 | description: string; 79 | url: string; 80 | stars: string; 81 | } 82 | 83 | declare interface Dribbble { 84 | image: string; 85 | title: string; 86 | likes: string; 87 | views: string; 88 | author: string; 89 | authorAvatar: string; 90 | url: string; 91 | } 92 | 93 | declare interface YoutubeChannel { 94 | id: string; 95 | name: string; 96 | thumbnail: string; 97 | } 98 | 99 | declare interface YouTubeSearchResponse { 100 | kind: string; 101 | etag: string; 102 | nextPageToken: string; 103 | regionCode: string; 104 | pageInfo: { 105 | totalResults: number; 106 | resultsPerPage: number; 107 | }; 108 | items: YouTubeSearchItem[]; 109 | } 110 | 111 | declare interface YoutubePost { 112 | id?: string; 113 | enclosures: any[]; 114 | title: string; 115 | link: string; 116 | thumbnail: string; 117 | description: string; 118 | } 119 | 120 | declare interface YouTubeSearchItem { 121 | kind: string; 122 | etag: string; 123 | id: { 124 | kind: string; 125 | channelId: string; 126 | }; 127 | snippet: { 128 | publishedAt: string; 129 | channelId: string; 130 | title: string; 131 | description: string; 132 | thumbnails: { 133 | default: { 134 | url: string; 135 | }; 136 | }; 137 | channelTitle: string; 138 | liveBroadcastContent: string; 139 | publishTime: string; 140 | }; 141 | } 142 | -------------------------------------------------------------------------------- /utils/getYoutubeChannelId.ts: -------------------------------------------------------------------------------- 1 | import { load } from "cheerio"; 2 | 3 | const fetchOptions = { 4 | headers: { 5 | "User-Agent": 6 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36", 7 | }, 8 | }; 9 | 10 | /** 11 | * Check YouTube Url 12 | * 13 | * @param {string} url 14 | * @returns {boolean} 15 | */ 16 | const checkUrl = (url: string): boolean => 17 | url.indexOf("youtube.com") !== -1 || url.indexOf("youtu.be") !== -1; 18 | 19 | /** 20 | * Get YouTube Channel ID By Url 21 | * 22 | * @param {string} url Channel Url 23 | * @returns {Promise} Channel ID 24 | */ 25 | export const channelId = async (url: string): Promise => { 26 | if (checkUrl(url)) { 27 | const ytChannelPageResponse = await fetch(url, fetchOptions); 28 | const ytChannelPageData = await ytChannelPageResponse.text(); 29 | const $ = load(ytChannelPageData); 30 | const id = $('meta[itemprop="channelId"]').attr("content"); 31 | if (id) { 32 | return id; 33 | } 34 | } else { 35 | throw new Error(`"${url}" is not a YouTube url.`); 36 | } 37 | 38 | throw new Error(`Unable to get "${url}" channel id.`); 39 | }; 40 | -------------------------------------------------------------------------------- /utils/index.ts: -------------------------------------------------------------------------------- 1 | import rssParser from "./rssparser"; 2 | 3 | export async function sleep(ms: number) { 4 | return new Promise((resolve) => setTimeout(resolve, ms)); 5 | } 6 | 7 | export function formatNumber(num: number): string { 8 | if (Math.abs(num) >= 1e6) { 9 | const million = Math.sign(num) * (Math.abs(num) / 1e6); 10 | if (Math.abs(million) >= 1000) { 11 | return (Math.sign(million) * (Math.abs(million) / 1000)).toFixed(1) + "M"; 12 | } else { 13 | return million.toFixed(1) + "M"; 14 | } 15 | } else if (Math.abs(num) >= 1000) { 16 | return (Math.sign(num) * (Math.abs(num) / 1000)).toFixed(1) + "k"; 17 | } else { 18 | return Math.sign(num) * Math.abs(num) + ""; 19 | } 20 | } 21 | 22 | export const today = new Date().toLocaleDateString("en-US", { 23 | weekday: "short", 24 | year: "numeric", 25 | month: "short", 26 | day: "numeric", 27 | }); 28 | 29 | export { rssParser }; 30 | 31 | export function getTimeAgo(epochTimestamp: number): string { 32 | const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds 33 | const timeDifference = currentTime - epochTimestamp; 34 | 35 | if (timeDifference < 60) { 36 | return `${timeDifference}s ago`; 37 | } else if (timeDifference < 3600) { 38 | const minutes = Math.floor(timeDifference / 60); 39 | return `${minutes}m ago`; 40 | } else if (timeDifference < 86400) { 41 | const hours = Math.floor(timeDifference / 3600); 42 | return `${hours}h ago`; 43 | } else if (timeDifference < 2592000) { 44 | const days = Math.floor(timeDifference / 86400); 45 | return `${days}d ago`; 46 | } else if (timeDifference < 31536000) { 47 | const months = Math.floor(timeDifference / 2592000); 48 | return `${months}mn ago`; 49 | } else { 50 | const years = Math.floor(timeDifference / 31536000); 51 | return `${years}y ago`; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /utils/rssparser.ts: -------------------------------------------------------------------------------- 1 | import { XMLParser } from "fast-xml-parser"; 2 | 3 | export default async (url: string) => { 4 | if (!/(^http(s?):\/\/[^\s$.?#].[^\s]*)/i.test(url)) return null; 5 | 6 | const response = await fetch(url); 7 | const data = await response.text(); 8 | 9 | const xml = new XMLParser({ 10 | attributeNamePrefix: "", 11 | textNodeName: "$text", 12 | ignoreAttributes: false, 13 | }); 14 | 15 | const result = xml.parse(data); 16 | 17 | let channel = 18 | result.rss && result.rss.channel ? result.rss.channel : result.feed; 19 | if (Array.isArray(channel)) channel = channel[0]; 20 | 21 | const rss = { 22 | title: channel.title ?? "", 23 | description: channel.description ?? "", 24 | link: channel.link && channel.link.href ? channel.link.href : channel.link, 25 | image: channel.image 26 | ? channel.image.url 27 | : channel["itunes:image"] 28 | ? channel["itunes:image"].href 29 | : "", 30 | category: channel.category || [], 31 | items: [], 32 | }; 33 | 34 | let items = channel.item || channel.entry || []; 35 | if (items && !Array.isArray(items)) items = [items]; 36 | 37 | for (let i = 0; i < items.length; i++) { 38 | const val = items[i]; 39 | const media = {}; 40 | 41 | const obj = { 42 | id: val.guid && val.guid.$text ? val.guid.$text : val.id, 43 | title: val.title && val.title.$text ? val.title.$text : val.title, 44 | description: 45 | val.summary && val.summary.$text ? val.summary.$text : val.description, 46 | link: val.link && val.link.href ? val.link.href : val.link, 47 | author: 48 | val.author && val.author.name ? val.author.name : val["dc:creator"], 49 | published: val.created 50 | ? Date.parse(val.created) 51 | : val.pubDate 52 | ? Date.parse(val.pubDate) 53 | : Date.now(), 54 | created: val.updated 55 | ? Date.parse(val.updated) 56 | : val.pubDate 57 | ? Date.parse(val.pubDate) 58 | : val.created 59 | ? Date.parse(val.created) 60 | : Date.now(), 61 | category: val.category || [], 62 | content: 63 | val.content && val.content.$text 64 | ? val.content.$text 65 | : val["content:encoded"], 66 | enclosures: val.enclosure 67 | ? Array.isArray(val.enclosure) 68 | ? val.enclosure 69 | : [val.enclosure] 70 | : [], 71 | }; 72 | 73 | [ 74 | "content:encoded", 75 | "podcast:transcript", 76 | "itunes:summary", 77 | "itunes:author", 78 | "itunes:explicit", 79 | "itunes:duration", 80 | "itunes:season", 81 | "itunes:episode", 82 | "itunes:episodeType", 83 | "itunes:image", 84 | ].forEach((s) => { 85 | if (val[s]) obj[s.replace(":", "_") as keyof typeof obj] = val[s]; 86 | }); 87 | 88 | if (val["media:thumbnail"]) { 89 | Object.assign(media, { thumbnail: val["media:thumbnail"] }); 90 | obj.enclosures.push(val["media:thumbnail"]); 91 | } 92 | 93 | if (val["media:content"]) { 94 | Object.assign(media, { thumbnail: val["media:content"] }); 95 | obj.enclosures.push(val["media:content"]); 96 | } 97 | 98 | if (val["media:group"]) { 99 | if (val["media:group"]["media:title"]) 100 | obj.title = val["media:group"]["media:title"]; 101 | 102 | if (val["media:group"]["media:description"]) 103 | obj.description = val["media:group"]["media:description"]; 104 | 105 | if (val["media:group"]["media:thumbnail"]) 106 | obj.enclosures.push(val["media:group"]["media:thumbnail"].url); 107 | } 108 | 109 | Object.assign(obj, { media }); 110 | // @ts-ignore 111 | rss.items.push(obj); 112 | } 113 | 114 | return rss; 115 | }; 116 | --------------------------------------------------------------------------------