├── .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 |
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 |
6 | {nav.map(function(li, index) {
7 | let locale_slug = locale
8 | if (locale === 'en') {
9 | locale_slug = ''
10 | }
11 | return (
12 | -
13 | {li.name}
14 |
15 | )
16 | })}
17 |
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 |
48 | {
49 | data.site.siteMetadata.languages.map(lang => {
50 | return (
51 | {lang.localized_name[locale]} |
52 | )
53 | })
54 | }
55 |
56 |
57 |
58 | )
59 | }}
60 | />
61 | )
62 |
--------------------------------------------------------------------------------