├── .babelrc ├── .eslintrc ├── .gitignore ├── README.md ├── artifacts ├── react-static-browser-plugins.js └── react-static-templates.js ├── config.js ├── package-lock.json ├── package.json ├── public ├── robots.txt └── thumbnail.PNG ├── src ├── App.js ├── app.css ├── components │ └── Router.js ├── containers │ ├── Dynamic.js │ └── Post.js ├── index.js └── pages │ ├── 404.js │ ├── about.js │ ├── index.js │ └── post.js ├── static.config.js ├── tmp └── dev-server │ └── index.html └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react-static/babel-preset.js"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "react-app" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React-Static + Cosmic JS 2 | 3 | ![react-static-cosmicjs-blog](public/thumbnail.PNG "The index page of the starter blog") 4 | 5 | > This repo contains an example blog website that is built with [React-Static](https://react-static.js.org), and [Cosmic JS](https://www.cosmicjs.com). 6 | 7 | ### [View Demo](https://cosmicjs.com/apps/react-static-blog) 8 | 9 | ## Prerequisites 10 | 11 | - Node (I recommend using v8.2.0 or higher) 12 | - [React-Static CLI](https://react-static.js.org) 13 | 14 | ## Getting Started 15 | 16 | ``` bash 17 | git clone https://github.com/sumitkharche/react-static-cosmicjs-blog.git 18 | cd react-static-cosmicjs-blog 19 | npm install or yarn install 20 | ``` 21 | ### Run 22 | ``` bash 23 | npm run start 24 | ``` 25 | Open http://localhost:3000. 26 | 27 | ### Production 28 | ``` bash 29 | npm run build 30 | ``` 31 | -------------------------------------------------------------------------------- /artifacts/react-static-browser-plugins.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | import plugin0 from '../node_modules/react-static-plugin-reach-router/browser.api.js' 3 | 4 | // Plugins 5 | const plugins = [{ 6 | location: "../node_modules/react-static-plugin-source-filesystem", 7 | plugins: [], 8 | hooks: {} 9 | }, 10 | { 11 | location: "../node_modules/react-static-plugin-reach-router", 12 | plugins: [], 13 | hooks: plugin0({}) 14 | }, 15 | { 16 | location: "../node_modules/react-static-plugin-sitemap/dist", 17 | plugins: [], 18 | hooks: {} 19 | }, 20 | { 21 | location: "..", 22 | plugins: [], 23 | hooks: {} 24 | }] 25 | 26 | // Export em! 27 | export default plugins -------------------------------------------------------------------------------- /artifacts/react-static-templates.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | // Template Map 5 | export default { 6 | '../src/pages/404.js': require('../src/pages/404.js').default, 7 | '../src/pages/about.js': require('../src/pages/about.js').default, 8 | '../src/pages/index.js': require('../src/pages/index.js').default, 9 | '../src/pages/post.js': require('../src/pages/post.js').default, 10 | '../src/pages/post': require('../src/pages/post').default 11 | } 12 | 13 | export const notFoundTemplate = '../src/pages/404.js' 14 | 15 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | bucket: { 3 | slug: process.env.COSMIC_BUCKET || 'coffee-blog', 4 | read_key: process.env.COSMIC_READ_KEY || '', 5 | write_key: process.env.COSMIC_WRITE_KEY || '', 6 | port: process.env.PORT || '', 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-static-cosmicjs-blog", 3 | "private": true, 4 | "version": "1.0.0", 5 | "scripts": { 6 | "start": "react-static start", 7 | "stage": "react-static build --staging", 8 | "build": "react-static build", 9 | "analyze": "react-static build --analyze", 10 | "serve": "serve dist -p 3000" 11 | }, 12 | "dependencies": { 13 | "@reach/router": "^1.2.1", 14 | "axios": "^0.18.0", 15 | "graphql-request": "^1.8.2", 16 | "react": "^16.8.2", 17 | "react-dom": "^16.8.2", 18 | "react-markdown": "^4.0.8", 19 | "react-static": "^7.0.0", 20 | "react-static-plugin-reach-router": "^7.0.0", 21 | "react-static-plugin-sitemap": "^7.0.0", 22 | "react-static-plugin-source-filesystem": "^7.0.0" 23 | }, 24 | "devDependencies": { 25 | "babel-eslint": "9.x", 26 | "eslint": "5.x", 27 | "eslint-config-react-app": "^3.0.8", 28 | "eslint-config-react-tools": "1.x.x", 29 | "eslint-plugin-flowtype": "2.x", 30 | "eslint-plugin-import": "2.x", 31 | "eslint-plugin-jsx-a11y": "6.x", 32 | "eslint-plugin-react": "7.x", 33 | "serve": "10.1.2" 34 | }, 35 | "browserslist": [ 36 | "last 1 version", 37 | "> 1%", 38 | "maintained node versions", 39 | "not dead" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | -------------------------------------------------------------------------------- /public/thumbnail.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/react-static-blog/85280e05538aee05ca8b551811b44a385a839c2f/public/thumbnail.PNG -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Root, Routes, addPrefetchExcludes } from 'react-static' 3 | // 4 | import { Link, Router } from 'components/Router' 5 | import Dynamic from 'containers/Dynamic' 6 | 7 | import './app.css' 8 | 9 | // Any routes that start with 'dynamic' will be treated as non-static routes 10 | addPrefetchExcludes(['dynamic']) 11 | 12 | const isActive = ({ isCurrent }) => { 13 | return isCurrent ? { className: "active" } : { className: "header-link" }; 14 | }; 15 | 16 | function App() { 17 | return ( 18 | 19 |
20 |

