├── Devfolio Performance.png ├── LICENSE ├── README.md ├── gatsby-browser.js ├── gatsby-node.js └── src ├── components ├── Blog.js ├── Blogs.js ├── Footer.js ├── Hero.js ├── Interests.js ├── Jobs.js ├── Layout.js ├── Navbar.js ├── Project.js ├── Projects.js ├── Quotes.js ├── Radar.js ├── SEO.js ├── Services.js ├── Sidebar.js └── Title.js ├── pages ├── 404.js ├── about.js ├── blog.js ├── contact.js ├── index.js └── projects.js └── templates └── blog-template.js /Devfolio Performance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineeringwitharavind/devfolio/e565c277e298c45669c038f1332e49193f448259/Devfolio Performance.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Aravind 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## devfolio 2 | 3 | > Built  🛠   a personal Portfolio using React, Gatsby, and Strapi. 4 | 5 | #### Tech Stack 6 | 7 | [![MIT](https://img.shields.io/badge/License-MIT-628AFF?style=flat&logo=license)](https://github.com/engineeringwitharavind/devFolio/blob/master/LICENSE) 8 | [![npm](https://img.shields.io/npm/v/npm.svg?style=flat-square)](https://www.npmjs.com/package/npm) 9 | [![react](https://img.shields.io/badge/frontend-react-61daf9?style=flat&logo=React)](https://reactjs.org/) 10 | [![GraphQL](https://img.shields.io/badge/using-GraphQL-ec3f77?style=flat&logo=graphql)](https://graphql.org/) 11 | [![Gatsby](https://img.shields.io/badge/using-Gatsby-663399?style=flat&logo=gatsby)](https://www.gatsbyjs.com/) 12 | [![Strapi](https://img.shields.io/badge/using-Strapi-8e74f7?style=flat&logo=strapi)](https://strapi.io/) 13 | [![icons](https://img.shields.io/badge/icons-react--icons-ec5c8d?style=flat&logo=React)](https://react-icons.github.io/react-icons/) 14 | 15 | ![screenshot](https://aravind.netlify.app/twitter-img.png) 16 | 17 | ![lighthouse_score](https://github.com/engineeringwitharavind/devFolio/blob/master/Devfolio%20Performance.png) 18 | -------------------------------------------------------------------------------- /gatsby-browser.js: -------------------------------------------------------------------------------- 1 | import "./src/css/main.css"; 2 | -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | // create pages dynamically 4 | exports.createPages = async ({ graphql, actions }) => { 5 | const { createPage } = actions; 6 | const result = await graphql(` 7 | { 8 | blogs: allStrapiBlogs { 9 | nodes { 10 | slug 11 | } 12 | } 13 | } 14 | `); 15 | 16 | result.data.blogs.nodes.forEach((blog) => { 17 | createPage({ 18 | path: `/blogs/${blog.slug}`, 19 | component: path.resolve(`src/templates/blog-template.js`), 20 | context: { 21 | slug: blog.slug, 22 | }, 23 | }); 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /src/components/Blog.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import Image from "gatsby-image"; 4 | import { Link } from "gatsby"; 5 | 6 | const Blog = ({ id, title, image, date, stack, slug, desc }) => { 7 | return ( 8 | 14 |
15 | {image && ( 16 | 17 | )} 18 |
19 |

{title}

20 |

{desc}

21 |
22 | {stack.map((item) => { 23 | return {item.title}; 24 | })} 25 |

{date}

