├── .prettierrc ├── .gitignore ├── gatsby-browser.js ├── gatsby-ssr.js ├── scripts ├── object-type.json ├── import.js └── objects.json ├── src ├── components │ ├── header.js │ ├── footer.js │ ├── index.css │ ├── nav.js │ └── layout.js ├── pages │ └── 404.js └── templates │ └── page.js ├── .eslintrc.js ├── README.md ├── gatsby-config.js ├── package.json ├── LICENSE └── gatsby-node.js /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project dependencies 2 | .cache 3 | node_modules 4 | yarn-error.log 5 | 6 | # Build directory 7 | /public 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /gatsby-browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Browser APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/browser-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it -------------------------------------------------------------------------------- /gatsby-ssr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's SSR (Server Side Rendering) APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/ssr-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it -------------------------------------------------------------------------------- /scripts/object-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Pages", 3 | "slug": "pages", 4 | "singular": "Page", 5 | "localization": true, 6 | "locales": ["en","de"], 7 | "priority_locale": "en", 8 | "options": { 9 | "slug_field": true, 10 | "content_editor": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/components/header.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link } from 'gatsby' 3 | 4 | const Header = ({ siteTitle }) => ( 5 |
6 |

7 | 8 | {siteTitle} 9 |

10 |
11 | ) 12 | 13 | export default Header 14 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | }, 6 | "plugins": [ 7 | "react", 8 | ], 9 | "globals": { 10 | "graphql": false, 11 | }, 12 | "parserOptions": { 13 | "ecmaVersion": 8, 14 | "sourceType": "module", 15 | "ecmaFeatures": { 16 | "experimentalObjectRestSpread": true, 17 | "jsx": true, 18 | }, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/components/footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const Footer = () => ( 4 |
5 | © 6 | {new Date().getFullYear()} Cosmic JS{' '} 7 | Gatsby Starter.{' '} 8 | 9 | View the code 10 | 11 | . 12 |
13 | ) 14 | 15 | export default Footer 16 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Helmet from 'react-helmet' 3 | import Layout from '../components/layout' 4 | 5 | const NotFoundPage = () => ( 6 | 7 | 8 |

404 Page Not Found

9 |
10 | Oops! The content you are looking for does not exist in your Cosmic JS 11 | Bucket. 12 |
13 |
14 | ) 15 | 16 | export default NotFoundPage 17 | -------------------------------------------------------------------------------- /src/components/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: sans-serif; 3 | } 4 | body { 5 | margin: 0; 6 | padding: 0; 7 | } 8 | .main, .footer { 9 | padding: 0 20px 20px; 10 | max-width: 960px; 11 | margin: 0 auto; 12 | } 13 | .hero { 14 | background: #29ABE2; 15 | width: 100%; 16 | } 17 | .hero h1 { 18 | margin: 0; 19 | font-size: 30px; 20 | padding: 30px; 21 | max-width: 960px; 22 | margin: 0 auto; 23 | } 24 | .hero h1 a { 25 | color: #fff; 26 | text-decoration: none; 27 | } -------------------------------------------------------------------------------- /src/components/nav.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Link from 'gatsby-link' 3 | 4 | const Nav = ({ nav, locale}) => ( 5 | 18 | ) 19 | 20 | export default Nav 21 | -------------------------------------------------------------------------------- /scripts/import.js: -------------------------------------------------------------------------------- 1 | const Cosmic = require('cosmicjs') 2 | const api = Cosmic() 3 | const COSMIC_BUCKET = process.env.COSMIC_BUCKET || 'node-starter' 4 | const bucket = api.bucket({ 5 | slug: COSMIC_BUCKET, 6 | read_key: process.env.COSMIC_READ_KEY, 7 | write_key: process.env.COSMIC_WRITE_KEY 8 | }) 9 | const default_objects = require('./objects') 10 | const default_object_type = require('./object-type') 11 | const importObjects = async () => { 12 | try { 13 | const res = await bucket.getObjects() 14 | if(res.status === 'empty') { 15 | bucket.addObjectType(default_object_type) 16 | default_objects.forEach(object => { 17 | bucket.addObject(object) 18 | }) 19 | } 20 | } catch (e) { 21 | console.log(e) 22 | } 23 | } 24 | importObjects() 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gatsby Localization Starter 2 | Gatsby starter app with localization powered by [Cosmic](https://cosmicjs.com) 🚀 3 | 4 | ## Installation 5 | Option 1: Download code. Connects to demo Bucket. 6 | ```bash 7 | git clone https://github.com/cosmicjs/gatsby-localization-starter 8 | cd gatsby-localization-starter 9 | npm install 10 | npm run develop 11 | ``` 12 | 13 | Option 2: Download via the [Cosmic CLI](https://github.com/cosmicjs/cosmic-cli). Installs demo content and connects to your Cosmic Bucket. 14 | ```bash 15 | npm i -g cosmic-cli 16 | 17 | # Login to your Cosmic account 18 | cosmic login 19 | 20 | # Installs example content to a new or existing Bucket and downloads the app locally 21 | cosmic init gatsby-localization-starter 22 | cd gatsby-localization-starter 23 | cosmic start 24 | ``` 25 | -------------------------------------------------------------------------------- /src/templates/page.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Helmet from 'react-helmet' 3 | import { graphql } from 'gatsby' 4 | import Layout from '../components/layout' 5 | 6 | class PageTemplate extends React.Component { 7 | render() { 8 | const page = this.props.data.cosmicjsPages 9 | const locale = this.props.pageContext.locale 10 | return ( 11 | 12 | {page && ( 13 |
14 | 15 |

{page.title}

16 |
17 |
18 | )} 19 | 20 | ) 21 | } 22 | } 23 | 24 | export default PageTemplate 25 | 26 | export const pageQuery = graphql` 27 | query PageBySlug($slug: String!) { 28 | cosmicjsPages(id: { eq: $slug }) { 29 | title 30 | content 31 | } 32 | } 33 | ` 34 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: 'Cosmic JS Gatsby Starter Localization', 4 | nav: [ 5 | { slug: '', name: 'Home' }, 6 | { slug: 'about', name: 'About' }, 7 | { slug: 'contact', name: 'Contact' }, 8 | { slug: 'not-found', name: 'Not Found' }, 9 | ], 10 | languages: [ 11 | { slug: '', localized_name: { en: 'English', es: 'Inglés', de: 'Englisch'} }, 12 | { slug: 'de', localized_name: { en: 'German', es: 'Alemán', de: 'Deutsche'} }, 13 | ], 14 | }, 15 | plugins: [ 16 | 'gatsby-plugin-react-helmet', 17 | { 18 | resolve: `gatsby-source-cosmicjs`, 19 | options: { 20 | bucketSlug: process.env.COSMIC_BUCKET || `gatsby-localization`, 21 | objectTypes: [`pages`], 22 | // If you have enabled read_key to fetch data (optional). 23 | apiAccess: { 24 | read_key: process.env.COSMIC_READ_KEY || ``, 25 | } 26 | } 27 | }, 28 | ], 29 | } 30 | -------------------------------------------------------------------------------- /scripts/objects.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "Home", 4 | "slug": "home", 5 | "content": "This is the home page content.", 6 | "type_slug": "pages", 7 | "locale": "en" 8 | }, 9 | { 10 | "title": "Zuhause", 11 | "slug": "home", 12 | "content": "Dies ist der Inhalt der Startseite.", 13 | "type_slug": "pages", 14 | "locale": "de" 15 | }, 16 | { 17 | "title": "About", 18 | "slug": "about", 19 | "content": "This is the about page content.", 20 | "type_slug": "pages", 21 | "locale": "en" 22 | }, 23 | { 24 | "title": "Über", 25 | "slug": "about", 26 | "content": "Dies ist der ungefähre Seiteninhalt.", 27 | "type_slug": "pages", 28 | "locale": "de" 29 | }, 30 | { 31 | "title": "Contact", 32 | "slug": "contact", 33 | "content": "This is the contact page content.", 34 | "type_slug": "pages", 35 | "locale": "en" 36 | }, 37 | { 38 | "title": "Kontakt", 39 | "slug": "contact", 40 | "content": "Dies ist der Inhalt der Kontaktseite.", 41 | "type_slug": "pages", 42 | "locale": "de" 43 | } 44 | ] -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-starter", 3 | "description": "Cosmic JS Gatsby Starter", 4 | "version": "1.0.0", 5 | "dependencies": { 6 | "cosmicjs": "^3.2.8", 7 | "gatsby": "^2.0.17", 8 | "gatsby-plugin-react-helmet": "^3.0.0", 9 | "gatsby-source-cosmicjs": "0.0.6", 10 | "lodash": "^4.17.11", 11 | "react": "^16.5.2", 12 | "react-dom": "^16.5.2", 13 | "react-helmet": "^5.2.0" 14 | }, 15 | "license": "MIT", 16 | "scripts": { 17 | "start": "gatsby build; gatsby serve --port $PORT", 18 | "build": "gatsby build", 19 | "develop": "gatsby develop --port $PORT", 20 | "lint": "./node_modules/.bin/eslint --ext .js,.jsx --ignore-pattern public .", 21 | "format": "prettier --write 'src/**/*.js'", 22 | "import": "node ./scripts/import.js", 23 | "test": "echo \"Error: no test specified\" && exit 1" 24 | }, 25 | "devDependencies": { 26 | "eslint": "^4.19.1", 27 | "eslint-plugin-react": "^7.11.1", 28 | "prettier": "^1.14.3" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "https://github.com/cosmicjs/gatsby-starter" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 gatsbyjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- 1 | const each = require('lodash/each') 2 | const find = require('lodash/find') 3 | const path = require('path') 4 | 5 | exports.createPages = ({ 6 | graphql, 7 | actions 8 | }) => { 9 | const { 10 | createPage 11 | } = actions 12 | 13 | return new Promise((resolve, reject) => { 14 | const pageTemplate = path.resolve('./src/templates/page.js') 15 | resolve( 16 | graphql( 17 | ` 18 | { 19 | allCosmicjsPages{ 20 | edges{ 21 | node{ 22 | id 23 | slug 24 | locale 25 | } 26 | } 27 | } 28 | } 29 | ` 30 | ).then(result => { 31 | if (result.errors) { 32 | console.log(result.errors) 33 | reject(result.errors) 34 | } 35 | 36 | const pages = result.data.allCosmicjsPages.edges; 37 | 38 | each(pages, page => { 39 | page = page.node 40 | $slugLocale = page.locale === 'en' ? '' : `/${page.locale}` 41 | $slug = page.slug === 'home' ? `${$slugLocale}/` : `${$slugLocale}/${page.slug}` 42 | createPage({ 43 | path: $slug, 44 | component: pageTemplate, 45 | context: { 46 | slug: page.id, 47 | locale: page.locale 48 | }, 49 | }) 50 | }) 51 | }) 52 | ) 53 | }) 54 | } -------------------------------------------------------------------------------- /src/components/layout.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Helmet from 'react-helmet' 3 | import { StaticQuery, graphql } from 'gatsby' 4 | 5 | import Header from './header' 6 | import Nav from './nav' 7 | import Footer from './footer' 8 | import Link from 'gatsby-link' 9 | import './index.css' 10 | 11 | export default ({ children, locale }) => ( 12 | { 34 | const siteTitle = data.site.siteMetadata.title 35 | const siteNav = data.site.siteMetadata.nav 36 | return ( 37 |
38 | 44 |
45 |
46 | {children} 47 |
56 |
58 | ) 59 | }} 60 | /> 61 | ) 62 | --------------------------------------------------------------------------------