React-Static & Cosmic JS blog

21 | 29 |
30 |
31 | Loading...}> 32 | 33 | 34 | 35 | 36 | 37 |
38 |
39 | Powered by 40 | react-static 45 | 46 | React-Static 47 | 48 | and 49 | cosmicjs 54 | 55 | Cosmic JS 56 | 57 |
58 |
59 | ) 60 | } 61 | 62 | export default App 63 | -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | * { 2 | scroll-behavior: smooth; 3 | } 4 | 5 | body { 6 | font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', 7 | Helvetica, Arial, 'Lucida Grande', sans-serif; 8 | font-weight: 300; 9 | font-size: 16px; 10 | margin: 0; 11 | padding: 0; 12 | } 13 | 14 | /* Home */ 15 | .container { 16 | max-width: 960px; 17 | margin: 0 auto; 18 | } 19 | 20 | .card { 21 | display: flex; 22 | align-items: center; 23 | margin-bottom: 16px; 24 | border: 1px solid #eee; 25 | overflow: hidden; 26 | border-radius: 5px; 27 | } 28 | .card:hover { 29 | box-shadow: 1px 1px 5px #999; 30 | } 31 | 32 | .card-img { 33 | display: block; 34 | height: 100%; 35 | width:200px; 36 | } 37 | 38 | .card-tag { 39 | margin-right: 0.5em; 40 | color: white; 41 | background: mediumaquamarine; 42 | padding: 0.3em 0.5em; 43 | border-radius: 50px; 44 | } 45 | 46 | /* Post */ 47 | .placeholder { 48 | height: 366px; 49 | background-color: #eee; 50 | } 51 | 52 | article { 53 | margin: 0 auto; 54 | max-width: 650px; 55 | } 56 | 57 | /* About */ 58 | .about-header { 59 | text-align: center; 60 | } 61 | .about-avatar { 62 | height: 150px; 63 | width: auto; 64 | border-radius: 10px; 65 | border: 5px solid salmon; 66 | } 67 | .about-author { 68 | margin-bottom: 72px; 69 | } 70 | 71 | /*footer*/ 72 | .footer { 73 | width: 100%; 74 | padding: 40px; 75 | } 76 | 77 | .footer-logo { 78 | width: 25px; 79 | height: 25px; 80 | margin: 0px 4px -6px 3px; 81 | } 82 | 83 | a { 84 | text-decoration: none; 85 | color: #108db8; 86 | font-weight: bold; 87 | } 88 | 89 | img { 90 | max-width: 100%; 91 | } 92 | 93 | /* Header */ 94 | header { 95 | padding: 24px 32px; 96 | margin-bottom: 32px; 97 | text-align: center; 98 | background: #0e1e25; 99 | } 100 | .header-h1 { 101 | padding-bottom: 2px; 102 | font-weight: 100; 103 | color:white; 104 | } 105 | .header-nav { 106 | max-width: 650px; 107 | margin: 0 auto; 108 | } 109 | .header-link { 110 | font-size: 18px; 111 | margin-right: 16px; 112 | } 113 | 114 | .active { 115 | font-size: 18px; 116 | margin-right: 16px; 117 | font-weight: bold; 118 | text-decoration: underline; 119 | } 120 | 121 | .content { 122 | padding: 1rem; 123 | } 124 | -------------------------------------------------------------------------------- /src/components/Router.js: -------------------------------------------------------------------------------- 1 | export { Link, Router } from '@reach/router' 2 | -------------------------------------------------------------------------------- /src/containers/Dynamic.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export default () => ( 4 |
5 | This is a dynamic page! It will not be statically exported, but is available 6 | at runtime 7 |
8 | ) 9 | -------------------------------------------------------------------------------- /src/containers/Post.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useRouteData } from 'react-static' 3 | // 4 | import { Link } from 'components/Router' 5 | 6 | export default function Post() { 7 | const { post } = useRouteData() 8 | return ( 9 |
10 | {'<'} Back 11 |
12 |

