🛠️ build(static): change from astro to gatsby
76
.gitignore
vendored
@@ -1,21 +1,69 @@
|
||||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# macOS-specific files
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# dotenv environment variable files
|
||||
.env*
|
||||
|
||||
# gatsby files
|
||||
.cache/
|
||||
public
|
||||
|
||||
# Mac files
|
||||
.DS_Store
|
||||
|
||||
# Yarn
|
||||
yarn-error.log
|
||||
.pnp/
|
||||
.pnp.js
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
4
.prettierignore
Normal file
@@ -0,0 +1,4 @@
|
||||
.cache
|
||||
package.json
|
||||
package-lock.json
|
||||
public
|
7
.prettierrc
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
4
.vscode/extensions.json
vendored
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
.vscode/launch.json
vendored
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
22
LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 gatsbyjs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
141
README.md
@@ -1,54 +1,117 @@
|
||||
# Starlight Starter Kit: Basics
|
||||
<p align="center">
|
||||
<img src="https://i.imgur.com/ROJE2rc.png" width="100" alt="bartzalewski.com logo" />
|
||||
</p>
|
||||
|
||||
[](https://starlight.astro.build)
|
||||
<h1 align="center">
|
||||
bartzalewski.com - v2
|
||||
</h1>
|
||||
|
||||
```
|
||||
npm create astro@latest -- --template starlight
|
||||
```
|
||||
<p align="center">
|
||||
This is a project of my new, refreshed website, that is free to use.
|
||||
</p>
|
||||
|
||||
[](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics)
|
||||
[](https://codesandbox.io/p/sandbox/github/withastro/starlight/tree/main/examples/basics)
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwithastro%2Fstarlight%2Ftree%2Fmain%2Fexamples%2Fbasics&project-name=my-starlight-docs&repository-name=my-starlight-docs)
|
||||
<p align="center">
|
||||
<a href="https://app.netlify.com/sites/eager-lichterman-b07f67/deploys" target="_blank">
|
||||
<img src="https://api.netlify.com/api/v1/badges/84b336d8-8c1f-484e-ad19-efabafc468f0/deploy-status" alt="Netlify Status" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||

|
||||
|
||||
## 🚀 Project Structure
|
||||
## ⭐ How To Install?
|
||||
|
||||
Inside of your Astro + Starlight project, you'll see the following folders and files:
|
||||
To be able to use this properly, you need to choose between the three versions of this portfolio. If you want to make sure that it'll work for you, just don't install it via the master branch, because it won't start for you. There are 3 versions down below, depending on what you choose, you will have to do different things to make it fully working.
|
||||
|
||||
```
|
||||
.
|
||||
├── public/
|
||||
├── src/
|
||||
│ ├── assets/
|
||||
│ ├── content/
|
||||
│ │ ├── docs/
|
||||
│ │ └── config.ts
|
||||
│ └── env.d.ts
|
||||
├── astro.config.mjs
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
### Choose your version:
|
||||
|
||||
Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name.
|
||||
- <a href="#contentful">Contentful Blog</a>
|
||||
|
||||
Images can be added to `src/assets/` and embedded in Markdown with a relative link.
|
||||
- [Markdown blog](https://github.com/bartzalewski/bartzalewski.com-v2/tree/md-blog)
|
||||
|
||||
Static assets, like favicons, can be placed in the `public/` directory.
|
||||
- [No blog](https://github.com/bartzalewski/bartzalewski.com-v2/tree/no-blog)
|
||||
|
||||
## 🧞 Commands
|
||||
<h2 id="contentful">
|
||||
1️⃣ Contentful Blog Installation
|
||||
</h2>
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
1. Create [Contentful](http://contentful.com) account.
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
2. Create New Content Model with fields:
|
||||
|
||||
## 👀 Want to learn more?
|
||||
- title (Short Text)
|
||||
- slug (Short Text)
|
||||
- publishedDate (Date & time)
|
||||
- background (Media)
|
||||
- Body (Rich text)
|
||||
|
||||
Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat).
|
||||
3. Add a new post and publish it.
|
||||
|
||||
4. In the portfolio root directory, create a file ".env", and paste the following code to it:
|
||||
|
||||
```
|
||||
CONTENTFUL_SPACE_ID=YOUR_CONTENTFUL_SPACE_ID
|
||||
CONTENTFUL_ACCESS_TOKEN=YOUR_CONTENTFUL_ACCESS_TOKEN
|
||||
```
|
||||
|
||||
5. Paste your IDs and re-run the development server.
|
||||
|
||||
<h2 id="markdown">
|
||||
2️⃣ Markdown blog/No blog Installation
|
||||
</h2>
|
||||
|
||||
No configuration at all. Just install.
|
||||
|
||||
### Installation and set up:
|
||||
|
||||
1. Install [Node.js](https://nodejs.org)
|
||||
|
||||
2. Install the Gatsby CLI
|
||||
|
||||
```
|
||||
npm install -g gatsby-cli
|
||||
```
|
||||
|
||||
3. CD to the forked repo
|
||||
|
||||
```
|
||||
cd bartzalewski.com-v2
|
||||
```
|
||||
|
||||
4. Install the packages
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
5. Start the development server
|
||||
|
||||
```
|
||||
npm start
|
||||
```
|
||||
|
||||
## 📝 How to make the Contact Form work?
|
||||
|
||||
[Click here](https://github.com/bartzalewski/bartzalewski.com-v2-mail)
|
||||
|
||||
## ⚠️ Using it as Your Portfolio
|
||||
|
||||
As I'm making this repo public for all, you can easily get it and use it how you want. But, there is a must. You need to attribute me. You must leave alone the attribution under the copyright statement ("Created By Bart Zalewski").
|
||||
|
||||
In the beginning, I created this website only for myself, for portfolio purposes. Now, you can just download it and use it for your purposes.
|
||||
|
||||
### TL;DR
|
||||
|
||||
You can fork this repository, but please give me proper credit by linking back to my website - [bartzalewski.com](https://bartzalewski.com).
|
||||
|
||||
Thank you! 💚
|
||||
|
||||
## ✨ What kind of technologies did I use?
|
||||
|
||||
- GatsbyJS
|
||||
- styled-components
|
||||
- Contentful
|
||||
- React Helmet
|
||||
|
||||
## Follow me!
|
||||
|
||||
[Website](https://www.bartzalewski.com) • [Instagram](https://www.instagram.com/bart.code) • [YouTube](https://www.youtube.com/channel/UCwkU0-_RJbS16X5pbcW-tPQ)
|
||||
|
@@ -1,35 +0,0 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import starlight from '@astrojs/starlight';
|
||||
|
||||
import tailwind from "@astrojs/tailwind";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: 'https://Snigdha-OS.github.io',
|
||||
base: 'Snigdha-OS.github.io',
|
||||
integrations: [starlight({
|
||||
title: 'SNIGDHA OS',
|
||||
customCss: [
|
||||
// Path to Snigdha OS Custom CSS Files
|
||||
'./src/styles/custom.css',
|
||||
],
|
||||
social: {
|
||||
github: 'https://github.com/Snigdha-OS/',
|
||||
facebook: 'https://facebook.com/',
|
||||
},
|
||||
sidebar: [{
|
||||
label: 'Guides',
|
||||
items: [
|
||||
// Each item here is one entry in the navigation menu.
|
||||
{
|
||||
label: 'Example Guide',
|
||||
link: '/guides/example/'
|
||||
}]
|
||||
}, {
|
||||
label: 'Reference',
|
||||
autogenerate: {
|
||||
directory: 'reference'
|
||||
}
|
||||
}]
|
||||
}), tailwind()]
|
||||
});
|
7
gatsby-browser.js
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Implement Gatsby's Browser APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/browser-apis/
|
||||
*/
|
||||
|
||||
// You can delete this file if you're not using it
|
49
gatsby-config.js
Normal file
@@ -0,0 +1,49 @@
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: `Bart Zalewski | Front-end Developer`,
|
||||
author: `Bart Zalewski`,
|
||||
role: `Front-end Developer`,
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
resolve: `gatsby-plugin-google-analytics`,
|
||||
options: {
|
||||
trackingId: process.env.GOOGLE_ANALYTICS_ID,
|
||||
head: true,
|
||||
anonymize: true,
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-react-helmet`,
|
||||
`gatsby-plugin-styled-components`,
|
||||
{
|
||||
resolve: `gatsby-source-contentful`,
|
||||
options: {
|
||||
spaceId: process.env.CONTENTFUL_SPACE_ID,
|
||||
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
name: `images`,
|
||||
path: `${__dirname}/src/images`,
|
||||
},
|
||||
},
|
||||
`gatsby-transformer-sharp`,
|
||||
`gatsby-plugin-sharp`,
|
||||
{
|
||||
resolve: `gatsby-plugin-manifest`,
|
||||
options: {
|
||||
name: `Bart Zalewski | Front-end Developer`,
|
||||
short_name: `Bart Zalewski`,
|
||||
start_url: `/`,
|
||||
background_color: `#02D463`,
|
||||
theme_color: `#02D463`,
|
||||
display: `minimal-ui`,
|
||||
icon: `src/images/logo.png`,
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-offline`,
|
||||
`gatsby-plugin-image`,
|
||||
],
|
||||
}
|
39
gatsby-node.js
Normal file
@@ -0,0 +1,39 @@
|
||||
const path = require('path')
|
||||
|
||||
module.exports.createPages = async ({ graphql, actions }) => {
|
||||
const { createPage } = actions
|
||||
const blogTemplate = path.resolve('./src/templates/blog.js')
|
||||
const res = await graphql(`
|
||||
query {
|
||||
allContentfulBlogPost {
|
||||
edges {
|
||||
node {
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
res.data.allContentfulBlogPost.edges.forEach((edge) => {
|
||||
createPage({
|
||||
component: blogTemplate,
|
||||
path: `/blog/${edge.node.slug}`,
|
||||
context: {
|
||||
slug: edge.node.slug,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
exports.onCreateWebpackConfig = ({ stage, actions }) => {
|
||||
if (stage.startsWith('develop')) {
|
||||
actions.setWebpackConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'react-dom': '@hot-loader/react-dom',
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
7
gatsby-ssr.js
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/ssr-apis/
|
||||
*/
|
||||
|
||||
// You can delete this file if you're not using it
|
25768
package-lock.json
generated
77
package.json
@@ -1,22 +1,63 @@
|
||||
{
|
||||
"name": "",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro check && astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"name": "bartzalewski.com-v2",
|
||||
"private": true,
|
||||
"description": "Bart Zalewski | Front-end Developer",
|
||||
"version": "0.1.0",
|
||||
"author": "Bart Zalewski <me@bartzalewski.com>",
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.7.0",
|
||||
"@astrojs/starlight": "^0.24.2",
|
||||
"@astrojs/starlight-tailwind": "^2.0.3",
|
||||
"@astrojs/tailwind": "^5.1.0",
|
||||
"astro": "^4.10.2",
|
||||
"sharp": "^0.32.5",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"typescript": "^5.4.5"
|
||||
"@contentful/rich-text-react-renderer": "^15.11.1",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.3.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.0.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.0.0",
|
||||
"@fortawesome/react-fontawesome": "^0.1.17",
|
||||
"@hot-loader/react-dom": "^17.0.2",
|
||||
"axios": "^0.25.0",
|
||||
"babel-plugin-styled-components": "^2.0.2",
|
||||
"gatsby": "^4.6.2",
|
||||
"gatsby-image": "^3.11.0",
|
||||
"gatsby-plugin-google-analytics": "^4.6.0",
|
||||
"gatsby-plugin-image": "^2.6.0",
|
||||
"gatsby-plugin-manifest": "^4.6.0",
|
||||
"gatsby-plugin-offline": "^5.6.0",
|
||||
"gatsby-plugin-react-helmet": "^5.6.0",
|
||||
"gatsby-plugin-sharp": "^4.6.0",
|
||||
"gatsby-plugin-styled-components": "^5.6.0",
|
||||
"gatsby-remark-images-contentful": "^5.6.0",
|
||||
"gatsby-source-contentful": "^7.4.0",
|
||||
"gatsby-source-filesystem": "^4.6.0",
|
||||
"gatsby-transformer-sharp": "^4.6.0",
|
||||
"gatsby-transformer-sqip": "^4.6.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-scrollspy": "^3.4.3",
|
||||
"react-spring": "^9.4.2",
|
||||
"smooth-scroll": "^16.1.3",
|
||||
"styled-components": "^5.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"env-cmd": "^10.1.0",
|
||||
"prettier": "^2.5.1"
|
||||
},
|
||||
"keywords": [
|
||||
"gatsby"
|
||||
],
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "env-cmd -f .env.production gatsby build",
|
||||
"develop": "env-cmd -f .env.development gatsby develop",
|
||||
"format": "prettier --write \"**/*.{js,jsx,json,md}\"",
|
||||
"start": "npm run develop",
|
||||
"serve": "gatsby serve",
|
||||
"clean": "gatsby clean",
|
||||
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/gatsbyjs/gatsby/issues"
|
||||
}
|
||||
}
|
||||
|
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M81 36 64 0 47 36l-1 2-9-10a6 6 0 0 0-9 9l10 10h-2L0 64l36 17h2L28 91a6 6 0 1 0 9 9l9-10 1 2 17 36 17-36v-2l9 10a6 6 0 1 0 9-9l-9-9 2-1 36-17-36-17-2-1 9-9a6 6 0 1 0-9-9l-9 10v-2Zm-17 2-2 5c-4 8-11 15-19 19l-5 2 5 2c8 4 15 11 19 19l2 5 2-5c4-8 11-15 19-19l5-2-5-2c-8-4-15-11-19-19l-2-5Z" clip-rule="evenodd"/><path d="M118 19a6 6 0 0 0-9-9l-3 3a6 6 0 1 0 9 9l3-3Zm-96 4c-2 2-6 2-9 0l-3-3a6 6 0 1 1 9-9l3 3c3 2 3 6 0 9Zm0 82c-2-2-6-2-9 0l-3 3a6 6 0 1 0 9 9l3-3c3-2 3-6 0-9Zm96 4a6 6 0 0 1-9 9l-3-3a6 6 0 1 1 9-9l3 3Z"/><style>path{fill:#000}@media (prefers-color-scheme:dark){path{fill:#fff}}</style></svg>
|
Before Width: | Height: | Size: 696 B |
Before Width: | Height: | Size: 96 KiB |
167
src/components/about.js
Normal file
@@ -0,0 +1,167 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
|
||||
import bart from '../images/bart.jpg'
|
||||
|
||||
const AboutSection = styled.section`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding: 100px 0;
|
||||
`
|
||||
const Container = styled.div`
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
`
|
||||
const Wrapper = styled.div`
|
||||
width: 50%;
|
||||
`
|
||||
const Title = styled.h2``
|
||||
const Description = styled.p`
|
||||
width: 80%;
|
||||
margin-top: 50px;
|
||||
color: #bdbdbd;
|
||||
text-align: left;
|
||||
`
|
||||
const List = styled.ul`
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(140px, 200px));
|
||||
margin-top: 25px;
|
||||
`
|
||||
const Item = styled.li`
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
color: #bdbdbd;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:hover {
|
||||
span {
|
||||
color: #02d463;
|
||||
transition: 0.2s;
|
||||
}
|
||||
}
|
||||
|
||||
.skill__icon {
|
||||
margin-right: 15px;
|
||||
color: #02d463;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
&.skill__jquery {
|
||||
transition: 0.2s;
|
||||
|
||||
.skill__icon,
|
||||
span {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
span {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
`
|
||||
const ItemText = styled.span``
|
||||
const Image = styled.img`
|
||||
opacity: 0.4;
|
||||
transition: 0.5s;
|
||||
box-shadow: 0px 0px 20px rgba(0, 0, 0, 1);
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
transition: 0.5s;
|
||||
}
|
||||
`
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
<AboutSection id="about">
|
||||
<div className="container container--secondary">
|
||||
<Container className="container container--primary about__container">
|
||||
<Wrapper className="about__wrapper">
|
||||
<Title>About me</Title>
|
||||
<Description className="about__desc section__desc">
|
||||
I began my coding journey in December 2018 as a self-taught developer. My passion lies in crafting modern, visually appealing websites enhanced with subtle animations. I'm deeply committed to my work and always eager to collaborate on exciting projects. If you have an idea or project in mind, I'd love to hear from you!
|
||||
</Description>
|
||||
<Description className="section__desc">
|
||||
Technologies that I use:
|
||||
</Description>
|
||||
<List>
|
||||
<Item>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'react']}
|
||||
className="skill__icon"
|
||||
/>
|
||||
<ItemText>React</ItemText>
|
||||
</Item>
|
||||
<Item>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'node-js']}
|
||||
className="skill__icon"
|
||||
/>
|
||||
<ItemText>Node.js</ItemText>
|
||||
</Item>
|
||||
<Item>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'js-square']}
|
||||
className="skill__icon"
|
||||
/>
|
||||
<ItemText>JavaScript</ItemText>
|
||||
</Item>
|
||||
<Item>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'php']}
|
||||
className="skill__icon"
|
||||
/>
|
||||
<ItemText>PHP</ItemText>
|
||||
</Item>
|
||||
<Item>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'html5']}
|
||||
className="skill__icon"
|
||||
/>
|
||||
<ItemText>HTML</ItemText>
|
||||
</Item>
|
||||
<Item>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'sass']}
|
||||
className="skill__icon"
|
||||
/>
|
||||
<ItemText>S(CSS)</ItemText>
|
||||
</Item>
|
||||
<Item>
|
||||
<FontAwesomeIcon icon="fire" className="skill__icon" />
|
||||
<ItemText>Firebase</ItemText>
|
||||
</Item>
|
||||
<Item>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'bootstrap']}
|
||||
className="skill__icon"
|
||||
/>
|
||||
<ItemText>Bootstrap</ItemText>
|
||||
</Item>
|
||||
<Item>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'figma']}
|
||||
className="skill__icon"
|
||||
/>
|
||||
<ItemText>Figma</ItemText>
|
||||
</Item>
|
||||
<Item className="skill__jquery">
|
||||
<FontAwesomeIcon icon="cross" className="skill__icon" />
|
||||
<ItemText>jQuery</ItemText>
|
||||
</Item>
|
||||
</List>
|
||||
</Wrapper>
|
||||
<Image src={bart} alt="Bart Zalewski" loading="lazy" />
|
||||
</Container>
|
||||
</div>
|
||||
</AboutSection>
|
||||
)
|
||||
}
|
118
src/components/blog.js
Normal file
@@ -0,0 +1,118 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { Link, graphql, useStaticQuery } from 'gatsby'
|
||||
|
||||
const BlogSection = styled.section`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding: 100px 0;
|
||||
`
|
||||
const Container = styled.div`
|
||||
align-items: flex-end;
|
||||
`
|
||||
const Title = styled.h2``
|
||||
const Description = styled.p`
|
||||
text-align: center;
|
||||
margin: 50px 0;
|
||||
color: #bdbdbd;
|
||||
`
|
||||
const List = styled.ul`
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 20px;
|
||||
width: 100%;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
margin-bottom: 50px;
|
||||
`
|
||||
const Box = styled.li`
|
||||
background: #111;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
transition: 0.4s;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
opacity: 0.4;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-10px);
|
||||
transition: 0.4s;
|
||||
opacity: 1;
|
||||
}
|
||||
`
|
||||
const Image = styled.img`
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border-radius: 4px;
|
||||
object-fit: cover;
|
||||
`
|
||||
const PostTitle = styled.p`
|
||||
font-family: 'JetBrains Mono';
|
||||
direction: ltr;
|
||||
margin: 10px 0 5px;
|
||||
`
|
||||
const PostTime = styled.p`
|
||||
font-size: 14px;
|
||||
color: #bdbdbd;
|
||||
direction: ltr;
|
||||
`
|
||||
|
||||
export default function Blog() {
|
||||
const data = useStaticQuery(graphql`
|
||||
query {
|
||||
allContentfulBlogPost(
|
||||
sort: { fields: publishedDate, order: DESC }
|
||||
limit: 8
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
title
|
||||
slug
|
||||
publishedDate(formatString: "MMMM Do, YYYY")
|
||||
background {
|
||||
file {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
const output = data.allContentfulBlogPost.edges.map((element) => {
|
||||
const { id, slug, background, title, publishedDate } = element.node
|
||||
return (
|
||||
<Box key={id} className="blog__box">
|
||||
<Link to={`/blog/${slug}`}>
|
||||
<Image
|
||||
className="blog__img"
|
||||
src={background.file.url}
|
||||
alt={title}
|
||||
loading="lazy"
|
||||
/>
|
||||
<PostTitle className="blog__title">{title}</PostTitle>
|
||||
<PostTime className="blog__time">{publishedDate}</PostTime>
|
||||
</Link>
|
||||
</Box>
|
||||
)
|
||||
})
|
||||
return (
|
||||
<BlogSection id="blog">
|
||||
<div className="container container--secondary">
|
||||
<Container className="container container--primary blog__container">
|
||||
<Title>Blog</Title>
|
||||
<Description className="blog__desc section__desc">
|
||||
Check out my blog!
|
||||
</Description>
|
||||
<List className="blog__wrapper">{output}</List>
|
||||
<Link to="/blog" className="btn btn--primary">
|
||||
See more
|
||||
</Link>
|
||||
</Container>
|
||||
</div>
|
||||
</BlogSection>
|
||||
)
|
||||
}
|
57
src/components/board/board.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import BoardBox from './boardBox'
|
||||
|
||||
import grammarlyWebM from '../../images/projects/grammarlydark.webm'
|
||||
import hoppWebM from '../../images/projects/hopp.webm'
|
||||
import joindevsWebM from '../../images/projects/joindevs.webm'
|
||||
import bartzalewskiV2WebM from '../../images/projects/bartzalewski-v2.webm'
|
||||
|
||||
const BoardWrapper = styled.div`
|
||||
width: 100%;
|
||||
background: #212121;
|
||||
box-shadow: 0px 0px 40px rgba(0, 0, 0, 0.5);
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: -50px;
|
||||
padding-top: 56.25%;
|
||||
transform: rotate3d(0.5, -0.866, 0, 15deg) rotate(-1deg);
|
||||
`
|
||||
const Grid = styled.div`
|
||||
display: grid;
|
||||
grid-gap: 10px;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
outline: 10px solid #222;
|
||||
`
|
||||
|
||||
const Board = () => {
|
||||
return (
|
||||
<BoardWrapper className="board__container">
|
||||
<Grid className="board__grid">
|
||||
<BoardBox
|
||||
bgwebm={joindevsWebM}
|
||||
title="JoinDevs"
|
||||
url="https://joindevs.com/"
|
||||
/>
|
||||
<BoardBox bgwebm={hoppWebM} title="HOPP" url="https://hopp.pl/" />
|
||||
<BoardBox
|
||||
bgwebm={grammarlyWebM}
|
||||
title="Grammarly Dark"
|
||||
url="https://chrome.google.com/webstore/detail/grammarly-dark/noojmhngiheennhgaffkfboanjpbkpep"
|
||||
/>
|
||||
<BoardBox
|
||||
bgwebm={bartzalewskiV2WebM}
|
||||
title="Bart Zalewski v2"
|
||||
url="https://bartzalewski.com/"
|
||||
/>
|
||||
</Grid>
|
||||
</BoardWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export default Board
|
100
src/components/board/boardBox.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import React, { useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { useSpring, animated as a } from 'react-spring'
|
||||
|
||||
const Container = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #111;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
`
|
||||
const Wrapper = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
outline: none;
|
||||
left: -10px;
|
||||
top: -10px;
|
||||
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.5));
|
||||
|
||||
.back {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.front {
|
||||
background: #222;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
video,
|
||||
.back {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: fill;
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
`
|
||||
const Source = styled.source``
|
||||
const Title = styled.p``
|
||||
const Button = styled.a``
|
||||
|
||||
const BoardBox = ({ bgwebm, title, url }) => {
|
||||
const [flipped, set] = useState(false)
|
||||
const { transform, opacity } = useSpring({
|
||||
opacity: flipped ? 1 : 0,
|
||||
transform: `perspective(600px) rotateX(${flipped ? 180 : 0}deg)`,
|
||||
config: { mass: 5, tension: 500, friction: 80 },
|
||||
})
|
||||
return (
|
||||
<Container className="board__wrapper">
|
||||
<Wrapper
|
||||
className="board__box"
|
||||
onMouseEnter={() => set((state) => !state)}
|
||||
onMouseLeave={() => set((state) => !state)}
|
||||
role="button"
|
||||
tabIndex="0"
|
||||
>
|
||||
<a.video
|
||||
className="back"
|
||||
loop={true}
|
||||
autoPlay={true}
|
||||
muted={true}
|
||||
playsInline={true}
|
||||
style={{
|
||||
opacity: opacity.interpolate((o) => 1 - o),
|
||||
transform,
|
||||
}}
|
||||
>
|
||||
<Source src={bgwebm} type="video/webm" />
|
||||
</a.video>
|
||||
<a.div
|
||||
className="front"
|
||||
style={{
|
||||
opacity,
|
||||
transform: transform.interpolate((t) => `${t} rotateX(180deg)`),
|
||||
}}
|
||||
>
|
||||
<Title>{title}</Title>
|
||||
<Button
|
||||
className="btn btn--secondary"
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
View
|
||||
</Button>
|
||||
</a.div>
|
||||
</Wrapper>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default BoardBox
|
251
src/components/contact.js
Normal file
@@ -0,0 +1,251 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import axios from 'axios'
|
||||
|
||||
const ContactSection = styled.section`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #111;
|
||||
padding: 100px 0;
|
||||
`
|
||||
const Title = styled.h2``
|
||||
const Description = styled.p`
|
||||
text-align: center;
|
||||
margin: 50px 0;
|
||||
color: #bdbdbd;
|
||||
`
|
||||
const Success = styled.span``
|
||||
const Failure = styled.span``
|
||||
const Form = styled.form`
|
||||
margin: 50px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
|
||||
.btn {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
input[type='submit'] {
|
||||
font-family: 'JetBrains Mono';
|
||||
cursor: pointer;
|
||||
font-size: inherit;
|
||||
background: #02d463 !important;
|
||||
color: inherit;
|
||||
width: fit-content;
|
||||
padding: 10px 17.5px;
|
||||
height: auto;
|
||||
border: 2px solid #02d463;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
color: #02d463;
|
||||
background: transparent !important;
|
||||
}
|
||||
}
|
||||
`
|
||||
const InputField = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&.focus input,
|
||||
&.focus textarea {
|
||||
border-color: #02d463;
|
||||
}
|
||||
|
||||
&.focus label {
|
||||
color: #02d463;
|
||||
transition: 0.2s;
|
||||
}
|
||||
`
|
||||
const InputFieldGrid = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-gap: 10px;
|
||||
width: 50%;
|
||||
`
|
||||
const InputFieldTextarea = styled.div`
|
||||
margin-top: 1rem;
|
||||
width: 50%;
|
||||
|
||||
&.focus input,
|
||||
&.focus textarea {
|
||||
border-color: #02d463;
|
||||
}
|
||||
|
||||
&.focus label {
|
||||
color: #02d463;
|
||||
transition: 0.2s;
|
||||
}
|
||||
`
|
||||
const Label = styled.label`
|
||||
color: #333;
|
||||
margin-bottom: 0.5rem;
|
||||
text-shadow: 0px 0px 10px black;
|
||||
font-size: 14px;
|
||||
`
|
||||
const Input = styled.input`
|
||||
border-radius: 4px;
|
||||
border: 2px solid #1a1a1a;
|
||||
height: 60px;
|
||||
width: 100%;
|
||||
font-family: 'JetBrains Mono';
|
||||
background: transparent;
|
||||
color: #02d463;
|
||||
transition: 0.2s;
|
||||
outline: none;
|
||||
font-size: inherit;
|
||||
padding: 15px;
|
||||
background: #1a1a1a;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
|
||||
&:focus {
|
||||
border-color: #02d463;
|
||||
transition: 0.2s;
|
||||
}
|
||||
`
|
||||
const Textarea = styled.textarea`
|
||||
border-radius: 4px;
|
||||
border: 2px solid #1a1a1a;
|
||||
width: 100%;
|
||||
font-family: 'JetBrains Mono';
|
||||
background: transparent;
|
||||
color: #02d463;
|
||||
transition: 0.2s;
|
||||
outline: none;
|
||||
font-size: inherit;
|
||||
padding: 15px;
|
||||
background: #1a1a1a;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
height: 200px;
|
||||
resize: none;
|
||||
margin-top: 6px;
|
||||
|
||||
&:focus {
|
||||
border-color: #02d463;
|
||||
transition: 0.2s;
|
||||
}
|
||||
`
|
||||
|
||||
export default function Contact() {
|
||||
const resetForm = () => document.getElementById('contact-form').reset()
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
const name = document.getElementById('name').value
|
||||
const email = document.getElementById('email').value
|
||||
const message = document.getElementById('message').value
|
||||
const success = document.getElementById('success')
|
||||
const failure = document.getElementById('failure')
|
||||
|
||||
axios({
|
||||
method: 'POST',
|
||||
url: 'https://bartzalewski-v2-api.herokuapp.com/send',
|
||||
data: {
|
||||
name: name,
|
||||
email: email,
|
||||
message: message,
|
||||
},
|
||||
}).then((response) => {
|
||||
if (response.data.msg === 'success') {
|
||||
success.style.display = 'block'
|
||||
|
||||
resetForm()
|
||||
} else if (response.data.msg === 'fail') {
|
||||
failure.style.display = 'block'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const inputs = document.querySelectorAll('.input__field-input')
|
||||
|
||||
function addcl() {
|
||||
let parent = this.parentNode
|
||||
parent.classList.add('focus')
|
||||
}
|
||||
|
||||
function remcl() {
|
||||
let parent = this.parentNode
|
||||
if (this.value === '') {
|
||||
parent.classList.remove('focus')
|
||||
}
|
||||
}
|
||||
|
||||
inputs.forEach((input) => {
|
||||
input.addEventListener('focus', addcl)
|
||||
input.addEventListener('blur', remcl)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<ContactSection id="contact">
|
||||
<div className="container container--secondary">
|
||||
<div className="container container--primary">
|
||||
<Title>Get in touch</Title>
|
||||
<Description className="contact__desc section__desc">
|
||||
Contact me!
|
||||
</Description>
|
||||
<Success id="success" className="colored" style={{ display: 'none' }}>
|
||||
Message sent!
|
||||
</Success>
|
||||
<Failure id="failure" style={{ color: '#FF5252', display: 'none' }}>
|
||||
Message failed to sent!
|
||||
</Failure>
|
||||
<Form
|
||||
onSubmit={handleSubmit}
|
||||
method="POST"
|
||||
className="contact__wrapper"
|
||||
id="contact-form"
|
||||
>
|
||||
<InputFieldGrid className="input__field--grid">
|
||||
<InputField className="input__field">
|
||||
<Label htmlFor="name">Name</Label>
|
||||
<Input
|
||||
aria-label="Name"
|
||||
required
|
||||
className="input__field-input"
|
||||
id="name"
|
||||
name="name"
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</InputField>
|
||||
<InputField className="input__field">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input
|
||||
aria-label="Email"
|
||||
required
|
||||
className="input__field-input"
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</InputField>
|
||||
</InputFieldGrid>
|
||||
<InputFieldTextarea className="input__field input__textarea">
|
||||
<Label htmlFor="message">Message</Label>
|
||||
<Textarea
|
||||
aria-label="Message"
|
||||
required
|
||||
className="input__field-input"
|
||||
id="message"
|
||||
name="message"
|
||||
></Textarea>
|
||||
</InputFieldTextarea>
|
||||
<Input
|
||||
aria-label="Submit"
|
||||
type="submit"
|
||||
value="Submit"
|
||||
className="btn btn--primary"
|
||||
/>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</ContactSection>
|
||||
)
|
||||
}
|
29
src/components/defaults/head.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useStaticQuery, graphql } from 'gatsby'
|
||||
|
||||
const Head = ({ title }) => {
|
||||
const data = useStaticQuery(graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
return (
|
||||
<Helmet
|
||||
title={
|
||||
title
|
||||
? `${title} - ${data.site.siteMetadata.title}`
|
||||
: `${data.site.siteMetadata.title}`
|
||||
}
|
||||
>
|
||||
<meta name="description" content="Bart Zalewski | Front-end Developer" />
|
||||
</Helmet>
|
||||
)
|
||||
}
|
||||
|
||||
export default Head
|
37
src/components/defaults/layout.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import GlobalStyle from '../../theme/globalStyle'
|
||||
import styled from 'styled-components'
|
||||
import Footer from '../footer'
|
||||
|
||||
const LayoutWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
main {
|
||||
flex-grow: 1;
|
||||
}
|
||||
`
|
||||
const Main = styled.main``
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
if (typeof window !== 'undefined') require('smooth-scroll')('a[href*="#"]')
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', () => {
|
||||
const isTop = window.scrollY > 200
|
||||
const nav = document.getElementById('nav')
|
||||
if (nav)
|
||||
isTop ? nav.classList.add('scrolled') : nav.classList.remove('scrolled')
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<GlobalStyle />
|
||||
<Main>{children}</Main>
|
||||
<Footer />
|
||||
</LayoutWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export default Layout
|
130
src/components/footer.js
Normal file
@@ -0,0 +1,130 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { OutboundLink } from 'gatsby-plugin-google-analytics'
|
||||
|
||||
const FooterWrapper = styled.footer`
|
||||
height: 100px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #111;
|
||||
color: white;
|
||||
border-top: 1px solid #212121;
|
||||
`
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
`
|
||||
const Links = styled.div`
|
||||
.footer__link {
|
||||
color: white;
|
||||
margin-right: 20px;
|
||||
transition: 0.2s;
|
||||
|
||||
&:hover {
|
||||
color: #02d463;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
filter: drop-shadow(0px 0px 3px black);
|
||||
}
|
||||
}
|
||||
`
|
||||
const Descriptions = styled.div`
|
||||
.footer__copy {
|
||||
font-size: 14px;
|
||||
}
|
||||
.footer__credit {
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
}
|
||||
`
|
||||
const Description = styled.p``
|
||||
|
||||
const Footer = () => {
|
||||
return (
|
||||
<FooterWrapper>
|
||||
<div className="container container--secondary">
|
||||
<Container className="footer__container container--primary">
|
||||
<Links className="footer__links">
|
||||
<OutboundLink
|
||||
href="https://www.instagram.com/bart.code/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="footer__link"
|
||||
title="Instagram"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'instagram']}
|
||||
className="about__icon"
|
||||
/>
|
||||
</OutboundLink>
|
||||
<OutboundLink
|
||||
href="https://github.com/bartzalewski"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="footer__link"
|
||||
title="GitHub"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'github']}
|
||||
className="about__icon"
|
||||
/>
|
||||
</OutboundLink>
|
||||
<OutboundLink
|
||||
href="https://www.linkedin.com/in/bartzalewski/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="footer__link"
|
||||
title="LinkedIn"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={['fab', 'linkedin']}
|
||||
className="about__icon"
|
||||
/>
|
||||
</OutboundLink>
|
||||
<a
|
||||
href="mailto:me@bartzalewski.com"
|
||||
className="footer__link"
|
||||
title="Email"
|
||||
>
|
||||
<FontAwesomeIcon icon="envelope" />
|
||||
</a>
|
||||
<OutboundLink
|
||||
href="/resume.pdf"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="footer__link"
|
||||
title="Resume"
|
||||
>
|
||||
<FontAwesomeIcon icon="paperclip" />
|
||||
</OutboundLink>
|
||||
</Links>
|
||||
<Descriptions className="footer__desc section__desc">
|
||||
<Description className="footer__copy">
|
||||
Copyright {new Date().getFullYear()} © Bart Zalewski
|
||||
</Description>
|
||||
<Description className="footer__credit">
|
||||
Created by{' '}
|
||||
<a
|
||||
href="https://github.com/bartzalewski/bartzalewski.com-v2"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="Bart Zalewski | Front-end Developer"
|
||||
>
|
||||
Bart Zalewski
|
||||
</a>
|
||||
</Description>
|
||||
</Descriptions>
|
||||
</Container>
|
||||
</div>
|
||||
</FooterWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export default Footer
|
137
src/components/header.js
Normal file
@@ -0,0 +1,137 @@
|
||||
import React, { useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { Link } from 'gatsby'
|
||||
import Scrollspy from 'react-scrollspy'
|
||||
|
||||
import Resume from './resume'
|
||||
|
||||
const HeaderWrapper = styled.header`
|
||||
height: 100px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
transition: 0.4s;
|
||||
position: absolute;
|
||||
`
|
||||
const Navbar = styled.nav`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
|
||||
.navbar__logo {
|
||||
font-family: 'Grand Hotel';
|
||||
font-size: 36px;
|
||||
color: white;
|
||||
transition: 0.2s ease;
|
||||
text-shadow: 0px 0px 10px black;
|
||||
&:hover {
|
||||
color: #02d463;
|
||||
transition: 0.2s ease;
|
||||
}
|
||||
}
|
||||
`
|
||||
const LinkItem = styled(Link)`
|
||||
margin-right: 20px;
|
||||
transition: 0.2s;
|
||||
text-shadow: 0px 0px 10px black;
|
||||
|
||||
&:hover:not(.navbar__resume) {
|
||||
color: #02d463;
|
||||
transition: 0.2s;
|
||||
}
|
||||
`
|
||||
|
||||
const Header = () => {
|
||||
const [sidenavOpened, setSidenavOpened] = useState(false)
|
||||
|
||||
return (
|
||||
<HeaderWrapper id="nav">
|
||||
<Scrollspy
|
||||
id="sidenav"
|
||||
className={sidenavOpened ? 'sidenav sidenav--open' : 'sidenav'}
|
||||
style={{ padding: 0 }}
|
||||
items={['home', 'about', 'projects', 'blog', 'contact']}
|
||||
currentClassName="colored"
|
||||
offset={-60}
|
||||
>
|
||||
<LinkItem
|
||||
href="/#home"
|
||||
className="navbar__link"
|
||||
style={{ display: 'none' }}
|
||||
>
|
||||
Home
|
||||
</LinkItem>
|
||||
<div role="button" onClick={() => setSidenavOpened(!sidenavOpened)}>
|
||||
<LinkItem href="/#about">About</LinkItem>
|
||||
</div>
|
||||
<div role="button" onClick={() => setSidenavOpened(!sidenavOpened)}>
|
||||
<LinkItem href="/#projects">Projects</LinkItem>
|
||||
</div>
|
||||
<div role="button" onClick={() => setSidenavOpened(!sidenavOpened)}>
|
||||
<LinkItem href="/#blog">Blog</LinkItem>
|
||||
</div>
|
||||
<div role="button" onClick={() => setSidenavOpened(!sidenavOpened)}>
|
||||
<LinkItem href="/#contact">Contact</LinkItem>
|
||||
</div>
|
||||
<Resume />
|
||||
</Scrollspy>
|
||||
<Navbar id="navbar" className="navbar__container container--secondary">
|
||||
<LinkItem href="/#" className="navbar__logo">
|
||||
Bart
|
||||
</LinkItem>
|
||||
<div className="hamburger__container">
|
||||
<button
|
||||
aria-label="menu"
|
||||
className="hamburger"
|
||||
onClick={() => setSidenavOpened(!sidenavOpened)}
|
||||
onKeyDown={() => setSidenavOpened(!sidenavOpened)}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
sidenavOpened
|
||||
? 'hamburger__wrapper icon close'
|
||||
: 'hamburger__wrapper icon'
|
||||
}
|
||||
>
|
||||
<span className="hamburger--line top"></span>
|
||||
<span className="hamburger--line middle"></span>
|
||||
<span className="hamburger--line bottom"></span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<Scrollspy
|
||||
className="navbar__links"
|
||||
items={['home', 'about', 'projects', 'blog', 'contact']}
|
||||
currentClassName="colored"
|
||||
offset={-60}
|
||||
>
|
||||
<LinkItem
|
||||
href="/#home"
|
||||
className="navbar__link"
|
||||
style={{ display: 'none' }}
|
||||
>
|
||||
Home
|
||||
</LinkItem>
|
||||
<LinkItem href="/#about" className="navbar__link">
|
||||
About
|
||||
</LinkItem>
|
||||
<LinkItem href="/#projects" className="navbar__link">
|
||||
Projects
|
||||
</LinkItem>
|
||||
<LinkItem href="/#blog" className="navbar__link">
|
||||
Blog
|
||||
</LinkItem>
|
||||
<LinkItem href="/#contact" className="navbar__link">
|
||||
Contact
|
||||
</LinkItem>
|
||||
<Resume />
|
||||
</Scrollspy>
|
||||
</Navbar>
|
||||
</HeaderWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export default Header
|
178
src/components/hero.js
Normal file
@@ -0,0 +1,178 @@
|
||||
import React from 'react'
|
||||
import { graphql, useStaticQuery } from 'gatsby'
|
||||
import styled from 'styled-components'
|
||||
import { trackCustomEvent } from 'gatsby-plugin-google-analytics'
|
||||
import { Link } from 'gatsby'
|
||||
|
||||
import Header from './header'
|
||||
import Board from './board/board'
|
||||
|
||||
import bg from '../images/bg.jpg'
|
||||
import cross from '../images/decorations/cross.svg'
|
||||
import tick from '../images/decorations/tick.svg'
|
||||
import circle from '../images/decorations/circle.svg'
|
||||
|
||||
const HeroSection = styled.section`
|
||||
background-image: url(${bg});
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
height: fit-content;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
.container__hero--secondary {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 5rem 0;
|
||||
}
|
||||
.colored {
|
||||
text-shadow: 0px 0px 10px black;
|
||||
}
|
||||
`
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
flex-direction: column !important;
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
`
|
||||
const HeroContainer = styled.div`
|
||||
justify-content: flex-start;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin-top: 100px;
|
||||
`
|
||||
const Left = styled.div`
|
||||
width: 50%;
|
||||
z-index: 1;
|
||||
`
|
||||
const Greeting = styled.p``
|
||||
const Author = styled.h1``
|
||||
const Role = styled.h2``
|
||||
const Description = styled.p`
|
||||
width: 80%;
|
||||
margin: 50px 0;
|
||||
color: #bdbdbd;
|
||||
text-align: left;
|
||||
`
|
||||
const Right = styled.div`
|
||||
width: 50%;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
perspective: 700px;
|
||||
`
|
||||
const Image = styled.img`
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
|
||||
&.decoration__cross {
|
||||
left: 50%;
|
||||
top: 0;
|
||||
transition: 0.2s;
|
||||
filter: drop-shadow(0px 0px 15px #ff5252);
|
||||
&:hover {
|
||||
transform: rotate(180deg);
|
||||
transition: 0.2s;
|
||||
filter: none;
|
||||
}
|
||||
}
|
||||
&.decoration__tick {
|
||||
left: 35%;
|
||||
bottom: 10%;
|
||||
transition: 0.2s;
|
||||
filter: drop-shadow(0px 0px 15px #02d463);
|
||||
&:hover {
|
||||
transform: scale(0.9);
|
||||
transition: 0.2s;
|
||||
filter: none;
|
||||
}
|
||||
}
|
||||
&.decoration__circle {
|
||||
left: 75%;
|
||||
top: 20%;
|
||||
transition: 0.2s;
|
||||
filter: drop-shadow(0px 0px 15px #00cde2);
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
transition: 0.2s;
|
||||
filter: none;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default function Hero() {
|
||||
const data = useStaticQuery(graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
author
|
||||
role
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
const { author, role } = data.site.siteMetadata
|
||||
|
||||
return (
|
||||
<HeroSection id="home">
|
||||
<Header />
|
||||
<HeroContainer className="container hero__container">
|
||||
<div className="container__hero--secondary container--secondary">
|
||||
<Container className="container--primary">
|
||||
<Left className="hero__left">
|
||||
<Greeting className="colored">Hi, I am</Greeting>
|
||||
<Author>{author}</Author>
|
||||
<Role className="hero__sub">{role}</Role>
|
||||
<Description className="hero__desc section__desc">
|
||||
I specialize in designing, building, shipping, and scaling
|
||||
beautiful, usable products with blazing-fast efficiency.
|
||||
</Description>
|
||||
<Link
|
||||
href="#projects"
|
||||
className="btn btn--primary"
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
trackCustomEvent({
|
||||
category: 'See my work Button',
|
||||
action: 'Click',
|
||||
label: 'Gatsby Google Analytics See my work Button',
|
||||
})
|
||||
}}
|
||||
>
|
||||
See my work
|
||||
</Link>
|
||||
</Left>
|
||||
<Right className="hero__right">
|
||||
<Board />
|
||||
</Right>
|
||||
<Image
|
||||
className="decoration decoration__cross"
|
||||
src={cross}
|
||||
alt="cross"
|
||||
loading="lazy"
|
||||
/>
|
||||
<Image
|
||||
className="decoration decoration__tick"
|
||||
src={tick}
|
||||
alt="tick"
|
||||
loading="lazy"
|
||||
/>
|
||||
<Image
|
||||
className="decoration decoration__circle"
|
||||
src={circle}
|
||||
alt="circle"
|
||||
loading="lazy"
|
||||
/>
|
||||
</Container>
|
||||
</div>
|
||||
</HeroContainer>
|
||||
</HeroSection>
|
||||
)
|
||||
}
|
87
src/components/project.js
Normal file
@@ -0,0 +1,87 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
|
||||
const Box = styled.div`
|
||||
&:hover {
|
||||
span,
|
||||
svg,
|
||||
video {
|
||||
opacity: 1;
|
||||
transition: 0.2s;
|
||||
}
|
||||
}
|
||||
`
|
||||
const Video = styled.video`
|
||||
width: 100%;
|
||||
opacity: 0.4;
|
||||
transition: 0.5s;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 0px 10px black;
|
||||
`
|
||||
const Source = styled.source``
|
||||
const Links = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 10px;
|
||||
span {
|
||||
font-size: 14px;
|
||||
text-shadow: 0px 0px 10px black;
|
||||
opacity: 0.4;
|
||||
transition: 0.2s;
|
||||
}
|
||||
`
|
||||
const Wrapper = styled.div``
|
||||
const Link = styled.a`
|
||||
margin-right: 10px;
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transition: 0.2s;
|
||||
filter: drop-shadow(0px 0px 3px black);
|
||||
opacity: 0.4;
|
||||
&:hover {
|
||||
color: #02d463;
|
||||
transition: 0.2s;
|
||||
}
|
||||
}
|
||||
`
|
||||
const Title = styled.span``
|
||||
|
||||
const Project = ({ title, bgwebm, github, external }) => (
|
||||
<Box className="work__box">
|
||||
<Video
|
||||
alt={title}
|
||||
loop={true}
|
||||
autoPlay={true}
|
||||
muted={true}
|
||||
playsInline={true}
|
||||
>
|
||||
<Source src={bgwebm} type="video/webm" />
|
||||
</Video>
|
||||
<Links className="work__links">
|
||||
<Wrapper>
|
||||
<Link
|
||||
href={github}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="GitHub"
|
||||
>
|
||||
<FontAwesomeIcon icon={['fab', 'github']} className="about__icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href={external}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="External"
|
||||
>
|
||||
<FontAwesomeIcon icon="external-link-alt" />
|
||||
</Link>
|
||||
</Wrapper>
|
||||
<Title>{title}</Title>
|
||||
</Links>
|
||||
</Box>
|
||||
)
|
||||
|
||||
export default Project
|
165
src/components/projects.js
Normal file
@@ -0,0 +1,165 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import Project from './project'
|
||||
|
||||
import hoppWebM from '../images/projects/hopp.webm'
|
||||
import grammarlyWebM from '../images/projects/grammarlydark.webm'
|
||||
import pagetifyWebM from '../images/projects/pagetify.webm'
|
||||
import schoolifyWebM from '../images/projects/schoolify.webm'
|
||||
import dojrzewajWebM from '../images/projects/dojrzewaj.webm'
|
||||
import centrummotoWebM from '../images/projects/centrummoto.webm'
|
||||
import cz5pWebM from '../images/projects/cz5p.webm'
|
||||
import teleanWebM from '../images/projects/telean.webm'
|
||||
import darkpaypalWebM from '../images/projects/darkpaypal.webm'
|
||||
import bartzalewskiV1WebM from '../images/projects/bartzalewski-v1.webm'
|
||||
import joindevsWebM from '../images/projects/joindevs.webm'
|
||||
import bartzalewskiV2WebM from '../images/projects/bartzalewski-v2.webm'
|
||||
|
||||
const ProjectsWrapper = styled.section`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
background: #111;
|
||||
padding: 100px 0;
|
||||
`
|
||||
const WorkWrapper = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-gap: 60px 20px;
|
||||
width: 100%;
|
||||
`
|
||||
const Title = styled.h2``
|
||||
const Description = styled.p`
|
||||
text-align: center;
|
||||
margin: 50px 0;
|
||||
color: #bdbdbd;
|
||||
`
|
||||
const Animation = styled.div`
|
||||
&:nth-of-type(2),
|
||||
&:nth-of-type(5),
|
||||
&:nth-of-type(8),
|
||||
&:nth-of-type(11) {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
&:nth-of-type(3),
|
||||
&:nth-of-type(6),
|
||||
&:nth-of-type(9),
|
||||
&:nth-of-type(12) {
|
||||
margin-top: 100px;
|
||||
}
|
||||
`
|
||||
|
||||
export default function Projects() {
|
||||
return (
|
||||
<ProjectsWrapper id="projects">
|
||||
<div className="container container--secondary">
|
||||
<div className="container container--primary">
|
||||
<Title>My side projects</Title>
|
||||
<Description className="work__desc section__desc">
|
||||
Check out my portfolio!
|
||||
</Description>
|
||||
<WorkWrapper className="work__wrapper">
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="JoinDevs"
|
||||
bgwebm={joindevsWebM}
|
||||
github="#!"
|
||||
external="https://joindevs.com/"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="HOPP"
|
||||
bgwebm={hoppWebM}
|
||||
github="#!"
|
||||
external="https://hopp.pl/"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="Grammarly Dark"
|
||||
bgwebm={grammarlyWebM}
|
||||
github="https://github.com/bartzalewski/grammarly-dark"
|
||||
external="https://www.producthunt.com/posts/grammarly-dark"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="My second portfolio"
|
||||
bgwebm={bartzalewskiV2WebM}
|
||||
github="https://github.com/bartzalewski/bartzalewski.com-v2"
|
||||
external="https://bartzalewski.com/"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="Pagetify"
|
||||
bgwebm={pagetifyWebM}
|
||||
github="https://github.com/bartzalewski/pagetify"
|
||||
external="https://pagetify.com/"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="Schoolify"
|
||||
bgwebm={schoolifyWebM}
|
||||
github="https://github.com/bartzalewski/schoolify"
|
||||
external="https://schoolify.app/"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="dojrzewaj.pl"
|
||||
bgwebm={dojrzewajWebM}
|
||||
github="#!"
|
||||
external="https://dojrzewaj.pl/"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="Centrum Moto"
|
||||
bgwebm={centrummotoWebM}
|
||||
github="#!"
|
||||
external="https://centrummoto.pl/"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="coza500plus.pl"
|
||||
bgwebm={cz5pWebM}
|
||||
github="https://github.com/bartzalewski/coza500plus"
|
||||
external="https://coza500plus.pl/"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="Telean"
|
||||
bgwebm={teleanWebM}
|
||||
github="https://github.com/bartzalewski/telean-website"
|
||||
external="https://telean-website.herokuapp.com/"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="Dark PayPal"
|
||||
bgwebm={darkpaypalWebM}
|
||||
github="https://github.com/bartzalewski/darkness"
|
||||
external="#!"
|
||||
/>
|
||||
</Animation>
|
||||
<Animation className="work--animation">
|
||||
<Project
|
||||
title="My first portfolio"
|
||||
bgwebm={bartzalewskiV1WebM}
|
||||
github="https://github.com/bartzalewski/bartzalewski.com-v1"
|
||||
external="https://bartzalewski-v1.herokuapp.com/"
|
||||
/>
|
||||
</Animation>
|
||||
</WorkWrapper>
|
||||
</div>
|
||||
</div>
|
||||
</ProjectsWrapper>
|
||||
)
|
||||
}
|
15
src/components/resume.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react'
|
||||
import { OutboundLink } from 'gatsby-plugin-google-analytics'
|
||||
|
||||
const Resume = () => (
|
||||
<OutboundLink
|
||||
href="/resume.pdf"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="navbar__link navbar__resume btn btn--secondary"
|
||||
>
|
||||
Resume
|
||||
</OutboundLink>
|
||||
)
|
||||
|
||||
export default Resume
|
@@ -1,6 +0,0 @@
|
||||
import { defineCollection } from 'astro:content';
|
||||
import { docsSchema } from '@astrojs/starlight/schema';
|
||||
|
||||
export const collections = {
|
||||
docs: defineCollection({ schema: docsSchema() }),
|
||||
};
|
@@ -1,11 +0,0 @@
|
||||
---
|
||||
title: Example Guide
|
||||
description: A guide in my new Starlight docs site.
|
||||
---
|
||||
|
||||
Guides lead a user through a specific task they want to accomplish, often with a sequence of steps.
|
||||
Writing a good guide requires thinking about what your users are trying to do.
|
||||
|
||||
## Further reading
|
||||
|
||||
- Read [about how-to guides](https://diataxis.fr/how-to-guides/) in the Diátaxis framework
|
@@ -1,36 +0,0 @@
|
||||
---
|
||||
title: SNIGDHA OS
|
||||
description: Get started building your docs site with Starlight.
|
||||
template: splash
|
||||
hero:
|
||||
tagline: Congrats on setting up a new Starlight project!
|
||||
image:
|
||||
file: ../../assets/houston.webp
|
||||
actions:
|
||||
- text: Download
|
||||
link: /guides/example/
|
||||
icon: right-arrow
|
||||
variant: primary
|
||||
- text: Read the Starlight docs
|
||||
link: https://starlight.astro.build
|
||||
icon: external
|
||||
---
|
||||
|
||||
import { Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGrid stagger>
|
||||
<Card title="Update content" icon="pencil">
|
||||
Edit `src/content/docs/index.mdx` to see this page change.
|
||||
</Card>
|
||||
<Card title="Add new content" icon="add-document">
|
||||
Add Markdown or MDX files to `src/content/docs` to create new pages.
|
||||
</Card>
|
||||
<Card title="Configure your site" icon="setting">
|
||||
Edit your `sidebar` and other config in `astro.config.mjs`.
|
||||
</Card>
|
||||
<Card title="Read the docs" icon="open-book">
|
||||
Learn more in [the Starlight Docs](https://starlight.astro.build/).
|
||||
</Card>
|
||||
</CardGrid>
|
@@ -1,11 +0,0 @@
|
||||
---
|
||||
title: Example Reference
|
||||
description: A reference page in my new Starlight docs site.
|
||||
---
|
||||
|
||||
Reference pages are ideal for outlining how things work in terse and clear terms.
|
||||
Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what you're documenting.
|
||||
|
||||
## Further reading
|
||||
|
||||
- Read [about reference](https://diataxis.fr/reference/) in the Diátaxis framework
|
2
src/env.d.ts
vendored
@@ -1,2 +0,0 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
BIN
src/images/bart.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/images/bg.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
3
src/images/decorations/circle.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="47" height="47" viewBox="0 0 47 47" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="23.5" cy="23.5" r="21" stroke="#00CDE2" stroke-width="5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 174 B |
4
src/images/decorations/cross.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="3.41516" y="9.15039" width="50" height="5" transform="rotate(30 3.41516 9.15039)" fill="#FF5252"/>
|
||||
<rect x="38.4808" y="3.41504" width="50" height="5" transform="rotate(120 38.4808 3.41504)" fill="#FF5252"/>
|
||||
</svg>
|
After Width: | Height: | Size: 320 B |
4
src/images/decorations/tick.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="63" height="54" viewBox="0 0 63 54" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="15.6919" y="38.1289" width="50" height="5" transform="rotate(-28.6386 15.6919 38.1289)" fill="#02D463"/>
|
||||
<rect x="16.9618" y="43.5635" width="25" height="5" transform="rotate(-118.639 16.9618 43.5635)" fill="#02D463"/>
|
||||
</svg>
|
After Width: | Height: | Size: 331 B |
BIN
src/images/logo.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
src/images/projects/bartzalewski-v1.webm
Normal file
BIN
src/images/projects/bartzalewski-v2.webm
Normal file
BIN
src/images/projects/centrummoto.webm
Normal file
BIN
src/images/projects/cz5p.webm
Normal file
BIN
src/images/projects/darkpaypal.webm
Normal file
BIN
src/images/projects/dojrzewaj.webm
Normal file
BIN
src/images/projects/grammarlydark.webm
Normal file
BIN
src/images/projects/hopp.webm
Normal file
BIN
src/images/projects/joindevs.webm
Normal file
BIN
src/images/projects/pagetify.webm
Normal file
BIN
src/images/projects/schoolify.webm
Normal file
BIN
src/images/projects/telean.webm
Normal file
32
src/pages/404.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import Head from '../components/defaults/head'
|
||||
import Layout from '../components/defaults/layout'
|
||||
import Header from '../components/header'
|
||||
|
||||
const Container = styled.div`
|
||||
margin: 100px auto auto;
|
||||
text-align: center;
|
||||
`
|
||||
const Title = styled.h1`
|
||||
margin: 50px 0;
|
||||
`
|
||||
const Description = styled.p``
|
||||
|
||||
const NotFoundPage = () => (
|
||||
<Layout>
|
||||
<Head title="404 Not Found" />
|
||||
<Header />
|
||||
<Container className="container container--secondary">
|
||||
<div className="container container--primary">
|
||||
<Title>NOT FOUND</Title>
|
||||
<Description>
|
||||
You just hit a route that doesn't exist... the sadness.
|
||||
</Description>
|
||||
</div>
|
||||
</Container>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
export default NotFoundPage
|
123
src/pages/blog.js
Normal file
@@ -0,0 +1,123 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { Link, graphql, useStaticQuery } from 'gatsby'
|
||||
|
||||
import Head from '../components/defaults/head'
|
||||
import Layout from '../components/defaults/layout'
|
||||
import Header from '../components/header'
|
||||
|
||||
const Container = styled.div`
|
||||
margin: 100px auto auto;
|
||||
text-align: center;
|
||||
|
||||
h1 {
|
||||
margin: 50px 0;
|
||||
}
|
||||
|
||||
.blog {
|
||||
&__container {
|
||||
align-items: flex-end;
|
||||
}
|
||||
&__desc {
|
||||
text-align: center;
|
||||
margin: 50px 0;
|
||||
color: #bdbdbd;
|
||||
}
|
||||
&__wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 20px;
|
||||
width: 90%;
|
||||
list-style: none;
|
||||
margin: 50px 0;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
}
|
||||
&__box {
|
||||
background: #111;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
transition: 0.4s;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
opacity: 0.4;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-10px);
|
||||
transition: 0.4s;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
&__img {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border-radius: 4px;
|
||||
object-fit: cover;
|
||||
}
|
||||
&__title {
|
||||
font-family: 'JetBrains Mono';
|
||||
direction: ltr;
|
||||
margin: 10px 0 5px;
|
||||
}
|
||||
&__time {
|
||||
font-size: 14px;
|
||||
color: #bdbdbd;
|
||||
direction: ltr;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const BlogPage = () => {
|
||||
const data = useStaticQuery(graphql`
|
||||
query {
|
||||
allContentfulBlogPost(sort: { fields: publishedDate, order: DESC }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
title
|
||||
slug
|
||||
publishedDate(formatString: "MMMM Do, YYYY")
|
||||
background {
|
||||
file {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const output = data.allContentfulBlogPost.edges.map((element) => {
|
||||
const { id, slug, background, title, publishedDate } = element.node
|
||||
return (
|
||||
<li key={id} className="blog__box">
|
||||
<Link to={`/blog/${slug}`}>
|
||||
<img
|
||||
className="blog__img"
|
||||
src={background.file.url}
|
||||
alt={title}
|
||||
loading="lazy"
|
||||
/>
|
||||
<p className="blog__title">{title}</p>
|
||||
<p className="blog__time">{publishedDate}</p>
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Head title="All posts" />
|
||||
<Header />
|
||||
<Container className="container container--secondary">
|
||||
<div className="container container--primary">
|
||||
<h1>All posts</h1>
|
||||
<p>Read now!</p>
|
||||
</div>
|
||||
<ul className="blog__wrapper">{output}</ul>
|
||||
</Container>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export default BlogPage
|
21
src/pages/index.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
import Layout from '../components/defaults/layout'
|
||||
import Head from '../components/defaults/head'
|
||||
import Hero from '../components/hero'
|
||||
import About from '../components/about'
|
||||
import Projects from '../components/projects'
|
||||
import Blog from '../components/blog'
|
||||
import Contact from '../components/contact'
|
||||
|
||||
const IndexPage = () => (
|
||||
<Layout>
|
||||
<Head />
|
||||
<Hero />
|
||||
<About />
|
||||
<Projects />
|
||||
<Blog />
|
||||
<Contact />
|
||||
</Layout>
|
||||
)
|
||||
|
||||
export default IndexPage
|
@@ -1,183 +0,0 @@
|
||||
:root,
|
||||
::backdrop {
|
||||
/* Colors (dark mode) */
|
||||
--sl-color-white: hsl(0, 0%, 100%); /* “white” */
|
||||
--sl-color-gray-1: hsl(224, 20%, 94%);
|
||||
--sl-color-gray-2: hsl(224, 6%, 77%);
|
||||
--sl-color-gray-3: hsl(224, 6%, 56%);
|
||||
--sl-color-gray-4: hsl(224, 7%, 36%);
|
||||
--sl-color-gray-5: hsl(224, 10%, 23%);
|
||||
--sl-color-gray-6: hsl(224, 14%, 16%);
|
||||
--sl-color-black: hsl(224, 10%, 10%);
|
||||
|
||||
--sl-hue-orange: 41;
|
||||
--sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%);
|
||||
--sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%);
|
||||
--sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%);
|
||||
--sl-hue-green: 101;
|
||||
--sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%);
|
||||
--sl-color-green: hsl(var(--sl-hue-green), 82%, 63%);
|
||||
--sl-color-green-high: hsl(var(--sl-hue-green), 82%, 80%);
|
||||
--sl-hue-blue: 234;
|
||||
--sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%);
|
||||
--sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%);
|
||||
--sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%);
|
||||
--sl-hue-purple: 281;
|
||||
--sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%);
|
||||
--sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%);
|
||||
--sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%);
|
||||
--sl-hue-red: 339;
|
||||
--sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%);
|
||||
--sl-color-red: hsl(var(--sl-hue-red), 82%, 63%);
|
||||
--sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%);
|
||||
|
||||
--sl-color-accent-low: hsl(224, 54%, 20%);
|
||||
--sl-color-accent: hsl(224, 100%, 60%);
|
||||
--sl-color-accent-high: hsl(224, 100%, 85%);
|
||||
|
||||
--sl-color-text: var(--sl-color-gray-2);
|
||||
--sl-color-text-accent: var(--sl-color-accent-high);
|
||||
--sl-color-text-invert: var(--sl-color-accent-low);
|
||||
--sl-color-bg: var(--sl-color-black);
|
||||
--sl-color-bg-nav: var(--sl-color-gray-6);
|
||||
--sl-color-bg-sidebar: var(--sl-color-gray-6);
|
||||
--sl-color-bg-inline-code: var(--sl-color-gray-5);
|
||||
--sl-color-bg-accent: var(--sl-color-accent-high);
|
||||
--sl-color-hairline-light: var(--sl-color-gray-5);
|
||||
--sl-color-hairline: var(--sl-color-gray-6);
|
||||
--sl-color-hairline-shade: var(--sl-color-black);
|
||||
|
||||
--sl-color-backdrop-overlay: hsla(223, 13%, 10%, 0.66);
|
||||
|
||||
/* Shadows (dark mode) */
|
||||
--sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.12), 0px 2px 1px hsla(0, 0%, 0%, 0.24);
|
||||
--sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.08), 0px 5px 2px hsla(0, 0%, 0%, 0.08),
|
||||
0px 3px 2px hsla(0, 0%, 0%, 0.12), 0px 1px 1px hsla(0, 0%, 0%, 0.15);
|
||||
--sl-shadow-lg: 0px 25px 7px hsla(0, 0%, 0%, 0.03), 0px 16px 6px hsla(0, 0%, 0%, 0.1),
|
||||
0px 9px 5px hsla(223, 13%, 10%, 0.33), 0px 4px 4px hsla(0, 0%, 0%, 0.75),
|
||||
0px 4px 2px hsla(0, 0%, 0%, 0.25);
|
||||
|
||||
/* Text size and line height */
|
||||
--sl-text-xs: 0.8125rem; /* 13px */
|
||||
--sl-text-sm: 0.875rem; /* 14px */
|
||||
--sl-text-base: 1rem; /* 16px */
|
||||
--sl-text-lg: 1.125rem; /* 18px */
|
||||
--sl-text-xl: 1.25rem; /* 20px */
|
||||
--sl-text-2xl: 1.5rem; /* 24px */
|
||||
--sl-text-3xl: 1.8125rem; /* 29px */
|
||||
--sl-text-4xl: 2.1875rem; /* 35px */
|
||||
--sl-text-5xl: 2.625rem; /* 42px */
|
||||
--sl-text-6xl: 4rem; /* 64px */
|
||||
|
||||
--sl-text-body: var(--sl-text-base);
|
||||
--sl-text-body-sm: var(--sl-text-xs);
|
||||
--sl-text-code: var(--sl-text-sm);
|
||||
--sl-text-code-sm: var(--sl-text-xs);
|
||||
--sl-text-h1: var(--sl-text-4xl);
|
||||
--sl-text-h2: var(--sl-text-3xl);
|
||||
--sl-text-h3: var(--sl-text-2xl);
|
||||
--sl-text-h4: var(--sl-text-xl);
|
||||
--sl-text-h5: var(--sl-text-lg);
|
||||
|
||||
--sl-line-height: 1.75;
|
||||
--sl-line-height-headings: 1.2;
|
||||
|
||||
--sl-font-system: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
--sl-font-system-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
|
||||
'Courier New', monospace;
|
||||
--__sl-font: var(--sl-font, var(--sl-font-system)), var(--sl-font-system);
|
||||
--__sl-font-mono: var(--sl-font-mono, var(--sl-font-system-mono)), var(--sl-font-system-mono);
|
||||
|
||||
/** Key layout values */
|
||||
--sl-nav-height: 3.5rem;
|
||||
--sl-nav-pad-x: 1rem;
|
||||
--sl-nav-pad-y: 0.75rem;
|
||||
--sl-mobile-toc-height: 3rem;
|
||||
--sl-sidebar-width: 18.75rem;
|
||||
--sl-sidebar-pad-x: 1rem;
|
||||
--sl-content-width: 45rem;
|
||||
--sl-content-pad-x: 1rem;
|
||||
--sl-menu-button-size: 2rem;
|
||||
--sl-nav-gap: var(--sl-content-pad-x);
|
||||
/* Offset required to show outline inside an element instead of round the outside */
|
||||
--sl-outline-offset-inside: -0.1875rem;
|
||||
|
||||
/* Global z-index values */
|
||||
--sl-z-index-toc: 4;
|
||||
--sl-z-index-menu: 5;
|
||||
--sl-z-index-navbar: 10;
|
||||
--sl-z-index-skiplink: 20;
|
||||
}
|
||||
|
||||
:root[data-theme='light'],
|
||||
[data-theme='light'] ::backdrop {
|
||||
/* Colours (light mode) */
|
||||
--sl-color-white: hsl(224, 10%, 10%);
|
||||
--sl-color-gray-1: hsl(224, 14%, 16%);
|
||||
--sl-color-gray-2: hsl(224, 10%, 23%);
|
||||
--sl-color-gray-3: hsl(224, 7%, 36%);
|
||||
--sl-color-gray-4: hsl(224, 6%, 56%);
|
||||
--sl-color-gray-5: hsl(224, 6%, 77%);
|
||||
--sl-color-gray-6: hsl(224, 20%, 94%);
|
||||
--sl-color-gray-7: hsl(224, 19%, 97%);
|
||||
--sl-color-black: hsl(0, 0%, 100%);
|
||||
|
||||
--sl-color-orange-high: hsl(var(--sl-hue-orange), 80%, 25%);
|
||||
--sl-color-orange: hsl(var(--sl-hue-orange), 90%, 60%);
|
||||
--sl-color-orange-low: hsl(var(--sl-hue-orange), 90%, 88%);
|
||||
--sl-color-green-high: hsl(var(--sl-hue-green), 80%, 22%);
|
||||
--sl-color-green: hsl(var(--sl-hue-green), 90%, 46%);
|
||||
--sl-color-green-low: hsl(var(--sl-hue-green), 85%, 90%);
|
||||
--sl-color-blue-high: hsl(var(--sl-hue-blue), 80%, 30%);
|
||||
--sl-color-blue: hsl(var(--sl-hue-blue), 90%, 60%);
|
||||
--sl-color-blue-low: hsl(var(--sl-hue-blue), 88%, 90%);
|
||||
--sl-color-purple-high: hsl(var(--sl-hue-purple), 90%, 30%);
|
||||
--sl-color-purple: hsl(var(--sl-hue-purple), 90%, 60%);
|
||||
--sl-color-purple-low: hsl(var(--sl-hue-purple), 80%, 90%);
|
||||
--sl-color-red-high: hsl(var(--sl-hue-red), 80%, 30%);
|
||||
--sl-color-red: hsl(var(--sl-hue-red), 90%, 60%);
|
||||
--sl-color-red-low: hsl(var(--sl-hue-red), 80%, 90%);
|
||||
|
||||
--sl-color-accent-high: hsl(234, 80%, 30%);
|
||||
--sl-color-accent: hsl(234, 90%, 60%);
|
||||
--sl-color-accent-low: hsl(234, 88%, 90%);
|
||||
|
||||
--sl-color-text-accent: var(--sl-color-accent);
|
||||
--sl-color-text-invert: var(--sl-color-black);
|
||||
--sl-color-bg-nav: var(--sl-color-gray-7);
|
||||
--sl-color-bg-sidebar: var(--sl-color-bg);
|
||||
--sl-color-bg-inline-code: var(--sl-color-gray-6);
|
||||
--sl-color-bg-accent: var(--sl-color-accent);
|
||||
--sl-color-hairline-light: var(--sl-color-gray-6);
|
||||
--sl-color-hairline-shade: var(--sl-color-gray-6);
|
||||
|
||||
--sl-color-backdrop-overlay: hsla(225, 9%, 36%, 0.66);
|
||||
|
||||
/* Shadows (light mode) */
|
||||
--sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.06), 0px 2px 1px hsla(0, 0%, 0%, 0.06);
|
||||
--sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.03), 0px 5px 2px hsla(0, 0%, 0%, 0.03),
|
||||
0px 3px 2px hsla(0, 0%, 0%, 0.06), 0px 1px 1px hsla(0, 0%, 0%, 0.06);
|
||||
--sl-shadow-lg: 0px 25px 7px rgba(0, 0, 0, 0.01), 0px 16px 6px hsla(0, 0%, 0%, 0.03),
|
||||
0px 9px 5px hsla(223, 13%, 10%, 0.08), 0px 4px 4px hsla(0, 0%, 0%, 0.16),
|
||||
0px 4px 2px hsla(0, 0%, 0%, 0.04);
|
||||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
:root {
|
||||
--sl-nav-height: 4rem;
|
||||
--sl-nav-pad-x: 1.5rem;
|
||||
--sl-text-h1: var(--sl-text-5xl);
|
||||
--sl-text-h2: var(--sl-text-4xl);
|
||||
--sl-text-h3: var(--sl-text-3xl);
|
||||
--sl-text-h4: var(--sl-text-2xl);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 72rem) {
|
||||
:root {
|
||||
--sl-content-pad-x: 1.5rem;
|
||||
--sl-mobile-toc-height: 0rem;
|
||||
}
|
||||
}
|
136
src/templates/blog.js
Normal file
@@ -0,0 +1,136 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { graphql } from 'gatsby'
|
||||
import { documentToReactComponents } from '@contentful/rich-text-react-renderer'
|
||||
|
||||
import Layout from '../components/defaults/layout'
|
||||
import Head from '../components/defaults/head'
|
||||
import Header from '../components/header'
|
||||
|
||||
export const query = graphql`
|
||||
query ($slug: String!) {
|
||||
contentfulBlogPost(slug: { eq: $slug }) {
|
||||
title
|
||||
publishedDate(formatString: "MMMM Do, YYYY")
|
||||
background {
|
||||
file {
|
||||
url
|
||||
}
|
||||
}
|
||||
body {
|
||||
raw
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const BlogSection = styled.div`
|
||||
margin: 100px auto auto;
|
||||
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 32px;
|
||||
font-family: 'JetBrains Mono';
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 25px;
|
||||
color: #bdbdbd;
|
||||
text-shadow: 0px 0px 10px black;
|
||||
}
|
||||
|
||||
span {
|
||||
text-shadow: 0px 0px 10px black;
|
||||
color: #bdbdbd;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
img {
|
||||
margin-top: 25px;
|
||||
width: 100%;
|
||||
opacity: 0.4;
|
||||
transition: 0.4s;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
transition: 0.4s;
|
||||
}
|
||||
}
|
||||
|
||||
.container--primary {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.container__blog {
|
||||
width: 680px;
|
||||
}
|
||||
|
||||
.blog__content {
|
||||
margin-bottom: 50px;
|
||||
margin-top: 25px;
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
.blog__img {
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
margin-top: 50px;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
transition: 0.4s;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const Blog = ({ data }) => {
|
||||
const options = {
|
||||
renderNode: {
|
||||
'embedded-asset-block': (node) => {
|
||||
const alt = node.data.target.fields.title['en-US']
|
||||
const url = node.data.target.fields.file['en-US'].url
|
||||
return <img alt={alt} src={url} loading="lazy" />
|
||||
},
|
||||
},
|
||||
}
|
||||
const { title, publishedDate, background, body } = data.contentfulBlogPost
|
||||
return (
|
||||
<Layout>
|
||||
<Head title={title} />
|
||||
<Header />
|
||||
<BlogSection className="container container--secondary">
|
||||
<div className="container container--primary container__blog">
|
||||
<h2 className="post__title">{title}</h2>
|
||||
<span>{publishedDate}</span>
|
||||
<img
|
||||
className="blog__img"
|
||||
src={background.file.url}
|
||||
alt={title}
|
||||
loading="lazy"
|
||||
/>
|
||||
<div className="blog__content">
|
||||
{documentToReactComponents(JSON.parse(body.raw), options)}
|
||||
</div>
|
||||
</div>
|
||||
</BlogSection>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export default Blog
|
435
src/theme/globalStyle.js
Normal file
@@ -0,0 +1,435 @@
|
||||
import { createGlobalStyle } from 'styled-components'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { fab } from '@fortawesome/free-brands-svg-icons'
|
||||
import {
|
||||
faEnvelope,
|
||||
faPaperclip,
|
||||
faExternalLinkAlt,
|
||||
faFire,
|
||||
faCross,
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
library.add(fab, faEnvelope, faPaperclip, faExternalLinkAlt, faFire, faCross)
|
||||
|
||||
const GlobalStyle = createGlobalStyle`
|
||||
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap');
|
||||
|
||||
@font-face {
|
||||
font-family: 'Grand Hotel';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: local('Grand Hotel'), local('GrandHotel-Regular'), url('https://fonts.gstatic.com/s/grandhotel/v7/7Au7p_IgjDKdCRWuR1azplQKGFw.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
*, *::before, *::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
}
|
||||
::selection {
|
||||
background: #02D463;
|
||||
color: white;
|
||||
}
|
||||
html {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
color: white;
|
||||
background: #1a1a1a;
|
||||
font-family: 'JetBrains Mono';
|
||||
}
|
||||
body::-webkit-scrollbar {
|
||||
width: 0.5em;
|
||||
}
|
||||
body::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
body::-webkit-scrollbar-thumb {
|
||||
background: #333;
|
||||
outline: 1px solid white;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background: #02D463;
|
||||
}
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
h1 {
|
||||
font-size: 64px;
|
||||
font-family: 'JetBrains Mono';
|
||||
}
|
||||
h2 {
|
||||
font-size: 36px;
|
||||
font-family: 'JetBrains Mono';
|
||||
}
|
||||
h1, h2 {
|
||||
text-shadow: 0px 0px 10px black;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
&--primary {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
&--secondary {
|
||||
width: 90%;
|
||||
max-width: 1400px;
|
||||
}
|
||||
}
|
||||
.default-link {
|
||||
&__link {
|
||||
margin: 0 10px;
|
||||
display: inline-flex;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
transition: 0.5s ease;
|
||||
|
||||
&:hover {
|
||||
color: #02d463;
|
||||
transition: 0.5s ease;
|
||||
}
|
||||
|
||||
&:before {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: #02d463;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
&:hover:before {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
padding: 10px 17.5px;
|
||||
border-radius: 4px;
|
||||
border: 2px solid transparent;
|
||||
transition: .2s ease;
|
||||
box-shadow: 0px 0px 20px rgba(0,0,0,0.5);
|
||||
outline: none;
|
||||
-webkit-appearance: none;
|
||||
|
||||
&:hover {
|
||||
transition: .2s ease;
|
||||
}
|
||||
|
||||
&--primary {
|
||||
color: white;
|
||||
background: #02D463;
|
||||
|
||||
&:hover {
|
||||
background: transparent;
|
||||
color: #02D463;
|
||||
border: 2px solid #02D463;
|
||||
}
|
||||
}
|
||||
|
||||
&--secondary {
|
||||
color: #02D463;
|
||||
border: 2px solid #02D463;
|
||||
|
||||
&:hover {
|
||||
background: #02D463;
|
||||
color: white;
|
||||
border: 2px solid #02D463;
|
||||
}
|
||||
}
|
||||
}
|
||||
.colored {
|
||||
color: #02D463 !important;
|
||||
}
|
||||
.section__desc {
|
||||
text-shadow: 0px 0px 10px black;
|
||||
}
|
||||
.scrolled {
|
||||
&&& {
|
||||
position: fixed;
|
||||
transition: .4s;
|
||||
z-index: 5;
|
||||
background: #1a1a1a;
|
||||
box-shadow: 0px 0px 20px rgba(0,0,0,.5);
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
/* SIDENAV */
|
||||
|
||||
.hamburger {
|
||||
display: none;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
z-index: 4;
|
||||
outline: none;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
.hamburger__wrapper {
|
||||
width: 25px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
.hamburger--line {
|
||||
background-color: #02D463;
|
||||
}
|
||||
}
|
||||
}
|
||||
.hamburger--line {
|
||||
position: absolute;
|
||||
height: 3px;
|
||||
width: 100%;
|
||||
transition: all cubic-bezier(0.26, 0.1, 0.27, 1.55) 0.35s;
|
||||
background-color: #fff;
|
||||
}
|
||||
.top {
|
||||
top: 0%;
|
||||
width: 75%;
|
||||
left: 0%;
|
||||
}
|
||||
.middle {
|
||||
top: 45%;
|
||||
width: 75%;
|
||||
}
|
||||
.bottom {
|
||||
top: 90%;
|
||||
width: 75%;
|
||||
left: 0%;
|
||||
}
|
||||
.icon.close .top {
|
||||
transform: rotate(45deg);
|
||||
top: 48%;
|
||||
width: 100%;
|
||||
}
|
||||
.icon.close .middle,
|
||||
.icon.close .bottom {
|
||||
transform: rotate(-45deg);
|
||||
top: 48%;
|
||||
width: 100%;
|
||||
}
|
||||
.sidenav--open {
|
||||
width: 40% !important;
|
||||
transition: 0.5s;
|
||||
}
|
||||
.sidenav {
|
||||
width: 0px;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
z-index: 3;
|
||||
background-color: #111;
|
||||
transition: 0.2s ease-in-out;
|
||||
overflow: hidden;
|
||||
box-shadow: 0px 0px 10px rgba(0,0,0,.5);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
a {
|
||||
margin: 30px 0;
|
||||
text-decoration: none;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
transition: 0.2s ease-in-out;
|
||||
color: inherit;
|
||||
|
||||
:hover:not(.navbar__resume) {
|
||||
color: #02D463;
|
||||
}
|
||||
|
||||
&.navbar__resume {
|
||||
margin-left: 0;
|
||||
color: #02D463;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.active {
|
||||
width: 100%;
|
||||
height: fit-content;
|
||||
font-weight: 500;
|
||||
color: #49a9e0;
|
||||
}
|
||||
&__more {
|
||||
transform: translateX(1rem);
|
||||
|
||||
a {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidenav__content {
|
||||
position: relative;
|
||||
width: fit-content !important;
|
||||
}
|
||||
|
||||
/* SIDENAV END */
|
||||
|
||||
@media screen and (max-width: 1280px) {
|
||||
.board__container {
|
||||
bottom: -200px;
|
||||
right: -100px;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1080px) {
|
||||
.board__container {
|
||||
bottom: -50px;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 768px) {
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 48px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
}
|
||||
h3 {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
footer {
|
||||
height: 120px !important;
|
||||
}
|
||||
#home {
|
||||
background-attachment: scroll;
|
||||
}
|
||||
.hamburger {
|
||||
display: block;
|
||||
}
|
||||
.navbar__links {
|
||||
display: none;
|
||||
}
|
||||
.container__blog {
|
||||
width: auto !important;
|
||||
}
|
||||
.post__title {
|
||||
font-size: 30px !important;
|
||||
}
|
||||
.blog__content {
|
||||
font-size: 18px !important;
|
||||
|
||||
h3 {
|
||||
font-size: 26px !important;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 21px !important;
|
||||
}
|
||||
}
|
||||
.board__container {
|
||||
position: relative !important;
|
||||
top: auto !important;
|
||||
left: 0 !important;
|
||||
transform: none !important;
|
||||
border: 5px solid #222 !important;
|
||||
border-radius: 5px !important;
|
||||
}
|
||||
.board__grid {
|
||||
outline: 0 !important;
|
||||
grid-gap: 5px !important;
|
||||
}
|
||||
.board__box {
|
||||
left: -5px !important;
|
||||
top: -5px !important;
|
||||
}
|
||||
.decoration {
|
||||
opacity: .5;
|
||||
}
|
||||
.decoration__tick {
|
||||
left: 65% !important;
|
||||
top: 50% !important;
|
||||
}
|
||||
.container__hero--secondary {
|
||||
margin: 2rem 0 !important;
|
||||
}
|
||||
.hero__left, .hero__right {
|
||||
width: 100% !important;
|
||||
}
|
||||
.about__container {
|
||||
flex-direction: column-reverse !important;
|
||||
img {
|
||||
align-self: flex-start !important;
|
||||
margin-bottom: 50px;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
.about__wrapper {
|
||||
width: 100% !important;
|
||||
}
|
||||
.about__desc, .hero__desc {
|
||||
width: 100% !important;
|
||||
}
|
||||
.work__wrapper, .blog__wrapper {
|
||||
grid-template-columns: repeat(1, 1fr) !important;
|
||||
}
|
||||
.work--animation {
|
||||
margin: 0 !important;
|
||||
}
|
||||
.input__field--grid, .input__textarea {
|
||||
width: 100% !important;
|
||||
}
|
||||
.input__field--grid {
|
||||
grid-template-columns: repeat(1,1fr) !important;
|
||||
}
|
||||
.footer__container {
|
||||
flex-direction: column;
|
||||
}
|
||||
.footer__desc {
|
||||
text-align: center;
|
||||
}
|
||||
.footer__copy {
|
||||
margin-top: 25px;
|
||||
}
|
||||
.footer__link {
|
||||
margin: 0 20px !important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 400px) {
|
||||
.footer__links {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.footer__link {
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default GlobalStyle
|
BIN
static/resume.pdf
Normal file
@@ -1,8 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
}
|