diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index fac3973..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - extends: ['airbnb', 'prettier', 'plugin:cypress/recommended'], - rules: { - 'react/jsx-filename-extension': 'off', - 'react/require-default-props': 'off', - }, - parser: 'babel-eslint', - env: { - browser: true, - node: true, - jest: true, - }, -}; diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..c8fd215 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,20 @@ +{ + "extends": ["airbnb", "prettier"], + "plugins": ["react", "jsx-a11y", "import"], + "rules": { + "react/prefer-stateless-function": "off", + "react/prop-types": "off", + "react/no-danger": "off", + "jsx-a11y/anchor-is-valid": [ "error", { + "components": [ "Link" ], + "specialLink": [ "hrefLeft", "hrefRight", "to" ], + "aspects": [ "noHref", "invalidHref", "preferButton" ] + }] + }, + "settings": { + "import/core-modules": [] + }, + "env": { + "browser": true + } +} diff --git a/.gitignore b/.gitignore index 3bb8dbc..d6952ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,8 @@ +### Node ### # Logs logs *.log npm-debug.log* -yarn-debug.log* -yarn-error.log* # Runtime data pids @@ -23,21 +22,15 @@ coverage # 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 (https://nodejs.org/api/addons.html) +# Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ +node_modules +jspm_packages # Optional npm cache directory .npm @@ -48,21 +41,22 @@ typings/ # Optional REPL history .node_repl_history +# Output of 'npm pack' +*.tgz + # Yarn Integrity file .yarn-integrity -# dotenv environment variables file -.env - -# next.js build output -.next - -.cache/ +# Build Files public/ +.cache/ + +# Gatsby context .gatsby-context.js -netlify.toml -# mac FS -.DS_Store -.vscode/ \ No newline at end of file +# Bundle stats +bundle-stats.json + +#etc +.env diff --git a/.huskyrc b/.huskyrc deleted file mode 100644 index 4d077c8..0000000 --- a/.huskyrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "hooks": { - "pre-commit": "lint-staged" - } -} diff --git a/.lintstagedrc b/.lintstagedrc deleted file mode 100644 index 44b3895..0000000 --- a/.lintstagedrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "*.{js,json,css,md}": ["prettier --write", "git add"] -} diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 6c4bda6..0000000 --- a/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -trailingComma: "all" -singleQuote: true -printWidth: 80 \ No newline at end of file diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 0000000..11b2e3e --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,6 @@ +{ + "extends": ["stylelint-config-standard", "stylelint-config-prettier"], + "rules": { + "indentation": 4 + } +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index caff6ef..1d690bc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,3 +17,15 @@ Do you want to write a blog post for us, but have no ideas? We have ideas for yo - How to use Slack - Resume tips - What do I need to know to get my first dev job? + +## To-Do's +- Configure SEO Component +- Configure Disqus Component +- Comfigure Social Media Components +- omg someone make this stupid thing pretty +- Add Cypress.io +- Do something with theme.ui +- Hero images for blog posts +- Component that pulls correct author info from Contentful +- Configure Google Analytics (or remove?) +- remove netlify modules \ No newline at end of file diff --git a/README.md b/README.md index cabbf2d..f3e139a 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,7 @@ -
-
- - Operation Code Hacktoberfest Banner - -
-
-
- -# 🎃 Hacktoberfest 🎃 - -[All the details you need](https://github.com/OperationCode/START_HERE/blob/master/README.md#-hacktoberfest-) before participating with us. - -
- # Operation Code Blog Hello! We are starting to collect blog posts for the Operation Code blog so we can build a backlog of content. We want to welcome all kinds of contributors, so if you have a blog post you would like to see on whatever blogging platform we use, read below. +Want to contribute? [Start Here!](https://github.com/OperationCode/START_HERE/blob/master/README.md) [Need Ideas?](https://github.com/OperationCode/blog/blob/master/CONTRIBUTING.md#available-topics) ## How To Contribute diff --git a/bin/contentful-config.json b/bin/contentful-config.json deleted file mode 100644 index d744d96..0000000 --- a/bin/contentful-config.json +++ /dev/null @@ -1,1548 +0,0 @@ -{ - "contentTypes": [ - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "project", - "type": "ContentType", - "createdAt": "2018-09-07T23:18:52.188Z", - "updatedAt": "2018-09-07T23:18:56.446Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 1, - "version": 2, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 1, - "firstPublishedAt": "2018-09-07T23:18:56.446Z", - "publishedAt": "2018-09-07T23:18:56.446Z" - }, - "displayField": "name", - "name": "Project", - "description": "Project description", - "fields": [ - { - "id": "name", - "name": "Name", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "publishedDate", - "name": "PublishedDate", - "type": "Date", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "logo", - "name": "Logo", - "type": "Link", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false, - "linkType": "Asset" - }, - { - "id": "repositoryUrl", - "name": "RepositoryUrl", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "description", - "name": "Description", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "projectUrl", - "name": "ProjectUrl", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "type", - "name": "Type", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - } - ] - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "about", - "type": "ContentType", - "createdAt": "2018-09-07T23:18:52.234Z", - "updatedAt": "2018-09-17T12:05:25.813Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 5, - "version": 10, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 9, - "firstPublishedAt": "2018-09-07T23:18:58.249Z", - "publishedAt": "2018-09-17T12:05:25.813Z" - }, - "displayField": "name", - "name": "About", - "description": "All information related to personal data.", - "fields": [ - { - "id": "name", - "name": "Name", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "description", - "name": "Description", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "roles", - "name": "Roles", - "type": "Array", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false, - "items": { - "type": "Symbol", - "validations": [] - } - }, - { - "id": "socialLinks", - "name": "Social Links", - "type": "Array", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false, - "items": { - "type": "Link", - "validations": [ - { - "linkContentType": ["socialLink"] - } - ], - "linkType": "Entry" - } - }, - { - "id": "profile", - "name": "Profile", - "type": "Link", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false, - "linkType": "Asset" - }, - { - "id": "aboutMe", - "name": "About me", - "type": "Text", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "projects", - "name": "Projects", - "type": "Array", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false, - "items": { - "type": "Link", - "validations": [ - { - "linkContentType": ["project"] - } - ], - "linkType": "Entry" - } - } - ] - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "socialLink", - "type": "ContentType", - "createdAt": "2018-09-07T23:18:52.248Z", - "updatedAt": "2018-09-17T12:03:26.939Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 2, - "version": 4, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 3, - "firstPublishedAt": "2018-09-07T23:18:57.463Z", - "publishedAt": "2018-09-17T12:03:26.939Z" - }, - "displayField": "name", - "name": "Social Link", - "description": "Social Link to display with a font awesome icon.", - "fields": [ - { - "id": "name", - "name": "Name", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "url", - "name": "URL", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - }, - { - "id": "fontAwesomeIcon", - "name": "Font Awesome Icon", - "type": "Symbol", - "localized": false, - "required": false, - "validations": [], - "disabled": false, - "omitted": false - } - ] - } - ], - "editorInterfaces": [ - { - "sys": { - "id": "default", - "type": "EditorInterface", - "space": { - "sys": { - "id": "ntiequ7mc6q6", - "type": "Link", - "linkType": "Space" - } - }, - "version": 2, - "createdAt": "2018-09-07T23:18:56.627Z", - "createdBy": { - "sys": { - "id": "2XGcyQ3vKgm55htxMAIqsM", - "type": "Link", - "linkType": "User" - } - }, - "updatedAt": "2018-09-07T23:19:00.619Z", - "updatedBy": { - "sys": { - "id": "2XGcyQ3vKgm55htxMAIqsM", - "type": "Link", - "linkType": "User" - } - }, - "contentType": { - "sys": { - "id": "project", - "type": "Link", - "linkType": "ContentType" - } - }, - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - } - }, - "controls": [ - { - "fieldId": "name", - "widgetId": "singleLine" - }, - { - "fieldId": "publishedDate", - "widgetId": "datePicker" - }, - { - "fieldId": "logo", - "widgetId": "assetLinkEditor" - }, - { - "fieldId": "repositoryUrl", - "widgetId": "singleLine" - }, - { - "fieldId": "description", - "widgetId": "singleLine" - }, - { - "fieldId": "projectUrl", - "widgetId": "singleLine" - }, - { - "fieldId": "type", - "widgetId": "singleLine" - } - ] - }, - { - "sys": { - "id": "default", - "type": "EditorInterface", - "space": { - "sys": { - "id": "ntiequ7mc6q6", - "type": "Link", - "linkType": "Space" - } - }, - "version": 10, - "createdAt": "2018-09-07T23:18:58.429Z", - "createdBy": { - "sys": { - "id": "2XGcyQ3vKgm55htxMAIqsM", - "type": "Link", - "linkType": "User" - } - }, - "updatedAt": "2018-09-17T12:05:26.511Z", - "updatedBy": { - "sys": { - "id": "2XGcyQ3vKgm55htxMAIqsM", - "type": "Link", - "linkType": "User" - } - }, - "contentType": { - "sys": { - "id": "about", - "type": "Link", - "linkType": "ContentType" - } - }, - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - } - }, - "controls": [ - { - "fieldId": "name", - "widgetId": "singleLine" - }, - { - "fieldId": "description", - "widgetId": "singleLine" - }, - { - "fieldId": "roles", - "widgetId": "tagEditor" - }, - { - "fieldId": "socialLinks", - "settings": { - "bulkEditing": false - }, - "widgetId": "entryLinksEditor" - }, - { - "fieldId": "profile", - "widgetId": "assetLinkEditor" - }, - { - "fieldId": "aboutMe", - "widgetId": "markdown" - }, - { - "fieldId": "projects", - "settings": { - "bulkEditing": false - }, - "widgetId": "entryLinksEditor" - } - ] - }, - { - "sys": { - "id": "default", - "type": "EditorInterface", - "space": { - "sys": { - "id": "ntiequ7mc6q6", - "type": "Link", - "linkType": "Space" - } - }, - "version": 4, - "createdAt": "2018-09-07T23:18:57.615Z", - "createdBy": { - "sys": { - "id": "2XGcyQ3vKgm55htxMAIqsM", - "type": "Link", - "linkType": "User" - } - }, - "updatedAt": "2018-09-17T12:03:27.550Z", - "updatedBy": { - "sys": { - "id": "2XGcyQ3vKgm55htxMAIqsM", - "type": "Link", - "linkType": "User" - } - }, - "contentType": { - "sys": { - "id": "socialLink", - "type": "Link", - "linkType": "ContentType" - } - }, - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - } - }, - "controls": [ - { - "fieldId": "name", - "widgetId": "singleLine" - }, - { - "fieldId": "url", - "widgetId": "singleLine" - }, - { - "fieldId": "fontAwesomeIcon", - "widgetId": "singleLine" - } - ] - } - ], - "entries": [ - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "5lzMxuCX84uYqmgGmU8iKU", - "type": "Entry", - "createdAt": "2018-09-08T08:08:42.747Z", - "updatedAt": "2018-09-17T12:09:24.193Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 12, - "version": 1186, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 1185, - "firstPublishedAt": "2018-09-08T08:18:29.722Z", - "publishedAt": "2018-09-17T12:09:24.193Z", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "about" - } - } - }, - "fields": { - "name": { - "en-US": "Mate" - }, - "description": { - "en-US": "Gatsby v2 starter to create a top notch portfolio!" - }, - "roles": { - "en-US": [ - "Quick setup 🚀", - "Responsive 📱", - "PWA ✨", - "Contentful CMS 🔧" - ] - }, - "socialLinks": { - "en-US": [ - { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "4SrlLN9bt6Yew2UyGgM06a" - } - }, - { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "3DpgtG8qI8QCWyEAuME4Ku" - } - }, - { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "114ApRkJZq640w8G2GwM8w" - } - }, - { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "4J6WFTjoMUCmQKuKAaOsqE" - } - } - ] - }, - "profile": { - "en-US": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "6nf3rNaaVaUqYcoAcciSeC" - } - } - }, - "aboutMe": { - "en-US": "Hello 👋 I'm Mate a gatsby starter which is focus on simplicity and extensibility. It's build with Gatsby(duh), [Rebass](https://jxnblk.com/rebass/) (styled-component system) and [Contentful](https://www.contentful.com/).\n\nThe starter will give you 4 sections (it's really easy to add more if you want 😃):\n* [Landing:](#home) Displays a nice greeting with your name, also your roles (what you are) and all your social links.\n* [About:](#about) Show the about section where you can write about who you are, what you like to do, etc. Also you can add a photo next to it!\n* [Project:](#projects) Displays a card for all your project that you've made and also the posibility to link with github or and external link." - }, - "projects": { - "en-US": [ - { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "6Y7EIx73nUCWuoIWcsuM00" - } - }, - { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "2GKNR2f4z6IwAg6a2MmKCc" - } - }, - { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "5paxSRHbAkmgMc4WSW8S66" - } - } - ] - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "4SrlLN9bt6Yew2UyGgM06a", - "type": "Entry", - "createdAt": "2018-09-08T08:10:31.702Z", - "updatedAt": "2018-09-08T08:10:51.574Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 1, - "version": 10, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 9, - "firstPublishedAt": "2018-09-08T08:10:51.574Z", - "publishedAt": "2018-09-08T08:10:51.574Z", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "socialLink" - } - } - }, - "fields": { - "name": { - "en-US": "Github" - }, - "url": { - "en-US": "https://github.com/EmaSuriano/gatsby-starter-mate/blob/master/README.md" - }, - "fontAwesomeIcon": { - "en-US": "github" - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "5paxSRHbAkmgMc4WSW8S66", - "type": "Entry", - "createdAt": "2018-09-08T08:25:47.955Z", - "updatedAt": "2018-09-08T09:40:56.658Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 2, - "version": 51, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 50, - "firstPublishedAt": "2018-09-08T08:38:15.314Z", - "publishedAt": "2018-09-08T09:40:56.657Z", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "project" - } - } - }, - "fields": { - "name": { - "en-US": "Google" - }, - "publishedDate": { - "en-US": "1998-06-19T00:00+02:00" - }, - "logo": { - "en-US": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "3AorRmtWOsGQ4o8gK0YWKG" - } - } - }, - "repositoryUrl": { - "en-US": "https://github.com/google" - }, - "description": { - "en-US": "It is the most-used search engine on the World Wide Web, handling more than three billion searches each day." - }, - "projectUrl": { - "en-US": "https://www.google.com/" - }, - "type": { - "en-US": "Web" - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "2GKNR2f4z6IwAg6a2MmKCc", - "type": "Entry", - "createdAt": "2018-09-08T09:31:01.989Z", - "updatedAt": "2018-09-08T09:43:24.088Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 2, - "version": 32, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 31, - "firstPublishedAt": "2018-09-08T09:34:11.498Z", - "publishedAt": "2018-09-08T09:43:24.088Z", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "project" - } - } - }, - "fields": { - "name": { - "en-US": "Gatsby JS" - }, - "publishedDate": { - "en-US": "2016-09-01T00:00+02:00" - }, - "logo": { - "en-US": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "6rkOXCpyvuekYIgy6U6gGu" - } - } - }, - "repositoryUrl": { - "en-US": "https://github.com/gatsbyjs/gatsby" - }, - "description": { - "en-US": " Gatsby is a React-based, GraphQL powered, static site generator. Overall think, part Jekyll, part create-react-app." - }, - "projectUrl": { - "en-US": "https://www.gatsbyjs.org/" - }, - "type": { - "en-US": "Framework" - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "6Y7EIx73nUCWuoIWcsuM00", - "type": "Entry", - "createdAt": "2018-09-08T09:34:51.064Z", - "updatedAt": "2018-09-08T09:38:14.627Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 4, - "version": 20, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 19, - "firstPublishedAt": "2018-09-08T09:35:59.528Z", - "publishedAt": "2018-09-08T09:38:14.627Z", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "project" - } - } - }, - "fields": { - "name": { - "en-US": "Facebook" - }, - "publishedDate": { - "en-US": "2004-09-01T00:00+02:00" - }, - "logo": { - "en-US": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "u3Um4zkMrAaQioyq4oSIW" - } - } - }, - "repositoryUrl": { - "en-US": "https://github.com/facebook" - }, - "description": { - "en-US": "Facebook is a popular free social networking website that allows registered users to keep in touch with friends." - }, - "projectUrl": { - "en-US": "http://facebook.com/" - }, - "type": { - "en-US": "Web" - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "3DpgtG8qI8QCWyEAuME4Ku", - "type": "Entry", - "createdAt": "2018-09-17T12:07:45.316Z", - "updatedAt": "2018-09-17T12:08:02.358Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 1, - "version": 14, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 13, - "firstPublishedAt": "2018-09-17T12:08:02.358Z", - "publishedAt": "2018-09-17T12:08:02.358Z", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "socialLink" - } - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "114ApRkJZq640w8G2GwM8w", - "type": "Entry", - "createdAt": "2018-09-17T12:08:27.655Z", - "updatedAt": "2018-09-17T12:08:43.183Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 1, - "version": 5, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 4, - "firstPublishedAt": "2018-09-17T12:08:43.183Z", - "publishedAt": "2018-09-17T12:08:43.183Z", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "socialLink" - } - } - }, - "fields": { - "name": { - "en-US": "Contact me" - }, - "url": { - "en-US": "https://emanuelsuriano.typeform.com/to/OeETl6" - }, - "fontAwesomeIcon": { - "en-US": "envelope" - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "4J6WFTjoMUCmQKuKAaOsqE", - "type": "Entry", - "createdAt": "2018-09-17T12:08:48.454Z", - "updatedAt": "2018-09-17T12:08:57.490Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 1, - "version": 5, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 4, - "firstPublishedAt": "2018-09-17T12:08:57.490Z", - "publishedAt": "2018-09-17T12:08:57.490Z", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "socialLink" - } - } - }, - "fields": { - "name": { - "en-US": "Twitter" - }, - "url": { - "en-US": "https://twitter.com/emasuriano" - }, - "fontAwesomeIcon": { - "en-US": "twitter" - } - } - } - ], - "assets": [ - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "3AorRmtWOsGQ4o8gK0YWKG", - "type": "Asset", - "createdAt": "2018-09-08T08:26:24.437Z", - "updatedAt": "2018-09-23T09:26:16.789Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 2, - "version": 27, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 26, - "firstPublishedAt": "2018-09-08T08:29:51.622Z", - "publishedAt": "2018-09-23T09:26:16.789Z" - }, - "fields": { - "title": { - "en-US": "Google Logo" - }, - "description": { - "en-US": "Logo from Google" - }, - "file": { - "en-US": { - "url": "//images.ctfassets.net/ntiequ7mc6q6/3AorRmtWOsGQ4o8gK0YWKG/bafdc9f6551a2b487fe0126158630b27/google_PNG19630.png", - "details": { - "size": 39228, - "image": { - "width": 1000, - "height": 1000 - } - }, - "fileName": "google_PNG19630.png", - "contentType": "image/png" - } - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "6rkOXCpyvuekYIgy6U6gGu", - "type": "Asset", - "createdAt": "2018-09-08T09:32:36.676Z", - "updatedAt": "2018-09-08T09:33:34.682Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 1, - "version": 15, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 14, - "firstPublishedAt": "2018-09-08T09:33:34.682Z", - "publishedAt": "2018-09-08T09:33:34.682Z" - }, - "fields": { - "title": { - "en-US": "Gatsby logo" - }, - "description": { - "en-US": "Gatsby logo" - }, - "file": { - "en-US": { - "url": "//images.ctfassets.net/ntiequ7mc6q6/6rkOXCpyvuekYIgy6U6gGu/9369860d91a93b58c949fedfc8967703/1_t5EnAu3eSWJA0rmZ9v3xuw.png", - "details": { - "size": 111702, - "image": { - "width": 1600, - "height": 1600 - } - }, - "fileName": "1*t5EnAu3eSWJA0rmZ9v3xuw.png", - "contentType": "image/png" - } - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "u3Um4zkMrAaQioyq4oSIW", - "type": "Asset", - "createdAt": "2018-09-08T09:36:25.346Z", - "updatedAt": "2018-09-08T09:36:43.100Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 1, - "version": 14, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 13, - "firstPublishedAt": "2018-09-08T09:36:43.100Z", - "publishedAt": "2018-09-08T09:36:43.100Z" - }, - "fields": { - "title": { - "en-US": "Facebook logo" - }, - "description": { - "en-US": "Facebook logo" - }, - "file": { - "en-US": { - "url": "//images.ctfassets.net/ntiequ7mc6q6/u3Um4zkMrAaQioyq4oSIW/876e172d31bbc05ab2599e77188ea545/600px-Facebook_logo__28square_29.png", - "details": { - "size": 13209, - "image": { - "width": 600, - "height": 600 - } - }, - "fileName": "600px-Facebook_logo_%28square%29.png", - "contentType": "image/png" - } - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "id": "6nf3rNaaVaUqYcoAcciSeC", - "type": "Asset", - "createdAt": "2018-09-09T20:57:29.181Z", - "updatedAt": "2018-09-09T20:57:42.989Z", - "environment": { - "sys": { - "id": "master", - "type": "Link", - "linkType": "Environment" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedCounter": 1, - "version": 11, - "publishedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "publishedVersion": 10, - "firstPublishedAt": "2018-09-09T20:57:42.989Z", - "publishedAt": "2018-09-09T20:57:42.989Z" - }, - "fields": { - "title": { - "en-US": "Mate Logo" - }, - "description": { - "en-US": "Mate Logo" - }, - "file": { - "en-US": { - "url": "//images.ctfassets.net/ntiequ7mc6q6/6nf3rNaaVaUqYcoAcciSeC/4433ecac61b8aa767edd9e11739bb30a/Mate_Logo.png", - "details": { - "size": 52527, - "image": { - "width": 946, - "height": 948 - } - }, - "fileName": "Mate Logo.png", - "contentType": "image/png" - } - } - } - } - ], - "locales": [ - { - "name": "English (United States)", - "code": "en-US", - "fallbackCode": null, - "default": true, - "contentManagementApi": true, - "contentDeliveryApi": true, - "optional": false, - "sys": { - "type": "Locale", - "id": "0pUiiR5cRgkeh1qLZ5imRa", - "version": 1, - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "ntiequ7mc6q6" - } - }, - "environment": { - "sys": { - "type": "Link", - "linkType": "Environment", - "id": "master" - } - }, - "createdBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "createdAt": "2018-09-07T23:17:03Z", - "updatedBy": { - "sys": { - "type": "Link", - "linkType": "User", - "id": "2XGcyQ3vKgm55htxMAIqsM" - } - }, - "updatedAt": "2018-09-07T23:17:03Z" - } - } - ], - "webhooks": [], - "roles": [] -} diff --git a/bin/setup.js b/bin/setup.js deleted file mode 100644 index e520287..0000000 --- a/bin/setup.js +++ /dev/null @@ -1,72 +0,0 @@ -const spaceImport = require('contentful-import'); -const inquirer = require('inquirer'); -const chalk = require('chalk'); -const path = require('path'); -const { writeFileSync } = require('fs'); -const envfile = require('envfile'); - -const exportFile = require('./contentful-config.json'); - -console.log(` - To set up this project you need to provide your Space ID - and the belonging API access tokens. - You can find all the needed information in your Contentful space under: - ${chalk.yellow( - `app.contentful.com ${chalk.red('->')} Space Settings ${chalk.red( - '->', - )} API keys`, - )} - The ${chalk.green('Content Management API Token')} - will be used to import and write data to your space. - The ${chalk.green('Content Delivery API Token')} - will be used to ship published production-ready content in your Gatsby app. - The ${chalk.green('Content Preview API Token')} - will be used to show not published data in your development environment. - Ready? Let's do it! 🎉 -`); - -const questions = [ - { - name: 'spaceId', - message: 'Your Space ID', - validate: input => - /^[a-z0-9]{12}$/.test(input) || - 'Space ID must be 12 lowercase characters', - }, - { - name: 'deliveryToken', - message: 'Your Content Delivery API access token', - }, - { - name: 'managementToken', - message: 'Your Content Management API access token', - }, -]; - -inquirer - .prompt(questions) - .then(({ spaceId, deliveryToken, managementToken }) => { - console.log('Writing config file...'); - - const configFilePath = path.resolve(__dirname, '..', '.env'); - const envData = envfile.stringifySync({ - SPACE_ID: spaceId, - ACCESS_TOKEN: deliveryToken, - }); - - writeFileSync(configFilePath, envData); - console.log(`Config file ${chalk.yellow(configFilePath)} written`); - - return { spaceId, managementToken }; - }) - .then(({ spaceId, managementToken }) => - spaceImport({ spaceId, managementToken, content: exportFile }), - ) - .then(() => { - console.log( - `All set! You can now run ${chalk.yellow( - 'yarn develop', - )} to see it in action.`, - ); - }) - .catch(error => console.error(error)); diff --git a/colors.js b/colors.js deleted file mode 100644 index 7a84fd9..0000000 --- a/colors.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - background: '#F7F7F7', - backgroundDark: '#E2E2E2', - - primary: '#3ED6F0', - primaryLight: '#71A2B6', - primaryDark: '#7C8483', - - secondary: '#252E3E', - secondaryLight: '#C2D3CD', - secondaryDark: '#252E3E', -}; diff --git a/data/SiteConfig.js b/data/SiteConfig.js new file mode 100644 index 0000000..1b1cb5b --- /dev/null +++ b/data/SiteConfig.js @@ -0,0 +1,65 @@ +const config = { + siteTitle: "Operation Code Blog", // Site title. + siteTitleShort: "OC Blog", // Short site title for homescreen (PWA). Preferably should be under 12 characters to prevent truncation. + siteTitleAlt: "Operationcode.org Blog", // Alternative site title for SEO. + siteLogo: "/logos/logo-1024.png", // Logo used for SEO and manifest. + siteUrl: "http://www.operationcode.org", // Domain of your website without pathPrefix. + pathPrefix: "/", // Prefixes all links. For cases when deployed to example.github.io/gatsby-advanced-starter/. + siteDescription: "Operation Code's Blog.", // Website description used for RSS feeds/meta description tag. + siteRss: "/rss.xml", // Path to the RSS file. + siteFBAppID: "1825356251115265", // FB Application ID for using app insights + googleAnalyticsID: "UA-47311644-5", // GA tracking ID. + disqusShortname: "https-vagr9k-github-io-gatsby-advanced-starter", // Disqus shortname. + postDefaultCategoryID: "Tech", // Default category for posts. + dateFromFormat: "YYYY-MM-DD", // Date format used in the frontmatter. + dateFormat: "MMMM Do, YYYY", // Date format for display. + postsPerPage: 5, // Amount of posts displayed per listing page. + userName: "OC Admin", // Username to display in the author segment. + userEmail: "staff@operationcode.org", // Email used for RSS feed's author segment + userTwitter: "", // Optionally renders "Follow Me" in the UserInfo segment. + userLocation: "Located Worldwide!", // User location to display in the author segment. + userAvatar: "https://api.adorable.io/avatars/150/test.png", // User avatar to display in the author segment. + userDescription: + "Yeah, I like animals better than people sometimes... Especially dogs. Dogs are the best. Every time you come home, they act like they haven't seen you in a year. And the good thing about dogs... is they got different dogs for different people.", // User description to display in the author segment. + // Links to social profiles/projects you want to display in the author segment/navigation bar. + userLinks: [ + { + label: "GitHub", + url: "https://github.com/operationcode", + iconClassName: "fa fa-github" + }, + { + label: "Twitter", + url: "https://twitter.com/operation_code", + iconClassName: "fa fa-twitter" + }, + { + label: "Email", + url: "staff@operationcode.org", + iconClassName: "fa fa-envelope" + } + ], + copyright: "Copyright © 2020. Operation Code", // Copyright string for the footer of the website and RSS feed. + themeColor: "#c62828", // Used for setting manifest and progress theme colors. + backgroundColor: "#e0e0e0" // Used for setting manifest background color. +}; + +// Validate + +// Make sure pathPrefix is empty if not needed +if (config.pathPrefix === "/") { + config.pathPrefix = ""; +} else { + // Make sure pathPrefix only contains the first forward slash + config.pathPrefix = `/${config.pathPrefix.replace(/^\/|\/$/g, "")}`; +} + +// Make sure siteUrl doesn't have an ending forward slash +if (config.siteUrl.substr(-1) === "/") + config.siteUrl = config.siteUrl.slice(0, -1); + +// Make sure siteRss has a starting forward slash +if (config.siteRss && config.siteRss[0] !== "/") + config.siteRss = `/${config.siteRss}`; + +module.exports = config; diff --git a/gatsby-config.js b/gatsby-config.js index 2da27e7..d835d7d 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -1,54 +1,114 @@ -const contentful = require('contentful'); -const manifestConfig = require('./manifest-config'); -require('dotenv').config(); +const urljoin = require("url-join"); +const path = require("path"); +const dotenv = require('dotenv'); +const config = require("./data/SiteConfig"); -const { ACCESS_TOKEN, SPACE_ID, ANALYTICS_ID, DETERMINISTIC } = process.env; -const client = contentful.createClient({ - space: SPACE_ID, - accessToken: ACCESS_TOKEN, -}); +dotenv.config({ + path: `.env.${process.env.CONTENTFUL_ACCESS_TOKEN}`, +}) -const plugins = [ - 'gatsby-plugin-react-helmet', - { - resolve: 'gatsby-plugin-web-font-loader', - options: { - google: { - families: ['Cabin', 'Open Sans'], +module.exports = { + pathPrefix: config.pathPrefix === "" ? "/" : config.pathPrefix, + siteMetadata: { + siteUrl: urljoin(config.siteUrl, config.pathPrefix), + rssMetadata: { + site_url: urljoin(config.siteUrl, config.pathPrefix), + feed_url: urljoin(config.siteUrl, config.pathPrefix, config.siteRss), + title: config.siteTitle, + description: config.siteDescription, + image_url: `${urljoin( + config.siteUrl, + config.pathPrefix + )}/logos/logo-512.png`, + copyright: config.copyright + } + }, + plugins: [ + "gatsby-plugin-react-helmet", + "gatsby-plugin-lodash", + { + resolve: "gatsby-source-filesystem", + options: { + name: "assets", + path: `${__dirname}/static/` + } + }, + { + resolve: `gatsby-source-contentful`, + options: { + spaceId: `oinav3dadfu6`, + accessToken: `Rj4njwVCTk6zozoDiAm2-rr1uedDicBOuwC3HsX-Ymk`, }, }, - }, - { - resolve: 'gatsby-plugin-manifest', - options: manifestConfig, - }, - 'gatsby-plugin-styled-components', - { - resolve: 'gatsby-source-contentful', - options: { - spaceId: SPACE_ID, - accessToken: ACCESS_TOKEN, + { + resolve: "gatsby-transformer-remark", + options: { + plugins: [ + { + resolve: "gatsby-remark-images", + options: { + maxWidth: 690 + } + }, + { + resolve: "gatsby-remark-responsive-iframe" + }, + "gatsby-remark-copy-linked-files", + "gatsby-remark-autolink-headers", + "gatsby-remark-prismjs" + ] + } }, - }, - 'gatsby-transformer-remark', - 'gatsby-plugin-offline', -]; - -module.exports = client.getEntries().then(() => { - if (ANALYTICS_ID) { - plugins.push({ - resolve: 'gatsby-plugin-google-analytics', + { + resolve: `gatsby-plugin-emotion`, options: { - trackingId: ANALYTICS_ID, + // Accepts all options defined by `babel-plugin-emotion` plugin. }, - }); - } - - return { - siteMetadata: { - deterministicBehaviour: !!DETERMINISTIC, }, - plugins, - }; -}); + { + resolve: "gatsby-plugin-google-analytics", + options: { + trackingId: config.googleAnalyticsID + } + }, + { + resolve: "gatsby-plugin-nprogress", + options: { + color: config.themeColor + } + }, + 'gatsby-plugin-theme-ui', + 'gatsby-plugin-sass', + "gatsby-plugin-sharp", + "gatsby-transformer-sharp", + "gatsby-plugin-catch-links", + "gatsby-plugin-twitter", + "gatsby-plugin-sitemap", + { + resolve: "gatsby-plugin-manifest", + options: { + name: config.siteTitle, + short_name: config.siteTitleShort, + description: config.siteDescription, + start_url: config.pathPrefix, + background_color: config.backgroundColor, + theme_color: config.themeColor, + display: "minimal-ui", + icons: [ + { + src: "/logos/logo-192.png", + sizes: "192x192", + type: "image/png" + }, + { + src: "/logos/logo-512.png", + sizes: "512x512", + type: "image/png" + } + ] + } + }, + "gatsby-plugin-offline", + ] +}; diff --git a/gatsby-node.js b/gatsby-node.js new file mode 100644 index 0000000..7c89720 --- /dev/null +++ b/gatsby-node.js @@ -0,0 +1,140 @@ +/* eslint "no-console": "off" */ + +const path = require("path"); +const _ = require("lodash"); +const moment = require("moment"); +const siteConfig = require("./data/SiteConfig"); + +exports.createPages = async ({ graphql, actions }) => { + const { createPage } = actions; + const postPage = path.resolve("src/templates/post.jsx"); + const tagPage = path.resolve("src/templates/tag.jsx"); + const categoryPage = path.resolve("src/templates/category.jsx"); + const listingPage = path.resolve("./src/templates/listing.jsx"); + + // Get a full list of markdown posts + const blogQueryResult = await graphql(` + { + allContentfulBlogPost { + edges { + node { + author { + name + github + email + } + publishDate(formatString: "MMMM Do, YYYY") + slug + description { + description + } + tags + title + category + body { + childMarkdownRemark { + timeToRead + } + } + } + } + } + } + `); + + if (blogQueryResult.errors) { + console.error(blogQueryResult.errors); + throw blogQueryResult.errors; + } + + const tagSet = new Set(); + const categorySet = new Set(); + + const postsEdges = blogQueryResult.data.allContentfulBlogPost.edges; + + // Sort posts + postsEdges.sort((postA, postB) => { + const dateA = moment( + postA.node.publishDate, + siteConfig.dateFromFormat + ); + + const dateB = moment( + postB.node.publishDate, + siteConfig.dateFromFormat + ); + + if (dateA.isBefore(dateB)) return 1; + if (dateB.isBefore(dateA)) return -1; + + return 0; + }); + + // Paging + const { postsPerPage } = siteConfig; + const pageCount = Math.ceil(postsEdges.length / postsPerPage); + + [...Array(pageCount)].forEach((_val, pageNum) => { + createPage({ + path: pageNum === 0 ? `/` : `/${pageNum + 1}/`, + component: listingPage, + context: { + limit: postsPerPage, + skip: pageNum * postsPerPage, + pageCount, + currentPageNum: pageNum + 1 + } + }); + }); + + // Post page creating + postsEdges.forEach((edge, index) => { + // Generate a list of tags + if (edge.node.tags) { + edge.node.tags.forEach(tag => { + tagSet.add(tag); + }); + } + + // Generate a list of categories + if (edge.node.category) { + categorySet.add(edge.node.category); + } + + // Create post pages + const nextID = index + 1 < postsEdges.length ? index + 1 : 0; + const prevID = index - 1 >= 0 ? index - 1 : postsEdges.length - 1; + const nextEdge = postsEdges[nextID]; + const prevEdge = postsEdges[prevID]; + + createPage({ + path: edge.node.slug, + component: postPage, + context: { + slug: edge.node.slug, + nexttitle: nextEdge.node.title, + nextslug: nextEdge.node.slug, + prevtitle: prevEdge.node.title, + prevslug: prevEdge.node.slug + } + }); + }); + + // Create tag pages + tagSet.forEach(tag => { + createPage({ + path: `/tags/${_.kebabCase(tag)}/`, + component: tagPage, + context: { tag } + }); + }); + + // Create category pages + categorySet.forEach(category => { + createPage({ + path: `/categories/${_.kebabCase(category)}/`, + component: categoryPage, + context: { category } + }); + }); +}; diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..d517475 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES6", + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "baseUrl": "src", + "jsx": "react", + "paths": { + "*": ["*", "src/*"] + } + }, + "typeAcquisition": { + "enable": true + }, + "typingOptions": { + "enableAutoDiscovery": true + }, + "compileOnSave": true, + "allowJS": true, + "include": [ + "src/**/*" + ] +} diff --git a/manifest-config.js b/manifest-config.js deleted file mode 100644 index 440f424..0000000 --- a/manifest-config.js +++ /dev/null @@ -1,11 +0,0 @@ -const colors = require('./colors'); - -module.exports = { - name: 'Mate Gatsby Starter', - short_name: 'Mate Gatsby Starter', - start_url: '/', - background_color: colors.background, - theme_color: colors.primary, - display: 'minimal-ui', - icon: 'media/icon.png', -}; diff --git a/media/404.png b/media/404.png deleted file mode 100644 index 16106d0..0000000 Binary files a/media/404.png and /dev/null differ diff --git a/media/about.png b/media/about.png deleted file mode 100644 index ff8b1a6..0000000 Binary files a/media/about.png and /dev/null differ diff --git a/media/contentful-about-change.png b/media/contentful-about-change.png deleted file mode 100644 index 554f68f..0000000 Binary files a/media/contentful-about-change.png and /dev/null differ diff --git a/media/gatsby-starter-mate-logo.png b/media/gatsby-starter-mate-logo.png deleted file mode 100644 index b7f7925..0000000 Binary files a/media/gatsby-starter-mate-logo.png and /dev/null differ diff --git a/media/home.png b/media/home.png deleted file mode 100644 index 454fe76..0000000 Binary files a/media/home.png and /dev/null differ diff --git a/media/icon.png b/media/icon.png deleted file mode 100644 index c12897d..0000000 Binary files a/media/icon.png and /dev/null differ diff --git a/media/lighthouse-score.png b/media/lighthouse-score.png deleted file mode 100644 index 20616d0..0000000 Binary files a/media/lighthouse-score.png and /dev/null differ diff --git a/media/projects.png b/media/projects.png deleted file mode 100644 index 9d4d74e..0000000 Binary files a/media/projects.png and /dev/null differ diff --git a/media/writing.png b/media/writing.png deleted file mode 100644 index 90c5c58..0000000 Binary files a/media/writing.png and /dev/null differ diff --git a/package.json b/package.json index 794a649..199204f 100644 --- a/package.json +++ b/package.json @@ -1,83 +1,95 @@ { - "name": "gatsby-starter-mate", - "version": "2.5.1", - "description": "Gatsby v2 starter to create a top notch portfolio!", - "main": "index.js", - "scripts": { - "build": "gatsby clean && gatsby build", - "dev": "yarn develop", - "develop": "gatsby clean && GATSBY_GRAPHQL_IDE=playground gatsby develop", - "start": "npm run develop", - "serve": "npm run build && gatsby serve -p 9000", - "lint": "eslint ./src", - "setup": "node ./bin/setup.js", - "e2e:open": "cypress open", - "e2e:ci": "DETERMINISTIC=true start-server-and-test serve http://localhost:9000 'percy exec -- cypress run'" + "name": "gatsby-starter-advanced", + "description": "GatsbyJS starter that includes examples for advanced use cases.", + "version": "1.1.0", + "author": "Ruben Harutyunyan ", + "dependencies": { + "@emotion/core": "^10.0.22", + "@emotion/styled": "^10.0.22", + "@mdx-js/react": "^1.5.1", + "dotenv": "^8.2.0", + "gatsby": "^2.15.28", + "gatsby-cli": "^2.8.22", + "gatsby-image": "^2.2.23", + "gatsby-plugin-catch-links": "^2.1.12", + "gatsby-plugin-emotion": "^4.1.12", + "gatsby-plugin-env-variables": "^1.0.1", + "gatsby-plugin-feed": "^2.3.15", + "gatsby-plugin-google-analytics": "^2.1.19", + "gatsby-plugin-lodash": "^3.1.10", + "gatsby-plugin-manifest": "^2.2.20", + "gatsby-plugin-netlify-cms": "^4.1.22", + "gatsby-plugin-nprogress": "^2.1.9", + "gatsby-plugin-offline": "^3.0.11", + "gatsby-plugin-react-helmet": "^3.1.10", + "gatsby-plugin-sass": "^2.1.26", + "gatsby-plugin-sharp": "^2.2.27", + "gatsby-plugin-sitemap": "^2.2.16", + "gatsby-plugin-theme-ui": "^0.2.43", + "gatsby-plugin-twitter": "^2.1.9", + "gatsby-remark-autolink-headers": "^2.1.13", + "gatsby-remark-copy-linked-files": "^2.1.23", + "gatsby-remark-images": "^3.1.25", + "gatsby-remark-prismjs": "^3.3.16", + "gatsby-remark-responsive-iframe": "^2.2.20", + "gatsby-source-contentful": "^2.1.50", + "gatsby-source-filesystem": "^2.1.28", + "gatsby-transformer-remark": "^2.6.26", + "gatsby-transformer-sharp": "^2.2.19", + "husky": "^3.1.0", + "lodash": "^4.17.15", + "moment": "^2.24.0", + "netlify-cms-app": "^2.9.7", + "node-sass": "^4.13.0", + "prismjs": "^1.16.0", + "react": "^16.10.1", + "react-disqus-comments": "^1.4.0", + "react-dom": "^16.10.1", + "react-helmet": "^5.2.1", + "react-share": "^3.0.1", + "react-twitter-widgets": "^1.7.1", + "theme-ui": "^0.2.44", + "url-join": "^4.0.0" }, - "repository": { - "type": "git", - "url": "git+https://github.com/EmaSuriano/gatsby-starter-mate.git" + "devDependencies": { + "cli-glob": "^0.1.0", + "eslint": "^6.5.0", + "eslint-config-airbnb": "^18.0.1", + "eslint-config-prettier": "^6.3.0", + "eslint-plugin-import": "^2.17.2", + "eslint-plugin-jsx-a11y": "^6.2.1", + "eslint-plugin-react": "^7.13.0", + "gh-pages": "^2.0.1", + "prettier": "^1.17.0", + "remark-cli": "^7.0.0", + "remark-preset-lint-recommended": "^3.0.2", + "stylelint": "^11.0.0", + "stylelint-config-prettier": "^6.0.0", + "stylelint-config-standard": "^19.0.0", + "write-good": "^1.0.1" }, "keywords": [ - "gatsby", - "starter", - "contentful", - "PWA", - "portfolio" + "gatsby" ], - "author": "Ema Suriano", "license": "MIT", - "bugs": { - "url": "https://github.com/EmaSuriano/gatsby-starter-mate/issues" - }, - "homepage": "https://github.com/EmaSuriano/gatsby-starter-mate#readme", - "dependencies": { - "@tippy.js/react": "^2.2.3", - "contentful": "^7.0.3", - "dotenv": "^7.0.0", - "envfile": "^3.0.0", - "gatsby": "^2.3.27", - "gatsby-plugin-google-analytics": "^2.0.18", - "gatsby-plugin-manifest": "^2.0.29", - "gatsby-plugin-offline": "^2.0.25", - "gatsby-plugin-preload-link-crossorigin": "^1.0.2", - "gatsby-plugin-react-helmet": "^3.0.12", - "gatsby-plugin-styled-components": "^3.0.7", - "gatsby-plugin-web-font-loader": "^1.0.4", - "gatsby-source-contentful": "^2.0.52", - "gatsby-transformer-remark": "^2.3.10", - "inquirer": "^6.2.0", - "prop-types": "^15.6.2", - "react": "^16.7.0", - "react-dom": "^16.7.0", - "react-fontawesome": "^1.6.1", - "react-headroom": "^2.2.4", - "react-helmet": "^5.2.0", - "react-markdown": "^4.0.3", - "react-reveal": "^1.2.2", - "react-scroll-section": "^1.3.0", - "react-text-loop": "^2.0.1", - "rebass": "^3.0.0", - "styled-components": "^4.0.2" + "main": "n/a", + "scripts": { + "develop": "gatsby develop", + "dev": "npm run develop", + "serve": "gatsby serve", + "build": "gatsby build", + "build:pp": "gatsby build --prefix-paths", + "build:gh": "npm run clean && npm run build:pp && gh-pages -d public", + "clean": "rm -rf public && rm -rf .cache", + "lint:js": "eslint --ext .js,.jsx .", + "lint:md": "remark content/", + "write-good": "write-good $(glob 'content/posts/**/*.md')", + "format:js": "prettier '**/*.{js,jsx}' --write", + "format:styles": "prettier '**/*.{css,scss}' --write" }, - "devDependencies": { - "@percy/cypress": "^2.1.1", - "@testing-library/cypress": "^5.0.0", - "axe-core": "^3.3.2", - "chalk": "^2.4.1", - "contentful-import": "^7.4.0", - "cypress": "^3.4.1", - "cypress-axe": "^0.5.1", - "eslint": "^5.6.0", - "eslint-config-airbnb": "^17.1.0", - "eslint-config-prettier": "^4.1.0", - "eslint-plugin-cypress": "^2.6.1", - "eslint-plugin-import": "^2.17.2", - "eslint-plugin-jsx-a11y": "^6.1.1", - "eslint-plugin-react": "^7.12.3", - "husky": "^1.3.1", - "lint-staged": "^8.1.0", - "prettier": "^1.18.2", - "start-server-and-test": "^1.10.0" + "remarkConfig": { + "plugins": [ + "remark-preset-lint-recommended" + ] } } diff --git a/src/components/About/About.css b/src/components/About/About.css new file mode 100644 index 0000000..b12fbec --- /dev/null +++ b/src/components/About/About.css @@ -0,0 +1,7 @@ +.about { + display: flex; + justify-content: center; + align-content: center; + align-items: center; + min-height: 300px; +} diff --git a/src/components/About/About.jsx b/src/components/About/About.jsx new file mode 100644 index 0000000..cebeb87 --- /dev/null +++ b/src/components/About/About.jsx @@ -0,0 +1,16 @@ +import React, { Component } from "react"; +import "./About.css"; + +class About extends Component { + render() { + return ( +
+

