├── docs ├── example.png ├── example-objects.png ├── example-localised.png ├── localisation-settings.png └── article.md ├── now.json ├── src ├── components │ ├── layouts │ │ ├── common │ │ │ ├── Container.js │ │ │ ├── GlobalStyles.js │ │ │ └── Head.js │ │ ├── Default.js │ │ └── Blog.js │ ├── molecules │ │ ├── PostList.js │ │ ├── Footer.js │ │ └── Header.js │ ├── modules │ │ ├── SitePage.js │ │ ├── BlogPost.js │ │ ├── SitePostListing.js │ │ └── withLocale.js │ └── atoms │ │ ├── HTMLContentArea.js │ │ ├── PostTile.js │ │ ├── HeaderNav.js │ │ └── LocaleSelector.js └── pages │ └── index.js ├── gatsby-config.js ├── config.js ├── package.json ├── LICENSE ├── .gitignore ├── gatsby-node.js └── README.md /docs/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/gatsby-localization-app-starter/master/docs/example.png -------------------------------------------------------------------------------- /docs/example-objects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/gatsby-localization-app-starter/master/docs/example-objects.png -------------------------------------------------------------------------------- /docs/example-localised.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/gatsby-localization-app-starter/master/docs/example-localised.png -------------------------------------------------------------------------------- /docs/localisation-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmicjs/gatsby-localization-app-starter/master/docs/localisation-settings.png -------------------------------------------------------------------------------- /now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "name": "gatsby-localisation-starter", 4 | "builds": [ 5 | { 6 | "src": "package.json", 7 | "use": "@now/static-build", 8 | "config": { "distDir": "public" } 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /src/components/layouts/common/Container.js: -------------------------------------------------------------------------------- 1 | import styled from '@emotion/styled'; 2 | 3 | import appConfig from '../../../../config'; 4 | 5 | export default styled.div` 6 | max-width: ${ 7 | ({ maxWidth = appConfig.responsive.defaultContainerMaxWidth }) => maxWidth}; 8 | min-height: ${({ minHeight }) => minHeight}; 9 | margin: 0 auto; 10 | padding: 0 1rem; 11 | `; -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | 'gatsby-plugin-emotion', 4 | 'gatsby-plugin-react-helmet', 5 | { 6 | resolve: `gatsby-source-cosmicjs`, 7 | options: { 8 | bucketSlug: 'minimal-gatsby-localisation-site', 9 | objectTypes: ['blog-posts', 'pages'], 10 | apiAccess: { 11 | read_key: ``, 12 | } 13 | } 14 | } 15 | ], 16 | } 17 | -------------------------------------------------------------------------------- /src/components/molecules/PostList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | 4 | import PostTile from '../atoms/PostTile'; 5 | 6 | const PostListContainer = styled.section` 7 | display: flex; 8 | `; 9 | 10 | export default function PostList({ posts, locale, ...rest }) { 11 | return ( 12 | 13 | {posts.map(({ node: postNode }) => ( 14 | 19 | ))} 20 | 21 | ); 22 | } -------------------------------------------------------------------------------- /src/components/layouts/common/GlobalStyles.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import { Global, css } from '@emotion/core'; 3 | import { normalize } from 'polished'; 4 | 5 | const normalizeStyles = normalize(); 6 | 7 | const globalStyles = css` 8 | body { 9 | font-family: 'Open Sans', 'Franklin Gothic Medium', Arial, sans-serif; 10 | } 11 | `; 12 | 13 | export default () => ( 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { graphql } from 'gatsby'; 3 | import { Redirect } from '@reach/router'; 4 | 5 | import withLocale from '../components/modules/withLocale'; 6 | 7 | // redirect the index page based on the preferred locale 8 | // otherwise redirect to the first detected available locale 9 | export default withLocale(({ locale }) => ( 10 | 14 | ), { fromLocation: false }); 15 | 16 | // specifically query index site pages 17 | export const query = graphql` 18 | { 19 | allCosmicjsPages(filter: {slug: {eq: "index" }}){ 20 | edges{ 21 | node{ 22 | slug 23 | locale 24 | } 25 | } 26 | } 27 | } 28 | `; 29 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | // shared config values used within various parts of the application 2 | 3 | module.exports = { 4 | // the default locale to prefer if no window.navigator values 5 | // can be resolved 6 | fallbackLocale: 'en-US', 7 | // fallback site title if none is provided via props 8 | fallbackSiteTitle: 'Gatsby Localization Website', 9 | // settings for default colors 10 | theme: { 11 | primaryAccent: '#8ad', 12 | // speed to do standard ui transitions 13 | primaryTransitionSpeed: '.2s', 14 | }, 15 | // settings for responsive/layout configuration 16 | responsive: { 17 | // max width size for a default static page 18 | defaultContainerMaxWidth: '960px', 19 | // default minimum page height 20 | defaultMinimumPageHeight: 'calc(100vh - 256px)', 21 | // max width size for content blog posts 22 | blogPostContainerMaxWidth: '760px', 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /src/components/layouts/common/Head.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Helmet } from 'react-helmet'; 3 | 4 | import appConfig from '../../../../config'; 5 | 6 | function generatePageTitle(title, siteTitle) { 7 | const finalTitleParts = []; 8 | 9 | if (title) { 10 | // prepend page-specific title if provided 11 | finalTitleParts.push(title); 12 | } 13 | 14 | finalTitleParts.push(siteTitle || appConfig.fallbackSiteTitle); 15 | 16 | // trim surrounding whitespace of each part 17 | // separate with pipe character if more than one part provided 18 | return finalTitleParts 19 | .map(part => part.trim()) 20 | .join(' | '); 21 | } 22 | 23 | export default function Head({ 24 | title, siteTitle, children, 25 | }) { 26 | return ( 27 | 28 | {generatePageTitle(title, siteTitle)} 29 | {children} 30 | 31 | ); 32 | } -------------------------------------------------------------------------------- /src/components/molecules/Footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { readableColor, lighten } from 'polished'; 4 | 5 | import appConfig from '../../../config'; 6 | 7 | import Container from '../layouts/common/Container'; 8 | 9 | import LocaleSelector from '../atoms/LocaleSelector'; 10 | 11 | const { primaryAccent } = appConfig.theme; 12 | 13 | export const FooterWrapper = styled.footer` 14 | padding: 2.5rem 1rem; 15 | background-color: ${lighten(0.2, primaryAccent)}; 16 | border-top: solid 5px ${lighten(0.15, primaryAccent)}; 17 | color: ${readableColor(primaryAccent)}; 18 | `; 19 | 20 | export default function Footer({ locale, children }) { 21 | return ( 22 | 23 | 24 | 27 | {children} 28 | 29 | 30 | ); 31 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-localisation-starter", 3 | "description": "Gatsby example site using gatsby-source-cosmicjs", 4 | "license": "MIT", 5 | "scripts": { 6 | "develop": "gatsby develop", 7 | "build": "gatsby build", 8 | "now-build": "npm run build", 9 | "start": "npm run develop", 10 | "serve": "gatsby serve" 11 | }, 12 | "dependencies": { 13 | "@emotion/core": "^10.0.10", 14 | "@emotion/styled": "^10.0.10", 15 | "gatsby": "^2.0.17", 16 | "gatsby-plugin-emotion": "^4.0.6", 17 | "gatsby-plugin-react-helmet": "^3.0.12", 18 | "gatsby-source-cosmicjs": "0.0.7", 19 | "htmr": "^0.7.0", 20 | "moment": "^2.24.0", 21 | "polished": "^3.2.0", 22 | "react": "^16.3.2", 23 | "react-dom": "^16.3.2", 24 | "react-helmet": "^5.2.0" 25 | }, 26 | "devDependencies": { 27 | "eslint": "^4.19.1", 28 | "eslint-plugin-react": "^7.11.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/components/modules/SitePage.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { graphql } from 'gatsby'; 3 | 4 | import DefaultLayout from '../layouts/Default'; 5 | import HTMLContentArea from '../atoms/HTMLContentArea'; 6 | import withLocale from './withLocale'; 7 | 8 | function SitePage({ data, locale }) { 9 | const { 10 | cosmicjsPages: page, 11 | allCosmicjsPages: { edges: allPages }, 12 | } = data; 13 | 14 | return ( 15 | 19 | {page.content} 20 | 21 | } 22 | locale={locale} 23 | allPages={allPages} 24 | /> 25 | ); 26 | } 27 | 28 | export default withLocale(SitePage); 29 | 30 | export const query = graphql` 31 | query SitePageQuery($id: String!) { 32 | cosmicjsPages(id: { eq: $id }) { 33 | title 34 | content 35 | } 36 | allCosmicjsPages { 37 | edges{ 38 | node{ 39 | locale 40 | title 41 | slug 42 | } 43 | } 44 | } 45 | } 46 | `; -------------------------------------------------------------------------------- /src/components/layouts/Default.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | 3 | import appConfig from '../../../config'; 4 | 5 | import GlobalStyles from './common/GlobalStyles'; 6 | import Container from './common/Container'; 7 | import Head from './common/Head'; 8 | 9 | import Header from '../molecules/Header'; 10 | import Footer from '../molecules/Footer'; 11 | 12 | export default function DefaultLayout({ 13 | title, siteTitle, headerBackgroundColor, 14 | content, locale, allPages, 15 | }) { 16 | return ( 17 | 18 | 19 | 23 |
30 | 33 | {content} 34 | 35 |