{post.title}

13 |

{post.body}

14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import { AppContainer } from 'react-hot-loader' 4 | 5 | // Your top level component 6 | import App from './App' 7 | 8 | // Export your top level component as JSX (for static rendering) 9 | export default App 10 | 11 | // Render your app 12 | if (typeof document !== 'undefined') { 13 | const target = document.getElementById('root') 14 | 15 | const renderMethod = target.hasChildNodes() 16 | ? ReactDOM.hydrate 17 | : ReactDOM.render 18 | 19 | const render = Comp => { 20 | renderMethod( 21 | 22 | 23 | , 24 | target 25 | ) 26 | } 27 | 28 | // Render! 29 | render(App) 30 | 31 | // Hot Module Replacement 32 | if (module && module.hot) { 33 | module.hot.accept('./App', () => { 34 | render(App) 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export default () => ( 4 |
5 |

404 - Oh no's! We couldn't find that page :(

6 |
7 | ) 8 | -------------------------------------------------------------------------------- /src/pages/about.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export default () => ( 4 |
5 |

React Static is a progressive static site generator for React.

6 |

Cosmic JS is Headless CMS API and toolkit to build modern apps faster,together.

7 |

This application uses both React-Static and Cosmic JS to bulid next generation JAMStack apps.

8 |
9 | ) 10 | -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {withRouteData} from 'react-static' 3 | import {Link } from '@reach/router' 4 | 5 | export default withRouteData(({posts}) =>( 6 | 7 |
8 | {posts.map(post => ( 9 | 10 |
11 | {post.metadata.title} 16 |
17 |
18 |

{post.metadata.title}

19 |
20 | 21 | ))} 22 |
23 |
24 | )) 25 | -------------------------------------------------------------------------------- /src/pages/post.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {withRouteData} from 'react-static' 3 | import Markdown from "react-markdown"; 4 | import { Link } from 'components/Router' 5 | 6 | export default withRouteData(({post}) => ( 7 | 8 |
9 | {'<'} Back 10 |
11 |
12 |

{post.metadata.title}

13 |
14 | {post.metadata.title} 18 |
19 | 20 |
21 |
22 | )) 23 | -------------------------------------------------------------------------------- /static.config.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import axios from 'axios' 3 | import config from './config' 4 | 5 | const gph_query = `{ 6 | getObjects(bucket_slug: "${config.bucket.slug}", input: { 7 | type: "posts", 8 | limit: 20, 9 | read_key: "${config.bucket.read_key}", 10 | }) { 11 | _id 12 | type_slug 13 | slug 14 | title 15 | metadata 16 | created_at 17 | } 18 | }`; 19 | 20 | export default { 21 | getRoutes: async () => { 22 | const posts = await axios.post('https://graphql.cosmicjs.com/v1', { 23 | query:gph_query 24 | }) 25 | .then(function (response) { 26 | return response.data.data.getObjects 27 | }) 28 | 29 | return [ 30 | { 31 | path: '/', 32 | getData: () => ({ 33 | posts, 34 | }), 35 | children: posts.map(post => ({ 36 | path: `/post/${post._id}`, 37 | template: 'src/pages/post', 38 | getData: () => ({ 39 | post, 40 | }), 41 | })), 42 | }, 43 | ] 44 | }, 45 | plugins: [ 46 | [ 47 | require.resolve('react-static-plugin-source-filesystem'), 48 | { 49 | location: path.resolve('./src/pages'), 50 | }, 51 | ], 52 | require.resolve('react-static-plugin-reach-router'), 53 | require.resolve('react-static-plugin-sitemap'), 54 | ], 55 | } 56 | -------------------------------------------------------------------------------- /tmp/dev-server/index.html: -------------------------------------------------------------------------------- 1 |
--------------------------------------------------------------------------------