+ Edit About component or pages/about.jsx to include your information. +

+
+ ); + } +} + +export default About; diff --git a/src/components/Card.js b/src/components/Card.js deleted file mode 100644 index 0963bd7..0000000 --- a/src/components/Card.js +++ /dev/null @@ -1,37 +0,0 @@ -import styled from 'styled-components'; -import { Card as CardRebass } from 'rebass'; - -export const CardContainer = styled.div` - display: grid; - grid-gap: 30px; - - grid-template-columns: repeat( - auto-fill, - minmax(${props => props.minWidth}, 1fr) - ); - justify-items: center; - - @media only screen and (max-width: 400px) { - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); - } -`; - -export const Card = styled(CardRebass).attrs({ - bg: 'white', - boxShadow: 0, - borderRadius: 8, -})` - position: relative; - box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); - transition: all 0.25s; - top: 0; - height: 100%; - cursor: ${props => (props.onClick ? 'pointer' : 'default')}; - - &:hover { - top: -10px; - box-shadow: 0 12px 16px rgba(0, 0, 0, 0.2); - } -`; - -export default Card; diff --git a/src/components/Disqus/Disqus.jsx b/src/components/Disqus/Disqus.jsx new file mode 100644 index 0000000..a564db5 --- /dev/null +++ b/src/components/Disqus/Disqus.jsx @@ -0,0 +1,51 @@ +import React, { Component } from "react"; +import ReactDisqusComments from "react-disqus-comments"; +import urljoin from "url-join"; +import config from "../../../data/SiteConfig"; + +class Disqus extends Component { + constructor(props) { + super(props); + this.state = { + toasts: [] + }; + this.notifyAboutComment = this.notifyAboutComment.bind(this); + this.onSnackbarDismiss = this.onSnackbarDismiss.bind(this); + } + + onSnackbarDismiss() { + const [, ...toasts] = this.state.toasts; + this.setState({ toasts }); + } + + notifyAboutComment() { + const toasts = this.state.toasts.slice(); + toasts.push({ text: "New comment available!" }); + this.setState({ toasts }); + } + + render() { + const { postNode } = this.props; + if (!config.disqusShortname) { + return null; + } + const post = postNode; + const url = urljoin( + config.siteUrl, + config.pathPrefix, + postNode.slug + ); + return ( + + ); + } +} + +export default Disqus; diff --git a/src/components/Footer.js b/src/components/Footer.js deleted file mode 100644 index ed1b035..0000000 --- a/src/components/Footer.js +++ /dev/null @@ -1,78 +0,0 @@ -import React from 'react'; -import styled from 'styled-components'; -import { StaticQuery, graphql } from 'gatsby'; -import { Text, Box, Link, Flex } from 'rebass'; -import Fade from 'react-reveal/Fade'; -import SocialLink from './SocialLink'; - -const FooterContainer = styled.div` - min-width: 320px; - max-width: 1366px; - display: flex; - flex: 0 1 auto; - flex-direction: row; - justify-content: space-between; - align-items: center; - margin: auto; -`; - -const TextFooter = styled(Text)` - color: ${props => props.theme.colors.background}; - - & a { - color: ${props => props.theme.colors.background}; - } -`; - -const Footer = () => ( - { - const { name, socialLinks } = data.contentfulAbout; - - return ( - - - - - {`${name} Portfolio - Powered by `} - Gatsby - and - - Contentful - - - ❤️ - - - - - - {socialLinks.map(({ id, ...rest }) => ( - - - - ))} - - - - - ); - }} - /> -); - -export default Footer; diff --git a/src/components/Footer/Footer.css b/src/components/Footer/Footer.css new file mode 100644 index 0000000..511796c --- /dev/null +++ b/src/components/Footer/Footer.css @@ -0,0 +1,25 @@ +.footer { + justify-content: center; + align-content: center; + padding: 10px 5px 5px; +} + +.notice-container { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-content: center; + align-items: center; + margin-top: 25px; +} + +@media (max-width: 640px - 1px) { + .notice-container { + justify-content: space-around; + } +} + +.notice-container h4 { + text-align: center; + margin: 0; +} diff --git a/src/components/Footer/Footer.jsx b/src/components/Footer/Footer.jsx new file mode 100644 index 0000000..fe85868 --- /dev/null +++ b/src/components/Footer/Footer.jsx @@ -0,0 +1,36 @@ +import React, { Component } from "react"; +import { Link } from "gatsby"; +import UserLinks from "../UserLinks/UserLinks"; +import "./Footer.css"; + +class Footer extends Component { + render() { + const { config } = this.props; + const url = config.siteRss; + const { copyright } = config; + if (!copyright) { + return null; + } + return ( + + ); + } +} + +export default Footer; diff --git a/src/components/Header.js b/src/components/Header.js deleted file mode 100644 index c4d5c6b..0000000 --- a/src/components/Header.js +++ /dev/null @@ -1,84 +0,0 @@ -import React, { Fragment } from 'react'; -import Headroom from 'react-headroom'; -import { Flex, Image } from 'rebass'; -import styled from 'styled-components'; -import { SectionLinks } from 'react-scroll-section'; -import Fade from 'react-reveal/Fade'; -import RouteLink from './RouteLink'; -import Logo from './Logo/Portfolio.svg'; - -const capitalize = s => s && s[0].toUpperCase() + s.slice(1); - -const HeaderContainer = styled(Headroom)` - .headroom--pinned { - background: ${props => props.theme.colors.primaryDark}; - } - - position: absolute; - width: 100%; -`; - -const formatLinks = allLinks => - Object.entries(allLinks).reduce( - (acc, [key, value]) => { - const isHome = key === 'home'; - return isHome - ? { - ...acc, - home: value, - } - : { - ...acc, - links: [...acc.links, { name: capitalize(key), value }], - }; - }, - { links: [], home: null }, - ); - -const Header = () => ( - - - - - {({ allLinks }) => { - const { home, links } = formatLinks(allLinks); - - const homeLink = home && ( - Portfolio Logo - ); - const navLinks = links.map(({ name, value }) => ( - - )); - - return ( - - {homeLink} - {navLinks} - - ); - }} - - - - -); - -export default Header; diff --git a/src/components/Helmet.js b/src/components/Helmet.js deleted file mode 100644 index f5972b6..0000000 --- a/src/components/Helmet.js +++ /dev/null @@ -1,88 +0,0 @@ -import React from 'react'; -import ReactHelmet from 'react-helmet'; -import { StaticQuery, graphql } from 'gatsby'; -import { withTheme } from 'styled-components'; -import PropTypes from 'prop-types'; - -const Helmet = ({ theme = {} }) => ( - { - const { name, description, profile } = data.contentfulAbout; - const title = `${name} Portfolio`; - - return ( - - - {title} - - - - - - - - - - - - - - - - - - - - - - - ); - }} - /> -); - -Helmet.propTypes = { - // eslint-disable-next-line - theme: PropTypes.object, -}; - -export default withTheme(Helmet); diff --git a/src/components/Hide.js b/src/components/Hide.js deleted file mode 100644 index 39afa96..0000000 --- a/src/components/Hide.js +++ /dev/null @@ -1,31 +0,0 @@ -import styled from 'styled-components'; - -const breakpoints = { - xs: '@media screen and (max-width: 40em)', - sm: '@media screen and (min-width: 40em) and (max-width: 52em)', - md: '@media screen and (min-width: 52em) and (max-width: 64em)', - lg: '@media screen and (min-width: 64em)', -}; - -const hidden = key => props => - props[key] && { - [breakpoints[key]]: { - display: 'none', - }, - }; - -const xs = hidden('xs'); -const sm = hidden('sm'); -const md = hidden('md'); -const lg = hidden('lg'); - -const customQuery = props => - props.query && { - [props.query]: { - display: 'none', - }, - }; - -const Hide = styled.div([], xs, sm, md, lg, customQuery); - -export default Hide; diff --git a/src/components/ImageSubtitle.js b/src/components/ImageSubtitle.js deleted file mode 100644 index dd79399..0000000 --- a/src/components/ImageSubtitle.js +++ /dev/null @@ -1,56 +0,0 @@ -import styled from 'styled-components'; -import { Box } from 'rebass'; -import PropTypes from 'prop-types'; - -const BORDER_SPACING = '20px'; -const BORDER_RADIUS = '8px'; - -const BORDER_PATH_MAP = { - 'top-left': `polygon(0 0%, 100% 0%, calc(100% - ${BORDER_SPACING}) 100%, 0% 100%);`, - 'top-right': `polygon(0 0%, 100% 0%, 100% 100%, ${BORDER_SPACING} 100%);`, - 'bottom-right': `polygon(${BORDER_SPACING} 0%, 100% 0%, 100% 100%, 0% 100%);`, - 'bottom-left': `polygon(0 0%, calc(100% - ${BORDER_SPACING}) 0%, 100% 100%, 0% 100%);`, -}; - -const BORDER_RADIUS_MAP = { - 'top-left': `${BORDER_RADIUS} 0 0 0`, - 'top-right': `0 ${BORDER_RADIUS} 0 0`, - 'bottom-right': `0 0 ${BORDER_RADIUS} 0`, - 'bottom-left': `0 0 0 ${BORDER_RADIUS}`, -}; - -const ImageSubtitle = styled(Box)` - position: absolute; - display: inline; - padding: 10px; - font-size: 14px; - font-weight: 600; - text-transform: uppercase; - - ${props => props.x}: 0; - ${props => props.y}: 0; - - ${props => - props.x === 'left' - ? `padding-right: ${BORDER_SPACING};` - : `padding-left: ${BORDER_SPACING};`} - clip-path: ${props => BORDER_PATH_MAP[`${props.y}-${props.x}`]}; - - ${props => - props.round && - `border-radius: ${BORDER_RADIUS_MAP[`${props.y}-${props.x}`]};`} -`; - -ImageSubtitle.propTypes = { - x: PropTypes.oneOf(['left', 'right']), - y: PropTypes.oneOf(['top', 'bottom']), - round: PropTypes.bool, -}; - -ImageSubtitle.defaultProps = { - x: 'left', - y: 'top', - round: false, -}; - -export default ImageSubtitle; diff --git a/src/components/Layout.js b/src/components/Layout.js deleted file mode 100644 index 431e2a2..0000000 --- a/src/components/Layout.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { useEffect } from 'react'; -import { createGlobalStyle, ThemeProvider } from 'styled-components'; -import PropTypes from 'prop-types'; -import { ScrollingProvider } from 'react-scroll-section'; -import config from 'react-reveal/globals'; -import colors from '../../colors'; -import Helmet from './Helmet'; - -const GlobalStyle = createGlobalStyle` - *, - *::after, - *::before { - box-sizing: inherit; - } - - body { - box-sizing: border-box; - margin: 0; - font-family: Cabin, 'Open Sans', sans-serif; - font-display: swap; - font-display: fallback; - overflow-x: hidden; - } -`; - -config({ ssrFadeout: true }); - -const loadScript = src => { - const tag = document.createElement('script'); - tag.src = src; - tag.defer = true; - - document.getElementsByTagName('body')[0].appendChild(tag); -}; - -const Layout = ({ children }) => { - useEffect(() => { - loadScript('https://use.fontawesome.com/fd58d214b9.js'); - }, []); - - return ( -
- - - - - {children} - - -
- ); -}; - -Layout.propTypes = { - children: PropTypes.node.isRequired, -}; - -export default Layout; diff --git a/src/components/LinkAnimated.js b/src/components/LinkAnimated.js deleted file mode 100644 index efffa40..0000000 --- a/src/components/LinkAnimated.js +++ /dev/null @@ -1,35 +0,0 @@ -import styled from 'styled-components'; - -const LinkAnimated = styled.span` - text-decoration: none; - position: relative; - margin-bottom: 0; - padding-bottom: 5px; - color: inherit; - ${props => - props.selected && - `border-bottom: 5px solid ${props.theme.colors.primaryLight}`}; - transition: 0.4s; - cursor: ${props => (props.onClick ? 'pointer' : 'default')}; - - &:after { - content: ''; - position: absolute; - right: 0; - width: 0; - bottom: -5px; - background: ${props => props.theme.colors.secondaryLight}; - height: 5px; - transition-property: width; - transition-duration: 0.3s; - transition-timing-function: ease-out; - } - - &:hover:after { - left: 0; - right: auto; - width: 100%; - } -`; - -export default LinkAnimated; diff --git a/src/components/Logo/Contenful.svg b/src/components/Logo/Contenful.svg deleted file mode 100644 index 99a3fde..0000000 --- a/src/components/Logo/Contenful.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - diff --git a/src/components/Logo/Gatsby.svg b/src/components/Logo/Gatsby.svg deleted file mode 100644 index 202346e..0000000 --- a/src/components/Logo/Gatsby.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/components/Logo/Portfolio.svg b/src/components/Logo/Portfolio.svg deleted file mode 100644 index c8f18d2..0000000 --- a/src/components/Logo/Portfolio.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/components/MarkdownRenderer.js b/src/components/MarkdownRenderer.js deleted file mode 100644 index bc72af1..0000000 --- a/src/components/MarkdownRenderer.js +++ /dev/null @@ -1,77 +0,0 @@ -import React from 'react'; -import { SectionLink } from 'react-scroll-section'; -import styled from 'styled-components'; -import PropTypes from 'prop-types'; - -const StyledLink = styled.a` - display: inline-block; - transition: color 250ms, text-shadow 250ms; - color: black; - cursor: pointer; - position: relative; - text-decoration: none; - - &:after { - position: absolute; - z-index: -1; - bottom: 1px; - left: 50%; - transform: translateX(-50%); - content: ''; - width: 100%; - height: 3px; - background-color: ${props => props.theme.colors.primaryLight}; - transition: all 250ms; - } - - &:hover { - color: white; - - &::after { - height: 110%; - width: 110%; - } - } -`; - -const MarkdownParagraph = styled.p` - line-height: 2em; - - &:first-child { - margin-top: 0em; - } -`; - -const MarkdownList = styled.ul` - margin: 0; -`; - -const MarkdownListItem = styled.li` - margin: 1em 0; - line-height: 2em; -`; - -const MarkdownLink = ({ href, children }) => { - const isInnerLink = href.startsWith('#'); - return isInnerLink ? ( - - {({ onClick }) => {children}} - - ) : ( - - {children} - - ); -}; - -MarkdownLink.propTypes = { - href: PropTypes.string.isRequired, - children: PropTypes.node, -}; - -export default { - paragraph: props => , - list: props => , - listItem: props => , - link: MarkdownLink, -}; diff --git a/src/components/MouseIcon.js b/src/components/MouseIcon.js deleted file mode 100644 index 5c80261..0000000 --- a/src/components/MouseIcon.js +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react'; -import styled, { keyframes } from 'styled-components'; -import PropTypes from 'prop-types'; - -const MouseContainer = styled.svg` - max-width: 2.5rem; - width: 100%; - height: auto; -`; - -const ScrollLink = styled.span` - position: absolute; - bottom: 1rem; - left: 50%; - transform: translateX(-50%); - cursor: pointer; - - @media only screen and (max-width: 700px) { - display: none; - } -`; - -const ScrollAnimation = keyframes` - 0%, - 20% { - transform: translateY(0) scaleY(1); - } - - 10% { - opacity: 1; - } - - 100% { - transform: translateY(36px) scaleY(2); - opacity: 0.01; - } -`; - -const Mouse = styled.rect.attrs(props => ({ - stroke: props.theme.colors.primary, - strokeWidth: '3', -}))``; - -const Scroll = styled.circle` - animation-name: ${ScrollAnimation}; - animation-duration: 1.5s; - animation-timing-function: cubic-bezier(0.65, -0.55, 0.25, 1.5); - animation-iteration-count: infinite; - transform-origin: 50% 20.5px; - will-change: transform; - fill: ${props => props.theme.colors.primary}; -`; - -const MouseIcon = ({ onClick }) => ( - - - - - - - - -); - -MouseIcon.propTypes = { - onClick: PropTypes.func, -}; - -export default MouseIcon; diff --git a/src/components/PostListing/PostListing.jsx b/src/components/PostListing/PostListing.jsx new file mode 100644 index 0000000..440c8a9 --- /dev/null +++ b/src/components/PostListing/PostListing.jsx @@ -0,0 +1,36 @@ +import React from "react"; +import { Link } from "gatsby"; + +class PostListing extends React.Component { + getPostList() { + const postList = []; + this.props.postEdges.forEach(postEdge => { + postList.push({ + path: postEdge.node.slug, + tags: postEdge.node.tags, + // cover: postEdge.node.frontmatter.cover, + title: postEdge.node.title, + date: postEdge.node.publishDate, + excerpt: postEdge.node.excerpt, + timeToRead: postEdge.node.body.childMarkdownRemark.timeToRead + }); + }); + return postList; + } + + render() { + const postList = this.getPostList(); + return ( +
+ {/* Your post list here. */ + postList.map(post => ( + +

{post.title}

+ + ))} +
+ ); + } +} + +export default PostListing; diff --git a/src/components/PostTags/PostTags.jsx b/src/components/PostTags/PostTags.jsx new file mode 100644 index 0000000..3e02ac4 --- /dev/null +++ b/src/components/PostTags/PostTags.jsx @@ -0,0 +1,25 @@ +import React, { Component } from "react"; +import _ from "lodash"; +import { Link } from "gatsby"; + +class PostTags extends Component { + render() { + const { tags } = this.props; + return ( +
+ {tags && + tags.map(tag => ( + + + + ))} +
+ ); + } +} + +export default PostTags; diff --git a/src/components/RouteLink.js b/src/components/RouteLink.js deleted file mode 100644 index 8fc9d6e..0000000 --- a/src/components/RouteLink.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import { Box } from 'rebass'; -import PropTypes from 'prop-types'; -import LinkAnimated from './LinkAnimated'; - -const RouteLink = ({ onClick, selected, name }) => ( - - - {name} - - -); - -RouteLink.propTypes = { - onClick: PropTypes.func, - selected: PropTypes.bool, - name: PropTypes.string, -}; - -export default RouteLink; diff --git a/src/components/SEO/SEO.jsx b/src/components/SEO/SEO.jsx new file mode 100644 index 0000000..8daa49d --- /dev/null +++ b/src/components/SEO/SEO.jsx @@ -0,0 +1,112 @@ +import React, { Component } from "react"; +import Helmet from "react-helmet"; +import urljoin from "url-join"; +import config from "../../../data/SiteConfig"; + +class SEO extends Component { + render() { + const { postNode, postPath, postSEO } = this.props; + let title; + let description; + let image; + let postURL; + if (postSEO) { + const postMeta = postNode.frontmatter; + ({ title } = postMeta); + description = postMeta.description + ? postMeta.description + : postNode.excerpt; + image = postMeta.cover; + postURL = urljoin(config.siteUrl, config.pathPrefix, postPath); + } else { + title = config.siteTitle; + description = config.siteDescription; + image = config.siteLogo; + } + + if ( + !image.match( + `(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]` + ) + ) + image = urljoin(config.siteUrl, config.pathPrefix, image); + + const blogURL = urljoin(config.siteUrl, config.pathPrefix); + const schemaOrgJSONLD = [ + { + "@context": "http://schema.org", + "@type": "WebSite", + url: blogURL, + name: title, + alternateName: config.siteTitleAlt ? config.siteTitleAlt : "" + } + ]; + if (postSEO) { + schemaOrgJSONLD.push( + { + "@context": "http://schema.org", + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + item: { + "@id": postURL, + name: title, + image + } + } + ] + }, + { + "@context": "http://schema.org", + "@type": "BlogPosting", + url: blogURL, + name: title, + alternateName: config.siteTitleAlt ? config.siteTitleAlt : "", + headline: title, + image: { + "@type": "ImageObject", + url: image + }, + description + } + ); + } + return ( + + {/* General tags */} + + + + {/* Schema.org tags */} + + + {/* OpenGraph tags */} + + {postSEO ? : null} + + + + + + {/* Twitter Card tags */} + + + + + + + ); + } +} + +export default SEO; diff --git a/src/components/Section.js b/src/components/Section.js deleted file mode 100644 index 079ba0b..0000000 --- a/src/components/Section.js +++ /dev/null @@ -1,61 +0,0 @@ -import React from 'react'; -import styled from 'styled-components'; -import { Section } from 'react-scroll-section'; -import { Heading } from 'rebass'; -import PropTypes from 'prop-types'; -import Slide from 'react-reveal/Slide'; -import LinkAnimated from './LinkAnimated'; - -const SectionContainer = styled.div` - min-height: 100vh; - min-width: 320px; - max-width: 1366px; - display: flex; - margin: auto; - flex: 0 1 auto; - flex-direction: column; - justify-content: center; - padding: 5em 1em; - scroll-behavior: smooth; -`; - -const DefaultBackground = () =>
; - -const Container = ({ id, children, Background = DefaultBackground }) => ( -
- - {children} -
-); - -Container.propTypes = { - id: PropTypes.string.isRequired, - children: PropTypes.node.isRequired, - Background: PropTypes.func, -}; - -const Header = ({ name, icon = '', label = '' }) => ( - - - - {name} - {icon && ( - - {icon} - - )} - - - -); - -Header.propTypes = { - name: PropTypes.string.isRequired, - icon: PropTypes.string, - label: PropTypes.string, -}; - -export default { - Container, - Header, -}; diff --git a/src/components/SectionContext.js b/src/components/SectionContext.js deleted file mode 100644 index 21c9195..0000000 --- a/src/components/SectionContext.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const noop = () => false; - -const { Provider, Consumer } = React.createContext({ - sections: [], - addSection: noop, -}); - -export class SectionProvider extends React.Component { - state = { - sections: [], - }; - - addSection = section => - this.setState(state => ({ sections: [...state.sections, section] })); - - render() { - const { sections } = this.state; - const { children } = this.props; - const value = { - sections, - addSection: this.addSection, - }; - - return {children}; - } -} - -SectionProvider.propTypes = { - children: PropTypes.node, -}; - -export const SectionConsumer = Consumer; diff --git a/src/components/SocialLink.js b/src/components/SocialLink.js deleted file mode 100644 index 6be0005..0000000 --- a/src/components/SocialLink.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import { Link } from 'rebass'; -import Tippy from '@tippy.js/react'; -import styled from 'styled-components'; -import PropTypes from 'prop-types'; -import FontAwesomeIcon from 'react-fontawesome'; - -const IconLink = styled(Link)` - transition: color 0.5s; - color: ${props => - props.theme.colors[props.color] || props.theme.colors.primary}; - text-decoration: none; - - &:hover { - color: ${props => props.theme.colors.primaryLight}; - } -`; - -const SocialLink = ({ fontAwesomeIcon, name, url, color }) => ( - - - - - -); - -SocialLink.propTypes = { - fontAwesomeIcon: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - url: PropTypes.string.isRequired, - color: PropTypes.string, -}; - -export default SocialLink; diff --git a/src/components/SocialLinks/SocialLinks.css b/src/components/SocialLinks/SocialLinks.css new file mode 100644 index 0000000..8b6d70b --- /dev/null +++ b/src/components/SocialLinks/SocialLinks.css @@ -0,0 +1,18 @@ +.social-links { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + align-content: center; + align-items: center; + margin: 15px 0; +} + +.social-links > div { + margin: 5px 15px; + cursor: pointer; +} + +.share-count { + text-align: center; +} diff --git a/src/components/SocialLinks/SocialLinks.jsx b/src/components/SocialLinks/SocialLinks.jsx new file mode 100644 index 0000000..5b6f150 --- /dev/null +++ b/src/components/SocialLinks/SocialLinks.jsx @@ -0,0 +1,63 @@ +import React, { Component } from "react"; +import { + FacebookShareButton, + LinkedinShareButton, + TwitterShareButton, + TelegramShareButton, + RedditShareButton, + FacebookShareCount, + RedditShareCount, + FacebookIcon, + TwitterIcon, + TelegramIcon, + LinkedinIcon, + RedditIcon +} from "react-share"; +import urljoin from "url-join"; +import config from "../../../data/SiteConfig"; +import "./SocialLinks.css"; + +class SocialLinks extends Component { + render() { + const { postNode, postPath, mobile } = this.props; + const post = postNode; + const url = urljoin(config.siteUrl, config.pathPrefix, postPath); + const iconSize = mobile ? 36 : 48; + const filter = count => (count > 0 ? count : ""); + const renderShareCount = count => ( +
{filter(count)}
+ ); + + return ( +
+ + + + {count => renderShareCount(count)} + + + + + + + + + {count => renderShareCount(count)} + + + + + + + + +
+ ); + } +} + +export default SocialLinks; diff --git a/src/components/Triangle.js b/src/components/Triangle.js deleted file mode 100644 index 60dc6af..0000000 --- a/src/components/Triangle.js +++ /dev/null @@ -1,42 +0,0 @@ -import styled from 'styled-components'; - -const Triangle = styled.div` - position: absolute; - width: 0; - height: 0; - z-index: -2; - - ${props => { - const color = props.theme.colors[props.color] || props.color; - const border = `${props.height[0]} solid ${color};`; - return props.invertY - ? `border-bottom: ${border}; bottom: 0;` - : `border-top: ${border};`; - }} - /* prettier stop */ - ${props => { - const border = `${props.width[0]} solid transparent;`; - return props.invertX - ? `border-left: ${border}; right: 0;` - : `border-right: ${border};`; - }} - - - @media only screen and (min-width: 768px) { - ${props => { - const height = props.height[1]; - return props.invertY - ? `border-bottom-width: ${height};` - : `border-top-width: ${height};`; - }} - /* prettier stop */ - ${props => { - const width = props.width[1]; - return props.invertX - ? `border-left-width: ${width};` - : `border-right-width: ${width};`; - }}; - } -`; - -export default Triangle; diff --git a/src/components/UserInfo/UserInfo.jsx b/src/components/UserInfo/UserInfo.jsx new file mode 100644 index 0000000..7f6268c --- /dev/null +++ b/src/components/UserInfo/UserInfo.jsx @@ -0,0 +1,17 @@ +import React, { Component } from "react"; +import { Follow } from "react-twitter-widgets"; + +class UserInfo extends Component { + render() { + const { userTwitter } = this.props.config; + const { expanded } = this.props; + return ( + + ); + } +} + +export default UserInfo; diff --git a/src/components/UserLinks/UserLinks.css b/src/components/UserLinks/UserLinks.css new file mode 100644 index 0000000..ba7d8c5 --- /dev/null +++ b/src/components/UserLinks/UserLinks.css @@ -0,0 +1,7 @@ +.user-links { + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + max-width: 100%; +} diff --git a/src/components/UserLinks/UserLinks.jsx b/src/components/UserLinks/UserLinks.jsx new file mode 100644 index 0000000..7bf0790 --- /dev/null +++ b/src/components/UserLinks/UserLinks.jsx @@ -0,0 +1,26 @@ +import React, { Component } from "react"; +import "./UserLinks.css"; + +class UserLinks extends Component { + getLinkElements() { + const { userLinks } = this.props.config; + const { labeled } = this.props; + return userLinks.map(link => ( + + + + )); + } + + render() { + const { userLinks } = this.props.config; + if (!userLinks) { + return null; + } + return
{this.getLinkElements()}
; + } +} + +export default UserLinks; diff --git a/src/favicon.png b/src/favicon.png new file mode 100755 index 0000000..dee3faf Binary files /dev/null and b/src/favicon.png differ diff --git a/src/layout/index.css b/src/layout/index.css new file mode 100644 index 0000000..8f867be --- /dev/null +++ b/src/layout/index.css @@ -0,0 +1,28 @@ +/* These are global styles */ + +* { + box-sizing: border-box; +} + +html { + height: 100%; +} + +body { + margin: 0; + padding: 0; + min-height: 100%; + min-width: 100%; +} + +#___gatsby #gatsby-focus-wrapper { + min-height: 100vh; + min-width: 100vw; +} + +.layout-container { + min-height: 100vh; + min-width: 100vw; + display: flex; + padding: 20px; +} diff --git a/src/layout/index.jsx b/src/layout/index.jsx new file mode 100644 index 0000000..4716233 --- /dev/null +++ b/src/layout/index.jsx @@ -0,0 +1,19 @@ +import React from "react"; +import Helmet from "react-helmet"; +import config from "../../data/SiteConfig"; +import "./index.css"; + +export default class MainLayout extends React.Component { + render() { + const { children } = this.props; + return ( +
+ + + + + {children} +
+ ); + } +} diff --git a/src/pages/404.js b/src/pages/404.js deleted file mode 100644 index b91f803..0000000 --- a/src/pages/404.js +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import { Heading, Box } from 'rebass'; -import Layout from '../components/Layout'; -import Section from '../components/Section'; -import Triangle from '../components/Triangle'; - -const Background = () => ( -
- - - - - -
-); - -const NotFoundPage = () => ( - - - - - 404 - - - {"There isn't anything here"} - - - - -); - -export default NotFoundPage; diff --git a/src/pages/about.jsx b/src/pages/about.jsx new file mode 100644 index 0000000..bcd3266 --- /dev/null +++ b/src/pages/about.jsx @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import Helmet from "react-helmet"; +import Layout from "../layout"; +import About from "../components/About/About"; +import config from "../../data/SiteConfig"; + +class AboutPage extends Component { + render() { + return ( + +
+ + +
+
+ ); + } +} + +export default AboutPage; diff --git a/src/pages/index.js b/src/pages/index.js deleted file mode 100644 index 19a1429..0000000 --- a/src/pages/index.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import Layout from '../components/Layout'; -import Landing from '../sections/Landing'; -import About from '../sections/About'; -import BlogFeed from '../sections/BlogFeed'; -import Header from '../components/Header'; -import Footer from '../components/Footer'; - -const IndexPage = () => ( - -
- - - -