├── .env.example ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── LICENSE.md ├── README.md ├── astro.config.mjs ├── bun.lock ├── keystatic.config.ts ├── package.json ├── public ├── apple-touch-icon.png ├── favicon copy.svg ├── favicon-96x96.png ├── favicon.ico ├── favicon.svg ├── robots.txt ├── site.webmanifest ├── web-app-manifest-192x192.png └── web-app-manifest-512x512.png ├── src ├── assets │ ├── images │ │ ├── Performances.png │ │ ├── articles │ │ │ ├── 10-tips-for-better-time-management │ │ │ │ └── cover.avif │ │ │ ├── a-function-s-existential-crisis │ │ │ │ └── cover.avif │ │ │ ├── exploring-the-benefits-of-daily-meditation │ │ │ │ └── cover.avif │ │ │ ├── how-to-build-a-capsule-wardrobe │ │ │ │ └── cover.avif │ │ │ ├── java-script-math-is-a-lie │ │ │ │ └── cover.avif │ │ │ ├── mastering-time-management │ │ │ │ └── cover.avif │ │ │ ├── promises-in-javascript-trust-issues-in-code │ │ │ │ └── cover.avif │ │ │ ├── the-art-of-minimalist-living │ │ │ │ └── cover.avif │ │ │ ├── the-basics-of-personal-finance │ │ │ │ └── cover.avif │ │ │ ├── the-benefits-of-meditation │ │ │ │ └── cover.avif │ │ │ ├── top-5-web-development-frameworks-for-2025 │ │ │ │ └── cover.avif │ │ │ ├── understanding-java-script-closures │ │ │ │ └── cover.avif │ │ │ └── why-does-this-hate-me-demystifying-java-script-s-this │ │ │ │ └── cover.avif │ │ ├── authors │ │ │ ├── ahmed-khan │ │ │ │ └── avatar.jpg │ │ │ ├── chloe-nguyen │ │ │ │ └── avatar.jpg │ │ │ ├── emily-devis │ │ │ │ └── avatar.jpg │ │ │ ├── jane-doe │ │ │ │ └── avatar.jpg │ │ │ ├── john-smith │ │ │ │ └── avatar.jpg │ │ │ ├── liam-leonard │ │ │ │ └── avatar.jpg │ │ │ ├── maria-gonzalez │ │ │ │ └── avatar.jpg │ │ │ ├── olivier-brown │ │ │ │ └── avatar.jpg │ │ │ ├── rajesh-patel │ │ │ │ └── avatar.jpg │ │ │ └── sofia-martinez │ │ │ │ └── avatar.jpg │ │ ├── default-avatar.jpg │ │ ├── default-image.jpg │ │ └── screenshot-astronews.png │ └── svgs │ │ ├── arrow-left-01.astro │ │ ├── arrow-left-double.astro │ │ ├── arrow-right-01.astro │ │ ├── arrow-right-02.astro │ │ ├── arrow-right-double.astro │ │ ├── calendar-04.astro │ │ ├── clipboard.astro │ │ ├── facebook.astro │ │ ├── github.astro │ │ ├── hashtag.astro │ │ ├── info.astro │ │ ├── linkedin.astro │ │ ├── menu.astro │ │ ├── moon.astro │ │ ├── new-twitter.astro │ │ ├── pen-01.astro │ │ ├── pencil-edit-01.astro │ │ ├── resources-add.astro │ │ ├── search-01.astro │ │ ├── share-08.astro │ │ ├── sun.astro │ │ ├── telegram.astro │ │ ├── time-04.astro │ │ ├── twitter.astro │ │ ├── user.astro │ │ ├── whatsapp.astro │ │ └── whatsapp.svg ├── components │ ├── bases │ │ ├── divider.astro │ │ ├── head.astro │ │ ├── icon.astro │ │ ├── navbar-item.astro │ │ ├── script.astro │ │ ├── share-item.astro │ │ └── theme-controller.astro │ ├── cards │ │ ├── authorCard.astro │ │ ├── mainHeadline.astro │ │ ├── newsCard.astro │ │ ├── subHeadlineCard.astro │ │ └── wideCard.astro │ ├── elements │ │ ├── menu-dropdown.astro │ │ ├── navbar.astro │ │ ├── share.astro │ │ └── top-header.astro │ └── shared │ │ ├── Carousel.astro │ │ ├── footer.astro │ │ ├── header.astro │ │ ├── pagination.astro │ │ └── view-list-header.astro ├── content.config.ts ├── content │ ├── articles │ │ ├── 10-tips-for-better-time-management │ │ │ └── index.mdx │ │ ├── a-function-s-existential-crisis │ │ │ └── index.mdx │ │ ├── exploring-the-benefits-of-daily-meditation │ │ │ └── index.mdx │ │ ├── how-to-build-a-capsule-wardrobe │ │ │ └── index.mdx │ │ ├── javascript-math-is-a-lie │ │ │ └── index.mdx │ │ ├── mastering-time-management │ │ │ └── index.mdx │ │ ├── promises-in-javascript-trust-issues-in-code │ │ │ └── index.mdx │ │ ├── the-art-of-minimalist-living │ │ │ └── index.mdx │ │ ├── the-basics-of-personal-finance │ │ │ └── index.mdx │ │ ├── the-benefits-of-meditation │ │ │ └── index.mdx │ │ ├── top-5-web-development-frameworks-for-2025 │ │ │ └── index.mdx │ │ ├── understanding-java-script-closures │ │ │ └── index.mdx │ │ └── why-does-this-hate-me-demystifying-java-script-s-this │ │ │ └── index.mdx │ ├── authors │ │ ├── ahmed-khan │ │ │ └── index.mdx │ │ ├── chloe-nguyen │ │ │ └── index.mdx │ │ ├── emily-devis │ │ │ └── index.mdx │ │ ├── jane-doe │ │ │ └── index.mdx │ │ ├── john-smith │ │ │ └── index.mdx │ │ ├── liam-leonard │ │ │ └── index.mdx │ │ ├── maria-gonzalez │ │ │ └── index.mdx │ │ ├── olivier-brown │ │ │ └── index.mdx │ │ ├── rajesh-patel │ │ │ └── index.mdx │ │ └── sofia-martinez │ │ │ └── index.mdx │ ├── categories │ │ ├── finance │ │ │ └── index.json │ │ ├── health │ │ │ └── index.json │ │ ├── lifestyle │ │ │ └── index.json │ │ ├── productivity │ │ │ └── index.json │ │ ├── programming │ │ │ └── index.json │ │ ├── technology │ │ │ └── index.json │ │ └── wellness │ │ │ └── index.json │ └── views │ │ ├── about.mdx │ │ ├── articles.mdx │ │ ├── author.mdx │ │ ├── authors.mdx │ │ ├── categories.mdx │ │ ├── contact.mdx │ │ ├── error404.mdx │ │ ├── home.mdx │ │ └── search.mdx ├── layouts │ ├── base.astro │ ├── content.astro │ └── list.astro ├── lib │ ├── config │ │ └── index.ts │ ├── handlers │ │ ├── articles.ts │ │ ├── authors.ts │ │ └── categories.ts │ ├── keystatic │ │ ├── articlesKs.ts │ │ ├── authorsKs.ts │ │ ├── categoriesKs.ts │ │ └── index.ts │ ├── schema │ │ └── index.ts │ ├── types │ │ └── index.ts │ └── utils │ │ ├── date.ts │ │ ├── getMeta.ts │ │ ├── letter.ts │ │ └── remarks.mjs ├── pages │ ├── 404.astro │ ├── _home │ │ ├── authors.astro │ │ ├── headerSection.astro │ │ ├── headlines.astro │ │ ├── latestNews.astro │ │ └── news-ticker.astro │ ├── about.astro │ ├── articles │ │ ├── [id].astro │ │ ├── [page].astro │ │ ├── _components │ │ │ └── article-header.astro │ │ └── index.astro │ ├── authors │ │ ├── [id] │ │ │ ├── [page].astro │ │ │ └── index.astro │ │ └── index.astro │ ├── categories │ │ ├── [category] │ │ │ ├── [page].astro │ │ │ └── index.astro │ │ └── index.astro │ ├── index.astro │ ├── rss.xml.js │ └── search │ │ └── index.astro └── styles │ └── global.css └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | RUN_KEYSTATIC=false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | 4 | # generated types 5 | .astro/ 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # logs 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | 23 | # jetbrains setting folder 24 | .idea/ 25 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.css": "tailwindcss" 4 | }, 5 | "editor.fontLigatures": "'calt', 'ss01', 'ss02', 'ss03', 'ss19', 'ss20'", 6 | "editor.fontFamily": "'Cascadia Code NF', Consolas, 'Courier New', monospace", 7 | "editor.tabSize": 2, 8 | "editor.formatOnSave": true 9 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | MIT License 4 | 5 | Copyright (c) 2024 Mohammad Rahmani 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Astro News 📰 2 | 3 | A news website built with Astro, designed to provide a modern and responsive news reading experience. 4 | 5 | > **ℹ️ Info** 6 | > Astro news is my first open-source project, so there may be some bugs or issues. I’ll address them as quickly as possible. 7 | 8 | ![Astro News](./src/assets/images/screenshot-astronews.png "Astro News") 9 | 10 | ![performances](./src/assets/images/Performances.png "Performances") 11 | 12 | ## 🌐 Demo 13 | 14 | Explore the live demo here: [**Live Demo**](https://astro-news-six.vercel.app/) 15 | 16 | ## 🚀 Installation 17 | 18 | Follow the steps below to set up and run the project locally: 19 | 20 | ### Clone the Repository 21 | 22 | ```bash 23 | git clone https://github.com/Mrahmani71/astro-news.git 24 | ``` 25 | 26 | ### Install Dependencies 27 | 28 | ``` bash 29 | bun install 30 | ``` 31 | 32 | ### Run Development Server 33 | 34 | ```bash 35 | bun dev 36 | ``` 37 | 38 | ### Running Keystatic CMS 39 | 40 | 1. Rename `.env.example` to `.env`. 41 | 42 | 2. Set `RUN_KEYSTATIC=true`. 43 | 44 | 3. Start the development server: 45 | 46 | ```bash 47 | bun dev 48 | ``` 49 | 50 | 4. Open `http://localhost:4321/keystatic` in your browser. 51 | 52 | ## ✨ Features 53 | 54 | ### Implemented Features 55 | 56 | - Content Layer 57 | - Keystatic CMS 58 | - Navigation 59 | - Responsive Design 60 | - Pagination 61 | - Search Functionality 62 | - RSS Feed 63 | - Sitemap 64 | - Dark Mode 65 | - SEO Optimization (~) 66 | 67 | ### Upcoming Features 68 | 69 | - Open Graph (OG) Image Generation 70 | 71 | ## 💻 Technologies 72 | 73 | This project leverages cutting-edge web technologies: 74 | 75 | - [Astro V5.7](https://astro.build) - Modern static site builder 76 | - [KeyStatic](https://keystatic.com) - Headless content-management system 77 | - [Tailwind CSS](https://tailwindcss.com) - Utility-first CSS framework 78 | - [DaisyUI](https://daisyui.com/) - Tailwind CSS component library 79 | - [TypeScript](https://typescriptlang.org) - Typed JavaScript 80 | - [MDX](https://mdxjs.com) - Markdown with JSX support 81 | - [Bun V1.2.10](https://bun.sh) - Fast JavaScript runtime 82 | - [Vercel](https://vercel.com) - Deployment platform 83 | - [HugeIcons](https://hugeicons.com) - Icon library 84 | 85 | ## 💡 Inspirations and Code Concepts 86 | 87 | This project draws inspiration from the following sources: 88 | 89 | ### Designs 90 | 91 | - [BBC News](https://www.bbc.com) 92 | - [NewsHub - News Website](https://dribbble.com/shots/21678041-NewsHub-News-Website) 93 | - [Let'sread - News Landing Page](https://dribbble.com/shots/24675325-Let-sread-News-Landing-Page) 94 | 95 | ### Articles 96 | 97 | - [Creating A Pagination Component With Astro](https://rimdev.io/creating-a-pagination-component-with-astro) 98 | - [Adding search to static Astro sites](https://website-thomas-astro.vercel.app/blog/search-static-astro-website) 99 | 100 | ## 📄 License 101 | 102 | Open sourced under the [MIT license](LICENSE.md). 103 | 104 | ## 🤝 Contributing 105 | 106 | Contributions, issues, and feature requests are welcome! Feel free to check the [issues page](https://github.com/Mrahmani71/astro-news/issues). 107 | -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import { defineConfig } from "astro/config"; 3 | import tailwindcss from "@tailwindcss/vite"; 4 | import mdx from "@astrojs/mdx"; 5 | import sitemap from "@astrojs/sitemap"; 6 | import { modifiedTime, readingTime } from "./src/lib/utils/remarks.mjs"; 7 | import { SITE } from "./src/lib/config"; 8 | import keystatic from "@keystatic/astro"; 9 | import react from "@astrojs/react"; 10 | import { loadEnv } from "vite"; 11 | import pagefind from "astro-pagefind"; 12 | 13 | const { RUN_KEYSTATIC } = loadEnv(import.meta.env.MODE, process.cwd(), ""); 14 | 15 | const integrations = [mdx(), sitemap(), pagefind()]; 16 | 17 | if (RUN_KEYSTATIC === "true") { 18 | integrations.push(react()); 19 | integrations.push(keystatic()); 20 | } 21 | 22 | // https://astro.build/config 23 | export default defineConfig({ 24 | site: SITE.url, 25 | base: SITE.basePath, 26 | markdown: { 27 | remarkPlugins: [readingTime, modifiedTime], 28 | }, 29 | experimental: { 30 | responsiveImages: true, 31 | }, 32 | image: {}, 33 | integrations, 34 | vite: { 35 | plugins: [tailwindcss()], 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /keystatic.config.ts: -------------------------------------------------------------------------------- 1 | import { articlesKs, authorsKs, categoriesKs } from "@/lib/keystatic"; 2 | import { config } from "@keystatic/core"; 3 | 4 | export default config({ 5 | storage: { 6 | kind: "local", 7 | }, 8 | ui: { 9 | brand: { 10 | name: "Astro News", 11 | }, 12 | navigation: ["---", "articles", "---", "authors", "categories"], 13 | }, 14 | collections: { 15 | articles: articlesKs, 16 | authors: authorsKs, 17 | categories: categoriesKs, 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "astro-news", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "build": "astro build", 8 | "preview": "astro preview", 9 | "astro": "astro" 10 | }, 11 | "dependencies": { 12 | "@astrojs/check": "^0.9.4", 13 | "@astrojs/mdx": "^4.2.4", 14 | "@astrojs/react": "^4.2.4", 15 | "@astrojs/rss": "^4.0.11", 16 | "@astrojs/sitemap": "^3.3.0", 17 | "@fontsource-variable/source-serif-4": "^5.2.6", 18 | "@fontsource/source-sans-pro": "^5.2.5", 19 | "@keystatic/astro": "^5.0.6", 20 | "@keystatic/core": "^0.5.47", 21 | "@pagefind/default-ui": "^1.3.0", 22 | "@tailwindcss/vite": "^4.1.4", 23 | "@types/react": "^19.1.2", 24 | "@types/react-dom": "^19.1.2", 25 | "astro": "^5.7.0", 26 | "astro-pagefind": "^1.8.3", 27 | "date-fns": "^4.1.0", 28 | "mdast-util-to-string": "^4.0.0", 29 | "pagefind": "^1.3.0", 30 | "react": "^19.1.0", 31 | "react-dom": "^19.1.0", 32 | "reading-time": "^1.5.0", 33 | "tailwindcss": "^4.1.4", 34 | "typescript": "^5.8.3" 35 | }, 36 | "devDependencies": { 37 | "@tailwindcss/typography": "^0.5.16", 38 | "daisyui": "^5.0.20" 39 | } 40 | } -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/public/favicon-96x96.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | 4 | Sitemap: https://astro-news-six.vercel.app/sitemap-index.xml -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Astro News", 3 | "short_name": "Astro News", 4 | "icons": [ 5 | { 6 | "src": "/web-app-manifest-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png", 9 | "purpose": "maskable" 10 | }, 11 | { 12 | "src": "/web-app-manifest-512x512.png", 13 | "sizes": "512x512", 14 | "type": "image/png", 15 | "purpose": "maskable" 16 | } 17 | ], 18 | "theme_color": "#ffffff", 19 | "background_color": "#ffffff", 20 | "display": "standalone" 21 | } -------------------------------------------------------------------------------- /public/web-app-manifest-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/public/web-app-manifest-192x192.png -------------------------------------------------------------------------------- /public/web-app-manifest-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/public/web-app-manifest-512x512.png -------------------------------------------------------------------------------- /src/assets/images/Performances.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/Performances.png -------------------------------------------------------------------------------- /src/assets/images/articles/10-tips-for-better-time-management/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/10-tips-for-better-time-management/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/a-function-s-existential-crisis/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/a-function-s-existential-crisis/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/exploring-the-benefits-of-daily-meditation/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/exploring-the-benefits-of-daily-meditation/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/how-to-build-a-capsule-wardrobe/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/how-to-build-a-capsule-wardrobe/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/java-script-math-is-a-lie/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/java-script-math-is-a-lie/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/mastering-time-management/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/mastering-time-management/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/promises-in-javascript-trust-issues-in-code/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/promises-in-javascript-trust-issues-in-code/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/the-art-of-minimalist-living/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/the-art-of-minimalist-living/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/the-basics-of-personal-finance/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/the-basics-of-personal-finance/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/the-benefits-of-meditation/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/the-benefits-of-meditation/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/top-5-web-development-frameworks-for-2025/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/top-5-web-development-frameworks-for-2025/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/understanding-java-script-closures/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/understanding-java-script-closures/cover.avif -------------------------------------------------------------------------------- /src/assets/images/articles/why-does-this-hate-me-demystifying-java-script-s-this/cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/articles/why-does-this-hate-me-demystifying-java-script-s-this/cover.avif -------------------------------------------------------------------------------- /src/assets/images/authors/ahmed-khan/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/ahmed-khan/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/authors/chloe-nguyen/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/chloe-nguyen/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/authors/emily-devis/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/emily-devis/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/authors/jane-doe/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/jane-doe/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/authors/john-smith/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/john-smith/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/authors/liam-leonard/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/liam-leonard/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/authors/maria-gonzalez/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/maria-gonzalez/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/authors/olivier-brown/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/olivier-brown/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/authors/rajesh-patel/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/rajesh-patel/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/authors/sofia-martinez/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/authors/sofia-martinez/avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/default-avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/default-avatar.jpg -------------------------------------------------------------------------------- /src/assets/images/default-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/default-image.jpg -------------------------------------------------------------------------------- /src/assets/images/screenshot-astronews.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrahmani71/astro-news/ed941bf3b30d42dc090beb49d5bce9db4ac3e0a1/src/assets/images/screenshot-astronews.png -------------------------------------------------------------------------------- /src/assets/svgs/arrow-left-01.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 30 | -------------------------------------------------------------------------------- /src/assets/svgs/arrow-left-double.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 35 | 36 | -------------------------------------------------------------------------------- /src/assets/svgs/arrow-right-01.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 30 | -------------------------------------------------------------------------------- /src/assets/svgs/arrow-right-02.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 35 | 36 | -------------------------------------------------------------------------------- /src/assets/svgs/arrow-right-double.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 35 | 36 | -------------------------------------------------------------------------------- /src/assets/svgs/calendar-04.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 35 | 41 | 42 | -------------------------------------------------------------------------------- /src/assets/svgs/clipboard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 28 | 32 | 37 | 38 | -------------------------------------------------------------------------------- /src/assets/svgs/facebook.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 30 | 31 | -------------------------------------------------------------------------------- /src/assets/svgs/github.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 35 | 36 | -------------------------------------------------------------------------------- /src/assets/svgs/hashtag.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { width = "20", height = "20", size } = Astro.props; 7 | --- 8 | 9 | 18 | 21 | 22 | -------------------------------------------------------------------------------- /src/assets/svgs/info.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { width = "20", height = "20", strokeWidth = "1.5", size } = Astro.props; 7 | --- 8 | 9 | 17 | 22 | 23 | -------------------------------------------------------------------------------- /src/assets/svgs/linkedin.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 27 | 31 | 36 | 37 | -------------------------------------------------------------------------------- /src/assets/svgs/menu.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 28 | 29 | -------------------------------------------------------------------------------- /src/assets/svgs/moon.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 24 | 30 | 31 | -------------------------------------------------------------------------------- /src/assets/svgs/new-twitter.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 30 | -------------------------------------------------------------------------------- /src/assets/svgs/pen-01.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | 13 | 19 | 25 | 26 | -------------------------------------------------------------------------------- /src/assets/svgs/pencil-edit-01.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | 13 | 19 | 24 | 25 | -------------------------------------------------------------------------------- /src/assets/svgs/resources-add.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 27 | 31 | 35 | 41 | 42 | -------------------------------------------------------------------------------- /src/assets/svgs/search-01.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 34 | 35 | -------------------------------------------------------------------------------- /src/assets/svgs/share-08.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | 13 | 17 | 21 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /src/assets/svgs/sun.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 24 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /src/assets/svgs/telegram.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 29 | 30 | -------------------------------------------------------------------------------- /src/assets/svgs/time-04.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 25 | 31 | 32 | -------------------------------------------------------------------------------- /src/assets/svgs/twitter.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 28 | 29 | -------------------------------------------------------------------------------- /src/assets/svgs/user.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | 13 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /src/assets/svgs/whatsapp.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Icon } from "@/lib/types"; 3 | 4 | type Props = Icon; 5 | 6 | const { 7 | width = "20", 8 | height = "20", 9 | color = "currentColor", 10 | strokeWidth = "1.5", 11 | size, 12 | } = Astro.props; 13 | --- 14 | 15 | 23 | 28 | 32 | 33 | -------------------------------------------------------------------------------- /src/assets/svgs/whatsapp.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/bases/divider.astro: -------------------------------------------------------------------------------- 1 | --- 2 | type Props = { 3 | responsive?: boolean; 4 | }; 5 | 6 | const { responsive = false } = Astro.props; 7 | --- 8 | 9 |
15 |
16 | -------------------------------------------------------------------------------- /src/components/bases/head.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import "@/styles/global.css"; 3 | import "@fontsource/source-sans-pro/400.css"; 4 | import "@fontsource/source-sans-pro/600.css"; 5 | import "@fontsource/source-sans-pro/700.css"; 6 | import "@fontsource-variable/source-serif-4"; 7 | import { ClientRouter } from "astro:transitions"; 8 | import { SITE } from "@/lib/config"; 9 | import type { ArticleMeta, Meta } from "@/lib/types"; 10 | 11 | type Props = { 12 | meta: Meta | ArticleMeta; 13 | }; 14 | 15 | const { meta } = Astro.props; 16 | 17 | // Type guard to check if props is ArticleMeta 18 | const isArticleMeta = (props: Props["meta"]): props is ArticleMeta => 19 | props.type === "article"; 20 | const canonicalURL = new URL(Astro.url.pathname, Astro.site).href; 21 | 22 | const OGImage = new URL(meta.ogImage, Astro.url).href; 23 | --- 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 47 | 48 | 49 | 50 | 51 | 52 | {meta.title} 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | { 74 | isArticleMeta(meta) ? ( 75 | <> 76 | 80 | 84 | 85 | {meta.authors.map((author) => ( 86 | <> 87 | 88 | 92 | 93 | ))} 94 | 95 | ) : null 96 | } 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/components/bases/icon.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Github from "@/assets/svgs/github.astro"; 3 | import NewTwitter from "@/assets/svgs/new-twitter.astro"; 4 | import Telegram from "@/assets/svgs/telegram.astro"; 5 | import Facebook from "@/assets/svgs/facebook.astro"; 6 | 7 | export interface Props { 8 | icon: string | undefined; 9 | } 10 | 11 | const { icon } = Astro.props; 12 | 13 | if (!icon) { 14 | throw new Error("Icon prop is required"); 15 | } 16 | --- 17 | 18 | {icon === "github" && } 19 | {icon === "telegram" && } 20 | {icon === "newTwitter" && } 21 | {icon === "facebook" && } 22 | -------------------------------------------------------------------------------- /src/components/bases/navbar-item.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Link } from "@/lib/types"; 3 | 4 | type Props = { 5 | item: Link; 6 | }; 7 | const currentPath = Astro.url.pathname; 8 | const { item } = Astro.props; 9 | 10 | function isActive(item: Link, currentPath: string) { 11 | const segment = currentPath.split("/")[2]; 12 | return ( 13 | (item.text === "Home" && currentPath === "/") || 14 | (item.text === "Articles" && 15 | segment !== undefined && 16 | !Number.isNaN(Number(segment)) && 17 | Number(segment) >= 1) || 18 | (item.text !== "Articles" && 19 | currentPath.split("/").includes(item.text.toLocaleLowerCase())) 20 | ); 21 | } 22 | 23 | function formatHref(href: string) { 24 | return href === "/" ? "/" : `${href}/1`; 25 | } 26 | --- 27 | 28 |
  • 36 | {item.text} 37 |
  • 38 | -------------------------------------------------------------------------------- /src/components/bases/script.astro: -------------------------------------------------------------------------------- 1 | 55 | -------------------------------------------------------------------------------- /src/components/bases/share-item.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Clipboard from "@/assets/svgs/clipboard.astro"; 3 | import Facebook from "@/assets/svgs/facebook.astro"; 4 | import Linkedin from "@/assets/svgs/linkedin.astro"; 5 | import Twitter from "@/assets/svgs/twitter.astro"; 6 | import Whatsapp from "@/assets/svgs/whatsapp.astro"; 7 | 8 | type Props = { 9 | className: string; 10 | title: string; 11 | dataAwSocialShare: string; 12 | dataAwUrl: string | URL; 13 | dataAwText: string; 14 | icon: "clipboard" | "facebook" | "linkedin" | "twitter" | "whatsapp"; 15 | }; 16 | 17 | const { className, title, dataAwSocialShare, dataAwUrl, dataAwText, icon } = 18 | Astro.props; 19 | 20 | const iconMap = { 21 | clipboard: Clipboard, 22 | facebook: Facebook, 23 | linkedin: Linkedin, 24 | twitter: Twitter, 25 | whatsapp: Whatsapp, 26 | } as const; 27 | 28 | const Icon = iconMap[icon]; 29 | --- 30 | 31 | 45 | 46 | 62 | -------------------------------------------------------------------------------- /src/components/bases/theme-controller.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Moon from "@/assets/svgs/moon.astro"; 3 | import Sun from "@/assets/svgs/sun.astro"; 4 | --- 5 | 6 | 20 | 21 | 54 | -------------------------------------------------------------------------------- /src/components/cards/authorCard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from "astro:assets"; 3 | import type { CollectionEntry } from "astro:content"; 4 | type Props = { 5 | author: CollectionEntry<"authors">; 6 | }; 7 | 8 | const { author } = Astro.props; 9 | --- 10 | 11 |
  • 12 | {author.data.name} 21 |
    22 |

    23 | 24 | 25 | {author.data.name} 26 | 27 |

    28 |

    {author.data.job}

    29 |
    30 |
  • 31 | -------------------------------------------------------------------------------- /src/components/cards/mainHeadline.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from "astro:assets"; 3 | import type { CollectionEntry } from "astro:content"; 4 | import { render } from "astro:content"; 5 | import Divider from "@/components/bases/divider.astro"; 6 | import { categoriesHandler } from "@/lib/handlers/categories"; 7 | import { getDateDistance } from "@/lib/utils/date"; 8 | 9 | type Props = { 10 | article: CollectionEntry<"articles">; 11 | }; 12 | 13 | const { article } = Astro.props; 14 | 15 | const { remarkPluginFrontmatter } = await render(article); 16 | 17 | const category = categoriesHandler.oneCategory(article.data.category.id); 18 | --- 19 | 20 |
    21 |
    22 | {article.data.covert_alt 30 |
    31 |
    32 |
    33 |

    36 | 37 | 38 | {article.data.title} 39 | 40 |

    41 |

    42 | {article.data.description} 43 |

    44 |
    45 |
    46 | {category.data.title} 48 | 49 | {getDateDistance(remarkPluginFrontmatter.lastModified)} 50 |
    51 |
    52 |
    53 | -------------------------------------------------------------------------------- /src/components/cards/newsCard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from "astro:assets"; 3 | import Divider from "../bases/divider.astro"; 4 | import type { CollectionEntry } from "astro:content"; 5 | import { render } from "astro:content"; 6 | import { categoriesHandler } from "@/lib/handlers/categories"; 7 | 8 | type Props = { 9 | article: CollectionEntry<"articles">; 10 | index: number; 11 | }; 12 | 13 | const { article, index } = Astro.props; 14 | 15 | const { remarkPluginFrontmatter } = await render(article); 16 | const category = categoriesHandler.oneCategory(article.data.category.id); 17 | --- 18 | 19 |
    22 |
    23 | {article.data.covert_alt 32 |
    33 |
    34 |

    37 | 38 | 39 | {article.data.title} 40 | 41 |

    42 |

    43 | {article.data.description} 44 |

    45 |
    46 | {category.data.title} 49 | 50 | {remarkPluginFrontmatter.minutesRead} 53 |
    54 |
    55 |
    56 | -------------------------------------------------------------------------------- /src/components/cards/subHeadlineCard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from "astro:assets"; 3 | import type { CollectionEntry } from "astro:content"; 4 | import Divider from "@/components/bases/divider.astro"; 5 | import { render } from "astro:content"; 6 | import { getDateDistance } from "@/lib/utils/date"; 7 | import { categoriesHandler } from "@/lib/handlers/categories"; 8 | 9 | type Props = { 10 | article: CollectionEntry<"articles">; 11 | isFirst?: boolean; 12 | isLast?: boolean; 13 | }; 14 | const { article, isLast, isFirst } = Astro.props; 15 | 16 | const { remarkPluginFrontmatter } = await render(article); 17 | const category = categoriesHandler.oneCategory(article.data.category.id); 18 | --- 19 | 20 |
    27 |
    28 |
    29 |
    30 |

    31 | 32 | 33 | {article.data.title} 34 | 35 |

    36 |

    39 | {article.data.description} 40 |

    41 |
    42 |
    43 |
    44 | {category.data.title} 46 | 47 | {getDateDistance(remarkPluginFrontmatter.lastModified)} 48 |
    49 |
    50 | 51 |
    54 | {article.data.covert_alt 63 |
    64 |
    65 | -------------------------------------------------------------------------------- /src/components/cards/wideCard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from "astro:assets"; 3 | import type { CollectionEntry } from "astro:content"; 4 | import { getDateDistance, normalizeDate } from "@/lib/utils/date"; 5 | import Divider from "../bases/divider.astro"; 6 | 7 | type Props = { 8 | article: CollectionEntry<"articles">; 9 | isLast: boolean; 10 | }; 11 | 12 | const { article, isLast } = Astro.props; 13 | --- 14 | 15 |
  • 18 | 23 |
    29 |
    30 | {article.data.covert_alt 39 |
    40 |
    41 |

    42 | 43 | 44 | {article.data.title} 45 | 46 |

    47 |

    48 | {article.data.description} 49 |

    50 |
    51 |
    52 | 60 | 61 | 62 | 63 | {article.data.category.id} 64 | 65 | 66 |
    67 |
    68 |
  • 69 | -------------------------------------------------------------------------------- /src/components/elements/menu-dropdown.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Menu from "@/assets/svgs/menu.astro"; 3 | import { NAVIGATION_LINKS, OTHER_LINKS } from "@/lib/config"; 4 | --- 5 | 6 | 58 | -------------------------------------------------------------------------------- /src/components/elements/navbar.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { NAVIGATION_LINKS } from "@/lib/config"; 3 | import NavbarItem from "../bases/navbar-item.astro"; 4 | --- 5 | 6 | 13 | -------------------------------------------------------------------------------- /src/components/elements/share.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import ShareItem from "@/components/bases/share-item.astro"; 3 | import ScriptShare from "@/components/bases/script.astro"; 4 | type Props = { 5 | text: string; 6 | }; 7 | const { pathname } = Astro.url; 8 | const { text } = Astro.props; 9 | --- 10 | 11 | <> 12 |
    13 | 21 | 29 | 30 | 38 | 39 | 47 | 48 | 56 |
    57 | 58 | 59 | -------------------------------------------------------------------------------- /src/components/elements/top-header.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Github from "@/assets/svgs/github.astro"; 3 | import Search01 from "@/assets/svgs/search-01.astro"; 4 | import MenuDropdown from "./menu-dropdown.astro"; 5 | import { SITE } from "@/lib/config"; 6 | import ThemeController from "../bases/theme-controller.astro"; 7 | --- 8 | 9 | 34 | -------------------------------------------------------------------------------- /src/components/shared/Carousel.astro: -------------------------------------------------------------------------------- 1 | --- 2 | // Carousel.astro 3 | interface Props { 4 | images: { 5 | src: string; 6 | alt: string; 7 | }[]; 8 | autoplay?: boolean; 9 | interval?: number; 10 | } 11 | 12 | const { 13 | images = [ 14 | { src: "/placeholder.svg?height=400&width=800", alt: "Slide 1" }, 15 | { src: "/placeholder.svg?height=400&width=800", alt: "Slide 2" }, 16 | { src: "/placeholder.svg?height=400&width=800", alt: "Slide 3" }, 17 | ], 18 | autoplay = true, 19 | interval = 5000, 20 | } = Astro.props as Props; 21 | --- 22 | 23 |
    29 | 30 |
    31 | { 32 | images.map((image, index) => ( 33 |
    38 | {image.alt} 43 |
    44 | )) 45 | } 46 |
    47 | 48 | 49 |
    50 | { 51 | images.map((_, index) => ( 52 |
    62 | 63 | 64 | 89 |
    90 | -------------------------------------------------------------------------------- /src/components/shared/footer.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { NAVIGATION_LINKS, SOCIAL_LINKS, OTHER_LINKS } from "@/lib/config"; 3 | import Hashtag from "@/assets/svgs/hashtag.astro"; 4 | import Icon from "../bases/icon.astro"; 5 | --- 6 | 7 |
    10 |
    11 |
    12 | 24 | 37 |
    38 |
    39 |
    40 | 62 | 71 |
    72 |
    73 |
    74 | -------------------------------------------------------------------------------- /src/components/shared/header.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import TopHeader from "../elements/top-header.astro"; 3 | import Navbar from "../elements/navbar.astro"; 4 | --- 5 | 6 |
    9 | 10 | 11 |
    12 | -------------------------------------------------------------------------------- /src/components/shared/pagination.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import ArrowLeftDouble from "@/assets/svgs/arrow-left-double.astro"; 3 | import ArrowRightDouble from "@/assets/svgs/arrow-right-double.astro"; 4 | import ArrowLeft01 from "@/assets/svgs/arrow-left-01.astro"; 5 | import ArrowRight01 from "@/assets/svgs/arrow-right-01.astro"; 6 | 7 | type Props = { 8 | length: number; 9 | currentUrl: string; 10 | currentPage: number; 11 | baseUrl: string; 12 | prevUrl: string | undefined; 13 | nextUrl: string | undefined; 14 | lastUrl: string; 15 | }; 16 | 17 | const { length, currentUrl, currentPage, baseUrl, prevUrl, nextUrl, lastUrl } = 18 | Astro.props; 19 | 20 | // Define the maximum number of visible buttons 21 | const maxVisibleButtons = 4; 22 | 23 | // Calculate the range of visible page numbers 24 | const startPage = Math.max(1, currentPage - Math.floor(maxVisibleButtons / 2)); 25 | const endPage = Math.min(length, startPage + maxVisibleButtons - 1); 26 | 27 | // Adjust the startPage if we're at the end of the pagination 28 | const adjustedStartPage = Math.max(1, endPage - maxVisibleButtons + 1); 29 | 30 | // Generate the pagination list based on the range 31 | const paginationList = Array.from( 32 | { length: endPage - adjustedStartPage + 1 }, 33 | (_, i) => adjustedStartPage + i 34 | ); 35 | --- 36 | 37 |
    43 | 107 |
    108 | -------------------------------------------------------------------------------- /src/components/shared/view-list-header.astro: -------------------------------------------------------------------------------- 1 | --- 2 | type Props = { 3 | title: string; 4 | }; 5 | const { title } = Astro.props; 6 | --- 7 | 8 |
    11 |

    {title}

    12 |
    13 | -------------------------------------------------------------------------------- /src/content.config.ts: -------------------------------------------------------------------------------- 1 | import { glob } from "astro/loaders"; 2 | import { defineCollection } from "astro:content"; 3 | import { 4 | articleSchema, 5 | authorSchema, 6 | categorySchema, 7 | viewSchema, 8 | } from "@/lib/schema"; 9 | 10 | const articleCollection = defineCollection({ 11 | loader: glob({ pattern: "**/*.mdx", base: "./src/content/articles" }), 12 | schema: ({ image }) => articleSchema(image), 13 | }); 14 | 15 | const viewCollection = defineCollection({ 16 | loader: glob({ pattern: "**/*.mdx", base: "./src/content/views" }), 17 | schema: viewSchema, 18 | }); 19 | 20 | const categoryCollection = defineCollection({ 21 | loader: glob({ pattern: "**/index.json", base: "./src/content/categories" }), 22 | schema: categorySchema, 23 | }); 24 | 25 | const authorCollection = defineCollection({ 26 | loader: glob({ pattern: "**/index.mdx", base: "./src/content/authors" }), 27 | schema: ({ image }) => authorSchema(image), 28 | }); 29 | 30 | export const collections = { 31 | articles: articleCollection, 32 | views: viewCollection, 33 | categories: categoryCollection, 34 | authors: authorCollection, 35 | }; 36 | -------------------------------------------------------------------------------- /src/content/articles/10-tips-for-better-time-management/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: true 5 | description: Learn how to optimize your schedule and accomplish more each day. 6 | title: 10 Tips for Better Time Management 7 | cover: '@assets/images/articles/10-tips-for-better-time-management/cover.avif' 8 | category: productivity 9 | publishedTime: 2024-11-14T00:00:00.000Z 10 | authors: 11 | - olivier-brown 12 | - jane-doe 13 | --- 14 | Time management is essential for achieving your goals efficiently. Here are ten practical tips to make the most of your time. 15 | 16 | ## 1. Prioritize Your Tasks 17 | 18 | Use a method like the Eisenhower Matrix to identify urgent and important tasks. 19 | 20 | ... 21 | -------------------------------------------------------------------------------- /src/content/articles/a-function-s-existential-crisis/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: false 5 | description: >- 6 | A lighthearted guide to recursion—aka that thing you call within itself until 7 | it forgets why it started. 8 | title: A Functions Existential Crisis 9 | cover: '@assets/images/articles/a-function-s-existential-crisis/cover.avif' 10 | category: programming 11 | publishedTime: 2025-04-14T23:39:00.000Z 12 | authors: 13 | - jane-doe 14 | --- 15 | Welcome to recursion, where functions call themselves like lost souls trying to find meaning. We’ll cover what recursion is, how it works, and how to keep your brain from crashing like your code. 16 | -------------------------------------------------------------------------------- /src/content/articles/exploring-the-benefits-of-daily-meditation/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: true 5 | description: >- 6 | Discover how a daily meditation practice can improve your mental clarity and 7 | well-being. 8 | title: Exploring the Benefits of Daily Meditation 9 | cover: '@assets/images/articles/exploring-the-benefits-of-daily-meditation/cover.avif' 10 | category: wellness 11 | publishedTime: 2024-11-18T00:00:00.000Z 12 | authors: 13 | - emily-devis 14 | --- 15 | Meditation is a simple practice with profound benefits. Learn how dedicating just a few minutes each day can transform your life. 16 | 17 | ## What Is Meditation? 18 | 19 | Meditation is the art of focusing your mind and achieving a heightened state of awareness. 20 | 21 | ... 22 | -------------------------------------------------------------------------------- /src/content/articles/how-to-build-a-capsule-wardrobe/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: true 5 | description: Streamline your wardrobe with timeless pieces that suit your style. 6 | title: How to Build a Capsule Wardrobe 7 | cover: '@assets/images/articles/how-to-build-a-capsule-wardrobe/cover.avif' 8 | category: wellness 9 | publishedTime: 2024-11-19T00:00:00.000Z 10 | authors: 11 | - chloe-nguyen 12 | --- 13 | A capsule wardrobe is about owning fewer clothes that offer endless outfit possibilities. Learn how to curate your perfect wardrobe. 14 | 15 | ## Why Choose a Capsule Wardrobe? 16 | 17 | Simplifying your wardrobe saves time, money, and reduces decision fatigue while ensuring you always feel confident in what you wear. 18 | 19 | ... 20 | -------------------------------------------------------------------------------- /src/content/articles/javascript-math-is-a-lie/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: false 5 | description: >- 6 | A hilariously painful journey through floating point math in JavaScript. Yes, 7 | 0.1 + 0.2 ≠ 0.3. 8 | title: JavaScript Math is a Lie 9 | cover: '@assets/images/articles/java-script-math-is-a-lie/cover.avif' 10 | category: programming 11 | publishedTime: 2025-04-15T04:43:00.000Z 12 | authors: 13 | - liam-leonard 14 | - jane-doe 15 | --- 16 | Ever tried `0.1 + 0.2 === 0.3` in JS? Yeah, it returns false. In this satirical-yet-informative piece, we dig into why JavaScript math feels like it’s gaslighting us and how to work around it without losing your mind. 17 | -------------------------------------------------------------------------------- /src/content/articles/mastering-time-management/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: true 5 | description: Learn practical strategies to manage your time and increase productivity. 6 | title: Mastering Time Management 7 | cover: '@assets/images/articles/mastering-time-management/cover.avif' 8 | category: productivity 9 | publishedTime: 2024-11-16T00:00:00.000Z 10 | authors: 11 | - liam-leonard 12 | --- 13 | Time is our most valuable resource, yet it often feels like there’s never enough of it. Mastering time management can help you achieve more with less stress. 14 | 15 | ## Why Time Management Matters 16 | 17 | Effective time management is key to balancing your personal and professional life, reducing stress, and achieving your goals. 18 | 19 | ... 20 | -------------------------------------------------------------------------------- /src/content/articles/promises-in-javascript-trust-issues-in-code/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: false 5 | description: ' An absurdly fun breakdown of promises, async/await, and why your code never waits when you want it to.' 6 | title: 'Promises in JavaScript: Trust Issues in Code' 7 | cover: '@assets/images/articles/promises-in-javascript-trust-issues-in-code/cover.avif' 8 | category: programming 9 | publishedTime: 2025-04-14T03:42:00.000Z 10 | authors: 11 | - john-smith 12 | --- 13 | Promises in JavaScript are like the friend who says they’ll help you move and shows up three hours late. In this article, we unpack promises, async/await, and how to stop chaining `.then()` like it’s a bad habit. 14 | -------------------------------------------------------------------------------- /src/content/articles/the-art-of-minimalist-living/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: true 5 | description: Discover how minimalism can bring clarity and purpose to your life. 6 | title: The Art of Minimalist Living 7 | cover: '@assets/images/articles/the-art-of-minimalist-living/cover.avif' 8 | category: lifestyle 9 | publishedTime: 2024-11-15T00:00:00.000Z 10 | authors: 11 | - maria-gonzalez 12 | --- 13 | Minimalism isn’t just about owning fewer things; it’s a mindset that emphasizes intentional living. Learn how to embrace minimalism and its benefits. 14 | 15 | ## What Is Minimalism? 16 | 17 | Minimalism is a lifestyle that encourages you to focus on what truly matters by eliminating excess. 18 | 19 | ... 20 | -------------------------------------------------------------------------------- /src/content/articles/the-basics-of-personal-finance/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: true 5 | description: >- 6 | Understand the fundamentals of budgeting, saving, and investing for a secure 7 | future. 8 | title: The Basics of Personal Finance 9 | cover: '@assets/images/articles/the-basics-of-personal-finance/cover.avif' 10 | category: finance 11 | publishedTime: 2024-11-17T00:00:00.000Z 12 | authors: 13 | - john-smith 14 | --- 15 | Personal finance is about more than just numbers; it’s about building habits that lead to financial freedom. Start your journey with these basics. 16 | 17 | ## Budgeting 101 18 | 19 | Creating and sticking to a budget is the foundation of financial health. Learn how to allocate your income wisely. 20 | 21 | ... 22 | -------------------------------------------------------------------------------- /src/content/articles/the-benefits-of-meditation/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: true 5 | description: Explore how meditation can enhance your mental and physical health. 6 | title: The Benefits of Meditation 7 | cover: '@assets/images/articles/the-benefits-of-meditation/cover.avif' 8 | category: health 9 | publishedTime: 2024-11-12T00:00:00.000Z 10 | authors: 11 | - sofia-martinez 12 | --- 13 | Meditation is a powerful tool for achieving mindfulness and reducing stress. This article delves into the science behind meditation and its practical benefits. 14 | 15 | ## Why Meditate? 16 | 17 | Meditation helps improve focus, reduce anxiety, and foster a sense of inner peace. 18 | 19 | ... 20 | -------------------------------------------------------------------------------- /src/content/articles/top-5-web-development-frameworks-for-2025/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: true 5 | description: A comparison of the most popular frameworks for modern web development. 6 | title: Top 5 Web Development Frameworks for 2025 7 | cover: '@assets/images/articles/top-5-web-development-frameworks-for-2025/cover.avif' 8 | category: technology 9 | publishedTime: 2024-11-13T00:00:00.000Z 10 | authors: 11 | - rajesh-patel 12 | --- 13 | Frameworks simplify the process of web development by providing pre-built tools and structures. Let’s compare React, Vue.js, Angular, Svelte, and Next.js. 14 | 15 | ## React 16 | 17 | React is a declarative, component-based JavaScript library for building user interfaces. 18 | 19 | ... 20 | -------------------------------------------------------------------------------- /src/content/articles/understanding-java-script-closures/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: true 4 | isSubHeadline: false 5 | description: An in-depth look at closures in JavaScript and their applications. 6 | title: Understanding JavaScript Closures 7 | cover: '@assets/images/articles/understanding-java-script-closures/cover.avif' 8 | category: programming 9 | publishedTime: 2024-11-11T00:00:00.000Z 10 | authors: 11 | - ahmed-khan 12 | - jane-doe 13 | --- 14 | Closures are a fundamental concept in JavaScript that allow functions to access variables from their outer scope. This article explains closures, their practical uses, and common pitfalls. 15 | 16 | ## What Are Closures? 17 | 18 | A closure is the combination of a function bundled together with references to its surrounding state. 19 | 20 | ```js 21 | function outerFunction(outerVariable) { 22 | return function innerFunction(innerVariable) { 23 | console.log(`Outer Variable: ${outerVariable}`); 24 | console.log(`Inner Variable: ${innerVariable}`); 25 | }; 26 | } 27 | 28 | const closureExample = outerFunction("I am from outerFunction"); 29 | 30 | // Calling the inner function with the closure 31 | closureExample("I am from innerFunction"); 32 | 33 | ``` 34 | -------------------------------------------------------------------------------- /src/content/articles/why-does-this-hate-me-demystifying-java-script-s-this/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | isDraft: false 3 | isMainHeadline: false 4 | isSubHeadline: false 5 | description: >- 6 | Why JavaScript's `this` keyword breaks brains and hearts—explained with 7 | relatable memes. 8 | title: Why Does this Hate Me? Demystifying JavaScripts this 9 | cover: >- 10 | @assets/images/articles/why-does-this-hate-me-demystifying-java-script-s-this/cover.avif 11 | category: programming 12 | publishedTime: 2025-04-15T10:36:00.000Z 13 | authors: 14 | - jane-doe 15 | - john-smith 16 | --- 17 | Ah yes, the infamous `this` keyword in JavaScript—responsible for more broken code and debugging tears than any other. In this article, we’ll laugh through the pain and explain what `this` actually means in different contexts. 18 | -------------------------------------------------------------------------------- /src/content/authors/ahmed-khan/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Ahmed Khan 3 | job: Political Correspondent 4 | avatar: '@assets/images/authors/ahmed-khan/avatar.jpg' 5 | bio: Ahmed provides in-depth analysis on political developments worldwide. 6 | social: 7 | - name: Twitter 8 | url: https://twitter.com 9 | icon: twitter-icon.svg 10 | --- 11 | -------------------------------------------------------------------------------- /src/content/authors/chloe-nguyen/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Chloe Nguyen 3 | job: Environmental Journalist 4 | avatar: '@assets/images/authors/chloe-nguyen/avatar.jpg' 5 | bio: Chloe reports on climate change, sustainability, and green innovations. 6 | social: 7 | - name: LinkedIn 8 | url: https://linkedin.com/in/chloenguyen 9 | icon: linkedin-icon.svg 10 | - name: Twitter 11 | url: https://twitter.com/chloenguyen 12 | icon: twitter-icon.svg 13 | --- 14 | -------------------------------------------------------------------------------- /src/content/authors/emily-devis/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Emily Davis 3 | job: Science Journalist 4 | avatar: '@assets/images/authors/emily-devis/avatar.jpg' 5 | bio: Emily writes about groundbreaking research in science and medicine. 6 | social: 7 | - name: LinkedIn 8 | url: https://linkedin.com/in/emilydavis 9 | icon: linkedin-icon.svg 10 | --- 11 | -------------------------------------------------------------------------------- /src/content/authors/jane-doe/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Jane Doe 3 | job: Investigative Journalist 4 | avatar: '@assets/images/authors/jane-doe/avatar.jpg' 5 | bio: >- 6 | Jane is an award-winning journalist specializing in investigative reporting on 7 | global issues. 8 | social: 9 | - name: Twitter 10 | url: https://twitter.com/janedoe 11 | icon: twitter-icon.svg 12 | - name: LinkedIn 13 | url: https://linkedin.com/in/janedoe 14 | icon: linkedin-icon.svg 15 | --- 16 | -------------------------------------------------------------------------------- /src/content/authors/john-smith/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: John Smith 3 | job: Tech Writer 4 | avatar: '@assets/images/authors/john-smith/avatar.jpg' 5 | bio: John covers the latest advancements in technology and startups. 6 | social: 7 | - name: Twitter 8 | url: https://twitter.com/johnsmith 9 | icon: twitter-icon.svg 10 | - name: GitHub 11 | url: https://github.com/johnsmith 12 | icon: github-icon.svg 13 | --- 14 | -------------------------------------------------------------------------------- /src/content/authors/liam-leonard/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Liam Leonard 3 | job: Sports Journalist 4 | avatar: '@assets/images/authors/liam-leonard/avatar.jpg' 5 | bio: Liam covers major sporting events and stories behind the games. 6 | social: 7 | - name: Twitter 8 | url: https://twitter.com/liamsports 9 | icon: twitter-icon.svg 10 | --- 11 | -------------------------------------------------------------------------------- /src/content/authors/maria-gonzalez/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Maria Gonzalez 3 | job: Travel Blogger & Journalist 4 | avatar: '@assets/images/authors/maria-gonzalez/avatar.jpg' 5 | bio: Maria explores the world, sharing stories from remote corners and hidden gems. 6 | social: 7 | - name: Instagram 8 | url: https://instagram.com/mariagonzalez 9 | icon: instagram-icon.svg 10 | - name: Facebook 11 | url: https://facebook.com/mariagonzalez 12 | icon: facebook-icon.svg 13 | --- 14 | -------------------------------------------------------------------------------- /src/content/authors/olivier-brown/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Oliver Brown 3 | job: Tech and Gaming Reporter 4 | avatar: '@assets/images/authors/olivier-brown/avatar.jpg' 5 | bio: Oliver writes reviews and in-depth analyses of the gaming industry. 6 | social: 7 | - name: YouTube 8 | url: https://youtube.com/olivergaming 9 | icon: youtube-icon.svg 10 | - name: Twitter 11 | url: https://twitter.com/oliverbrown 12 | icon: twitter-icon.svg 13 | --- 14 | -------------------------------------------------------------------------------- /src/content/authors/rajesh-patel/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Rajesh Patel 3 | job: Business and Finance Reporter 4 | avatar: '@assets/images/authors/rajesh-patel/avatar.jpg' 5 | bio: Rajesh analyzes financial trends and business innovations. 6 | social: 7 | - name: Twitter 8 | url: https://twitter.com/rajeshpatel 9 | icon: twitter-icon.svg 10 | - name: LinkedIn 11 | url: https://linkedin.com/in/rajeshpatel 12 | icon: linkedin-icon.svg 13 | --- 14 | -------------------------------------------------------------------------------- /src/content/authors/sofia-martinez/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Sofia Martinez 3 | job: Arts and Culture Critic 4 | avatar: '@assets/images/authors/sofia-martinez/avatar.jpg' 5 | bio: Sofia critiques art, literature, and cultural events with a keen eye. 6 | social: 7 | - name: Instagram 8 | url: https://instagram.com/sofiaarts 9 | icon: instagram-icon.svg 10 | --- 11 | -------------------------------------------------------------------------------- /src/content/categories/finance/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Finance", 3 | "path": "finance" 4 | } -------------------------------------------------------------------------------- /src/content/categories/health/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Health", 3 | "path": "health" 4 | } -------------------------------------------------------------------------------- /src/content/categories/lifestyle/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Lifestyle", 3 | "path": "lifestyle" 4 | } -------------------------------------------------------------------------------- /src/content/categories/productivity/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Productivity", 3 | "path": "productivity" 4 | } -------------------------------------------------------------------------------- /src/content/categories/programming/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Programming", 3 | "path": "programming" 4 | } -------------------------------------------------------------------------------- /src/content/categories/technology/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Technology" 3 | ,"path": "technology" 4 | } -------------------------------------------------------------------------------- /src/content/categories/wellness/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Wellness", 3 | "path": "wellness" 4 | } -------------------------------------------------------------------------------- /src/content/views/about.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "About" 3 | description: "Learn about the author, his background, and his interests." 4 | blocks: 5 | - name: "ABOUT" 6 | title: "About us" 7 | --- 8 | import screenshot from '../../assets/images/screenshot-astronews.png'; 9 | import performances from '../../assets/images/Performances.png'; 10 | import { Image } from 'astro:assets'; 11 | 12 | 13 | # Astro News 📰 14 | 15 | A news website built with Astro, designed to provide a modern and responsive news reading experience. 16 | 17 | > **ℹ️ Info** 18 | > Astro news is my first open-source project, so there may be some bugs or issues. I’ll address them as quickly as possible. 19 | 20 | Astro News 21 | PageSpeed Insights result 22 | 23 | ## 🌐 Demo 24 | 25 | Explore the live demo here: [**Live Demo**](https://astro-news-six.vercel.app/) 26 | 27 | ## 🚀 Installation 28 | 29 | Follow the steps below to set up and run the project locally: 30 | 31 | ### Clone the Repository 32 | 33 | ```bash 34 | git clone https://github.com/Mrahmani71/astro-news.git 35 | ``` 36 | 37 | ### Install Dependencies 38 | 39 | ``` bash 40 | bun install 41 | ``` 42 | 43 | ### Run Development Server 44 | 45 | ```bash 46 | bun dev 47 | ``` 48 | 49 | ### Running Keystatic CMS 50 | 51 | 1. Rename `.env.example` to `.env`. 52 | 53 | 2. Set `RUN_KEYSTATIC=true`. 54 | 55 | 3. Start the development server: 56 | 57 | ```bash 58 | bun dev 59 | ``` 60 | 61 | 4. Open `http://localhost:4321/keystatic` in your browser. 62 | 63 | ## ✨ Features 64 | 65 | ### Implemented Features 66 | 67 | - Content Layer 68 | - Keystatic CMS 69 | - Navigation 70 | - Responsive Design 71 | - Pagination 72 | - Search Functionality 73 | - RSS Feed 74 | - Sitemap 75 | - Dark Mode 76 | - SEO Optimization (~) 77 | 78 | ### Upcoming Features 79 | 80 | - Open Graph (OG) Image Generation 81 | 82 | ## 💻 Technologies 83 | 84 | This project leverages cutting-edge web technologies: 85 | 86 | - [Astro V5.7](https://astro.build) - Modern static site builder 87 | - [KeyStatic](https://keystatic.com) - Headless content-management system 88 | - [Tailwind CSS](https://tailwindcss.com) - Utility-first CSS framework 89 | - [DaisyUI](https://daisyui.com/) - Tailwind CSS component library 90 | - [TypeScript](https://typescriptlang.org) - Typed JavaScript 91 | - [MDX](https://mdxjs.com) - Markdown with JSX support 92 | - [Bun V1.2.10](https://bun.sh) - Fast JavaScript runtime 93 | - [Vercel](https://vercel.com) - Deployment platform 94 | - [HugeIcons](https://hugeicons.com) - Icon library 95 | 96 | ## 💡 Inspirations and Code Concepts 97 | 98 | This project draws inspiration from the following sources: 99 | 100 | ### Designs 101 | 102 | - [BBC News](https://www.bbc.com) 103 | - [NewsHub - News Website](https://dribbble.com/shots/21678041-NewsHub-News-Website) 104 | - [Let'sread - News Landing Page](https://dribbble.com/shots/24675325-Let-sread-News-Landing-Page) 105 | 106 | ### Articles 107 | 108 | - [Creating A Pagination Component With Astro](https://rimdev.io/creating-a-pagination-component-with-astro) 109 | - [Adding search to static Astro sites](https://website-thomas-astro.vercel.app/blog/search-static-astro-website) 110 | 111 | ## 📄 License 112 | 113 | Open sourced under the [MIT license](https://github.com/Mrahmani71/astro-news/blob/master/LICENSE.md). 114 | 115 | ## 🤝 Contributing 116 | 117 | Contributions, issues, and feature requests are welcome! Feel free to check the [issues page](https://github.com/Mrahmani71/astro-news/issues). -------------------------------------------------------------------------------- /src/content/views/articles.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Latest articles" 3 | description: "Leatest articles published in the Astro News." 4 | blocks: 5 | - name: "HEADER" 6 | title: "Latest Articles" 7 | --- -------------------------------------------------------------------------------- /src/content/views/author.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "articles" 3 | description: "List of articles by author in the Astro News." 4 | blocks: 5 | - name: "HEADER" 6 | title: "articles" 7 | description: "List of authors of the Astro News." 8 | - name: "ATTENTION" 9 | description: "These names and images are not real. The images are from Unsplash, used in this project to show how to add authors to articles." 10 | --- -------------------------------------------------------------------------------- /src/content/views/authors.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Authors" 3 | description: "Learn about the authors behind the Astro News." 4 | blocks: 5 | - name: "HEADER" 6 | title: "List of Authors" 7 | description: "List of authors of the Astro News." 8 | - name: "ATTENTION" 9 | description: "These names and images are not real. The images are from Unsplash, used in this project to show how to add authors to articles." 10 | --- -------------------------------------------------------------------------------- /src/content/views/categories.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Categories" 3 | description: "Learn about the categories of articles in the Astro News." 4 | blocks: 5 | - name: "HEADER" 6 | title: "List of Categories" 7 | --- -------------------------------------------------------------------------------- /src/content/views/contact.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Contact" 3 | description: "Contact us for any inquiries or feedback." 4 | blocks: 5 | - name: "CONTACT" 6 | title: "Contact Us" 7 | --- -------------------------------------------------------------------------------- /src/content/views/error404.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "404 - Page Not Found" 3 | description: "Page not found." 4 | blocks: 5 | - name: "HERO" 6 | title: "404 - Page Not Found" 7 | description: "Oops! The page you're looking for doesn't exist." 8 | link_text: "Return to Homepage" 9 | link_url: "/" 10 | --- -------------------------------------------------------------------------------- /src/content/views/home.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Astro News" 3 | description: "Welcome to the Astro News, a newsletter about Astro." 4 | blocks: 5 | - name: "HEADER" 6 | title: "Welcome to the Astro News" 7 | --- -------------------------------------------------------------------------------- /src/content/views/search.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Search" 3 | description: "Search articles in the Astro News." 4 | blocks: 5 | - name: "HEADER" 6 | title: "Search Articles" 7 | --- -------------------------------------------------------------------------------- /src/layouts/base.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { SITE } from "@/lib/config"; 3 | import Head from "@/components/bases/head.astro"; 4 | import Header from "@/components/shared/header.astro"; 5 | import Footer from "@/components/shared/footer.astro"; 6 | import type { Entry } from "@/lib/types"; 7 | import { getMeta } from "@/lib/utils/getMeta"; 8 | 9 | type Props = { 10 | entry: Entry; 11 | }; 12 | 13 | const { entry } = Astro.props; 14 | 15 | const meta = await getMeta(entry); 16 | --- 17 | 18 | 19 | 20 | 21 | 22 |
    23 |
    24 | 25 |
    26 |