pull/135/head
parent
a8bf229ea2
commit
bd4684f148
@ -0,0 +1,69 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Typescript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env*
|
||||||
|
|
||||||
|
# gatsby files
|
||||||
|
.cache/
|
||||||
|
public
|
||||||
|
|
||||||
|
# Mac files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Yarn
|
||||||
|
yarn-error.log
|
||||||
|
.pnp/
|
||||||
|
.pnp.js
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
@ -0,0 +1,4 @@
|
|||||||
|
.cache
|
||||||
|
package.json
|
||||||
|
package-lock.json
|
||||||
|
public
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5"
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 gatsbyjs
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
# TODO
|
||||||
|
|
||||||
|
- Filter and Sort for all pages (home page probably most important as it displays all tiers of ideas)
|
||||||
|
|
||||||
|
- If this gets accepted and merged update CONTRIBUTING.md to have new md app idea files to include necessary fields for Gatsby markdown plugin
|
||||||
|
|
||||||
|
- Style could use some love in general - currently just super simple css grid
|
||||||
|
|
||||||
|
- Update SEO for all pages to return accurate title for content
|
||||||
|
|
||||||
|
- IdeaTemplate needs a lof styling love. Currently only showing the HTML that is derived from the markdown files
|
||||||
|
|
||||||
|
- Look into possibly adding more fields to each markdown file to allow for more custom styling on each page (this can still be done by creating tight styling components
|
||||||
|
based on the exact structure of the markdown parsed HTML)
|
||||||
|
|
||||||
|
- look into some way to trigger rebuild of gatsby site when hosted(probably Netlify) every time a new Idea is merged in from a PR
|
||||||
|
|
||||||
|
- I believe github actions can do this?
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
# Gatsby
|
||||||
|
|
||||||
|
## Plugins
|
||||||
|
|
||||||
|
- gatsby-plugin-react-helmet
|
||||||
|
- gatsby-source-filesystem
|
||||||
|
- gatsby-transformer-sharp
|
||||||
|
- gatsby-plugin-sharp
|
||||||
|
- gatsby-plugin-manifest
|
||||||
|
- gatsby-source-filesystem
|
||||||
|
- gatsby-transformer-remark
|
||||||
|
- gatsby-plugin-styled-components
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
# NOTES
|
||||||
|
|
||||||
|
- each page is querying only the tier of idea that coincides with the page tier
|
||||||
|
- Gatsby createPages being used to create a new page for each project that displays the markdown file in HTML format currently
|
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Implement Gatsby's Browser APIs in this file.
|
||||||
|
*
|
||||||
|
* See: https://www.gatsbyjs.org/docs/browser-apis/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// You can delete this file if you're not using it
|
@ -0,0 +1,48 @@
|
|||||||
|
module.exports = {
|
||||||
|
siteMetadata: {
|
||||||
|
title: `AppIdeas`,
|
||||||
|
description: `Looking for you next project idea? Look to further!`,
|
||||||
|
author: ``,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
`gatsby-plugin-react-helmet`,
|
||||||
|
{
|
||||||
|
resolve: `gatsby-source-filesystem`,
|
||||||
|
options: {
|
||||||
|
name: `images`,
|
||||||
|
path: `${__dirname}/src/images`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
`gatsby-transformer-sharp`,
|
||||||
|
`gatsby-plugin-sharp`,
|
||||||
|
{
|
||||||
|
resolve: `gatsby-plugin-manifest`,
|
||||||
|
options: {
|
||||||
|
name: `gatsby-starter-default`,
|
||||||
|
short_name: `starter`,
|
||||||
|
start_url: `/`,
|
||||||
|
background_color: `#663399`,
|
||||||
|
theme_color: `#663399`,
|
||||||
|
display: `minimal-ui`,
|
||||||
|
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resolve: `gatsby-source-filesystem`,
|
||||||
|
options: {
|
||||||
|
name: `markdown-pages`,
|
||||||
|
path: `../Projects`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
`gatsby-transformer-remark`,
|
||||||
|
{
|
||||||
|
resolve: `gatsby-plugin-styled-components`,
|
||||||
|
options: {
|
||||||
|
// Add any options here
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// this (optional) plugin enables Progressive Web App + Offline functionality
|
||||||
|
// To learn more, visit: https://gatsby.dev/offline
|
||||||
|
// `gatsby-plugin-offline`,
|
||||||
|
],
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
const path = require(`path`)
|
||||||
|
|
||||||
|
exports.createPages = async ({ actions, graphql, reporter }) => {
|
||||||
|
const { createPage } = actions
|
||||||
|
const IdeaTemplate = path.resolve(`src/templates/IdeaTemplate.js`)
|
||||||
|
|
||||||
|
const result = await graphql(`
|
||||||
|
query {
|
||||||
|
allMarkdownRemark {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
frontmatter {
|
||||||
|
path
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Handle errors
|
||||||
|
if (result.errors) {
|
||||||
|
reporter.panicOnBuild(`Error while running GraphQL query.`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
|
||||||
|
createPage({
|
||||||
|
path: node.frontmatter.path,
|
||||||
|
component: IdeaTemplate,
|
||||||
|
context: {}, // additional data can be passed via context
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
|
||||||
|
*
|
||||||
|
* See: https://www.gatsbyjs.org/docs/ssr-apis/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// You can delete this file if you're not using it
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "gatsby-starter-default",
|
||||||
|
"private": true,
|
||||||
|
"description": "A simple starter to get up and developing quickly with Gatsby",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
|
||||||
|
"dependencies": {
|
||||||
|
"babel-plugin-styled-components": "^1.10.7",
|
||||||
|
"gatsby": "^2.19.7",
|
||||||
|
"gatsby-image": "^2.2.39",
|
||||||
|
"gatsby-plugin-manifest": "^2.2.39",
|
||||||
|
"gatsby-plugin-offline": "^3.0.32",
|
||||||
|
"gatsby-plugin-react-helmet": "^3.1.21",
|
||||||
|
"gatsby-plugin-sharp": "^2.4.3",
|
||||||
|
"gatsby-plugin-styled-components": "^3.1.19",
|
||||||
|
"gatsby-source-filesystem": "^2.1.48",
|
||||||
|
"gatsby-transformer-remark": "^2.6.50",
|
||||||
|
"gatsby-transformer-sharp": "^2.3.13",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react": "^16.12.0",
|
||||||
|
"react-dom": "^16.12.0",
|
||||||
|
"react-helmet": "^5.2.1",
|
||||||
|
"styled-components": "^5.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"prettier": "^1.19.1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"gatsby"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"build": "gatsby build",
|
||||||
|
"develop": "gatsby develop",
|
||||||
|
"format": "prettier --write \"**/*.{js,jsx,json,md}\"",
|
||||||
|
"start": "npm run develop",
|
||||||
|
"serve": "gatsby serve",
|
||||||
|
"clean": "gatsby clean",
|
||||||
|
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/gatsbyjs/gatsby/issues"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useStaticQuery, graphql } from 'gatsby';
|
||||||
|
import Img from 'gatsby-image';
|
||||||
|
|
||||||
|
const AppIdeaBanner = () => {
|
||||||
|
const data = useStaticQuery(graphql`
|
||||||
|
query {
|
||||||
|
placeholderImage: file(relativePath: { eq: "app-ideas.png" }) {
|
||||||
|
childImageSharp {
|
||||||
|
fluid(maxWidth: 300, maxHeight: 70) {
|
||||||
|
...GatsbyImageSharpFluid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
return <Img fluid={data.placeholderImage.childImageSharp.fluid} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppIdeaBanner;
|
@ -0,0 +1,33 @@
|
|||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { StyledHeader, Nav, NavItem, NavLink } from './header.styles';
|
||||||
|
|
||||||
|
const Header = ({ siteTitle }) => (
|
||||||
|
<StyledHeader>
|
||||||
|
<Nav>
|
||||||
|
<NavItem>
|
||||||
|
<NavLink to="/">All</NavLink>
|
||||||
|
</NavItem>
|
||||||
|
<NavItem>
|
||||||
|
<NavLink to="/beginner">Beginner</NavLink>
|
||||||
|
</NavItem>
|
||||||
|
<NavItem>
|
||||||
|
<NavLink to="/intermediate">Intermediate</NavLink>
|
||||||
|
</NavItem>
|
||||||
|
<NavItem>
|
||||||
|
<NavLink to="/advanced">Advanced</NavLink>
|
||||||
|
</NavItem>
|
||||||
|
</Nav>
|
||||||
|
</StyledHeader>
|
||||||
|
);
|
||||||
|
|
||||||
|
Header.propTypes = {
|
||||||
|
siteTitle: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
Header.defaultProps = {
|
||||||
|
siteTitle: ``,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
@ -0,0 +1,28 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
import { Link } from 'gatsby';
|
||||||
|
|
||||||
|
export const StyledHeader = styled.header`
|
||||||
|
color: #fff;
|
||||||
|
background: #211e1e;
|
||||||
|
height: 5rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Nav = styled.ul`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
margin: 0 2rem;
|
||||||
|
list-style: none;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const NavItem = styled.li``;
|
||||||
|
|
||||||
|
export const NavLink = styled(Link)`
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
color: #fff;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 500;
|
||||||
|
`;
|
@ -0,0 +1,40 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
IdeaItem,
|
||||||
|
IdeaItemLink,
|
||||||
|
IdeaTitle,
|
||||||
|
Tier,
|
||||||
|
HR,
|
||||||
|
} from './idea-list-item.styles';
|
||||||
|
|
||||||
|
const tierColor = tier => {
|
||||||
|
switch (tier) {
|
||||||
|
case 'beginner':
|
||||||
|
return '#67cc3f';
|
||||||
|
case 'intermediate':
|
||||||
|
return '#1670e5';
|
||||||
|
case 'advanced':
|
||||||
|
return '#ce1010';
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const IdeaListItem = ({
|
||||||
|
idea: {
|
||||||
|
excerpt,
|
||||||
|
frontmatter: { path, title, tier },
|
||||||
|
},
|
||||||
|
}) => (
|
||||||
|
<IdeaItem borderColor={tierColor(tier)}>
|
||||||
|
<IdeaItemLink to={path}>
|
||||||
|
<IdeaTitle>{title}</IdeaTitle>
|
||||||
|
<Tier backgroundColor={tierColor(tier)}>{tier}</Tier>
|
||||||
|
<HR color={tierColor(tier)} />
|
||||||
|
<p>{excerpt}</p>
|
||||||
|
</IdeaItemLink>
|
||||||
|
</IdeaItem>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default IdeaListItem;
|
@ -0,0 +1,33 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
import { Link } from 'gatsby';
|
||||||
|
|
||||||
|
export const IdeaItem = styled.li`
|
||||||
|
border: 1px solid #211e1e;
|
||||||
|
border-color: ${props => props.borderColor || '#211e1e'};
|
||||||
|
border-radius: 5px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const IdeaItemLink = styled(Link)`
|
||||||
|
text-decoration: none;
|
||||||
|
color: #211e1e;
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
padding: 1rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const IdeaTitle = styled.h2`
|
||||||
|
letter-spacing: 1px;
|
||||||
|
color: ${props => props.color || '#211e1e'};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const HR = styled.hr`
|
||||||
|
margin: 5px 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Tier = styled.small`
|
||||||
|
background-color: ${props => props.backgroundColor || '#211e1e'};
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 2px 5px;
|
||||||
|
`;
|
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import IdeaListItem from '../idea-list-item/idea-list-item.component';
|
||||||
|
|
||||||
|
import { IdeasList } from './idea-list.styles';
|
||||||
|
|
||||||
|
const IdeaList = ({ ideas }) => (
|
||||||
|
<IdeasList>
|
||||||
|
{ideas.map(({ node }) => (
|
||||||
|
<IdeaListItem key={node.id} idea={node} />
|
||||||
|
))}
|
||||||
|
</IdeasList>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default IdeaList;
|
@ -0,0 +1,10 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
export const IdeasList = styled.ul`
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
grid-gap: 1rem;
|
||||||
|
|
||||||
|
margin: 2rem;
|
||||||
|
list-style: none;
|
||||||
|
`;
|
@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* Layout component that queries for data
|
||||||
|
* with Gatsby's useStaticQuery component
|
||||||
|
*
|
||||||
|
* See: https://www.gatsbyjs.org/docs/use-static-query/
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useStaticQuery, graphql } from 'gatsby';
|
||||||
|
|
||||||
|
import Header from '../header/header.component';
|
||||||
|
import { MainLayout } from './layout.styles';
|
||||||
|
import AppIdeaBanner from '../app-idea-banner/app-idea-banner.component';
|
||||||
|
|
||||||
|
import './main.css';
|
||||||
|
|
||||||
|
const Layout = ({ children }) => {
|
||||||
|
const data = useStaticQuery(graphql`
|
||||||
|
query SiteTitleQuery {
|
||||||
|
site {
|
||||||
|
siteMetadata {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MainLayout>
|
||||||
|
<Header siteTitle={data.site.siteMetadata.title} />
|
||||||
|
<div style={{ position: 'relative' }}>
|
||||||
|
<AppIdeaBanner />
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
position: 'absolute',
|
||||||
|
height: '100%',
|
||||||
|
width: '100%',
|
||||||
|
top: '0',
|
||||||
|
left: '0',
|
||||||
|
background: 'rgba(0, 0, 0, 0.2)',
|
||||||
|
}}
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
<main>{children}</main>
|
||||||
|
<footer>
|
||||||
|
© {new Date().getFullYear()}, Built with
|
||||||
|
{` `}
|
||||||
|
<a href="https://www.gatsbyjs.org">Gatsby</a>
|
||||||
|
</footer>
|
||||||
|
</MainLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Layout.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Layout;
|
@ -0,0 +1,7 @@
|
|||||||
|
import styled from "styled-components"
|
||||||
|
|
||||||
|
export const MainLayout = styled.div`
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
`
|
@ -0,0 +1,11 @@
|
|||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* SEO component that queries for data with
|
||||||
|
* Gatsby's useStaticQuery React hook
|
||||||
|
*
|
||||||
|
* See: https://www.gatsbyjs.org/docs/use-static-query/
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import Helmet from "react-helmet"
|
||||||
|
import { useStaticQuery, graphql } from "gatsby"
|
||||||
|
|
||||||
|
function SEO({ description, lang, meta, title }) {
|
||||||
|
const { site } = useStaticQuery(
|
||||||
|
graphql`
|
||||||
|
query {
|
||||||
|
site {
|
||||||
|
siteMetadata {
|
||||||
|
title
|
||||||
|
description
|
||||||
|
author
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
const metaDescription = description || site.siteMetadata.description
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Helmet
|
||||||
|
htmlAttributes={{
|
||||||
|
lang,
|
||||||
|
}}
|
||||||
|
title={title}
|
||||||
|
titleTemplate={`%s | ${site.siteMetadata.title}`}
|
||||||
|
meta={[
|
||||||
|
{
|
||||||
|
name: `description`,
|
||||||
|
content: metaDescription,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: `og:title`,
|
||||||
|
content: title,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: `og:description`,
|
||||||
|
content: metaDescription,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: `og:type`,
|
||||||
|
content: `website`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `twitter:card`,
|
||||||
|
content: `summary`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `twitter:creator`,
|
||||||
|
content: site.siteMetadata.author,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `twitter:title`,
|
||||||
|
content: title,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `twitter:description`,
|
||||||
|
content: metaDescription,
|
||||||
|
},
|
||||||
|
].concat(meta)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
SEO.defaultProps = {
|
||||||
|
lang: `en`,
|
||||||
|
meta: [],
|
||||||
|
description: ``,
|
||||||
|
}
|
||||||
|
|
||||||
|
SEO.propTypes = {
|
||||||
|
description: PropTypes.string,
|
||||||
|
lang: PropTypes.string,
|
||||||
|
meta: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SEO
|
After Width: | Height: | Size: 149 KiB |
After Width: | Height: | Size: 163 KiB |
After Width: | Height: | Size: 21 KiB |
@ -0,0 +1,14 @@
|
|||||||
|
import React from "react"
|
||||||
|
|
||||||
|
import Layout from "../components/main-layout/layout.component"
|
||||||
|
import SEO from "../components/seo/seo.component"
|
||||||
|
|
||||||
|
const NotFoundPage = () => (
|
||||||
|
<Layout>
|
||||||
|
<SEO title="404: Not found" />
|
||||||
|
<h1>NOT FOUND</h1>
|
||||||
|
<p>You just hit a route that doesn't exist... the sadness.</p>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default NotFoundPage
|
@ -0,0 +1,38 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { graphql } from 'gatsby';
|
||||||
|
|
||||||
|
import Layout from '../components/main-layout/layout.component';
|
||||||
|
import SEO from '../components/seo/seo.component';
|
||||||
|
|
||||||
|
import IdeaList from '../components/idea-list/idea-list.component';
|
||||||
|
|
||||||
|
const AdvancedPage = ({ data }) => {
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<SEO title="Beginner Ideas" />
|
||||||
|
<IdeaList ideas={data.advancedIdeas.edges} />
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pageQuery = graphql`
|
||||||
|
query {
|
||||||
|
advancedIdeas: allMarkdownRemark(
|
||||||
|
sort: { fields: [frontmatter___title], order: ASC }
|
||||||
|
filter: { frontmatter: { tier: { eq: "advanced" } } }
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
excerpt
|
||||||
|
frontmatter {
|
||||||
|
path
|
||||||
|
title
|
||||||
|
tier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default AdvancedPage;
|
@ -0,0 +1,38 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { graphql } from 'gatsby';
|
||||||
|
|
||||||
|
import Layout from '../components/main-layout/layout.component';
|
||||||
|
import SEO from '../components/seo/seo.component';
|
||||||
|
|
||||||
|
import IdeaList from '../components/idea-list/idea-list.component';
|
||||||
|
|
||||||
|
const BeginnerPage = ({ data }) => {
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<SEO title="Beginner Ideas" />
|
||||||
|
<IdeaList ideas={data.beginnerIdeas.edges} />
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pageQuery = graphql`
|
||||||
|
query {
|
||||||
|
beginnerIdeas: allMarkdownRemark(
|
||||||
|
sort: { fields: [frontmatter___title], order: ASC }
|
||||||
|
filter: { frontmatter: { tier: { eq: "beginner" } } }
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
excerpt
|
||||||
|
frontmatter {
|
||||||
|
path
|
||||||
|
title
|
||||||
|
tier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default BeginnerPage;
|
@ -0,0 +1,35 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { graphql } from 'gatsby';
|
||||||
|
|
||||||
|
import Layout from '../components/main-layout/layout.component';
|
||||||
|
import SEO from '../components/seo/seo.component';
|
||||||
|
|
||||||
|
import IdeasList from '../components/idea-list/idea-list.component';
|
||||||
|
|
||||||
|
const IndexPage = ({ data }) => {
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<SEO title="Home" />
|
||||||
|
<IdeasList ideas={data.ideas.edges} />
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pageQuery = graphql`
|
||||||
|
query {
|
||||||
|
ideas: allMarkdownRemark {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
excerpt
|
||||||
|
frontmatter {
|
||||||
|
path
|
||||||
|
title
|
||||||
|
tier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default IndexPage;
|
@ -0,0 +1,38 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { graphql } from 'gatsby';
|
||||||
|
|
||||||
|
import Layout from '../components/main-layout/layout.component';
|
||||||
|
import SEO from '../components/seo/seo.component';
|
||||||
|
|
||||||
|
import IdeaList from '../components/idea-list/idea-list.component';
|
||||||
|
|
||||||
|
const IntermediatePage = ({ data }) => {
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<SEO title="Beginner Ideas" />
|
||||||
|
<IdeaList ideas={data.intermediateIdeas.edges} />
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pageQuery = graphql`
|
||||||
|
query {
|
||||||
|
intermediateIdeas: allMarkdownRemark(
|
||||||
|
sort: { fields: [frontmatter___title], order: ASC }
|
||||||
|
filter: { frontmatter: { tier: { eq: "intermediate" } } }
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
excerpt
|
||||||
|
frontmatter {
|
||||||
|
path
|
||||||
|
title
|
||||||
|
tier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default IntermediatePage;
|
@ -0,0 +1,36 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { graphql } from "gatsby"
|
||||||
|
|
||||||
|
import Layout from "../components/main-layout/layout.component"
|
||||||
|
|
||||||
|
export default function IdeaTemplate({
|
||||||
|
data, // this prop will be injected by the GraphQL query below.
|
||||||
|
}) {
|
||||||
|
const { markdownRemark } = data // data.markdownRemark holds your post data
|
||||||
|
const { frontmatter, html } = markdownRemark
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<div className="blog-post-container" style={{ margin: "1rem" }}>
|
||||||
|
<div className="blog-post">
|
||||||
|
{/* <h1>{frontmatter.title}</h1> */}
|
||||||
|
<div
|
||||||
|
className="blog-post-content"
|
||||||
|
dangerouslySetInnerHTML={{ __html: html }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export const pageQuery = graphql`
|
||||||
|
query($path: String!) {
|
||||||
|
markdownRemark(frontmatter: { path: { eq: $path } }) {
|
||||||
|
html
|
||||||
|
frontmatter {
|
||||||
|
path
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
Loading…
Reference in new issue