├── .env.example ├── .eslintrc.cjs ├── .gitignore ├── .npmrc ├── .vscode ├── extensions.json └── launch.json ├── README.md ├── astro.config.mjs ├── env.d.ts ├── package.json ├── pnpm-lock.yaml ├── prettier.config.cjs ├── public └── favicon │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── mstile-150x150.png │ ├── safari-pinned-tab.svg │ └── site.webmanifest ├── src ├── components │ ├── Author.astro │ ├── Card.astro │ ├── Footer.astro │ ├── Logo.astro │ ├── Metadata.astro │ ├── Navigation.astro │ └── PostBody.tsx ├── env.d.ts ├── images │ └── cosmic.svg ├── layouts │ └── Layout.astro ├── lib │ └── cosmic.js └── pages │ ├── blog │ ├── [slug].astro │ └── index.astro │ └── index.astro ├── tailwind.config.cjs └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | PUBLIC_COSMIC_BUCKET_SLUG= 2 | PUBLIC_COSMIC_READ_KEY= -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | extends: ['plugin:astro/recommended'], 4 | parser: '@typescript-eslint/parser', 5 | parserOptions: { 6 | tsconfigRootDir: __dirname, 7 | sourceType: 'module', 8 | ecmaVersion: 'latest' 9 | }, 10 | overrides: [ 11 | { 12 | files: ['*.astro'], 13 | parser: 'astro-eslint-parser', 14 | parserOptions: { 15 | parser: '@typescript-eslint/parser', 16 | extraFileExtensions: ['.astro', '.tsx', '.ts', '.jsx', '.js'] 17 | }, 18 | rules: { 19 | // override/add rules settings here, such as: 20 | // "astro/no-set-html-directive": "error" 21 | } 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | .output/ 4 | 5 | # dependencies 6 | node_modules/ 7 | 8 | # logs 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | pnpm-debug.log* 13 | 14 | 15 | # environment variables 16 | .env 17 | .env.production 18 | 19 | # macOS-specific files 20 | .DS_Store 21 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # Expose Astro dependencies for `pnpm` users 2 | shamefully-hoist=true 3 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple Astro Blog built with Astro and Cosmic 2 | 3 | To build this app, we’re going to use the following technologies: 4 | 5 | - [Astro](https://astro.build/) - A React framework for production that makes it easy to spin up a full-stack application. 6 | - [Cosmic](https://www.cosmicjs.com/) - A Headless CMS enables the independence of the data (content) layer and gives us the ability to quickly manage template content. 7 | - [Tailwind CSS](https://tailwindcss.com/) - A performant utility-first CSS framework that can be composed directly in your markup. 8 | 9 | ### Links 10 | 11 | - [Install the template](https://www.cosmicjs.com/marketplace/templates/simple-astro-blog) 12 | - [View the live demo](https://simple-astro-blog.vercel.app/) 13 | 14 | ## Screenshots 15 | 16 | ![Home Page](https://imgix.cosmicjs.com/e0b61790-32db-11ed-8a37-f1952c73e588-astro-cms-screenshot-4.png?w=1200&auto=format) 17 | 18 | ![Blog Page](https://cdn.cosmicjs.com/cbd90ee0-32db-11ed-8a37-f1952c73e588-astro-cms-screenshot-3.png) 19 | 20 | ## Getting started 21 | 22 | ### Environment Variables 23 | 24 | You'll need to create an .env file in the root of the project. Log in to Cosmic and from Bucket Settings > API Access take the following values: 25 | 26 | ``` 27 | //.env 28 | PUBLIC_COSMIC_BUCKET_SLUG=your_cosmic_slug 29 | PUBLIC_COSMIC_READ_KEY=your_cosmic_read_key 30 | ``` 31 | 32 | Install the dependencies with 33 | 34 | ``` 35 | pnpm install 36 | # or 37 | yarn install 38 | # or 39 | npm install 40 | ``` 41 | 42 | Then run the development server: 43 | 44 | ``` 45 | pnpm run dev 46 | # or 47 | yarn dev 48 | # or 49 | npm run dev 50 | ``` 51 | 52 | Open [http://localhost:3000](http://localhost:3000/) with your browser to see the result. 53 | 54 | You can start editing the page by modifying `src/pages/index.astro`. The page auto-updates as you edit the file. 55 | 56 | ## Deploy on Vercel 57 | 58 |

Use the following button to deploy to Vercel. You will need to add API accesss keys as environment variables. Find these in Bucket Settings > API Access.

59 |

60 | 61 |

62 | 63 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 64 | 65 | Your feedback and contributions are welcome! 66 | -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config' 2 | import react from '@astrojs/react' 3 | import tailwind from '@astrojs/tailwind' 4 | import robotsTxt from 'astro-robots-txt' 5 | 6 | // https://astro.build/config 7 | export default defineConfig({ 8 | integrations: [tailwind(), react(), robotsTxt()], 9 | site: 'https://simple-astro-blog.vercel.app' 10 | }) 11 | -------------------------------------------------------------------------------- /env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/basics", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview", 10 | "astro": "astro", 11 | "lint": "prettier --write \"**/*.{js,jsx,ts,tsx,md,mdx,astro}\" && eslint --fix \"src/**/*.{js,ts,jsx,tsx,astro}\"" 12 | }, 13 | "dependencies": { 14 | "@astrojs/react": "^3.0.0", 15 | "@astrojs/tailwind": "^5.0.0", 16 | "@astrojs/ts-plugin": "^1.0.4", 17 | "@cosmicjs/sdk": "^1.0.5", 18 | "astro": "^3.0.8", 19 | "date-fns": "^2.29.2", 20 | "react-markdown": "^8.0.3", 21 | "sharp": "^0.32.1", 22 | "tailwindcss": "^3.3.2" 23 | }, 24 | "devDependencies": { 25 | "@types/node": "^18.7.15", 26 | "@typescript-eslint/parser": "^5.59.2", 27 | "astro-robots-txt": "^0.3.8", 28 | "eslint": "^8.39.0", 29 | "eslint-plugin-astro": "^0.26.1", 30 | "eslint-plugin-jsx-a11y": "^6.7.1", 31 | "prettier": "^2.8.8", 32 | "prettier-config-standard": "^5.0.0", 33 | "prettier-plugin-astro": "^0.8.0", 34 | "prettier-plugin-tailwindcss": "^0.2.8", 35 | "react": "^18.2.0", 36 | "react-dom": "^18.2.0", 37 | "typescript": "^5.2.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /prettier.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("prettier").Config} */ 2 | module.exports = { 3 | ...require('prettier-config-standard'), 4 | pluginSearchDirs: [__dirname], 5 | plugins: [ 6 | require.resolve('prettier-plugin-astro'), 7 | require('prettier-plugin-tailwindcss') 8 | ], 9 | overrides: [ 10 | { 11 | files: '*.astro', 12 | options: { 13 | parser: 'astro' 14 | } 15 | } 16 | ], 17 | tailwindConfig: './tailwind.config.cjs' 18 | } 19 | -------------------------------------------------------------------------------- /public/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/simple-astro-blog/75a2c891b7d6200580095a08245c62b9d2ab7863/public/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/simple-astro-blog/75a2c891b7d6200580095a08245c62b9d2ab7863/public/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/simple-astro-blog/75a2c891b7d6200580095a08245c62b9d2ab7863/public/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/simple-astro-blog/75a2c891b7d6200580095a08245c62b9d2ab7863/public/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/simple-astro-blog/75a2c891b7d6200580095a08245c62b9d2ab7863/public/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/simple-astro-blog/75a2c891b7d6200580095a08245c62b9d2ab7863/public/favicon/favicon.ico -------------------------------------------------------------------------------- /public/favicon/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/simple-astro-blog/75a2c891b7d6200580095a08245c62b9d2ab7863/public/favicon/mstile-150x150.png -------------------------------------------------------------------------------- /public/favicon/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 41 | 72 | 82 | 93 | 124 | 137 | 165 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /public/favicon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /src/components/Author.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from 'astro:assets' 3 | const { name, imageUrl, about, linkedIn, twitter, gitHub } = Astro.props 4 | --- 5 | 6 |
7 | {name 15 |
16 |

About {name || 'the author'}

17 |

{about}

18 | 19 | 20 | 21 | 32 | 33 | 34 | 35 | 36 | 37 | 48 | 49 | 50 | 51 | 52 | 53 | 64 | 65 | 66 | 67 | 68 |
69 |
70 | -------------------------------------------------------------------------------- /src/components/Card.astro: -------------------------------------------------------------------------------- 1 | --- 2 | export interface Props { 3 | title: string 4 | body: string 5 | href: string 6 | tags: { 7 | title: string 8 | metadata: { 9 | color?: string 10 | } 11 | }[] 12 | } 13 | 14 | const { href, title, body, tags } = Astro.props 15 | --- 16 | 17 |
  • 18 | 19 |
    20 |

    21 | {title} 22 |

    23 |

    24 | {body} 25 |

    26 | { 27 | tags && ( 28 |
    29 | {tags?.map( 30 | (tag: { title: string; metadata: { color?: string } }) => ( 31 | 34 | {tag.title} 35 | 36 | ) 37 | )} 38 |
    39 | ) 40 | } 41 |
    42 |
    43 |
  • 44 | -------------------------------------------------------------------------------- /src/components/Footer.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Logo from './Logo.astro' 3 | --- 4 | 5 | 29 | -------------------------------------------------------------------------------- /src/components/Logo.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const iconColor = 'fill-[#28ABE2]' 3 | 4 | const { width, height } = Astro.props 5 | --- 6 | 7 | 15 | 18 | 21 | 24 | 27 | 30 | 33 | 36 | 39 | 42 | 45 | 48 | 51 | 54 | 57 | 60 | 63 | 66 | 69 | 70 | -------------------------------------------------------------------------------- /src/components/Metadata.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { getConfig } from '../lib/cosmic' 3 | const config = await getConfig() 4 | const defaultTitle = config.metadata.website_title 5 | const defaultDescription = config.metadata.website_description 6 | const defaultImage = config.metadata.og_image.imgix_url 7 | const defaultUrl = config.metadata.og_url 8 | const { title, description, imageUrl } = Astro.props 9 | --- 10 | 11 | 12 | {title || defaultTitle} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 41 | 47 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/components/Navigation.astro: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | 76 | -------------------------------------------------------------------------------- /src/components/PostBody.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactMarkdown from 'react-markdown' 3 | 4 | const components: {} = { 5 | p: (p: { children: string }) => { 6 | return

    {p.children}

    7 | }, 8 | a: (a: { children: string; href: string }) => { 9 | return ( 10 | 14 | {a.children} 15 | 16 | ) 17 | }, 18 | h2: (h2: { children: string }) => { 19 | return

    {h2.children}

    20 | }, 21 | h3: (h3: { children: string }) => { 22 | return

    {h3.children}

    23 | }, 24 | img: (img: { src: string; alt: string }) => { 25 | return ( 26 | {img.alt} 33 | ) 34 | } 35 | } 36 | 37 | const PostBody: React.FC<{ content: string }> = ({ content }) => { 38 | return ( 39 | 42 | {content} 43 | 44 | ) 45 | } 46 | export default PostBody 47 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/images/cosmic.svg: -------------------------------------------------------------------------------- 1 | 7 | 14 | 15 | 77 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/layouts/Layout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Footer from '../components/Footer.astro' 3 | import Metadata from '../components/Metadata.astro' 4 | import Navigation from '../components/Navigation.astro' 5 | const { title, description, imageUrl } = Astro.props 6 | import { ViewTransitions } from 'astro:transitions' 7 | --- 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | The source code for this blog is{' '} 18 | 22 | available on GitHub. 24 |
    25 | 26 |
    28 | 29 |
    30 |