first commit
3
.env.example
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
DEV_TO_API_KEY = your-api-key
|
||||||
|
GITHUB_API_KEY = your-api-key
|
||||||
|
NEXT_PUBLIC_GITHUB_USERNAME = itsnitinr
|
||||||
38
.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# cursor
|
||||||
|
.cursor
|
||||||
|
.env
|
||||||
128
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
|
and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the
|
||||||
|
overall community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or
|
||||||
|
advances of any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email
|
||||||
|
address, without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
nitinranganath@gmail.com.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series
|
||||||
|
of actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or
|
||||||
|
permanent ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within
|
||||||
|
the community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.0, available at
|
||||||
|
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||||
|
enforcement ladder](https://github.com/mozilla/diversity).
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
https://www.contributor-covenant.org/faq. Translations are available at
|
||||||
|
https://www.contributor-covenant.org/translations.
|
||||||
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Nitin Ranganath
|
||||||
|
|
||||||
|
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.
|
||||||
49
README.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# vscode-portfolio
|
||||||
|
[](https://open.vscode.dev/itsnitinr/vscode-portfolio)
|
||||||
|
|
||||||
|
A Visual Studio Code themed developer portfolio website built with Next.js and deployed on Vercel.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Features Roadmap
|
||||||
|
|
||||||
|
- [ ] Themes and customizations
|
||||||
|
- [x] GitHub Dark (default)
|
||||||
|
- [ ] One Dark Pro
|
||||||
|
- [x] Dracula
|
||||||
|
- [x] Ayu
|
||||||
|
- [x] Nord
|
||||||
|
- [ ] Interactive custom terminal
|
||||||
|
|
||||||
|
For other features and themes suggestions, please open an issue.
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
For fetching your articles from dev.to, create an `.env.local` file inside the project directory. Check the `.env.local.example` file for more information.
|
||||||
|
|
||||||
|
## Running Development Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||||
|
|
||||||
|
All VSCode related components can be found in the `components` folder. To change the content of the portfolio, check out the `pages` folder. To add or remove pages, modify `components/Sidebar.jsx` and `components/Tabsbar.jsx`.
|
||||||
|
|
||||||
|
## Next.js Resources
|
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/)
|
||||||
|
|
||||||
|
## Deploy on Vercel
|
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||||
52
components/ArticleCard.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import Image from 'next/image';
|
||||||
|
import { VscEye, VscHeart, VscComment } from 'react-icons/vsc';
|
||||||
|
|
||||||
|
import { Article } from '@/types';
|
||||||
|
|
||||||
|
import styles from '@/styles/ArticleCard.module.css';
|
||||||
|
|
||||||
|
interface ArticleCardProps {
|
||||||
|
article: Article;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ArticleCard = ({ article }: ArticleCardProps) => {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={article.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className={styles.container}
|
||||||
|
>
|
||||||
|
<div className={styles.imageWrapper}>
|
||||||
|
<Image
|
||||||
|
src={article.cover_image}
|
||||||
|
alt={article.title}
|
||||||
|
fill
|
||||||
|
sizes="(max-width: 768px) 100vw, 300px"
|
||||||
|
className={styles.image}
|
||||||
|
/>
|
||||||
|
<div className={styles.viewsBadge}>
|
||||||
|
<VscEye /> {article.page_views_count}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<h3 className={styles.title}>{article.title}</h3>
|
||||||
|
<p className={styles.description}>{article.description}</p>
|
||||||
|
|
||||||
|
<div className={styles.footer}>
|
||||||
|
<div className={styles.stats}>
|
||||||
|
<div className={styles.stat}>
|
||||||
|
<VscHeart className={styles.icon} />{' '}
|
||||||
|
{article.public_reactions_count}
|
||||||
|
</div>
|
||||||
|
<div className={styles.stat}>
|
||||||
|
<VscComment className={styles.icon} /> {article.comments_count}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ArticleCard;
|
||||||
49
components/Bottombar.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import {
|
||||||
|
VscBell,
|
||||||
|
VscCheck,
|
||||||
|
VscError,
|
||||||
|
VscWarning,
|
||||||
|
VscSourceControl,
|
||||||
|
} from 'react-icons/vsc';
|
||||||
|
import { SiNextdotjs } from 'react-icons/si';
|
||||||
|
|
||||||
|
import styles from '@/styles/Bottombar.module.css';
|
||||||
|
|
||||||
|
const Bottombar = () => {
|
||||||
|
return (
|
||||||
|
<footer className={styles.bottomBar}>
|
||||||
|
<div className={styles.container}>
|
||||||
|
<a
|
||||||
|
href="https://github.com/itsnitinr/vscode-portfolio"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
className={styles.section}
|
||||||
|
>
|
||||||
|
<VscSourceControl className={styles.icon} />
|
||||||
|
<p>main</p>
|
||||||
|
</a>
|
||||||
|
<div className={styles.section}>
|
||||||
|
<VscError className={styles.icon} />
|
||||||
|
<p className={styles.errorText}>0</p>
|
||||||
|
<VscWarning className={styles.icon} />
|
||||||
|
<p>0</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.section}>
|
||||||
|
<SiNextdotjs className={styles.icon} />
|
||||||
|
<p>Powered by Next.js</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.section}>
|
||||||
|
<VscCheck className={styles.icon} />
|
||||||
|
<p>Prettier</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.section}>
|
||||||
|
<VscBell />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Bottombar;
|
||||||
51
components/ContactCode.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import styles from '@/styles/ContactCode.module.css';
|
||||||
|
|
||||||
|
const contactItems = [
|
||||||
|
{
|
||||||
|
social: 'website',
|
||||||
|
link: 'Portfolio',
|
||||||
|
href: 'https://ahmed.galadima.talenttic.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
social: 'email',
|
||||||
|
link: 'ahmed.galadima@hotmail.com',
|
||||||
|
href: 'mailto:ahmed.galadima@hotmail.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
social: 'github',
|
||||||
|
link: 'galads',
|
||||||
|
href: 'https://github.com/glimz',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
social: 'linkedin',
|
||||||
|
link: 'Linkedin URL',
|
||||||
|
href: 'https://www.linkedin.com/in/ahmed-galadima',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
social: 'twitter',
|
||||||
|
link: 'galads',
|
||||||
|
href: 'https://x.com/Mr_galads',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const ContactCode = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.code}>
|
||||||
|
<p className={styles.line}>
|
||||||
|
<span className={styles.className}>.socials</span> {
|
||||||
|
</p>
|
||||||
|
{contactItems.map((item, index) => (
|
||||||
|
<p className={styles.line} key={index}>
|
||||||
|
{item.social}:{' '}
|
||||||
|
<a href={item.href} target="_blank" rel="noopener">
|
||||||
|
{item.link}
|
||||||
|
</a>
|
||||||
|
;
|
||||||
|
</p>
|
||||||
|
))}
|
||||||
|
<p className={styles.line}>}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ContactCode;
|
||||||
80
components/Explorer.tsx
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { VscChevronRight } from 'react-icons/vsc';
|
||||||
|
|
||||||
|
import styles from '@/styles/Explorer.module.css';
|
||||||
|
|
||||||
|
const explorerItems = [
|
||||||
|
{
|
||||||
|
name: 'home.tsx',
|
||||||
|
path: '/',
|
||||||
|
icon: '/logos/react_icon.svg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'about.html',
|
||||||
|
path: '/about',
|
||||||
|
icon: '/logos/html_icon.svg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'contact.css',
|
||||||
|
path: '/contact',
|
||||||
|
icon: '/logos/css_icon.svg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'projects.js',
|
||||||
|
path: '/projects',
|
||||||
|
icon: '/logos/js_icon.svg',
|
||||||
|
},
|
||||||
|
/* {
|
||||||
|
name: 'articles.json',
|
||||||
|
path: '/articles',
|
||||||
|
icon: '/logos/json_icon.svg',
|
||||||
|
}, */
|
||||||
|
{
|
||||||
|
name: 'github.md',
|
||||||
|
path: '/github',
|
||||||
|
icon: '/logos/markdown_icon.svg',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const Explorer = () => {
|
||||||
|
const [portfolioOpen, setPortfolioOpen] = useState(true);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.explorer}>
|
||||||
|
<p className={styles.title}>Explorer</p>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className={styles.checkbox}
|
||||||
|
id="portfolio-checkbox"
|
||||||
|
checked={portfolioOpen}
|
||||||
|
onChange={() => setPortfolioOpen(!portfolioOpen)}
|
||||||
|
/>
|
||||||
|
<label htmlFor="portfolio-checkbox" className={styles.heading}>
|
||||||
|
<VscChevronRight
|
||||||
|
className={styles.chevron}
|
||||||
|
style={portfolioOpen ? { transform: 'rotate(90deg)' } : {}}
|
||||||
|
/>
|
||||||
|
Portfolio
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
className={styles.files}
|
||||||
|
style={portfolioOpen ? { display: 'block' } : { display: 'none' }}
|
||||||
|
>
|
||||||
|
{explorerItems.map((item) => (
|
||||||
|
<Link href={item.path} key={item.name}>
|
||||||
|
<div className={styles.file}>
|
||||||
|
<Image src={item.icon} alt={item.name} height={18} width={18} />{' '}
|
||||||
|
<p>{item.name}</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Explorer;
|
||||||
35
components/Head.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import Head from 'next/head';
|
||||||
|
|
||||||
|
interface CustomHeadProps {
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CustomHead = ({ title }: CustomHeadProps) => {
|
||||||
|
return (
|
||||||
|
<Head>
|
||||||
|
<title>{title}</title>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Ahmed Galadima, Senior QA Engineer, Automation Consultant, Software Development, Test Automation, CI/CD, DevOps"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="keywords"
|
||||||
|
content="Ahmed Galadima, Senior QA Engineer, Automation Consultant, Software Development, Test Automation, CI/CD, DevOps"
|
||||||
|
/>
|
||||||
|
<meta property="og:title" content="Ahmed Galadima's Portfolio" />
|
||||||
|
<meta
|
||||||
|
property="og:description"
|
||||||
|
content="A Senior QA Engineer, Automation Consultant. Software Development, Test Automation, CI/CD, DevOps"
|
||||||
|
/>
|
||||||
|
<meta property="og:image" content="https://imgur.com/4zi5KkQ.png" />
|
||||||
|
<meta property="og:url" content="https://vscode-portfolio.vercel.app" />
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
</Head>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomHead;
|
||||||
|
|
||||||
|
CustomHead.defaultProps = {
|
||||||
|
title: 'Ahmed Galadima | Portfolio',
|
||||||
|
};
|
||||||
25
components/Illustration.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { SVGProps } from 'react';
|
||||||
|
|
||||||
|
const Illustration = (props: SVGProps<SVGSVGElement>) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={486}
|
||||||
|
height={534}
|
||||||
|
viewBox="0 0 486 534"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<circle cx={167} cy={60} r={60} fill="#D7F484" />
|
||||||
|
<circle cx={37.5} cy={215.5} r={37.5} fill="currentColor" />
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M486 144.469c-38.145-31.86-87.255-51.033-140.842-51.033-121.415 0-219.842 98.427-219.842 219.842 0 14.167 1.34 28.02 3.9 41.441 47.414-86.154 91.678-142.17 146.717-170.767 56.069-29.132 121.816-29.08 210.067-6.68v-32.803zm0 48.288v289.33c-38.145 31.86-87.255 51.033-140.842 51.033-100.321 0-184.947-67.197-211.325-159.037l1.502.805c49.937-93.22 94.046-149.844 147.514-177.625 52.014-27.025 114.411-27.498 203.151-4.506z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Illustration;
|
||||||
44
components/Layout.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
import Titlebar from '@/components/Titlebar';
|
||||||
|
import Sidebar from '@/components/Sidebar';
|
||||||
|
import Explorer from '@/components/Explorer';
|
||||||
|
import Bottombar from '@/components/Bottombar';
|
||||||
|
import Tabsbar from '@/components/Tabsbar';
|
||||||
|
|
||||||
|
import styles from '@/styles/Layout.module.css';
|
||||||
|
|
||||||
|
interface LayoutProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Layout = ({ children }: LayoutProps) => {
|
||||||
|
// set scroll to top of main content on url pathname change
|
||||||
|
const router = useRouter();
|
||||||
|
useEffect(() => {
|
||||||
|
const main = document.getElementById('main-editor');
|
||||||
|
if (main) {
|
||||||
|
main.scrollTop = 0;
|
||||||
|
}
|
||||||
|
}, [router.pathname]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Titlebar />
|
||||||
|
<div className={styles.main}>
|
||||||
|
<Sidebar />
|
||||||
|
<Explorer />
|
||||||
|
<div style={{ width: '100%' }}>
|
||||||
|
<Tabsbar />
|
||||||
|
<main id="main-editor" className={styles.content}>
|
||||||
|
{children}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Bottombar />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Layout;
|
||||||
51
components/ProjectCard.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
import { Project } from '@/types';
|
||||||
|
|
||||||
|
import styles from '@/styles/ProjectCard.module.css';
|
||||||
|
|
||||||
|
interface ProjectCardProps {
|
||||||
|
project: Project;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProjectCard = ({ project }: ProjectCardProps) => {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={project.link}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className={styles.card}
|
||||||
|
>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<div className={styles.logoWrapper}>
|
||||||
|
<Image
|
||||||
|
src={project.logo}
|
||||||
|
alt={`${project.title} logo`}
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
className={styles.logo}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p className={styles.type}>{project.type}</p>
|
||||||
|
<h3 className={styles.title}>{project.title}</h3>
|
||||||
|
<p className={styles.description}>{project.description}</p>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className={styles.footer}>
|
||||||
|
<p className={styles.date}>{project.date}</p>
|
||||||
|
<p className={styles.status} data-status={project.status.toLowerCase()}>
|
||||||
|
{project.status}
|
||||||
|
</p>
|
||||||
|
{/* <p className={styles.skills}>{project.skills}</p> */}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add hover effect to the card
|
||||||
|
// Add a gradient overlay on hover
|
||||||
|
|
||||||
|
|
||||||
|
export default ProjectCard;
|
||||||
71
components/RepoCard.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import {
|
||||||
|
VscEye,
|
||||||
|
VscRepoForked,
|
||||||
|
VscStarEmpty,
|
||||||
|
VscGithubAlt,
|
||||||
|
VscLinkExternal,
|
||||||
|
VscTypeHierarchy,
|
||||||
|
} from 'react-icons/vsc';
|
||||||
|
|
||||||
|
import { Repo } from '@/types';
|
||||||
|
|
||||||
|
import styles from '@/styles/RepoCard.module.css';
|
||||||
|
|
||||||
|
interface RepoCardProps {
|
||||||
|
repo: Repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RepoCard = ({ repo }: RepoCardProps) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.card}>
|
||||||
|
<div className={styles.cardHeader}>
|
||||||
|
<h3 className={styles.title}>{repo.name}</h3>
|
||||||
|
{repo.language && (
|
||||||
|
<div className={styles.language}>
|
||||||
|
<VscTypeHierarchy className={styles.languageIcon} />
|
||||||
|
<span>{repo.language}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<p>{repo.description || 'No description provided'}</p>
|
||||||
|
<div className={styles.stats}>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<VscStarEmpty className={styles.icon} />
|
||||||
|
{repo.stargazers_count}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<VscRepoForked className={styles.icon} />
|
||||||
|
{repo.forks}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<VscEye className={styles.icon} />
|
||||||
|
{repo.watchers}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a
|
||||||
|
href={repo.html_url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
title="View Repository"
|
||||||
|
>
|
||||||
|
<VscGithubAlt className={styles.icon} />
|
||||||
|
</a>
|
||||||
|
{repo.homepage && (
|
||||||
|
<a
|
||||||
|
href={repo.homepage}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
title="Visit Live Site"
|
||||||
|
>
|
||||||
|
<VscLinkExternal className={styles.icon} />
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RepoCard;
|
||||||
74
components/Sidebar.tsx
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import {
|
||||||
|
VscAccount,
|
||||||
|
VscSettings,
|
||||||
|
VscMail,
|
||||||
|
VscGithubAlt,
|
||||||
|
VscCode,
|
||||||
|
VscFiles,
|
||||||
|
VscEdit,
|
||||||
|
} from 'react-icons/vsc';
|
||||||
|
|
||||||
|
import styles from '@/styles/Sidebar.module.css';
|
||||||
|
|
||||||
|
const sidebarTopItems = [
|
||||||
|
{ Icon: VscFiles, path: '/' },
|
||||||
|
{ Icon: VscGithubAlt, path: '/github' },
|
||||||
|
{ Icon: VscCode, path: '/projects' },
|
||||||
|
{ Icon: VscEdit, path: '/articles' },
|
||||||
|
{ Icon: VscMail, path: '/contact' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const sidebarBottomItems = [
|
||||||
|
{ Icon: VscAccount, path: '/about' },
|
||||||
|
{ Icon: VscSettings, path: '/settings' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const Sidebar = () => {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<aside className={styles.sidebar}>
|
||||||
|
<div className={styles.sidebarTop}>
|
||||||
|
{sidebarTopItems.map(({ Icon, path }) => (
|
||||||
|
<Link href={path} key={path}>
|
||||||
|
<div
|
||||||
|
className={`${styles.iconContainer} ${
|
||||||
|
router.pathname === path && styles.active
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
size={16}
|
||||||
|
fill={
|
||||||
|
router.pathname === path
|
||||||
|
? 'rgb(225, 228, 232)'
|
||||||
|
: 'rgb(106, 115, 125)'
|
||||||
|
}
|
||||||
|
className={styles.icon}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className={styles.sidebarBottom}>
|
||||||
|
{sidebarBottomItems.map(({ Icon, path }) => (
|
||||||
|
<div className={styles.iconContainer} key={path}>
|
||||||
|
<Link href={path}>
|
||||||
|
<Icon
|
||||||
|
fill={
|
||||||
|
router.pathname === path
|
||||||
|
? 'rgb(225, 228, 232)'
|
||||||
|
: 'rgb(106, 115, 125)'
|
||||||
|
}
|
||||||
|
className={styles.icon}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Sidebar;
|
||||||
28
components/Tab.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
import styles from '@/styles/Tab.module.css';
|
||||||
|
|
||||||
|
interface TabProps {
|
||||||
|
icon: string;
|
||||||
|
filename: string;
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tab = ({ icon, filename, path }: TabProps) => {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link href={path}>
|
||||||
|
<div
|
||||||
|
className={`${styles.tab} ${router.pathname === path && styles.active}`}
|
||||||
|
>
|
||||||
|
<Image src={icon} alt={filename} height={18} width={18} />
|
||||||
|
<p>{filename}</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tab;
|
||||||
26
components/Tabsbar.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import Tab from '@/components/Tab';
|
||||||
|
|
||||||
|
import styles from '@/styles/Tabsbar.module.css';
|
||||||
|
|
||||||
|
const Tabsbar = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.tabs}>
|
||||||
|
<Tab icon="/logos/react_icon.svg" filename="home.tsx" path="/" />
|
||||||
|
<Tab icon="/logos/html_icon.svg" filename="about.html" path="/about" />
|
||||||
|
<Tab icon="/logos/css_icon.svg" filename="contact.css" path="/contact" />
|
||||||
|
<Tab icon="/logos/js_icon.svg" filename="projects.js" path="/projects" />
|
||||||
|
{/* <Tab
|
||||||
|
icon="/logos/json_icon.svg"
|
||||||
|
filename="articles.json"
|
||||||
|
path="/articles"
|
||||||
|
/> */}
|
||||||
|
<Tab
|
||||||
|
icon="/logos/markdown_icon.svg"
|
||||||
|
filename="github.md"
|
||||||
|
path="/github"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tabsbar;
|
||||||
40
components/ThemeInfo.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
import styles from '@/styles/ThemeInfo.module.css';
|
||||||
|
|
||||||
|
interface ThemeInfoProps {
|
||||||
|
icon: string;
|
||||||
|
name: string;
|
||||||
|
publisher: string;
|
||||||
|
theme: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ThemeInfo = ({ icon, name, publisher, theme }: ThemeInfoProps) => {
|
||||||
|
const setTheme = (theme: string) => {
|
||||||
|
document.documentElement.setAttribute('data-theme', theme);
|
||||||
|
localStorage.setItem('theme', theme);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.imageWrapper}>
|
||||||
|
<Image
|
||||||
|
src={icon}
|
||||||
|
alt={name}
|
||||||
|
height={80}
|
||||||
|
width={80}
|
||||||
|
className={styles.themeImage}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.info}>
|
||||||
|
<div>
|
||||||
|
<h3>{name}</h3>
|
||||||
|
<h5>{publisher}</h5>
|
||||||
|
</div>
|
||||||
|
<button onClick={() => setTheme(theme)}>Set Color Theme</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThemeInfo;
|
||||||
34
components/Titlebar.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
import styles from '@/styles/Titlebar.module.css';
|
||||||
|
|
||||||
|
const Titlebar = () => {
|
||||||
|
return (
|
||||||
|
<section className={styles.titlebar}>
|
||||||
|
<Image
|
||||||
|
src="/logos/vscode_icon.svg"
|
||||||
|
alt="VSCode Icon"
|
||||||
|
height={15}
|
||||||
|
width={15}
|
||||||
|
className={styles.icon}
|
||||||
|
/>
|
||||||
|
<div className={styles.items}>
|
||||||
|
<p>File</p>
|
||||||
|
<p>Edit</p>
|
||||||
|
<p>View</p>
|
||||||
|
<p>Go</p>
|
||||||
|
<p>Run</p>
|
||||||
|
<p>Terminal</p>
|
||||||
|
<p>Help</p>
|
||||||
|
</div>
|
||||||
|
<p className={styles.title}>Ahmed Galadima - Visual Studio Code</p>
|
||||||
|
<div className={styles.windowButtons}>
|
||||||
|
<span className={styles.minimize}></span>
|
||||||
|
<span className={styles.maximize}></span>
|
||||||
|
<span className={styles.close}></span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Titlebar;
|
||||||
69
data/projects.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
export interface Project {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
type: string;
|
||||||
|
logo: string;
|
||||||
|
link: string;
|
||||||
|
slug: string;
|
||||||
|
date: string;
|
||||||
|
status: string;
|
||||||
|
skills: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const projects: Project[] = [
|
||||||
|
{
|
||||||
|
title: 'Chopfood NG',
|
||||||
|
description: 'A delivery app for customers to easily order for food around their location.',
|
||||||
|
logo: '/logos/driwwwle.svg',
|
||||||
|
link: 'https://github.com/itsnitinr/driwwwle',
|
||||||
|
slug: 'driwwwle',
|
||||||
|
type: 'Software Development',
|
||||||
|
date: "2023-2024",
|
||||||
|
status: "Completed",
|
||||||
|
skills: "Angular, Node.js, Express, mySql, TypeScript"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Vendostack',
|
||||||
|
description: 'An ecommerce platform for vendors to sell their products online.',
|
||||||
|
logo: '/logos/vsc.svg',
|
||||||
|
link: 'https://vendostack.com',
|
||||||
|
slug: 'vscode-portfolio',
|
||||||
|
type: 'Software Development',
|
||||||
|
date: "2024-Present",
|
||||||
|
status: "Ongoing",
|
||||||
|
skills: "Angular, Node.js, Express, mySql, TypeScript, GraphQL, React"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ireferdoc',
|
||||||
|
description: 'A simple and elegant way to track your subscriptions and save money.',
|
||||||
|
logo: '/logos/subtrackt.svg',
|
||||||
|
link: 'https://ireferdoc.com',
|
||||||
|
slug: 'subtrackt',
|
||||||
|
type: 'Software Development',
|
||||||
|
date: "2021- Present",
|
||||||
|
status: "Completed",
|
||||||
|
skills: "Angular, Node.js, Express, mySql, TypeScript"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Safrafan',
|
||||||
|
description: 'VSCode extension to track and deploy your Coolify applications.',
|
||||||
|
logo: '/logos/coolify.svg',
|
||||||
|
link: 'https://github.com/itsnitinr/coolify-vscode-extension',
|
||||||
|
slug: 'coolify-vscode-extension',
|
||||||
|
type: 'Software Development',
|
||||||
|
date: "2021-2023",
|
||||||
|
status: "Archived",
|
||||||
|
skills: "React, TypeScript, Node.js, GitHub Action"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Arizult Consulting',
|
||||||
|
description: 'Conducted a 3-day QA audit, identifying 45+ critical bugs;',
|
||||||
|
logo: '/logos/coolify.svg',
|
||||||
|
link: 'https://github.com/itsnitinr/coolify-vscode-extension',
|
||||||
|
slug: 'coolify-vscode-extension',
|
||||||
|
type: 'QA Audit',
|
||||||
|
date: "2024-2025",
|
||||||
|
status: "Completed",
|
||||||
|
skills: "Playwright, TypeScript, Node.js, GitHub Action"
|
||||||
|
},
|
||||||
|
];
|
||||||
15
eslint.config.mjs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { dirname } from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { FlatCompat } from '@eslint/eslintrc';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
});
|
||||||
|
|
||||||
|
const eslintConfig = [
|
||||||
|
...compat.extends('next/core-web-vitals', 'next/typescript'),
|
||||||
|
];
|
||||||
|
export default eslintConfig;
|
||||||
5
next-env.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
|
||||||
14
next.config.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import type { NextConfig } from 'next';
|
||||||
|
|
||||||
|
const nextConfig: NextConfig = {
|
||||||
|
images: {
|
||||||
|
remotePatterns: [
|
||||||
|
{ hostname: 'res.cloudinary.com', protocol: 'https' },
|
||||||
|
{ hostname: 'avatars.githubusercontent.com', protocol: 'https' },
|
||||||
|
{ hostname: 'imgur.com', protocol: 'https' },
|
||||||
|
{ hostname: 'media2.dev.to', protocol: 'https' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
8710
package-lock.json
generated
Normal file
25
package.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "galads-portfolio",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "^15.3.2",
|
||||||
|
"react": "^19.1.0",
|
||||||
|
"react-dom": "^19.1.0",
|
||||||
|
"react-github-calendar": "^4.5.6",
|
||||||
|
"react-icons": "^5.5.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^22.13.10",
|
||||||
|
"@types/react": "^19.0.11",
|
||||||
|
"eslint": "^9.22.0",
|
||||||
|
"eslint-config-next": "^15.2.3",
|
||||||
|
"typescript": "^5.8.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
26
pages/_app.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import type { AppProps } from 'next/app';
|
||||||
|
|
||||||
|
import Layout from '@/components/Layout';
|
||||||
|
import Head from '@/components/Head';
|
||||||
|
|
||||||
|
import '@/styles/globals.css';
|
||||||
|
import '@/styles/themes.css';
|
||||||
|
|
||||||
|
function MyApp({ Component, pageProps }: AppProps) {
|
||||||
|
useEffect(() => {
|
||||||
|
const theme = localStorage.getItem('theme');
|
||||||
|
if (theme) {
|
||||||
|
document.documentElement.setAttribute('data-theme', theme);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<Head title={`Ahmed Galadima | ${pageProps.title}`} />
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyApp;
|
||||||
124
pages/about.tsx
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import styles from '@/styles/AboutPage.module.css';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { FaTools, FaRocket, FaCertificate, FaCodeBranch } from 'react-icons/fa';
|
||||||
|
|
||||||
|
const AboutPage = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<header className={styles.header}>
|
||||||
|
<h1 className={styles.title}>Ahmed Galadima</h1>
|
||||||
|
<div className={styles.subtitle}>Senior QA Engineer & Automation Consultant</div>
|
||||||
|
<p className={styles.tagline}>Turning quality assurance into competitive advantage</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div className={styles.aboutContent}>
|
||||||
|
<section className={styles.section}>
|
||||||
|
<div className={styles.highlightCard}>
|
||||||
|
<h2 className={styles.sectionTitle}>Value Proposition</h2>
|
||||||
|
<p className={styles.paragraph}>
|
||||||
|
I help startups and tech teams <span className={styles.highlight}>ship flawless software 30% faster </span>
|
||||||
|
through strategic test automation and CI/CD optimization. Proven track record of reducing post-launch
|
||||||
|
defects by 70%+ and QA costs by 40%+.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={styles.section}>
|
||||||
|
<h2 className={styles.sectionTitle}><FaRocket className={styles.icon} /> Key Achievements</h2>
|
||||||
|
<div className={styles.grid}>
|
||||||
|
<div className={styles.card}>
|
||||||
|
<h3>Process Automation</h3>
|
||||||
|
<ul className={styles.list}>
|
||||||
|
<li>Reduced regression testing time by 65% through Selenium frameworks</li>
|
||||||
|
<li>Implemented CI/CD pipelines cutting release cycles from 4 weeks to 10 days</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<br></br>
|
||||||
|
<div className={styles.card}>
|
||||||
|
<h3>Client Impact</h3>
|
||||||
|
<ul className={styles.list}>
|
||||||
|
<li>$50K+ saved in remediation costs for fintech clients</li>
|
||||||
|
<li>Zero critical bugs in 5+ MVP launches</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={styles.section}>
|
||||||
|
<h2 className={styles.sectionTitle}><FaTools className={styles.icon} /> Technical Arsenal</h2>
|
||||||
|
<div className={styles.techGrid}>
|
||||||
|
<div className={styles.techItem}>
|
||||||
|
<FaCodeBranch className={styles.techIcon} />
|
||||||
|
<div>
|
||||||
|
<h3>Automation</h3>
|
||||||
|
<p>Selenium · Cypress · Postman · JMeter</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.techItem}>
|
||||||
|
<FaCertificate className={styles.techIcon} />
|
||||||
|
<div>
|
||||||
|
<h3>CI/CD & DevOps</h3>
|
||||||
|
<p>Jenkins · Docker · GitLab CI · Kubernetes</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={styles.section}>
|
||||||
|
<h2 className={styles.sectionTitle}>Client Success Stories</h2>
|
||||||
|
<div className={styles.caseStudy}>
|
||||||
|
<h3>HealthTech Startup</h3>
|
||||||
|
<div className={styles.challenge}>
|
||||||
|
<span>Challenge:</span> MVP launch blocked by 100+ critical bugs
|
||||||
|
</div>
|
||||||
|
<div className={styles.solution}>
|
||||||
|
<span>Solution:</span> 3-day QA audit + automated regression suite
|
||||||
|
</div>
|
||||||
|
<div className={styles.outcome}>
|
||||||
|
<span>Outcome:</span> Zero critical bugs at launch · $500K seed funding secured
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={styles.section}>
|
||||||
|
<h2 className={styles.sectionTitle}>Credentials</h2>
|
||||||
|
<div className={styles.credentials}>
|
||||||
|
<div className={styles.badge}>
|
||||||
|
<FaCertificate className={styles.badgeIcon} />
|
||||||
|
ISTQB Advanced
|
||||||
|
</div>
|
||||||
|
<div className={styles.badge}>
|
||||||
|
<FaCertificate className={styles.badgeIcon} />
|
||||||
|
Certified ScrumMaster
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={styles.section}>
|
||||||
|
<h2 className={styles.sectionTitle}>Testimonials</h2>
|
||||||
|
<blockquote className={styles.testimonial}>
|
||||||
|
Ahmed's automation framework became our secret weapon for scaling.
|
||||||
|
Cut our testing costs by 60% while improving coverage.
|
||||||
|
<cite>- CTO, SaaS Platform</cite>
|
||||||
|
</blockquote>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.ctaSection}>
|
||||||
|
<Link href={"./contact"} className={styles.ctaButton}>
|
||||||
|
Let's Automate Your Quality
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getStaticProps() {
|
||||||
|
return {
|
||||||
|
props: { title: 'Expert QA Engineering Services' },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AboutPage;
|
||||||
58
pages/articles.tsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import ArticleCard from '@/components/ArticleCard';
|
||||||
|
|
||||||
|
import { Article } from '@/types';
|
||||||
|
|
||||||
|
import styles from '@/styles/ArticlesPage.module.css';
|
||||||
|
|
||||||
|
interface ArticlesPageProps {
|
||||||
|
articles: Article[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const ArticlesPage = ({ articles }: ArticlesPageProps) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.layout}>
|
||||||
|
<h1 className={styles.pageTitle}>My Articles</h1>
|
||||||
|
<p className={styles.pageSubtitle}>
|
||||||
|
Recent posts from{' '}
|
||||||
|
<a
|
||||||
|
href="https://dev.to/galads"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
className={styles.underline}
|
||||||
|
>
|
||||||
|
dev.to
|
||||||
|
</a>{' '}
|
||||||
|
where I share insights and tutorials about web development.
|
||||||
|
</p>
|
||||||
|
<div className={styles.container}>
|
||||||
|
{articles.length > 0 ? (
|
||||||
|
articles.map((article) => (
|
||||||
|
<ArticleCard key={article.id} article={article} />
|
||||||
|
))
|
||||||
|
) :(
|
||||||
|
<p>No articles available at the moment.</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getStaticProps() {
|
||||||
|
const res = await fetch(
|
||||||
|
'https://dev.to/api/articles/me/published?per_page=6',
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'api-key': process.env.DEV_TO_API_KEY!,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: { title: 'Articles', articles: data },
|
||||||
|
revalidate: 60,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ArticlesPage;
|
||||||
28
pages/contact.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import ContactCode from '@/components/ContactCode';
|
||||||
|
|
||||||
|
import styles from '@/styles/ContactPage.module.css';
|
||||||
|
|
||||||
|
const ContactPage = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.layout}>
|
||||||
|
<h1 className={styles.pageTitle}>Contact Me</h1>
|
||||||
|
<p className={styles.pageSubtitle}>
|
||||||
|
Feel free to reach out to me through any of the social platforms below.
|
||||||
|
I'm always open to new opportunities and connections.
|
||||||
|
</p>
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.contactContainer}>
|
||||||
|
<ContactCode />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getStaticProps() {
|
||||||
|
return {
|
||||||
|
props: { title: 'Contact' },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ContactPage;
|
||||||
99
pages/github.tsx
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import Image from 'next/image';
|
||||||
|
import GitHubCalendar from 'react-github-calendar';
|
||||||
|
import { VscRepo, VscPerson } from 'react-icons/vsc';
|
||||||
|
|
||||||
|
import RepoCard from '@/components/RepoCard';
|
||||||
|
import { Repo, User } from '@/types';
|
||||||
|
|
||||||
|
import styles from '@/styles/GithubPage.module.css';
|
||||||
|
|
||||||
|
interface GithubPageProps {
|
||||||
|
repos: Repo[];
|
||||||
|
user: User;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GithubPage = ({ repos, user }: GithubPageProps) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.layout}>
|
||||||
|
<div className={styles.pageHeading}>
|
||||||
|
<h1 className={styles.pageTitle}>GitHub</h1>
|
||||||
|
<p className={styles.pageSubtitle}>
|
||||||
|
Browse through my GitHub repositories and see what I've been
|
||||||
|
working on. These are some of my public repositories showcasing
|
||||||
|
various projects and skills.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.githubPage}>
|
||||||
|
<div className={styles.profileSection}>
|
||||||
|
<div className={styles.profileInfo}>
|
||||||
|
<Image
|
||||||
|
src={user.avatar_url}
|
||||||
|
className={styles.avatar}
|
||||||
|
alt={user.login}
|
||||||
|
width={100}
|
||||||
|
height={100}
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
<div className={styles.userInfo}>
|
||||||
|
<h2 className={styles.username}>{user.login}</h2>
|
||||||
|
<div className={styles.stats}>
|
||||||
|
<div className={styles.statItem}>
|
||||||
|
<VscRepo className={styles.statIcon} />
|
||||||
|
<span>{user.public_repos} repositories</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.statItem}>
|
||||||
|
<VscPerson className={styles.statIcon} />
|
||||||
|
<span>{user.followers} followers</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.sectionHeader}>
|
||||||
|
<h3 className={styles.sectionTitle}>Popular Repositories</h3>
|
||||||
|
</div>
|
||||||
|
<div className={styles.reposContainer}>
|
||||||
|
{repos.map((repo) => (
|
||||||
|
<RepoCard key={repo.id} repo={repo} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className={styles.contributions}>
|
||||||
|
<GitHubCalendar
|
||||||
|
username={process.env.NEXT_PUBLIC_GITHUB_USERNAME!}
|
||||||
|
hideColorLegend
|
||||||
|
hideMonthLabels
|
||||||
|
colorScheme="dark"
|
||||||
|
theme={{
|
||||||
|
dark: ['#161B22', '#0e4429', '#006d32', '#26a641', '#39d353'],
|
||||||
|
light: ['#161B22', '#0e4429', '#006d32', '#26a641', '#39d353'],
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getStaticProps() {
|
||||||
|
const userRes = await fetch(
|
||||||
|
`https://api.github.com/users/${process.env.NEXT_PUBLIC_GITHUB_USERNAME}`
|
||||||
|
);
|
||||||
|
const user = await userRes.json();
|
||||||
|
|
||||||
|
const repoRes = await fetch(
|
||||||
|
`https://api.github.com/users/${process.env.NEXT_PUBLIC_GITHUB_USERNAME}/repos?sort=pushed&per_page=6`
|
||||||
|
);
|
||||||
|
const repos = await repoRes.json();
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: { title: 'GitHub', repos, user },
|
||||||
|
revalidate: 600,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GithubPage;
|
||||||
137
pages/index.tsx
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { VscArrowRight } from 'react-icons/vsc';
|
||||||
|
|
||||||
|
import styles from '@/styles/HomePage.module.css';
|
||||||
|
|
||||||
|
export default function HomePage() {
|
||||||
|
const [activeLineIndex, setActiveLineIndex] = useState(0);
|
||||||
|
|
||||||
|
const codeLines = [
|
||||||
|
{ code: 'const HomePage = () => {', type: 'function' },
|
||||||
|
{
|
||||||
|
code: ' const [isLoaded, setIsLoaded] = useState(true);',
|
||||||
|
type: 'variable',
|
||||||
|
},
|
||||||
|
{ code: ' const developerInfo = {', type: 'variable' },
|
||||||
|
{ code: " name: 'Ahmed Galadima',", type: 'array-item' },
|
||||||
|
{ code: " role: 'Senior QA Engineer & Consultant',", type: 'array-item' },
|
||||||
|
{ code: " bio: 'Dynamic Senior QA Engineer & Consultant with over 10+ years of expertise'", type: 'array-item' },
|
||||||
|
{ code: ' };', type: 'array-end' },
|
||||||
|
{ code: '', type: 'blank' },
|
||||||
|
{ code: ' useEffect(() => {', type: 'nested-function' },
|
||||||
|
{
|
||||||
|
code: ' document.title = `${developerInfo.name} | Portfolio`;',
|
||||||
|
type: 'return',
|
||||||
|
},
|
||||||
|
{ code: ' setIsLoaded(true);', type: 'function-call' },
|
||||||
|
{ code: ' }, []);', type: 'close' },
|
||||||
|
{ code: '', type: 'blank' },
|
||||||
|
{ code: ' return (', type: 'return-object' },
|
||||||
|
{ code: ' <main className="hero-container">', type: 'object-method' },
|
||||||
|
{ code: ' <h1>{developerInfo.name}</h1>', type: 'object-method' },
|
||||||
|
{ code: ' <p>{developerInfo.role}</p>', type: 'object-method' },
|
||||||
|
{ code: ' <div className="cta">', type: 'object-method' },
|
||||||
|
{
|
||||||
|
code: ' <Link href="/projects">View Projects</Link>',
|
||||||
|
type: 'object-method',
|
||||||
|
},
|
||||||
|
{ code: ' </div>', type: 'object-method' },
|
||||||
|
{ code: ' </main>', type: 'object-method' },
|
||||||
|
{ code: ' );', type: 'close' },
|
||||||
|
{ code: '};', type: 'close-function' },
|
||||||
|
{ code: '', type: 'blank' },
|
||||||
|
{ code: 'export default HomePage;', type: 'function-call' },
|
||||||
|
];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setActiveLineIndex((prev) => (prev + 1) % codeLines.length);
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [codeLines.length]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.heroLayout}>
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.codeSection}>
|
||||||
|
<div className={styles.codeContainer}>
|
||||||
|
<div className={styles.editorContent}>
|
||||||
|
<div className={styles.lineNumbers}>
|
||||||
|
{codeLines.map((_, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`${styles.lineNumber} ${
|
||||||
|
index === activeLineIndex ? styles.activeLine : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{index + 1}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.codeEditor}>
|
||||||
|
{codeLines.map((line, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`${styles.codeLine} ${styles[line.type]} ${
|
||||||
|
index === activeLineIndex ? styles.highlightedLine : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{line.code}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.overlayGlow}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.infoSection}>
|
||||||
|
<h1 className={styles.developerName}>
|
||||||
|
Ahmed <span className={styles.accentText}>Galadima</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div className={styles.developerRole}>Senior QA Engineer & Consultant</div>
|
||||||
|
|
||||||
|
<p className={styles.bio}>
|
||||||
|
Dynamic Senior QA Engineer & Consultant with 10+ years of expertise in delivering 30% faster software releases and
|
||||||
|
40%+ cost savings for startups and enterprises. Specialize in transforming chaotic workflows into streamlined,
|
||||||
|
automation-driven processes that ensure client products exceed market standards.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className={styles.actionLinks}>
|
||||||
|
<Link href="/projects" className={styles.primaryLink}>
|
||||||
|
View Projects <VscArrowRight />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.decorElements}>
|
||||||
|
<div className={styles.codeFlare}></div>
|
||||||
|
<div className={styles.gridLines}></div>
|
||||||
|
<div className={styles.codeBlock1}>{'{'}</div>
|
||||||
|
<div className={styles.codeBlock2}>{'}'}</div>
|
||||||
|
<div className={styles.codeBlock3}>{'<>'}</div>
|
||||||
|
<div className={styles.codeBlock4}>{'/>'}</div>
|
||||||
|
<div className={styles.orb1}></div>
|
||||||
|
<div className={styles.orb2}></div>
|
||||||
|
<div className={styles.orb3}></div>
|
||||||
|
<div className={styles.codeSymbol1}>{'()'}</div>
|
||||||
|
<div className={styles.codeSymbol2}>{'[]'}</div>
|
||||||
|
<div className={styles.codeSymbol3}>{'=>'}</div>
|
||||||
|
<div className={styles.dotPattern}></div>
|
||||||
|
<div className={styles.mobileAccent}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStaticProps() {
|
||||||
|
return {
|
||||||
|
props: { title: 'Home' },
|
||||||
|
};
|
||||||
|
}
|
||||||
31
pages/projects.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import ProjectCard from '@/components/ProjectCard';
|
||||||
|
import { projects } from '@/data/projects';
|
||||||
|
|
||||||
|
import styles from '@/styles/ProjectsPage.module.css';
|
||||||
|
|
||||||
|
const ProjectsPage = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.layout}>
|
||||||
|
<h1 className={styles.pageTitle}>Software Development and QA Projects</h1>
|
||||||
|
<p className={styles.pageSubtitle}>
|
||||||
|
Here's a collection of my recent work. These projects showcase my
|
||||||
|
skills in web development, design, and problem-solving.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className={styles.container}>
|
||||||
|
{projects.map((project) => (
|
||||||
|
<ProjectCard key={project.slug} project={project} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getStaticProps() {
|
||||||
|
return {
|
||||||
|
props: { title: 'Projects' },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProjectsPage;
|
||||||
56
pages/settings.tsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import ThemeInfo from '@/components/ThemeInfo';
|
||||||
|
|
||||||
|
import styles from '@/styles/SettingsPage.module.css';
|
||||||
|
|
||||||
|
const SettingsPage = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.layout}>
|
||||||
|
<div className={styles.container}>
|
||||||
|
<ThemeInfo
|
||||||
|
name="GitHub Dark"
|
||||||
|
icon="/themes/github-dark.png"
|
||||||
|
publisher="GitHub"
|
||||||
|
theme="github-dark"
|
||||||
|
/>
|
||||||
|
<ThemeInfo
|
||||||
|
name="Dracula"
|
||||||
|
icon="/themes/dracula.png"
|
||||||
|
publisher="Dracula Theme"
|
||||||
|
theme="dracula"
|
||||||
|
/>
|
||||||
|
<ThemeInfo
|
||||||
|
name="Ayu Dark"
|
||||||
|
icon="/themes/ayu.png"
|
||||||
|
publisher="teabyii"
|
||||||
|
theme="ayu-dark"
|
||||||
|
/>
|
||||||
|
<ThemeInfo
|
||||||
|
name="Ayu Mirage"
|
||||||
|
icon="/themes/ayu.png"
|
||||||
|
publisher="teabyii"
|
||||||
|
theme="ayu-mirage"
|
||||||
|
/>
|
||||||
|
<ThemeInfo
|
||||||
|
name="Nord"
|
||||||
|
icon="/themes/nord.png"
|
||||||
|
publisher="arcticicestudio"
|
||||||
|
theme="nord"
|
||||||
|
/>
|
||||||
|
<ThemeInfo
|
||||||
|
name="Night Owl"
|
||||||
|
icon="/themes/night-owl.png"
|
||||||
|
publisher="sarah.drasner"
|
||||||
|
theme="night-owl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getStaticProps() {
|
||||||
|
return {
|
||||||
|
props: { title: 'Settings' },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SettingsPage;
|
||||||
BIN
public/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
1
public/logos/coolify.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg fill="none" height="400" viewBox="0 0 512 512" width="400" xmlns="http://www.w3.org/2000/svg"><g fill="#8c52ff"><path d="m188.548 188.548h-57.344v172.032h57.344zm0 229.376h229.376v-57.344h-229.376zm0-229.376h229.376v-57.344h-229.376z" fill-opacity=".302"/><path d="m170.446 170.446h-57.344v172.032h57.344zm0 229.376h229.376v-57.344h-229.376zm0-229.376h229.376v-57.344h-229.376z" fill-opacity=".502"/><path d="m152.344 152.344h-57.344v172.032h57.344zm0 229.376h229.376v-57.344h-229.376zm0-229.376h229.376v-57.344h-229.376z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 539 B |
3
public/logos/css_icon.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m5 3l-.65 3.34h13.59l-.44 2.16h-13.58l-.66 3.33h13.59l-.76 3.81-5.48 1.81-4.75-1.81.33-1.64h-3.34l-.79 4 7.85 3 9.05-3 1.2-6.03.24-1.21 1.54-7.76h-16.94z" fill="#42a5f5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 263 B |
74
public/logos/driwwwle.svg
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<mask id="mask0" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="72" height="72">
|
||||||
|
<rect width="72" height="72" rx="36" fill="#C4C4C4"/>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#mask0)">
|
||||||
|
<rect x="-18" y="-18" width="108" height="108" fill="url(#paint0_linear)"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter0_ddii)">
|
||||||
|
<path d="M36 6C19.458 6 6 19.458 6 36C6 52.542 19.458 66 36 66C52.542 66 66 52.542 66 36C66 19.458 52.542 6 36 6ZM12 36C12 33.303 12.468 30.714 13.293 28.293L18 33L24 39V45L30 51L33 54V59.793C21.183 58.308 12 48.216 12 36ZM54.99 50.619C53.031 49.041 50.061 48 48 48V45C48 43.4087 47.3679 41.8826 46.2426 40.7574C45.1174 39.6321 43.5913 39 42 39H30V30C31.5913 30 33.1174 29.3679 34.2426 28.2426C35.3679 27.1174 36 25.5913 36 24V21H39C40.5913 21 42.1174 20.3679 43.2426 19.2426C44.3679 18.1174 45 16.5913 45 15V13.767C53.784 17.334 60 25.95 60 36C59.9995 41.2941 58.2368 46.4374 54.99 50.619V50.619Z" fill="url(#paint1_linear)" fill-opacity="0.48" shape-rendering="crispEdges"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter1_ddd)">
|
||||||
|
<path d="M28.384 52.888C26.56 52.888 25.04 52.264 23.824 51.016C22.608 49.768 22 47.816 22 45.16C22 42.792 22.464 40.312 23.392 37.72C24.352 35.096 25.76 32.888 27.616 31.096C29.504 29.272 31.744 28.36 34.336 28.36C35.648 28.36 36.624 28.584 37.264 29.032C37.904 29.48 38.224 30.072 38.224 30.808V31L40.576 19.96L47.68 19L42.16 44.92C42.032 45.4 41.968 45.864 41.968 46.312C41.968 47.592 42.624 48.232 43.936 48.232C44.512 48.232 45.024 48.136 45.472 47.944C45.344 49.544 44.768 50.776 43.744 51.64C42.752 52.472 41.568 52.888 40.192 52.888C38.912 52.888 37.824 52.568 36.928 51.928C36.064 51.256 35.488 50.248 35.2 48.904C33.28 51.56 31.008 52.888 28.384 52.888ZM31.504 48.232C32.208 48.232 32.912 47.928 33.616 47.32C34.352 46.712 34.896 45.864 35.248 44.776L35.44 44.008L37.792 33.016C37.504 31.896 36.848 31.336 35.824 31.336C34.544 31.336 33.392 32.088 32.368 33.592C31.344 35.064 30.544 36.856 29.968 38.968C29.392 41.048 29.104 42.888 29.104 44.488C29.104 46.088 29.328 47.112 29.776 47.56C30.256 48.008 30.832 48.232 31.504 48.232Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_ddii" x="5" y="6" width="62" height="62" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="1"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.5"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.933333 0 0 0 0 0.909804 0 0 0 0.09 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="0.5"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.25"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.9316 0 0 0 0 0.91 0 0 0 0.18 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow" result="shape"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="2"/>
|
||||||
|
<feGaussianBlur stdDeviation="1"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.308333 0 0 0 0 0.0775973 0 0 0 0 0.146818 0 0 0 0.18 0"/>
|
||||||
|
<feBlend mode="normal" in2="shape" result="effect3_innerShadow"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="1"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.5"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.309804 0 0 0 0 0.0784314 0 0 0 0 0.145098 0 0 0 0.24 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect3_innerShadow" result="effect4_innerShadow"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_ddd" x="18" y="19" width="33.68" height="41.888" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="4"/>
|
||||||
|
<feGaussianBlur stdDeviation="2"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.18 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="2"/>
|
||||||
|
<feGaussianBlur stdDeviation="1"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.18 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="1"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.5"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.18 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect2_dropShadow" result="effect3_dropShadow"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<linearGradient id="paint0_linear" x1="36" y1="-18" x2="36" y2="90" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#F98FAF"/>
|
||||||
|
<stop offset="1" stop-color="#E7225D"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear" x1="36" y1="6" x2="36" y2="66" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#FA2867"/>
|
||||||
|
<stop offset="1" stop-color="#710526"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.8 KiB |
3
public/logos/html_icon.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m12 17.56l4.07-1.13.55-6.1h-7.24l-.18-2.03h7.6l.2-1.99h-10l.56 6.01h6.89l-.23 2.58-2.22.6-2.22-.6-.14-1.66h-2l.29 3.19 4.07 1.13m-7.93-14.56h15.86l-1.43 16.2-6.5 1.8-6.5-1.8-1.43-16.2z" fill="#e44d26"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 294 B |
3
public/logos/js_icon.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m3 3h18v18h-18v-18m4.73 15.04c.4.85 1.19 1.55 2.54 1.55 1.5 0 2.53-.8 2.53-2.55v-5.78h-1.7v5.74c0 .86-.35 1.08-.9 1.08-.58 0-.82-.4-1.09-.87l-1.38.83m5.98-.18c.5.98 1.51 1.73 3.09 1.73 1.6 0 2.8-.83 2.8-2.36 0-1.41-.81-2.04-2.25-2.66l-.42-.18c-.73-.31-1.04-.52-1.04-1.02 0-.41.31-.73.81-.73.48 0 .8.21 1.09.73l1.31-.87c-.55-.96-1.33-1.33-2.4-1.33-1.51 0-2.48.96-2.48 2.23 0 1.38.81 2.03 2.03 2.55l.42.18c.78.34 1.24.55 1.24 1.13 0 .48-.45.83-1.15.83-.83 0-1.31-.43-1.67-1.03l-1.38.8z" fill="#ffca28"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 593 B |
1
public/logos/json_icon.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m5 3h2v2h-2v5a2 2 0 0 1 -2 2 2 2 0 0 1 2 2v5h2v2h-2c-1.07-.27-2-.9-2-2v-4a2 2 0 0 0 -2 -2h-1v-2h1a2 2 0 0 0 2 -2v-4a2 2 0 0 1 2 -2m14 0a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1v2h-1a2 2 0 0 0 -2 2v4a2 2 0 0 1 -2 2h-2v-2h2v-5a2 2 0 0 1 2 -2 2 2 0 0 1 -2 -2v-5h-2v-2h2m-7 12a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1m-4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1m8 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" style="fill:#fbc02d"/></svg>
|
||||||
|
After Width: | Height: | Size: 567 B |
3
public/logos/markdown_icon.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m2.25 15.75v-8h2l3 3 3-3h2v8h-2v-5.17l-3 3-3-3v5.17h-2m14-8h3v4h2.5l-4 4.5-4-4.5h2.5z" fill="#42a5f5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 195 B |
3
public/logos/react_icon.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m12 10.11c1.03 0 1.87.84 1.87 1.89 0 1-.84 1.85-1.87 1.85s-1.87-.85-1.87-1.85c0-1.05.84-1.89 1.87-1.89m-4.63 9.89c.63.38 2.01-.2 3.6-1.7-.52-.59-1.03-1.23-1.51-1.9-.82-.08-1.63-.2-2.4-.36-.51 2.14-.32 3.61.31 3.96m.71-5.74l-.29-.51c-.11.29-.22.58-.29.86.27.06.57.11.88.16l-.3-.51m6.54-.76l.81-1.5-.81-1.5c-.3-.53-.62-1-.91-1.47-.54-.03-1.11-.03-1.71-.03s-1.17 0-1.71.03c-.29.47-.61.94-.91 1.47l-.81 1.5.81 1.5c.3.53.62 1 .91 1.47.54.03 1.11.03 1.71.03s1.17 0 1.71-.03c.29-.47.61-.94.91-1.47m-2.62-6.72c-.19.22-.39.45-.59.72h.59.59c-.2-.27-.4-.5-.59-.72m0 10.44c.19-.22.39-.45.59-.72h-.59-.59c.2.27.4.5.59.72m4.62-13.22c-.62-.38-2 .2-3.59 1.7.52.59 1.03 1.23 1.51 1.9.82.08 1.63.2 2.4.36.51-2.14.32-3.61-.32-3.96m-.7 5.74l.29.51c.11-.29.22-.58.29-.86-.27-.06-.57-.11-.88-.16l.3.51m1.45-7.05c1.47.84 1.63 3.05 1.01 5.63 2.54.75 4.37 1.99 4.37 3.68s-1.83 2.93-4.37 3.68c.62 2.58.46 4.79-1.01 5.63-1.46.84-3.45-.12-5.37-1.95-1.92 1.83-3.91 2.79-5.38 1.95-1.46-.84-1.62-3.05-1-5.63-2.54-.75-4.37-1.99-4.37-3.68s1.83-2.93 4.37-3.68c-.62-2.58-.46-4.79 1-5.63 1.47-.84 3.46.12 5.38 1.95 1.92-1.83 3.91-2.79 5.37-1.95m-.29 9.31c.34.75.64 1.5.89 2.26 2.1-.63 3.28-1.53 3.28-2.26s-1.18-1.63-3.28-2.26c-.25.76-.55 1.51-.89 2.26m-10.16 0c-.34-.75-.64-1.5-.89-2.26-2.1.63-3.28 1.53-3.28 2.26s1.18 1.63 3.28 2.26c.25-.76.55-1.51.89-2.26m9 2.26l-.3.51c.31-.05.61-.1.88-.16-.07-.28-.18-.57-.29-.86l-.29.51m-2.89 4.04c1.59 1.5 2.97 2.08 3.59 1.7.64-.35.83-1.82.32-3.96-.77.16-1.58.28-2.4.36-.48.67-.99 1.31-1.51 1.9m-4.95-8.56l.3-.51c-.31.05-.61.1-.88.16.07.28.18.57.29.86l.29-.51m2.89-4.04c-1.59-1.5-2.97-2.08-3.6-1.7-.63.35-.82 1.82-.31 3.96.77-.16 1.58-.28 2.4-.36.48-.67.99-1.31 1.51-1.9z" fill="#00bcd4"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
16
public/logos/subtrackt.svg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<svg width="47" height="36" viewBox="0 0 47 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 10.8C0 6.94044 0 5.01066 0.780431 3.54713C1.41023 2.36608 2.38298 1.40023 3.57247 0.774896C5.04645 0 6.99001 0 10.8771 0H36.1229C40.01 0 41.9536 0 43.4275 0.774896C44.617 1.40023 45.5898 2.36608 46.2196 3.54713C47 5.01066 47 6.94044 47 10.8V24.7315C46.8893 24.2291 46.69 23.7689 46.4021 23.3507C45.9491 22.6926 45.3149 22.1788 44.4994 21.8095C43.6888 21.4402 42.7398 21.2555 41.6525 21.2555C40.5844 21.2555 39.6306 21.4402 38.7913 21.8095C37.952 22.1788 37.2916 22.6926 36.81 23.3507C36.3331 24.0088 36.097 24.7783 36.1018 25.6589C36.097 26.7338 36.4523 27.5884 37.1676 28.2229C37.8829 28.8573 38.8581 29.3237 40.0932 29.622L41.6883 30.0197C42.2224 30.1476 42.673 30.2896 43.0402 30.4459C43.4122 30.6021 43.6935 30.7915 43.8843 31.0141C44.0798 31.2366 44.1775 31.5112 44.1775 31.8379C44.1775 32.1883 44.0703 32.4984 43.8557 32.7683C43.6411 33.0382 43.3383 33.2489 42.9472 33.4004C42.561 33.5519 42.1056 33.6277 41.581 33.6277C41.0469 33.6277 40.5677 33.5472 40.1433 33.3862C39.7236 33.2205 39.3874 32.9767 39.1347 32.6547C38.8867 32.328 38.746 31.9208 38.7127 31.4331H35.7155C35.7394 32.4795 35.9945 33.3578 36.4809 34.068C36.9721 34.7735 37.654 35.3062 38.5267 35.666C38.8237 35.7878 39.1381 35.889 39.4701 35.9696C38.5402 36 37.4437 36 36.1229 36H10.8771C6.99001 36 5.04645 36 3.57247 35.2251C2.38298 34.5998 1.41023 33.6339 0.780431 32.4529C0 30.9893 0 29.0596 0 25.2V10.8ZM4.02857 8C4.02857 5.79086 5.83222 4 8.05714 4H10.7429C12.9678 4 14.7714 5.79086 14.7714 8V10.6667C14.7714 12.8758 12.9678 14.6667 10.7429 14.6667H8.05714C5.83222 14.6667 4.02857 12.8758 4.02857 10.6667V8Z" fill="url(#paint0_linear_42_42)"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 10.8C0 6.94044 0 5.01066 0.780431 3.54713C1.41023 2.36608 2.38298 1.40023 3.57247 0.774896C5.04645 0 6.99001 0 10.8771 0H36.1229C40.01 0 41.9536 0 43.4275 0.774896C44.617 1.40023 45.5898 2.36608 46.2196 3.54713C47 5.01066 47 6.94044 47 10.8V24.7315C46.8893 24.2291 46.69 23.7689 46.4021 23.3507C45.9491 22.6926 45.3149 22.1788 44.4994 21.8095C43.6888 21.4402 42.7398 21.2555 41.6525 21.2555C40.5844 21.2555 39.6306 21.4402 38.7913 21.8095C37.952 22.1788 37.2916 22.6926 36.81 23.3507C36.3331 24.0088 36.097 24.7783 36.1018 25.6589C36.097 26.7338 36.4523 27.5884 37.1676 28.2229C37.8829 28.8573 38.8581 29.3237 40.0932 29.622L41.6883 30.0197C42.2224 30.1476 42.673 30.2896 43.0402 30.4459C43.4122 30.6021 43.6935 30.7915 43.8843 31.0141C44.0798 31.2366 44.1775 31.5112 44.1775 31.8379C44.1775 32.1883 44.0703 32.4984 43.8557 32.7683C43.6411 33.0382 43.3383 33.2489 42.9472 33.4004C42.561 33.5519 42.1056 33.6277 41.581 33.6277C41.0469 33.6277 40.5677 33.5472 40.1433 33.3862C39.7236 33.2205 39.3874 32.9767 39.1347 32.6547C38.8867 32.328 38.746 31.9208 38.7127 31.4331H35.7155C35.7394 32.4795 35.9945 33.3578 36.4809 34.068C36.9721 34.7735 37.654 35.3062 38.5267 35.666C38.8237 35.7878 39.1381 35.889 39.4701 35.9696C38.5402 36 37.4437 36 36.1229 36H10.8771C6.99001 36 5.04645 36 3.57247 35.2251C2.38298 34.5998 1.41023 33.6339 0.780431 32.4529C0 30.9893 0 29.0596 0 25.2V10.8ZM4.02857 8C4.02857 5.79086 5.83222 4 8.05714 4H10.7429C12.9678 4 14.7714 5.79086 14.7714 8V10.6667C14.7714 12.8758 12.9678 14.6667 10.7429 14.6667H8.05714C5.83222 14.6667 4.02857 12.8758 4.02857 10.6667V8Z" fill="black" fill-opacity="0.2"/>
|
||||||
|
<path d="M46.8723 30.0404C46.991 28.9288 46.9994 27.5253 47 25.6376H44.1346C44.0774 25.0647 43.8318 24.6196 43.3979 24.3024C42.9639 23.9852 42.375 23.8266 41.6311 23.8266C41.1256 23.8266 40.6988 23.8976 40.3507 24.0396C40.0026 24.1769 39.7355 24.3687 39.5496 24.6149C39.3683 24.8611 39.2777 25.1405 39.2777 25.453C39.2682 25.7134 39.323 25.9407 39.4423 26.1348C39.5662 26.3289 39.7355 26.497 39.9501 26.6391C40.1647 26.7764 40.4127 26.8971 40.694 27.0013C40.9754 27.1007 41.2758 27.1859 41.5953 27.257L42.9115 27.5695C43.5505 27.7115 44.137 27.9009 44.6711 28.1376C45.2052 28.3744 45.6678 28.6656 46.0588 29.0112C46.3953 29.3087 46.6665 29.6517 46.8723 30.0404Z" fill="url(#paint1_linear_42_42)"/>
|
||||||
|
<path d="M46.8723 30.0404C46.991 28.9288 46.9994 27.5253 47 25.6376H44.1346C44.0774 25.0647 43.8318 24.6196 43.3979 24.3024C42.9639 23.9852 42.375 23.8266 41.6311 23.8266C41.1256 23.8266 40.6988 23.8976 40.3507 24.0396C40.0026 24.1769 39.7355 24.3687 39.5496 24.6149C39.3683 24.8611 39.2777 25.1405 39.2777 25.453C39.2682 25.7134 39.323 25.9407 39.4423 26.1348C39.5662 26.3289 39.7355 26.497 39.9501 26.6391C40.1647 26.7764 40.4127 26.8971 40.694 27.0013C40.9754 27.1007 41.2758 27.1859 41.5953 27.257L42.9115 27.5695C43.5505 27.7115 44.137 27.9009 44.6711 28.1376C45.2052 28.3744 45.6678 28.6656 46.0588 29.0112C46.3953 29.3087 46.6665 29.6517 46.8723 30.0404Z" fill="black" fill-opacity="0.2"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_42_42" x1="6.63503" y1="7.05302e-08" x2="30.9511" y2="41.514" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#DDE1EB"/>
|
||||||
|
<stop offset="1" stop-color="#878587"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_42_42" x1="6.63503" y1="7.05302e-08" x2="30.9511" y2="41.514" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#DDE1EB"/>
|
||||||
|
<stop offset="1" stop-color="#878587"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.2 KiB |
4
public/logos/vercel.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
41
public/logos/vsc.svg
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<svg viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M70.9119 99.3171C72.4869 99.9307 74.2828 99.8914 75.8725 99.1264L96.4608 89.2197C98.6242 88.1787 100 85.9892 100 83.5872V16.4133C100 14.0113 98.6243 11.8218 96.4609 10.7808L75.8725 0.873756C73.7862 -0.130129 71.3446 0.11576 69.5135 1.44695C69.252 1.63711 69.0028 1.84943 68.769 2.08341L29.3551 38.0415L12.1872 25.0096C10.589 23.7965 8.35363 23.8959 6.86933 25.2461L1.36303 30.2549C-0.452552 31.9064 -0.454633 34.7627 1.35853 36.417L16.2471 50.0001L1.35853 63.5832C-0.454633 65.2374 -0.452552 68.0938 1.36303 69.7453L6.86933 74.7541C8.35363 76.1043 10.589 76.2037 12.1872 74.9905L29.3551 61.9587L68.769 97.9167C69.3925 98.5406 70.1246 99.0104 70.9119 99.3171ZM75.0152 27.2989L45.1091 50.0001L75.0152 72.7012V27.2989Z" fill="white"/>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#mask0)">
|
||||||
|
<path d="M96.4614 10.7962L75.8569 0.875542C73.4719 -0.272773 70.6217 0.211611 68.75 2.08333L1.29858 63.5832C-0.515693 65.2373 -0.513607 68.0937 1.30308 69.7452L6.81272 74.754C8.29793 76.1042 10.5347 76.2036 12.1338 74.9905L93.3609 13.3699C96.086 11.3026 100 13.2462 100 16.6667V16.4275C100 14.0265 98.6246 11.8378 96.4614 10.7962Z" fill="#0065A9"/>
|
||||||
|
<g filter="url(#filter0_d)">
|
||||||
|
<path d="M96.4614 89.2038L75.8569 99.1245C73.4719 100.273 70.6217 99.7884 68.75 97.9167L1.29858 36.4169C-0.515693 34.7627 -0.513607 31.9063 1.30308 30.2548L6.81272 25.246C8.29793 23.8958 10.5347 23.7964 12.1338 25.0095L93.3609 86.6301C96.086 88.6974 100 86.7538 100 83.3334V83.5726C100 85.9735 98.6246 88.1622 96.4614 89.2038Z" fill="#007ACC"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter1_d)">
|
||||||
|
<path d="M75.8578 99.1263C73.4721 100.274 70.6219 99.7885 68.75 97.9166C71.0564 100.223 75 98.5895 75 95.3278V4.67213C75 1.41039 71.0564 -0.223106 68.75 2.08329C70.6219 0.211402 73.4721 -0.273666 75.8578 0.873633L96.4587 10.7807C98.6234 11.8217 100 14.0112 100 16.4132V83.5871C100 85.9891 98.6234 88.1786 96.4586 89.2196L75.8578 99.1263Z" fill="#1F9CF0"/>
|
||||||
|
</g>
|
||||||
|
<g style="mix-blend-mode:overlay" opacity="0.25">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M70.8511 99.3171C72.4261 99.9306 74.2221 99.8913 75.8117 99.1264L96.4 89.2197C98.5634 88.1787 99.9392 85.9892 99.9392 83.5871V16.4133C99.9392 14.0112 98.5635 11.8217 96.4001 10.7807L75.8117 0.873695C73.7255 -0.13019 71.2838 0.115699 69.4527 1.44688C69.1912 1.63705 68.942 1.84937 68.7082 2.08335L29.2943 38.0414L12.1264 25.0096C10.5283 23.7964 8.29285 23.8959 6.80855 25.246L1.30225 30.2548C-0.513334 31.9064 -0.515415 34.7627 1.29775 36.4169L16.1863 50L1.29775 63.5832C-0.515415 65.2374 -0.513334 68.0937 1.30225 69.7452L6.80855 74.754C8.29285 76.1042 10.5283 76.2036 12.1264 74.9905L29.2943 61.9586L68.7082 97.9167C69.3317 98.5405 70.0638 99.0104 70.8511 99.3171ZM74.9544 27.2989L45.0483 50L74.9544 72.7012V27.2989Z" fill="url(#paint0_linear)"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_d" x="-8.39411" y="15.8291" width="116.727" height="92.2456" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||||
|
<feOffset/>
|
||||||
|
<feGaussianBlur stdDeviation="4.16667"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||||
|
<feBlend mode="overlay" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_d" x="60.4167" y="-8.07558" width="47.9167" height="116.151" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||||
|
<feOffset/>
|
||||||
|
<feGaussianBlur stdDeviation="4.16667"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||||
|
<feBlend mode="overlay" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<linearGradient id="paint0_linear" x1="49.9392" y1="0.257812" x2="49.9392" y2="99.7423" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="white"/>
|
||||||
|
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.3 KiB |
41
public/logos/vscode_icon.svg
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="none">
|
||||||
|
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="256" height="256">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M181.534 254.252C185.566 255.823 190.164 255.722 194.234 253.764L246.94 228.403C252.478 225.738 256 220.132 256 213.983V42.0181C256 35.8689 252.478 30.2638 246.94 27.5988L194.234 2.23681C188.893 -0.333132 182.642 0.296344 177.955 3.70418C177.285 4.191 176.647 4.73454 176.049 5.33354L75.149 97.3862L31.1992 64.0247C27.1079 60.9191 21.3853 61.1735 17.5855 64.63L3.48936 77.4525C-1.15853 81.6805 -1.16386 88.9926 3.47785 93.2274L41.5926 128L3.47785 162.773C-1.16386 167.008 -1.15853 174.32 3.48936 178.548L17.5855 191.37C21.3853 194.827 27.1079 195.081 31.1992 191.976L75.149 158.614L176.049 250.667C177.645 252.264 179.519 253.467 181.534 254.252ZM192.039 69.8853L115.479 128L192.039 186.115V69.8853Z" fill="white"/>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#mask0)">
|
||||||
|
<path d="M246.94 27.6383L194.193 2.24138C188.088 -0.698302 180.791 0.541721 175.999 5.33332L3.32371 162.773C-1.32082 167.008 -1.31548 174.32 3.33523 178.548L17.4399 191.37C21.2421 194.827 26.9682 195.081 31.0619 191.976L239.003 34.2269C245.979 28.9347 255.999 33.9103 255.999 42.6667V42.0543C255.999 35.9078 252.478 30.3047 246.94 27.6383Z" fill="#0065A9"/>
|
||||||
|
<g filter="url(#filter0_d)">
|
||||||
|
<path d="M246.94 228.362L194.193 253.759C188.088 256.698 180.791 255.458 175.999 250.667L3.32371 93.2272C-1.32082 88.9925 -1.31548 81.6802 3.33523 77.4523L17.4399 64.6298C21.2421 61.1733 26.9682 60.9188 31.0619 64.0245L239.003 221.773C245.979 227.065 255.999 222.09 255.999 213.333V213.946C255.999 220.092 252.478 225.695 246.94 228.362Z" fill="#007ACC"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter1_d)">
|
||||||
|
<path d="M194.196 253.763C188.089 256.7 180.792 255.459 176 250.667C181.904 256.571 192 252.389 192 244.039V11.9606C192 3.61057 181.904 -0.571175 176 5.33321C180.792 0.541166 188.089 -0.700607 194.196 2.23648L246.934 27.5985C252.476 30.2635 256 35.8686 256 42.0178V213.983C256 220.132 252.476 225.737 246.934 228.402L194.196 253.763Z" fill="#1F9CF0"/>
|
||||||
|
</g>
|
||||||
|
<g style="mix-blend-mode:overlay" opacity="0.25">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M181.378 254.252C185.41 255.822 190.008 255.722 194.077 253.764L246.783 228.402C252.322 225.737 255.844 220.132 255.844 213.983V42.0179C255.844 35.8687 252.322 30.2636 246.784 27.5986L194.077 2.23665C188.737 -0.333299 182.486 0.296177 177.798 3.70401C177.129 4.19083 176.491 4.73437 175.892 5.33337L74.9927 97.386L31.0429 64.0245C26.9517 60.9189 21.229 61.1734 17.4292 64.6298L3.33311 77.4523C-1.31478 81.6803 -1.32011 88.9925 3.3216 93.2273L41.4364 128L3.3216 162.773C-1.32011 167.008 -1.31478 174.32 3.33311 178.548L17.4292 191.37C21.229 194.827 26.9517 195.081 31.0429 191.976L74.9927 158.614L175.892 250.667C177.488 252.264 179.363 253.467 181.378 254.252ZM191.883 69.8851L115.323 128L191.883 186.115V69.8851Z" fill="url(#paint0_linear)"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_d" x="-21.4896" y="40.5225" width="298.822" height="236.149" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||||
|
<feOffset/>
|
||||||
|
<feGaussianBlur stdDeviation="10.6667"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||||
|
<feBlend mode="overlay" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_d" x="154.667" y="-20.6735" width="122.667" height="297.347" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||||
|
<feOffset/>
|
||||||
|
<feGaussianBlur stdDeviation="10.6667"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||||
|
<feBlend mode="overlay" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<linearGradient id="paint0_linear" x1="127.844" y1="0.659988" x2="127.844" y2="255.34" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="white"/>
|
||||||
|
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.4 KiB |
BIN
public/themes/ayu.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/themes/dracula.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
public/themes/github-dark.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
public/themes/night-owl.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
public/themes/nord.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
255
styles/AboutPage.module.css
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
.container {
|
||||||
|
max-width: 900px;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 4rem 1.5rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 2.75rem;
|
||||||
|
font-weight: 800;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: var(--accent-color);
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tagline {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aboutContent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionTitle {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlightCard {
|
||||||
|
background: var(--background-secondary);
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5rem;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: var(--background-secondary);
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list li::before {
|
||||||
|
content: "▹";
|
||||||
|
color: var(--accent-color);
|
||||||
|
margin-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.techGrid {
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5rem;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.techItem {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
background: var(--background-secondary);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.techItem h3 {
|
||||||
|
margin: 0 0 0.25rem 0;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.techItem p {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caseStudy {
|
||||||
|
background: var(--background-secondary);
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.caseStudy div {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caseStudy span {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.credentials {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.75rem 1.25rem;
|
||||||
|
background: var(--background-secondary);
|
||||||
|
border-radius: 50px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.testimonial {
|
||||||
|
padding: 2rem;
|
||||||
|
background: var(--background-secondary);
|
||||||
|
border-left: 4px solid var(--accent-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial cite {
|
||||||
|
display: block;
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-style: normal;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ctaSection {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ctaButton {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
background: var(--accent-color);
|
||||||
|
color: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ctaButton:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.techIcon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badgeIcon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.container {
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 2.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlightCard {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.techItem {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width: 480px) {
|
||||||
|
.title {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
118
styles/ArticleCard.module.css
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: var(--article-bg);
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageWrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
object-fit: cover;
|
||||||
|
transition: transform 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container:hover .image {
|
||||||
|
transform: scale(1.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewsBadge {
|
||||||
|
position: absolute;
|
||||||
|
top: 12px;
|
||||||
|
right: 12px;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
color: white;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 1.5rem;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: var(--accent-color);
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
opacity: 0.85;
|
||||||
|
margin: 0;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats {
|
||||||
|
display: flex;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 500;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
color: var(--accent-color);
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.readMore {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--accent-color);
|
||||||
|
padding: 6px 12px;
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
border-radius: 20px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container:hover .readMore {
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
color: var(--article-bg);
|
||||||
|
}
|
||||||
65
styles/ArticlesPage.module.css
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
.layout {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageTitle {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent-color);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSubtitle {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
max-width: 600px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline {
|
||||||
|
cursor: pointer;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
120deg,
|
||||||
|
var(--accent-color) 100%,
|
||||||
|
var(--accent-color) 100%
|
||||||
|
);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 0.2em;
|
||||||
|
background-position: 0 88%;
|
||||||
|
transition: background-size 0.25s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline:hover {
|
||||||
|
background-size: 100% 88%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.container {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageTitle {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSubtitle {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
styles/Bottombar.module.css
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
.bottomBar {
|
||||||
|
background: var(--bottombar-bg);
|
||||||
|
height: 25px;
|
||||||
|
border-top: 1px solid var(--bottombar-border);
|
||||||
|
color: rgb(225, 228, 232);
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottomBar a {
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
display: flex;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
height: 24px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 0.2rem;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: 'Source Sans Pro', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section:hover {
|
||||||
|
background: var(--bottombar-hover-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.bottomBar {
|
||||||
|
font-size: 0.6rem;
|
||||||
|
}
|
||||||
|
.section {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
67
styles/ContactCode.module.css
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
.code {
|
||||||
|
counter-reset: line;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
background-color: var(--article-bg);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 4px;
|
||||||
|
background: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line::before {
|
||||||
|
content: counter(line);
|
||||||
|
counter-increment: line;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
margin-right: 1rem;
|
||||||
|
color: grey;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code a {
|
||||||
|
color: var(--accent-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.className {
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.code {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
padding: 1.25rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
padding-left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line::before {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
83
styles/ContactPage.module.css
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
.layout {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > * {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container h1 {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageTitle {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent-color);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
line-height: 1.2;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSubtitle {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
max-width: 600px;
|
||||||
|
line-height: 1.6;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1200px) {
|
||||||
|
.container {
|
||||||
|
display: block;
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div:first-child {
|
||||||
|
border-right: none;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.flex {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form input {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 1.5rem 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageTitle {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSubtitle {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
77
styles/Explorer.module.css
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
.explorer {
|
||||||
|
background: var(--explorer-bg);
|
||||||
|
width: 18vw;
|
||||||
|
color: rgb(225, 228, 232);
|
||||||
|
font-family: 'Source Sans Pro', sans-serif;
|
||||||
|
border-right: 1px solid var(--explorer-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
font-weight: 300;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.files {
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file {
|
||||||
|
padding: 0.2rem 1rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file p {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file:hover {
|
||||||
|
background: var(--explorer-hover-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chevron {
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 2000px) {
|
||||||
|
.explorer {
|
||||||
|
width: 10vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.explorer {
|
||||||
|
width: 20vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.explorer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
258
styles/GithubPage.module.css
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
.layout {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageHeading {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.githubPage {
|
||||||
|
width: 100%;
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageTitle {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent-color);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSubtitle {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
max-width: 600px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profileSection {
|
||||||
|
background: var(--article-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profileInfo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding: 0 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 3px solid var(--accent-color);
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userInfo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-color);
|
||||||
|
margin: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username::before {
|
||||||
|
content: '@';
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--accent-color);
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
bottom: -4px;
|
||||||
|
width: 40px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats {
|
||||||
|
display: flex;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statItem {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.statIcon {
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profileLink {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
width: fit-content;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 0.3rem 0.7rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profileLink:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 1.5rem 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionIcon {
|
||||||
|
color: var(--accent-color);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionTitle {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reposContainer {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contributions {
|
||||||
|
background: var(--article-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contributions article {
|
||||||
|
width: 100% !important;
|
||||||
|
min-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline {
|
||||||
|
cursor: pointer;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
120deg,
|
||||||
|
var(--accent-color) 100%,
|
||||||
|
var(--accent-color) 100%
|
||||||
|
);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 0.2em;
|
||||||
|
background-position: 0 88%;
|
||||||
|
transition: background-size 0.25s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline:hover {
|
||||||
|
background-size: 100% 88%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.profileInfo {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageTitle {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSubtitle {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userInfo {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reposContainer {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1200px) {
|
||||||
|
.contributions {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.avatar {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username::before {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionIcon {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
padding: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionTitle {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) and (max-width: 900px) {
|
||||||
|
.reposContainer {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
842
styles/HomePage.module.css
Normal file
@@ -0,0 +1,842 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;700&family=Inter:wght@400;500;600;700&display=swap');
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.2fr 1fr;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4rem;
|
||||||
|
padding: 2rem 4rem;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editorContent {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
position: relative;
|
||||||
|
padding: 1rem 0;
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function {
|
||||||
|
color: #dcdcaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heroLayout {
|
||||||
|
position: relative;
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeSection {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeContainer {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 600px;
|
||||||
|
height: 550px;
|
||||||
|
background: var(--main-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.25);
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid var(--explorer-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.editorContent {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lineNumbers {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 16px 0;
|
||||||
|
width: 50px;
|
||||||
|
background: var(--main-bg);
|
||||||
|
color: #636e83;
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
font-size: 13px;
|
||||||
|
user-select: none;
|
||||||
|
text-align: right;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lineNumber {
|
||||||
|
line-height: 1.5;
|
||||||
|
padding: 2px 10px 2px 0;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeLine {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeEditor {
|
||||||
|
flex: 1;
|
||||||
|
padding: 16px 20px 16px 0;
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--text-color);
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #444 var(--main-bg);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeEditor::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeEditor::-webkit-scrollbar-track {
|
||||||
|
background: var(--main-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeEditor::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #444;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeLine {
|
||||||
|
padding: 2px 0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlightedLine {
|
||||||
|
background: rgba(255, 255, 255, 0.04);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlightedLine::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 3px;
|
||||||
|
background: var(--accent-color);
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Syntax Highlighting */
|
||||||
|
.function {
|
||||||
|
color: #c586c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.variable {
|
||||||
|
color: #9cdcfe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.array-start,
|
||||||
|
.array-end {
|
||||||
|
color: #dcdcaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.array-item {
|
||||||
|
color: #ce9178;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nested-function {
|
||||||
|
color: #c586c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.return {
|
||||||
|
color: #dcdcaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-call {
|
||||||
|
color: #4ec9b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close,
|
||||||
|
.close-function {
|
||||||
|
color: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
.return-object {
|
||||||
|
color: #9cdcfe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object-method {
|
||||||
|
color: #dcdcaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment {
|
||||||
|
color: #6a9955;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blank {
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlayGlow {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle at 50% 50%,
|
||||||
|
rgba(var(--accent-color-rgb), 0.03) 0%,
|
||||||
|
rgba(0, 0, 0, 0) 70%
|
||||||
|
);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Information Section */
|
||||||
|
.infoSection {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
padding: 3rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.developerName {
|
||||||
|
font-size: 4rem;
|
||||||
|
font-weight: 800;
|
||||||
|
margin: 0;
|
||||||
|
color: var(--text-color);
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accentText {
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.developerRole {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
margin-top: -0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
max-width: 35rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skillTags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skillTag {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 5px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
border: 1px solid;
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skillTag:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionLinks {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1.25rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primaryLink,
|
||||||
|
.secondaryLink,
|
||||||
|
.githubLink {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primaryLink {
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
color: white;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 1rem;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
isolation: isolate;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primaryLink::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: linear-gradient(
|
||||||
|
45deg,
|
||||||
|
transparent,
|
||||||
|
rgba(255, 255, 255, 0.2),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
transform: translateX(-100%);
|
||||||
|
transition: transform 0.5s ease;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primaryLink:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 8px 20px rgba(var(--accent-color-rgb), 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.primaryLink:hover::before {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decorative Elements */
|
||||||
|
.decorElements {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeFlare {
|
||||||
|
position: absolute;
|
||||||
|
top: -150px;
|
||||||
|
right: 10%;
|
||||||
|
width: 500px;
|
||||||
|
height: 500px;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle at center,
|
||||||
|
rgba(var(--accent-color-rgb), 0.08) 0%,
|
||||||
|
rgba(var(--accent-color-rgb), 0.02) 30%,
|
||||||
|
transparent 70%
|
||||||
|
);
|
||||||
|
filter: blur(40px);
|
||||||
|
opacity: 0.8;
|
||||||
|
z-index: -1;
|
||||||
|
animation: pulse 8s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gridLines {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
rgba(255, 255, 255, 0.02) 1px,
|
||||||
|
transparent 1px
|
||||||
|
),
|
||||||
|
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
|
||||||
|
background-size: 30px 30px;
|
||||||
|
z-index: -2;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeBlock1,
|
||||||
|
.codeBlock2,
|
||||||
|
.codeBlock3,
|
||||||
|
.codeBlock4 {
|
||||||
|
position: absolute;
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
color: rgba(var(--accent-color-rgb), 0.08);
|
||||||
|
font-size: 180px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
user-select: none;
|
||||||
|
filter: blur(2px);
|
||||||
|
animation: float 20s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeBlock1 {
|
||||||
|
top: 10%;
|
||||||
|
left: 0;
|
||||||
|
opacity: 0.15;
|
||||||
|
transform: rotate(-10deg);
|
||||||
|
animation-delay: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeBlock2 {
|
||||||
|
bottom: 10%;
|
||||||
|
right: 15%;
|
||||||
|
opacity: 0.1;
|
||||||
|
transform: rotate(10deg);
|
||||||
|
animation-delay: -7s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeBlock3 {
|
||||||
|
top: 30%;
|
||||||
|
right: 5%;
|
||||||
|
opacity: 0.05;
|
||||||
|
font-size: 150px;
|
||||||
|
animation-delay: -3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeBlock4 {
|
||||||
|
bottom: 10%;
|
||||||
|
left: 20%;
|
||||||
|
opacity: 0.08;
|
||||||
|
font-size: 160px;
|
||||||
|
animation-delay: -10s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orb1,
|
||||||
|
.orb2,
|
||||||
|
.orb3 {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
filter: blur(30px);
|
||||||
|
opacity: 0.2;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orb1 {
|
||||||
|
width: 300px;
|
||||||
|
height: 300px;
|
||||||
|
background: linear-gradient(135deg, var(--accent-color), transparent);
|
||||||
|
top: 20%;
|
||||||
|
left: 10%;
|
||||||
|
animation: orbFloat 15s infinite alternate ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orb2 {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
background: linear-gradient(45deg, rgba(97, 218, 251, 0.5), transparent);
|
||||||
|
bottom: 10%;
|
||||||
|
right: 5%;
|
||||||
|
animation: orbFloat 20s infinite alternate-reverse ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orb3 {
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle at center,
|
||||||
|
rgba(174, 129, 255, 0.6),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
top: 70%;
|
||||||
|
left: 30%;
|
||||||
|
animation: orbFloat 12s infinite alternate ease-in-out;
|
||||||
|
animation-delay: -5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeSymbol1,
|
||||||
|
.codeSymbol2,
|
||||||
|
.codeSymbol3 {
|
||||||
|
position: absolute;
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
color: rgba(255, 255, 255, 0.08);
|
||||||
|
font-size: 120px;
|
||||||
|
font-weight: 700;
|
||||||
|
filter: blur(1px);
|
||||||
|
user-select: none;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeSymbol1 {
|
||||||
|
top: 55%;
|
||||||
|
right: 8%;
|
||||||
|
opacity: 0.12;
|
||||||
|
transform: rotate(10deg);
|
||||||
|
animation: floatSlow 25s infinite alternate ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeSymbol2 {
|
||||||
|
bottom: 25%;
|
||||||
|
left: 7%;
|
||||||
|
opacity: 0.09;
|
||||||
|
transform: rotate(-5deg);
|
||||||
|
animation: floatSlow 22s infinite alternate-reverse ease-in-out;
|
||||||
|
animation-delay: -8s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeSymbol3 {
|
||||||
|
top: 15%;
|
||||||
|
left: 45%;
|
||||||
|
opacity: 0.07;
|
||||||
|
transform: rotate(5deg);
|
||||||
|
animation: floatSlow 18s infinite alternate ease-in-out;
|
||||||
|
animation-delay: -12s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dotPattern {
|
||||||
|
position: absolute;
|
||||||
|
top: 10%;
|
||||||
|
right: 30%;
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
background-image: radial-gradient(
|
||||||
|
circle,
|
||||||
|
rgba(255, 255, 255, 0.1) 1px,
|
||||||
|
transparent 1px
|
||||||
|
);
|
||||||
|
background-size: 15px 15px;
|
||||||
|
border-radius: 50%;
|
||||||
|
opacity: 0.3;
|
||||||
|
transform: rotate(-10deg);
|
||||||
|
animation: rotate 35s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 0.8;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.6;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes float {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translateY(0) rotate(0deg);
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
transform: translateY(-20px) rotate(2deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(0) rotate(0deg);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
transform: translateY(20px) rotate(-2deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes orbFloat {
|
||||||
|
0% {
|
||||||
|
transform: translate(0, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(20px, 20px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes floatSlow {
|
||||||
|
0% {
|
||||||
|
transform: translate(0, 0) rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(15px, 15px) rotate(5deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotate {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slidingGlow {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Styles */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.container {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 3rem;
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeSection {
|
||||||
|
justify-self: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeContainer {
|
||||||
|
height: 450px;
|
||||||
|
max-width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoSection {
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionLinks {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.container {
|
||||||
|
padding: 1.5rem;
|
||||||
|
gap: 2rem;
|
||||||
|
min-height: auto;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeContainer {
|
||||||
|
height: 380px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editorContent {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeLine {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.developerName {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.developerRole {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeBlock1,
|
||||||
|
.codeBlock2,
|
||||||
|
.codeBlock3,
|
||||||
|
.codeBlock4 {
|
||||||
|
opacity: 0.05;
|
||||||
|
font-size: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeSymbol1,
|
||||||
|
.codeSymbol2,
|
||||||
|
.codeSymbol3 {
|
||||||
|
font-size: 80px;
|
||||||
|
opacity: 0.05;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orb1,
|
||||||
|
.orb2,
|
||||||
|
.orb3 {
|
||||||
|
opacity: 0.1;
|
||||||
|
width: 70%;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dotPattern {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoSection {
|
||||||
|
text-align: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.container {
|
||||||
|
padding: 2rem 0;
|
||||||
|
gap: 1.5rem;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
justify-content: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the background gradient from heroLayout */
|
||||||
|
.heroLayout::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle at 30% 70%,
|
||||||
|
rgba(var(--accent-color-rgb), 0.06) 0%,
|
||||||
|
transparent 65%
|
||||||
|
);
|
||||||
|
z-index: -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.decorElements::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
rgba(255, 255, 255, 0.03) 1px,
|
||||||
|
transparent 1px
|
||||||
|
),
|
||||||
|
linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
|
||||||
|
background-size: 20px 20px;
|
||||||
|
opacity: 0.3;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileAccent {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 180px;
|
||||||
|
height: 180px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: conic-gradient(
|
||||||
|
from 0deg,
|
||||||
|
transparent,
|
||||||
|
rgba(var(--accent-color-rgb), 0.1),
|
||||||
|
rgba(var(--accent-color-rgb), 0.2),
|
||||||
|
rgba(var(--accent-color-rgb), 0.1),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
top: 15%;
|
||||||
|
right: 15%;
|
||||||
|
filter: blur(30px);
|
||||||
|
opacity: 0.7;
|
||||||
|
animation: rotateMobileAccent 15s linear infinite;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileAccent::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
top: 80%;
|
||||||
|
left: -150px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle at center,
|
||||||
|
rgba(120, 200, 255, 0.2),
|
||||||
|
transparent 70%
|
||||||
|
);
|
||||||
|
filter: blur(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeSection {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoSection {
|
||||||
|
text-align: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
max-width: 90%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoSection::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.developerName {
|
||||||
|
font-size: 2.8rem;
|
||||||
|
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.4);
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accentText {
|
||||||
|
text-shadow: 0 0 15px rgba(var(--accent-color-rgb), 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.developerRole {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
position: relative;
|
||||||
|
padding-bottom: 1.2rem;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||||
|
max-width: 320px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primaryLink {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 240px;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 20px rgba(var(--accent-color-rgb), 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.primaryLink:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 8px 20px rgba(var(--accent-color-rgb), 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide decorative elements on mobile */
|
||||||
|
.codeBlock1,
|
||||||
|
.codeBlock2,
|
||||||
|
.codeBlock3,
|
||||||
|
.codeBlock4,
|
||||||
|
.codeSymbol1,
|
||||||
|
.codeSymbol2,
|
||||||
|
.codeSymbol3,
|
||||||
|
.dotPattern,
|
||||||
|
.orb1,
|
||||||
|
.orb2,
|
||||||
|
.orb3 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotateMobileAccent {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileAccent {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
45
styles/Layout.module.css
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600&display=swap');
|
||||||
|
|
||||||
|
.main {
|
||||||
|
display: flex;
|
||||||
|
background: var(--main-bg);
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 2rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
flex: 1;
|
||||||
|
height: 85vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
overflow-x: hidden;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
scrollbar-width: 10px;
|
||||||
|
scrollbar-color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content::-webkit-scrollbar {
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content::-webkit-scrollbar-track {
|
||||||
|
background: var(--scrollbar-track-bg);
|
||||||
|
border-left: 1px solid #1e1f29;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--scrollbar-thumb-bg);
|
||||||
|
border-left: 1px solid #1e1f29;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.content {
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
184
styles/ProjectCard.module.css
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
.card {
|
||||||
|
background: var(--article-bg);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-radius: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
height: 250px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
z-index: 0;
|
||||||
|
opacity: 0.15;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover .background {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 1.75rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: calc(100% - 60px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logoWrapper {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid var(--accent-color);
|
||||||
|
color: var(--accent-color);
|
||||||
|
padding: 0.5rem 0.9rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link:hover {
|
||||||
|
background: var(--accent-color);
|
||||||
|
color: var(--bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin: 0.5rem 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags span {
|
||||||
|
margin: 0.5rem 0.5rem 0 0;
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline {
|
||||||
|
padding: 0.2rem 0;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
letter-spacing: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
120deg,
|
||||||
|
var(--accent-color) 100%,
|
||||||
|
var(--accent-color) 100%
|
||||||
|
);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 0.2em;
|
||||||
|
background-position: 0 88%;
|
||||||
|
transition: background-size 0.25s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline:hover {
|
||||||
|
background-size: 100% 88%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.75rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0 1.75rem 1.25rem;
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Badge styling */
|
||||||
|
.date, .status, .skills {
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
padding: 0.3rem 0.75rem;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status[data-status="active"] {
|
||||||
|
background: rgba(40, 167, 69, 0.15);
|
||||||
|
color: #28a745;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status[data-status="pending"] {
|
||||||
|
background: rgba(255, 193, 7, 0.15);
|
||||||
|
color: #ffc107;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status[data-status="archived"] {
|
||||||
|
background: rgba(108, 117, 125, 0.15);
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
margin-left: auto;
|
||||||
|
padding: 0.3rem 0.7rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
}
|
||||||
47
styles/ProjectsPage.module.css
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
.layout {
|
||||||
|
max-width: 1200px;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin: 2rem 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageTitle {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent-color);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSubtitle {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
max-width: 600px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.container {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageTitle {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSubtitle {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
133
styles/RepoCard.module.css
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
.card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
background: var(--article-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1.25rem;
|
||||||
|
height: 100%;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardHeader {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
row-gap: 0.75rem;
|
||||||
|
column-gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.3rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.05);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.languageIcon {
|
||||||
|
color: var(--accent-color);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card p {
|
||||||
|
margin: 0.75rem 0;
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 0.92rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: var(--accent-color);
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: -3px;
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: auto;
|
||||||
|
padding-top: 1rem;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats > div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats > div:first-child {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats > div:first-child > div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats > div:nth-child(2) {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats > div:nth-child(2) a {
|
||||||
|
opacity: 0.7;
|
||||||
|
transition: opacity 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats > div:nth-child(2) a:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
color: var(--accent-color);
|
||||||
|
margin-right: 0.3rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 400px) {
|
||||||
|
.card {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats > div:first-child {
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats > div:nth-child(2) {
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
styles/SettingsPage.module.css
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
.layout {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.container {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||||
|
gap: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 480px) {
|
||||||
|
.container {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settingsContainer {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
styles/Sidebar.module.css
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
.sidebar {
|
||||||
|
background: var(--sidebar-bg);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 4.5vw;
|
||||||
|
min-width: 40px;
|
||||||
|
height: calc(100vh - 30px - 25px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconContainer {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconContainer:hover {
|
||||||
|
background: var(--sidebar-hover-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
border-left: 2px solid var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
height: 48px;
|
||||||
|
width: 48px;
|
||||||
|
padding: 0.65rem 0;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 2000px) {
|
||||||
|
.sidebar {
|
||||||
|
width: 2.5vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1100px) {
|
||||||
|
.sidebar {
|
||||||
|
width: 6vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.sidebar {
|
||||||
|
width: 8vw;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
height: 48px;
|
||||||
|
width: 48px;
|
||||||
|
padding: 0.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.sidebar {
|
||||||
|
width: 10vw;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
padding: 0.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
styles/Tab.module.css
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.tab {
|
||||||
|
padding: 0.5rem 1.25rem;
|
||||||
|
background: var(--tab-bg);
|
||||||
|
color: #ececec;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid var(--tab-border);
|
||||||
|
font-family: 'Source Sans Pro', sans-serif;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab p {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
border-top: 1px solid var(--accent-color);
|
||||||
|
background: var(--tab-active-bg);
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
18
styles/Tabsbar.module.css
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.tabs {
|
||||||
|
display: flex;
|
||||||
|
/* flex-wrap: wrap; */
|
||||||
|
background: var(--tabs-bg);
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.tabs {
|
||||||
|
width: 78vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.tabs {
|
||||||
|
width: 89.5vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
74
styles/ThemeInfo.module.css
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
text-align: center;
|
||||||
|
padding: 2rem;
|
||||||
|
background-color: var(--explorer-bg);
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageWrapper {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.25rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.themeImage {
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info h3 {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
margin: 0 0 0.15rem 0;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info h5 {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
margin: 0 0 0.75rem 0;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info button {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
border: none;
|
||||||
|
background: var(--button-bg);
|
||||||
|
color: var(--button-text);
|
||||||
|
padding: 0.35rem 0.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 2px;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info button:focus {
|
||||||
|
outline: 1px solid var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.container {
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info h3 {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
66
styles/Titlebar.module.css
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
.titlebar {
|
||||||
|
background: var(--titlebar-bg);
|
||||||
|
height: 30px;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #fff;
|
||||||
|
font-family: 'Source Sans Pro', sans-serif;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
border-bottom: 1px solid #191d20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items > * {
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowButtons {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowButtons * {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
height: 13px;
|
||||||
|
width: 13px;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.minimize {
|
||||||
|
background: #f1fa8c;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maximize {
|
||||||
|
background: #50fa7b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
background: #ff5555;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.items p {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
flex: 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
styles/globals.css
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400&display=swap');
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
#__next {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
155
styles/themes.css
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
/* GitHub Dark */
|
||||||
|
:root {
|
||||||
|
--main-bg: #24292e;
|
||||||
|
--bg-text: rgba(56, 58, 61, 0.35);
|
||||||
|
--text-color: #efefef;
|
||||||
|
--accent-color: #f9826c;
|
||||||
|
--titlebar-bg: #1f2428;
|
||||||
|
--sidebar-bg: #24292e;
|
||||||
|
--sidebar-hover-bg: #1f2428;
|
||||||
|
--explorer-bg: #1f2428;
|
||||||
|
--explorer-hover-bg: #24292e;
|
||||||
|
--explorer-border: #161a1d;
|
||||||
|
--tabs-bg: #1f2428;
|
||||||
|
--tab-bg: #1f2428;
|
||||||
|
--tab-active-bg: #24292e;
|
||||||
|
--tab-border: #24292e;
|
||||||
|
--bottombar-bg: #24292e;
|
||||||
|
--bottombar-border: #1b1f23;
|
||||||
|
--button-bg: #176f2c;
|
||||||
|
--button-text: #dcffe4;
|
||||||
|
--bottombar-hover-bg: #4f4f52;
|
||||||
|
--scrollbar-track-bg: #24292e;
|
||||||
|
--scrollbar-thumb-bg: #333536;
|
||||||
|
--article-bg: #1f2428;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dracula */
|
||||||
|
[data-theme='dracula'] {
|
||||||
|
--main-bg: #282a36;
|
||||||
|
--bg-text: #313340;
|
||||||
|
--text-color: #efefef;
|
||||||
|
--accent-color: #bd93f9;
|
||||||
|
--titlebar-bg: #1e1f29;
|
||||||
|
--sidebar-bg: #343746;
|
||||||
|
--sidebar-hover-bg: #3c3d51;
|
||||||
|
--explorer-bg: #21222c;
|
||||||
|
--explorer-hover-bg: #313241;
|
||||||
|
--explorer-border: #161a1d;
|
||||||
|
--tabs-bg: #191a21;
|
||||||
|
--tab-bg: #21222c;
|
||||||
|
--tab-active-bg: #282a36;
|
||||||
|
--tab-border: #191a21;
|
||||||
|
--bottombar-bg: #191a21;
|
||||||
|
--bottombar-border: #191a21;
|
||||||
|
--button-bg: #44475a;
|
||||||
|
--button-text: #f8f8f2;
|
||||||
|
--bottombar-hover-bg: #4f4f52;
|
||||||
|
--scrollbar-track-bg: #282a36;
|
||||||
|
--scrollbar-thumb-bg: #454647;
|
||||||
|
--article-bg: #21222c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ayu Dark */
|
||||||
|
[data-theme='ayu-dark'] {
|
||||||
|
--main-bg: #0a0e14;
|
||||||
|
--bg-text: #101620;
|
||||||
|
--text-color: #efefef;
|
||||||
|
--accent-color: #e6b450;
|
||||||
|
--titlebar-bg: #1f2428;
|
||||||
|
--sidebar-bg: #0a0e14;
|
||||||
|
--sidebar-hover-bg: #00010a;
|
||||||
|
--explorer-bg: #0a0e14;
|
||||||
|
--explorer-hover-bg: #00010a;
|
||||||
|
--explorer-border: transparent;
|
||||||
|
--tabs-bg: #0a0e14;
|
||||||
|
--tab-bg: #0a0e14;
|
||||||
|
--tab-active-bg: #0a0e14;
|
||||||
|
--tab-border: transparent;
|
||||||
|
--bottombar-bg: #0a0e14;
|
||||||
|
--bottombar-border: transparent;
|
||||||
|
--button-bg: #e6b450;
|
||||||
|
--button-text: #0a0e14;
|
||||||
|
--bottombar-hover-bg: #4f4f52;
|
||||||
|
--scrollbar-track-bg: #0a0e14;
|
||||||
|
--scrollbar-thumb-bg: #454647;
|
||||||
|
--article-bg: #10121a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ayu Mirage */
|
||||||
|
[data-theme='ayu-mirage'] {
|
||||||
|
--main-bg: #1f2430;
|
||||||
|
--bg-text: #21242b;
|
||||||
|
--text-color: #efefef;
|
||||||
|
--accent-color: #e6b450;
|
||||||
|
--titlebar-bg: #1f2428;
|
||||||
|
--sidebar-bg: #1f2430;
|
||||||
|
--sidebar-hover-bg: #191e2a;
|
||||||
|
--explorer-bg: #1f2430;
|
||||||
|
--explorer-hover-bg: #191e2a;
|
||||||
|
--explorer-border: transparent;
|
||||||
|
--tabs-bg: #1f2430;
|
||||||
|
--tab-bg: #1f2430;
|
||||||
|
--tab-active-bg: #1f2430;
|
||||||
|
--tab-border: transparent;
|
||||||
|
--bottombar-bg: #1f2430;
|
||||||
|
--bottombar-border: transparent;
|
||||||
|
--button-bg: #e6b450;
|
||||||
|
--button-text: #1f2430;
|
||||||
|
--bottombar-hover-bg: #4f4f52;
|
||||||
|
--scrollbar-track-bg: #1f2430;
|
||||||
|
--scrollbar-thumb-bg: #454647;
|
||||||
|
--article-bg: #252e3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nord */
|
||||||
|
[data-theme='nord'] {
|
||||||
|
--main-bg: #2e3440;
|
||||||
|
--bg-text: #3b414d;
|
||||||
|
--text-color: #efefef;
|
||||||
|
--accent-color: #88c0d0;
|
||||||
|
--titlebar-bg: #1f2428;
|
||||||
|
--sidebar-bg: #2e3440;
|
||||||
|
--sidebar-hover-bg: #434c5e;
|
||||||
|
--explorer-bg: #2e3440;
|
||||||
|
--explorer-hover-bg: #434c5e;
|
||||||
|
--explorer-border: rgba(136, 192, 208, 0.2);
|
||||||
|
--tabs-bg: #2e3440;
|
||||||
|
--tab-bg: #2e3440;
|
||||||
|
--tab-active-bg: #3b4252;
|
||||||
|
--tab-border: transparent;
|
||||||
|
--bottombar-bg: #3b4252;
|
||||||
|
--bottombar-border: transparent;
|
||||||
|
--button-bg: #434c5e;
|
||||||
|
--button-text: #d8dee9;
|
||||||
|
--bottombar-hover-bg: #4f4f52;
|
||||||
|
--scrollbar-track-bg: #2e3440;
|
||||||
|
--scrollbar-thumb-bg: #454647;
|
||||||
|
--article-bg: #363f50;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Night Owl */
|
||||||
|
[data-theme='night-owl'] {
|
||||||
|
--main-bg: #011627;
|
||||||
|
--bg-text: #031d33;
|
||||||
|
--text-color: #89a4bb;
|
||||||
|
--accent-color: rgb(95, 126, 151);
|
||||||
|
--titlebar-bg: #011627;
|
||||||
|
--sidebar-bg: #011627;
|
||||||
|
--sidebar-hover-bg: #0e293f;
|
||||||
|
--explorer-bg: #011627;
|
||||||
|
--explorer-hover-bg: #0e293f;
|
||||||
|
--explorer-border: transparent;
|
||||||
|
--tabs-bg: #011627;
|
||||||
|
--tab-bg: #01111d;
|
||||||
|
--tab-active-bg: #0b2942;
|
||||||
|
--tab-border: rgb(39, 43, 59);
|
||||||
|
--bottombar-bg: #011627;
|
||||||
|
--bottombar-border: #262a39;
|
||||||
|
--button-bg: rgb(95, 126, 151);
|
||||||
|
--button-text: #fff;
|
||||||
|
--bottombar-hover-bg: #1b222f;
|
||||||
|
--scrollbar-track-bg: #011627;
|
||||||
|
--scrollbar-thumb-bg: #043254;
|
||||||
|
--article-bg: #031d33;
|
||||||
|
}
|
||||||
44
tsconfig.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2017",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"typeRoots": [
|
||||||
|
"./types",
|
||||||
|
"./node_modules/@types"
|
||||||
|
],
|
||||||
|
"allowJs": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
41
types/index.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
export interface Article {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
cover_image: string;
|
||||||
|
url: string;
|
||||||
|
page_views_count: number;
|
||||||
|
public_reactions_count: number;
|
||||||
|
comments_count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Project {
|
||||||
|
date: String;
|
||||||
|
status: String;
|
||||||
|
skills: String;
|
||||||
|
type: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
logo: string;
|
||||||
|
link: string;
|
||||||
|
slug: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Repo {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
language: string;
|
||||||
|
watchers: number;
|
||||||
|
forks: number;
|
||||||
|
stargazers_count: number;
|
||||||
|
html_url: string;
|
||||||
|
homepage: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface User {
|
||||||
|
login: string;
|
||||||
|
avatar_url: string;
|
||||||
|
public_repos: number;
|
||||||
|
followers: number;
|
||||||
|
}
|
||||||