26 |
27 |
28 |
29 | 30 | ); 31 | }; 32 | 33 | Blog.propTypes = { 34 | id: PropTypes.string.isRequired, 35 | title: PropTypes.string.isRequired, 36 | date: PropTypes.string.isRequired, 37 | stack: PropTypes.string.isRequired, 38 | desc: PropTypes.string.isRequired, 39 | slug: PropTypes.string.isRequired, 40 | image: PropTypes.object.isRequired, 41 | }; 42 | 43 | export default Blog; 44 | -------------------------------------------------------------------------------- /src/components/Blogs.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Title from "./Title"; 3 | import Blog from "./Blog"; 4 | import { Link } from "gatsby"; 5 | 6 | export const Blogs = ({ blogs, title, showLink }) => { 7 | return ( 8 |
9 | 10 | <div className="section-center blogs-center"> 11 | {blogs.map((blog) => { 12 | return <Blog key={blog.id} {...blog} />; 13 | })} 14 | </div> 15 | {showLink && ( 16 | <Link 17 | to="/blog" 18 | className="btn center-btn" 19 | aria-label="View All Articles" 20 | > 21 | all articles 22 | </Link> 23 | )} 24 | </section> 25 | ); 26 | }; 27 | 28 | export default Blogs; 29 | -------------------------------------------------------------------------------- /src/components/Footer.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import SocialLinks from "../constants/socialLinks"; 3 | import { GrGatsbyjs } from "react-icons/gr"; 4 | // npm install --save-dev @iconify/react @iconify/icons-simple-icons 5 | import { Icon } from "@iconify/react"; 6 | import netlifyIcon from "@iconify/icons-simple-icons/netlify"; 7 | import { FaReact } from "react-icons/fa"; 8 | 9 | const Footer = () => { 10 | return ( 11 | <footer aria-label="Footer" className="footer"> 12 | <div> 13 | <SocialLinks 14 | aria-label="Social Links" 15 | styleClass="footer-links" 16 | ></SocialLinks> 17 | <h5> 18 | © {new Date().getFullYear()},<span> Aravind. </span> Built with{" "} 19 | <GrGatsbyjs /> and <FaReact /> deployed on <Icon icon={netlifyIcon} /> 20 | </h5> 21 | </div> 22 | </footer> 23 | ); 24 | }; 25 | 26 | export default Footer; 27 | -------------------------------------------------------------------------------- /src/components/Hero.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Image from "gatsby-image"; 3 | import { Link } from "gatsby"; 4 | import TextLoop from "react-text-loop"; 5 | import { graphql, useStaticQuery } from "gatsby"; 6 | import SocialLinks from "../constants/socialLinks"; 7 | // ...GatsbyImageSharpFluid 8 | 9 | const query = graphql` 10 | { 11 | file(relativePath: { eq: "hero-img.png" }) { 12 | childImageSharp { 13 | fluid { 14 | ...GatsbyImageSharpFluid 15 | } 16 | } 17 | } 18 | } 19 | `; 20 | 21 | const Hero = () => { 22 | const { 23 | file: { 24 | childImageSharp: { fluid }, 25 | }, 26 | } = useStaticQuery(query); 27 | 28 | return ( 29 | <header className="hero"> 30 | <div className="section-center hero-center"> 31 | <Image fluid={fluid} className="hero-img" /> 32 | <article className="hero-info"> 33 | <div> 34 | <div className="underline"></div> 35 | <h3>I'm Aravind</h3> 36 | <h4> 37 | A{" "} 38 | <TextLoop className="text-loop"> 39 | <span>self-taught</span> 40 | <span>passionate</span> 41 | <span>pragmatic</span> 42 | </TextLoop>{" "} 43 | Software engineer 44 | </h4> 45 | <Link to="/contact" className="btn" aria-label="Contact Me"> 46 | Contact me 47 | </Link> 48 | <SocialLinks aria-label="Social Links" /> 49 | </div> 50 | </article> 51 | </div> 52 | </header> 53 | ); 54 | }; 55 | 56 | export default Hero; 57 | -------------------------------------------------------------------------------- /src/components/Interests.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Title from "./Title"; 3 | import interests from "../constants/interests"; 4 | 5 | const Interests = () => { 6 | return ( 7 | <section className="section bg-grey"> 8 | <Title title="Leisure" /> 9 | <div className="section-center services-center"> 10 | {interests.map((interest) => { 11 | const { id, icon, title, text } = interest; 12 | 13 | return ( 14 | <article key={id} className="interests"> 15 | {icon} 16 | <h4>{title}</h4> 17 | <div className="underline"></div> 18 | <p>{text}</p> 19 | </article> 20 | ); 21 | })} 22 | </div> 23 | </section> 24 | ); 25 | }; 26 | 27 | export default Interests; 28 | -------------------------------------------------------------------------------- /src/components/Jobs.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Title from "./Title"; 3 | import { FaAngleDoubleRight } from "react-icons/fa"; 4 | import { graphql, useStaticQuery } from "gatsby"; 5 | 6 | const query = graphql` 7 | { 8 | allStrapiJobs(sort: { fields: strapiId, order: DESC }) { 9 | nodes { 10 | strapiId 11 | company 12 | date 13 | position 14 | desc { 15 | id 16 | name 17 | } 18 | } 19 | } 20 | } 21 | `; 22 | 23 | const Jobs = () => { 24 | const data = useStaticQuery(query); 25 | const { 26 | allStrapiJobs: { nodes: jobs }, 27 | } = data; 28 | const [value, setValue] = React.useState(0); 29 | const { company, position, date, desc } = jobs[value]; 30 | 31 | return ( 32 | <section className="section jobs"> 33 | <Title title="experience" /> 34 | <div className="jobs-center"> 35 | {/* btn container */} 36 | <div className="btn-container"> 37 | {jobs.map((item, index) => { 38 | return ( 39 | <button 40 | aria-label="Company Name" 41 | key={item.strapiId} 42 | onClick={() => setValue(index)} 43 | className={`job-btn ${index === value && "active-btn"}`} 44 | > 45 | {item.company} 46 | </button> 47 | ); 48 | })} 49 | </div> 50 | {/* job info */} 51 | <article className="job-info"> 52 | <h3>{position}</h3> 53 | <h4>{company}</h4> 54 | <p className="job-date">{date}</p> 55 | {desc.map((item) => { 56 | return ( 57 | <div key={item.id} className="job-desc"> 58 | <FaAngleDoubleRight className="job-icon"></FaAngleDoubleRight> 59 | <p>{item.name}</p> 60 | </div> 61 | ); 62 | })} 63 | </article> 64 | </div> 65 | </section> 66 | ); 67 | }; 68 | 69 | export default Jobs; 70 | -------------------------------------------------------------------------------- /src/components/Layout.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | // import "../css/main.css" 3 | import Navbar from "./Navbar"; 4 | import Sidebar from "./Sidebar"; 5 | import Footer from "./Footer"; 6 | 7 | const Layout = ({ children }) => { 8 | const [isOpen, setIsOpen] = React.useState(false); 9 | 10 | const toggleSidebar = () => { 11 | setIsOpen(!isOpen); 12 | }; 13 | 14 | return ( 15 | <> 16 | <Navbar toggleSidebar={toggleSidebar} /> 17 | <Sidebar isOpen={isOpen} toggleSidebar={toggleSidebar} /> 18 | {children} 19 | <Footer /> 20 | </> 21 | ); 22 | }; 23 | 24 | export default Layout; 25 | -------------------------------------------------------------------------------- /src/components/Navbar.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import logo from "../assets/aravind-logo.svg"; 3 | import { FaAlignRight } from "react-icons/fa"; 4 | import PageLinks from "../constants/links"; 5 | 6 | const Navbar = ({ toggleSidebar }) => { 7 | return ( 8 | <nav className="navbar"> 9 | <div className="nav-center"> 10 | <div className="nav-header"> 11 | <img className="logo" src={logo} alt="logo" /> 12 | <button 13 | type="button" 14 | className="toggle-btn" 15 | aria-label="Toggle Sidebar" 16 | onClick={toggleSidebar} 17 | > 18 | <FaAlignRight></FaAlignRight> 19 | </button> 20 | </div> 21 | <PageLinks 22 | aria-label="Navigation Links" 23 | styleClass="nav-links" 24 | ></PageLinks> 25 | </div> 26 | </nav> 27 | ); 28 | }; 29 | 30 | export default Navbar; 31 | -------------------------------------------------------------------------------- /src/components/Project.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import Image from "gatsby-image"; 4 | import { FaGithub, FaExternalLinkAlt } from "react-icons/fa"; 5 | 6 | const Project = ({ description, title, github, stack, url, image }) => { 7 | return ( 8 | <article className="project"> 9 | {image && ( 10 | <Image fluid={image.childImageSharp.fluid} className="project-img" /> 11 | )} 12 | <div className="project-info"> 13 | <h3>{title}</h3> 14 | <p className="project-desc">{description}</p> 15 | <div className="project-stack"> 16 | {stack.map((item) => { 17 | return <span key={item.id}>{item.title}</span>; 18 | })} 19 | </div> 20 | <div className="project-links"> 21 | <a 22 | href={github} 23 | rel="noopener noreferrer" 24 | target="_blank" 25 | aria-label="Github Link" 26 | > 27 | <FaGithub className="project-icon" /> 28 | </a> 29 | <a 30 | href={url} 31 | rel="noopener noreferrer" 32 | target="_blank" 33 | aria-label="Project Link" 34 | > 35 | <FaExternalLinkAlt className="project-icon" /> 36 | </a> 37 | </div> 38 | </div> 39 | </article> 40 | ); 41 | }; 42 | 43 | // For Projects Number => <span className="project-number">0{index + 1}.</span> 44 | 45 | Project.propTypes = { 46 | title: PropTypes.string.isRequired, 47 | github: PropTypes.string.isRequired, 48 | url: PropTypes.string.isRequired, 49 | description: PropTypes.string.isRequired, 50 | image: PropTypes.object.isRequired, 51 | stack: PropTypes.arrayOf(PropTypes.object).isRequired, 52 | }; 53 | 54 | export default Project; 55 | -------------------------------------------------------------------------------- /src/components/Projects.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Title from "./Title"; 3 | import Project from "./Project"; 4 | import { Link } from "gatsby"; 5 | const Projects = ({ projects, title, showLink }) => { 6 | return ( 7 | <section className="section projects"> 8 | <Title title={title} /> 9 | <div className="section-center projects-center"> 10 | {projects.map((project, index) => { 11 | return <Project key={project.id} index={index} {...project} />; 12 | })} 13 | </div> 14 | {showLink && ( 15 | <Link 16 | to="/projects" 17 | className="btn center-btn" 18 | aria-label="View All Projects" 19 | > 20 | view all projects 21 | </Link> 22 | )} 23 | </section> 24 | ); 25 | }; 26 | 27 | export default Projects; 28 | -------------------------------------------------------------------------------- /src/components/Quotes.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Title from "./Title" 3 | import { FaQuoteLeft } from "react-icons/fa"; 4 | 5 | const Quotes = () => { 6 | return ( 7 | <section className="section bg-grey"> 8 | <Title title="Favourite Quote" /> 9 | <div className="section-center quote-center fa-quote-left" id="single-quote"> 10 | <p> 11 | <FaQuoteLeft style={{marginRight: "0.3em", color: "#49aeba"}}/> 12 | Your work is going to fill a large part of your life, and 13 | the only way to be truly satisfied is to do what you believe 14 | is great work. And the only way to do great work is to love 15 | what you do. If you haven’t found it yet, keep looking. 16 | Don’t settle. As with all matters of the heart, you’ll know 17 | when you find it. 18 | </p> 19 | <p className="about-steve"><span style={{color: "#49aeba",fontWeight:"600"}}>- Steve Jobs</span></p> 20 | </div> 21 | </section> 22 | ) 23 | } 24 | 25 | export default Quotes; -------------------------------------------------------------------------------- /src/components/Radar.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { Radar } from "react-chartjs-2"; 3 | import Title from "./Title"; 4 | 5 | const ChartData = () => { 6 | const [chartData, setChartData] = useState({}); 7 | 8 | const chart = () => { 9 | setChartData({ 10 | labels: [ 11 | "HTML5", 12 | "CSS3", 13 | "JavaScript", 14 | "Python", 15 | "Git", 16 | "SQL", 17 | "Gatsby.js", 18 | "MongoDB", 19 | "React.js", 20 | "Node.js", 21 | ], 22 | datasets: [ 23 | { 24 | label: "Interests", 25 | backgroundColor: "rgba(73,174,186,0.2)", 26 | borderColor: "rgba(73,174,186,1)", 27 | pointBackgroundColor: "rgba(255,99,132,1)", 28 | pointBorderColor: "#fff", 29 | pointHoverBackgroundColor: "#fff", 30 | pointHoverBorderColor: "rgba(255,99,132,1)", 31 | data: [85, 70, 90, 70, 75, 65, 75, 70, 85, 65], 32 | }, 33 | ], 34 | }); 35 | }; 36 | 37 | const options = { 38 | legend: { 39 | display: false, 40 | }, 41 | scale: { 42 | ticks: { 43 | beginAtZero: true, 44 | display: false, 45 | }, 46 | }, 47 | maintainAspectRatio: false, 48 | }; 49 | 50 | useEffect(() => { 51 | chart(); 52 | }, []); 53 | 54 | return ( 55 | <div> 56 | <Title title="Interests" /> 57 | <div className="canvas-container"> 58 | <Radar data={chartData} options={options} /> 59 | </div> 60 | </div> 61 | ); 62 | }; 63 | 64 | export default ChartData; 65 | -------------------------------------------------------------------------------- /src/components/SEO.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Helmet } from "react-helmet"; 3 | import { useStaticQuery, graphql } from "gatsby"; 4 | 5 | const query = graphql` 6 | { 7 | site { 8 | siteMetadata { 9 | author 10 | siteDesc: description 11 | image 12 | siteUrl 13 | siteTitle: title 14 | twitterUsername 15 | } 16 | } 17 | } 18 | `; 19 | 20 | const SEO = ({ title, description }) => { 21 | const { site } = useStaticQuery(query); 22 | const { 23 | siteDesc, 24 | siteTitle, 25 | siteUrl, 26 | image, 27 | author, 28 | twitterUsername, 29 | } = site.siteMetadata; 30 | return ( 31 | <Helmet htmlAttributes={{ lang: "en" }} title={`${title} | ${siteTitle}`}> 32 | <meta name="description" content={description || siteDesc} /> 33 | <meta name="image" content={image} /> 34 | <meta name="author" content={`${author}`} /> 35 | <meta property="og:title" content={`${title} | ${siteTitle}`} /> 36 | <meta property="og:description" content={siteDesc} /> 37 | <meta property="og:image" content={`${siteUrl}${image}`} /> 38 | <meta property="og:author" content="Aravind" /> 39 | <meta property="og:type" content="Website" /> 40 | {/* twitter Cards */} 41 | <meta name="twitter:card" content="summary_large_image" /> 42 | <meta name="twitter:creator" content={twitterUsername} /> 43 | <meta name="twitter:title" content={siteTitle} /> 44 | <meta name="twitter:description" content={siteDesc} /> 45 | <meta name="twitter:image" content={`${siteUrl}${image}`} /> 46 | </Helmet> 47 | ); 48 | }; 49 | 50 | export default SEO; 51 | -------------------------------------------------------------------------------- /src/components/Services.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Title from "./Title"; 3 | import services from "../constants/services"; 4 | import Radar from "./Radar"; 5 | 6 | const Services = () => { 7 | return ( 8 | <section className="section bg-grey"> 9 | <Title title="skills" /> 10 | <div className="section-center services-center"> 11 | {services.map((service) => { 12 | const { id, icon, title, text } = service; 13 | 14 | return ( 15 | <article key={id} className="service"> 16 | {icon} 17 | <h4>{title}</h4> 18 | <div className="underline"></div> 19 | <p>{text}</p> 20 | </article> 21 | ); 22 | })} 23 | </div> 24 | <Radar /> 25 | </section> 26 | ); 27 | }; 28 | 29 | export default Services; 30 | -------------------------------------------------------------------------------- /src/components/Sidebar.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Links from "../constants/links"; 3 | import SocialLinks from "../constants/socialLinks"; 4 | import { FaTimes } from "react-icons/fa"; 5 | 6 | const Sidebar = ({ isOpen, toggleSidebar }) => { 7 | return ( 8 | <aside className={`sidebar ${isOpen ? "show-sidebar" : ""}`}> 9 | <button 10 | aria-label="Close Button" 11 | className="close-btn" 12 | onClick={toggleSidebar} 13 | > 14 | <FaTimes /> 15 | </button> 16 | <div className="side-container"> 17 | <Links 18 | aria-label="Sidebar Links" 19 | styleClass={`${isOpen ? "sidebar-links" : ""}`} 20 | /> 21 | <SocialLinks 22 | aria-label="Social Links" 23 | styleClass={`${isOpen ? "sidebar-icons" : ""}`} 24 | /> 25 | </div> 26 | </aside> 27 | ); 28 | }; 29 | 30 | export default Sidebar; 31 | -------------------------------------------------------------------------------- /src/components/Title.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Title = ({ title }) => { 4 | return ( 5 | <div className="section-title"> 6 | <h3>{title || "default title"}</h3> 7 | <div className="underline"></div> 8 | </div> 9 | ); 10 | }; 11 | 12 | export default Title; 13 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Layout from "../components/Layout"; 3 | import { Link } from "gatsby"; 4 | import SEO from "../components/SEO"; 5 | 6 | const Error = () => { 7 | return ( 8 | <Layout> 9 | <SEO 10 | title="404 Page" 11 | description="Page is Not Available. Go to HOME Page" 12 | /> 13 | <main className="error-page"> 14 | <h3>oops! it's a dead end</h3> 15 | <Link to="/" className="btn"> 16 | back to home 17 | </Link> 18 | </main> 19 | </Layout> 20 | ); 21 | }; 22 | 23 | export default Error; 24 | -------------------------------------------------------------------------------- /src/pages/about.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Layout from "../components/Layout"; 3 | import { graphql } from "gatsby"; 4 | import Title from "../components/Title"; 5 | import Image from "gatsby-image"; 6 | import ReactMarkdown from "react-markdown"; 7 | import Interests from "../components/Interests"; 8 | import SEO from "../components/SEO"; 9 | import Quotes from "../components/Quotes"; 10 | // ...GatsbyImageSharpFluid 11 | 12 | const About = ({ 13 | data: { 14 | about: { nodes }, 15 | }, 16 | }) => { 17 | const { info, stack, title, image } = nodes[0]; 18 | 19 | return ( 20 | <Layout> 21 | <SEO title="About" description="About me" /> 22 | <section className="about-page"> 23 | <div className="section-center about-center"> 24 | <Image fluid={image.childImageSharp.fluid} className="about-img" /> 25 | <article className="about-text"> 26 | <Title title={title} /> 27 | <ReactMarkdown source={info} /> 28 | <div className="about-stack"> 29 | {stack.map((item) => { 30 | return <span key={item.id}>{item.title}</span>; 31 | })} 32 | </div> 33 | </article> 34 | </div> 35 | <Quotes /> 36 | <Interests /> 37 | </section> 38 | </Layout> 39 | ); 40 | }; 41 | 42 | export const query = graphql` 43 | { 44 | about: allStrapiAbout { 45 | nodes { 46 | stack { 47 | id 48 | title 49 | } 50 | title 51 | info 52 | image { 53 | childImageSharp { 54 | fluid { 55 | ...GatsbyImageSharpFluid 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | `; 63 | 64 | export default About; 65 | -------------------------------------------------------------------------------- /src/pages/blog.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Layout from "../components/Layout"; 3 | import { graphql } from "gatsby"; 4 | import Blogs from "../components/Blogs"; 5 | import SEO from "../components/SEO"; 6 | // ...GatsbyImageSharpFluid 7 | 8 | const Blog = ({ 9 | data: { 10 | allStrapiBlogs: { nodes: blogs }, 11 | }, 12 | }) => { 13 | return ( 14 | <Layout> 15 | <SEO title="Articles" description="Latest Articles by Aravind" /> 16 | <section className="blog-page"> 17 | <Blogs blogs={blogs} title="articles" /> 18 | </section> 19 | </Layout> 20 | ); 21 | }; 22 | 23 | export const query = graphql` 24 | { 25 | allStrapiBlogs(sort: { fields: date, order: DESC }, limit: 3) { 26 | nodes { 27 | slug 28 | desc 29 | date(formatString: "MMMM Do, YYYY") 30 | id 31 | title 32 | stack { 33 | id 34 | title 35 | } 36 | image { 37 | childImageSharp { 38 | fluid { 39 | ...GatsbyImageSharpFluid 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | `; 47 | 48 | export default Blog; 49 | -------------------------------------------------------------------------------- /src/pages/contact.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Layout from "../components/Layout"; 3 | import SEO from "../components/SEO"; 4 | 5 | const contact = () => { 6 | return ( 7 | <Layout> 8 | <SEO title="Contact" description="Contact Page" /> 9 | <section className="contact-page"> 10 | <article className="contact-form"> 11 | <h3>get in touch</h3> 12 | <form action="https://formspree.io/xdowwgkr" method="POST"> 13 | <div className="form-group"> 14 | <input 15 | type="text" 16 | name="name" 17 | placeholder="name" 18 | className="form-control" 19 | /> 20 | <input 21 | type="email" 22 | placeholder="email" 23 | name="email" 24 | className="form-control" 25 | /> 26 | <textarea 27 | name="message" 28 | rows="5" 29 | placeholder="message" 30 | className="form-control" 31 | ></textarea> 32 | </div> 33 | <button type="submit" className="submit-btn btn"> 34 | submit here 35 | </button> 36 | </form> 37 | </article> 38 | </section> 39 | </Layout> 40 | ); 41 | }; 42 | 43 | export default contact; 44 | -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { graphql } from "gatsby"; 3 | import Layout from "../components/Layout"; 4 | import Hero from "../components/Hero"; 5 | import Services from "../components/Services"; 6 | import Jobs from "../components/Jobs"; 7 | import Projects from "../components/Projects"; 8 | import Blogs from "../components/Blogs"; 9 | import SEO from "../components/SEO"; 10 | 11 | export default ({ data }) => { 12 | const { 13 | allStrapiProjects: { nodes: projects }, 14 | allStrapiBlogs: { nodes: blogs }, 15 | } = data; 16 | 17 | return ( 18 | <Layout> 19 | <SEO title="Home" description="Aravind's Home Page" /> 20 | <Hero /> 21 | <Services /> 22 | <Jobs /> 23 | <Projects projects={projects} title="featured projects" showLink /> 24 | <Blogs blogs={blogs} title="latest articles" showLink /> 25 | </Layout> 26 | ); 27 | }; 28 | 29 | export const query = graphql` 30 | { 31 | allStrapiProjects(filter: { featured: { eq: true } }) { 32 | nodes { 33 | github 34 | id 35 | description 36 | title 37 | url 38 | image { 39 | childImageSharp { 40 | fluid { 41 | ...GatsbyImageSharpFluid 42 | } 43 | } 44 | } 45 | stack { 46 | id 47 | title 48 | } 49 | } 50 | } 51 | allStrapiBlogs(sort: { fields: date, order: DESC }, limit: 3) { 52 | nodes { 53 | slug 54 | content 55 | desc 56 | date(formatString: "MMMM Do, YYYY") 57 | id 58 | title 59 | stack { 60 | id 61 | title 62 | } 63 | image { 64 | childImageSharp { 65 | fluid { 66 | ...GatsbyImageSharpFluid 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | `; 74 | -------------------------------------------------------------------------------- /src/pages/projects.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Layout from "../components/Layout"; 3 | import { graphql } from "gatsby"; 4 | import Projects from "../components/Projects"; 5 | import SEO from "../components/SEO"; 6 | 7 | const ProjectsPage = ({ 8 | data: { 9 | allStrapiProjects: { nodes: projects }, 10 | }, 11 | }) => { 12 | return ( 13 | <Layout> 14 | <SEO title="Projects" description="Aravind's Projects" /> 15 | <section className="projects-page"> 16 | <Projects projects={projects} title="all projects" /> 17 | </section> 18 | </Layout> 19 | ); 20 | }; 21 | 22 | export const query = graphql` 23 | { 24 | allStrapiProjects { 25 | nodes { 26 | github 27 | id 28 | description 29 | title 30 | url 31 | image { 32 | childImageSharp { 33 | fluid { 34 | ...GatsbyImageSharpFluid 35 | } 36 | } 37 | } 38 | stack { 39 | id 40 | title 41 | } 42 | } 43 | } 44 | } 45 | `; 46 | 47 | export default ProjectsPage; 48 | -------------------------------------------------------------------------------- /src/templates/blog-template.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { graphql, Link } from "gatsby"; 3 | import Layout from "../components/Layout"; 4 | import ReactMarkdown from "react-markdown"; 5 | import SEO from "../components/SEO"; 6 | 7 | const ComponentName = ({ data }) => { 8 | const { content, title, desc } = data.blog; 9 | return ( 10 | <Layout> 11 | <SEO title={title} description={desc} /> 12 | <section className="blog-template"> 13 | <div className="section-center"> 14 | <article className="blog-content"> 15 | <ReactMarkdown source={content} /> 16 | </article> 17 | <Link to="/blog" className="btn center-btn"> 18 | blog 19 | </Link> 20 | </div> 21 | </section> 22 | </Layout> 23 | ); 24 | }; 25 | 26 | export const query = graphql` 27 | query GetSingleBlog($slug: String) { 28 | blog: strapiBlogs(slug: { eq: $slug }) { 29 | content 30 | title 31 | desc 32 | } 33 | } 34 | `; 35 | 36 | export default ComponentName; 37 | --------------------------------------------------------------------------------