├── .nvmrc
├── .DS_Store
├── public
├── favicon.ico
├── favicon.png
├── Screenshot.png
├── fonts
│ ├── .DS_Store
│ ├── Roboto-Regular.ttf
│ ├── Inconsolata-Black.ttf
│ └── Inconsolata-Bold.ttf
├── images
│ ├── .DS_Store
│ └── x-icon.svg
├── zemerik_profile.png
├── profile_directory.png
├── screenshot_laptop.png
├── screenshot_phone.png
├── robots.txt
└── prism-dracula.css
├── .astro
├── settings.json
└── types.d.ts
├── src
├── env.d.ts
├── utils
│ ├── days.js
│ ├── years.js
│ ├── months.js
│ ├── colors.js
│ ├── format-number.js
│ ├── format-slug.js
│ ├── is-new-content.js
│ ├── create-excerpt.js
│ ├── format-date.js
│ ├── all-collections.js
│ └── create-tags-collection.js
├── pages
│ ├── api
│ │ ├── happy-by-city.ts
│ │ ├── reactions-by-slug.ts
│ │ ├── add-reaction.ts
│ │ └── page-view.ts
│ ├── tags.astro
│ ├── profiles.astro
│ ├── index.astro
│ ├── tags
│ │ ├── [...tag].astro
│ │ └── [tag]
│ │ │ └── og.png.ts
│ ├── posts
│ │ └── [...slug].astro
│ └── dashboard.astro
├── components
│ ├── aside.astro
│ ├── video-player.astro
│ ├── powered-by-mdx.astro
│ ├── astro-image.astro
│ ├── cta-internal.astro
│ ├── cta-external.astro
│ ├── code-sandbox.astro
│ ├── new-label.tsx
│ ├── list-top-ten-cities.astro
│ ├── table-of-contents.astro
│ ├── list-popular.astro
│ ├── list-top-referrers.astro
│ ├── tags-list.astro
│ ├── search-trigger.tsx
│ ├── stackblitz-embed.tsx
│ ├── featured-image-card.astro
│ ├── search-input.tsx
│ ├── nav-link.tsx
│ ├── loading.tsx
│ ├── click-to-copy-email.jsx
│ ├── audio-feed-embed.astro
│ ├── search-tags.tsx
│ ├── line-chart-visits.astro
│ ├── donut-chart-tags.astro
│ ├── profile-card.astro
│ ├── collections-list.astro
│ ├── happy-all-cities.tsx
│ ├── search-modal.tsx
│ ├── line-chart-years.astro
│ └── bar-chart-days.astro
├── content
│ ├── profiles
│ │ ├── harrysingh100.mdx
│ │ ├── axorax.mdx
│ │ ├── calllme-shadow.mdx
│ │ ├── sankitdev.mdx
│ │ ├── parthivkapoor0101.mdx
│ │ ├── Developer-Utkarsh.mdx
│ │ ├── rohitshah09.mdx
│ │ └── zemerik.mdx
│ └── config.js
├── services
│ └── resize-image.ts
└── layouts
│ ├── nav-links.ts
│ ├── main.astro
│ └── layout.tsx
├── SECURITY.md
├── tsconfig.json
├── .github
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ ├── style.yml
│ ├── documentation.yml
│ └── bug.yml
├── pull_request_template.md
└── workflows
│ └── greetings.yml
├── LICENCE
├── package.json
├── astro.config.mjs
├── .gitignore
├── CONTRIBUTING.md
├── README.md
├── CODE_OF_CONDUCT.md
└── tailwind.config.cjs
/.nvmrc:
--------------------------------------------------------------------------------
1 | v18.14.1
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/.DS_Store
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/favicon.png
--------------------------------------------------------------------------------
/.astro/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "_variables": {
3 | "lastUpdateCheck": 1726855220054
4 | }
5 | }
--------------------------------------------------------------------------------
/public/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/Screenshot.png
--------------------------------------------------------------------------------
/public/fonts/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/fonts/.DS_Store
--------------------------------------------------------------------------------
/public/images/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/images/.DS_Store
--------------------------------------------------------------------------------
/src/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
--------------------------------------------------------------------------------
/public/zemerik_profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/zemerik_profile.png
--------------------------------------------------------------------------------
/public/profile_directory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/profile_directory.png
--------------------------------------------------------------------------------
/public/screenshot_laptop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/screenshot_laptop.png
--------------------------------------------------------------------------------
/public/screenshot_phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/screenshot_phone.png
--------------------------------------------------------------------------------
/public/fonts/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/fonts/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/src/utils/days.js:
--------------------------------------------------------------------------------
1 | const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
2 |
3 | export default days;
4 |
--------------------------------------------------------------------------------
/src/utils/years.js:
--------------------------------------------------------------------------------
1 | const years = ['2019', '2020', '2021', '2022', '2023', '2024'];
2 |
3 | export default years;
4 |
--------------------------------------------------------------------------------
/public/fonts/Inconsolata-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/fonts/Inconsolata-Black.ttf
--------------------------------------------------------------------------------
/public/fonts/Inconsolata-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zemerik/ZemProfiles/HEAD/public/fonts/Inconsolata-Bold.ttf
--------------------------------------------------------------------------------
/src/pages/api/happy-by-city.ts:
--------------------------------------------------------------------------------
1 | import type { APIRoute } from 'astro';
2 |
3 | export const config = {
4 | runtime: 'edge',
5 | };
6 |
--------------------------------------------------------------------------------
/src/pages/api/reactions-by-slug.ts:
--------------------------------------------------------------------------------
1 | import type { APIRoute } from 'astro';
2 |
3 | export const config = {
4 | runtime: 'edge',
5 | };
6 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /ghosts/
3 | Allow: /ghosts$
4 | Allow: /
5 |
6 | Sitemap: https://zemprofiles.vercel.app/sitemap-index.xml
--------------------------------------------------------------------------------
/src/utils/months.js:
--------------------------------------------------------------------------------
1 | const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
2 |
3 | export default months;
4 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Reporting a Vulnerability
4 |
5 | > To Report a Vulnerability, kindly email at [zemerikY@gmail.com](mailto:zemeriky@gmail.com)
6 |
--------------------------------------------------------------------------------
/src/utils/colors.js:
--------------------------------------------------------------------------------
1 | const colors = ['teal', 'mauve', 'salmon', 'yellow', 'lime', 'blood', 'electric', 'pink', 'starfleet', 'fuchsia'];
2 |
3 | export default colors;
4 |
--------------------------------------------------------------------------------
/src/utils/format-number.js:
--------------------------------------------------------------------------------
1 | export const formatNumber = (number) => {
2 | const formatter = new Intl.NumberFormat();
3 |
4 | return formatter.format(number);
5 | };
6 |
--------------------------------------------------------------------------------
/src/pages/api/add-reaction.ts:
--------------------------------------------------------------------------------
1 | import type { APIRoute } from 'astro';
2 | import { geolocation } from '@vercel/edge';
3 |
4 | export const config = {
5 | runtime: 'edge',
6 | };
7 |
--------------------------------------------------------------------------------
/src/pages/api/page-view.ts:
--------------------------------------------------------------------------------
1 | import type { APIRoute } from 'astro';
2 | import { geolocation } from '@vercel/edge';
3 |
4 | export const config = {
5 | runtime: 'edge',
6 | };
7 |
--------------------------------------------------------------------------------
/src/components/aside.astro:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/utils/format-slug.js:
--------------------------------------------------------------------------------
1 | import slugify from 'slugify';
2 |
3 | export const formatSlug = (string) => {
4 | return slugify(string.replace(/\./g, '-'), {
5 | lower: true,
6 | strict: true,
7 | });
8 | };
9 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "astro/tsconfigs/base",
3 | "compilerOptions": {
4 | "checkJs": false,
5 | "allowJs": true,
6 | "jsx": "react-jsx",
7 | "jsxImportSource": "@builder.io/qwik"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/content/profiles/harrysingh100.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | base: posts
3 | title: Harry Singh
4 | tags: [Python, Javascript, HTML]
5 | date: 2024-05-09
6 | author: Harry Singh
7 | featuredImage: https://avatars.githubusercontent.com/u/167010005?v=4
8 | ---
9 |
10 | I HACK
--------------------------------------------------------------------------------
/src/components/video-player.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { src } = Astro.props;
3 | ---
4 |
5 |
6 |
7 | This browser does not display the video tag.
8 |
9 |
--------------------------------------------------------------------------------
/src/content/profiles/axorax.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | base: posts
3 | title: Axorax
4 | tags: [Javascript, Python, HTML, CSS, Typescript, Lua]
5 | date: 2024-08-18
6 | author: Axorax
7 | featuredImage: https://avatars.githubusercontent.com/u/78349410?v=4
8 | ---
9 |
10 | I like to do stuff... 😗
--------------------------------------------------------------------------------
/public/images/x-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/services/resize-image.ts:
--------------------------------------------------------------------------------
1 | // https://cloudinary.com/documentation/image_transformations
2 | // https://cloudinary.com/documentation/media_optimization
3 | export const resizeImage = (url, width, height): string => {
4 | const string = url.split(/upload(?=.)/);
5 | const newUrl = `${string[0]}upload/h_${height},w_${width}/q_100/f_auto${string[1]}`;
6 | return newUrl;
7 | };
8 |
--------------------------------------------------------------------------------
/src/utils/is-new-content.js:
--------------------------------------------------------------------------------
1 | const isNewContent = (inputDate) => {
2 | const currentDate = new Date();
3 | const inputDateObj = new Date(inputDate);
4 |
5 | const timeDifference = currentDate - inputDateObj;
6 |
7 | const daysDifference = timeDifference / (1000 * 60 * 60 * 24);
8 |
9 | return daysDifference < 30;
10 | };
11 |
12 | export default isNewContent;
13 |
--------------------------------------------------------------------------------
/src/content/profiles/calllme-shadow.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | base: posts
3 | title: Shadow
4 | tags: [Python, Javascript, Html, Css, GFX Designer]
5 | date: 2024-05-08
6 | author: Shadow
7 | featuredImage: https://avatars.githubusercontent.com/u/166983377?v=4
8 | ---
9 |
10 | Hey, it is Shadow I'm a GFX Designer and a Python & JavaScript Developer. I like to Watch Anime and Do some GFX Projects for free
--------------------------------------------------------------------------------
/src/components/powered-by-mdx.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { period, className } = Astro.props;
3 | ---
4 |
5 |
6 | {period ?
{`Totals from last ${period} Days`} : null}
7 |
Powered by{' '}
8 |
MDX
9 |
10 |
--------------------------------------------------------------------------------
/src/components/astro-image.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import { Image } from 'astro:assets';
3 | import { resizeImage } from '../services/resize-image';
4 |
5 | const { width, height, alt, url, className = 'w-full' } = Astro.props;
6 | ---
7 |
8 |
15 |
--------------------------------------------------------------------------------
/src/content/profiles/sankitdev.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | base: posts
3 | title: Ankit Singh
4 | tags: [JavaScript, TypeScript, React, Node, Next Js]
5 | date: 2024-09-20
6 | author: sankitdev
7 | featuredImage: https://avatars.githubusercontent.com/u/56855070?v=4
8 | ---
9 |
10 | # Hi I am Ankit Singh
11 |
12 | ## I love building web apps with the MERN stack—React, Node.js, Express, and MongoDB. Coding is my playground, where I turn ideas into real, functional projects!
13 |
--------------------------------------------------------------------------------
/src/utils/create-excerpt.js:
--------------------------------------------------------------------------------
1 | import MarkdownIt from 'markdown-it';
2 | import sanitizeHtml from 'sanitize-html';
3 | const parser = new MarkdownIt();
4 |
5 | export const createExcerpt = (body) => {
6 | return sanitizeHtml(
7 | parser
8 | .render(body)
9 | .split('\n')
10 | .slice(0, 6)
11 | .map((str) => {
12 | return str.replace(/<\/?[^>]+(>|$)/g, '').split('\n');
13 | })
14 | .flat()
15 | .join(' ')
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/src/components/cta-internal.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { href, classNames = 'my-12 justify-center' } = Astro.props;
3 | ---
4 |
5 |
13 |
--------------------------------------------------------------------------------
/src/utils/format-date.js:
--------------------------------------------------------------------------------
1 | import days from './days';
2 |
3 | export const formatDate = (dateString, showTime = false) => {
4 | const date = new Date(dateString);
5 |
6 | const dateStamp = new Date(dateString).toLocaleString('en-US', {
7 | timeZone: 'UTC',
8 | day: 'numeric',
9 | month: 'long',
10 | weekday: 'long',
11 | year: 'numeric',
12 | });
13 | const timeStamp = date.toLocaleTimeString();
14 |
15 | return `${dateStamp} ${showTime ? `@${timeStamp}` : ''}`;
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/cta-external.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { href, className = 'my-24' } = Astro.props;
3 | ---
4 |
5 |
15 |
--------------------------------------------------------------------------------
/src/utils/all-collections.js:
--------------------------------------------------------------------------------
1 | import { getCollection } from 'astro:content';
2 |
3 | export const profiles = await getCollection('profiles');
4 |
5 | export const collections = [...profiles];
6 |
7 | export const search = collections
8 | .filter((item) => item.data.draft !== true)
9 | .map((data) => {
10 | const {
11 | slug,
12 | data: { base, title, date },
13 | } = data;
14 |
15 | return {
16 | date: date,
17 | title: title,
18 | base: base,
19 | path: `/${base}/${slug}`,
20 | };
21 | })
22 | .sort((a, b) => b.date - a.date);
23 |
--------------------------------------------------------------------------------
/src/components/code-sandbox.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { id } = Astro.props;
3 | ---
4 |
5 |
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
9 | **Is your feature request related to a problem? Please describe.**
10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11 |
12 | **Describe the solution you'd like**
13 | A clear and concise description of what you want to happen.
14 |
15 | **Describe alternatives you've considered**
16 | A clear and concise description of any alternative solutions or features you've considered.
17 |
18 | **Additional context**
19 | Add any other context or screenshots about the feature request here.
--------------------------------------------------------------------------------
/src/content/profiles/parthivkapoor0101.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | base: posts
3 | title: Parthiv Kapoor
4 | tags: [DSA, Python, Java]
5 | date: 2024-10-26
6 | author: parthivkapoor0101
7 | featuredImage: https://avatars.githubusercontent.com/u/182854493?v=4
8 | ---
9 |
10 | DSA expert specialising in machine learning with a B - Tech degree
11 |
12 |
13 | Hey, I am Parthiv,
14 |
15 | I recently completed my b-tech degree from Agra, India. I have a deep knowledge of data structures and backend languages like Python and Java. Feel free to contact me if you would like to hire me!!
16 |
17 | Thank you for reading. If you have any job ideas or suggestions, feel free to let me know!
18 |
19 | Regards,
20 | Parthiv Kapoor
21 |
--------------------------------------------------------------------------------
/src/content/profiles/Developer-Utkarsh.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | base: posts
3 | title: Utkarsh Tiwari
4 | tags: [JavaScript, TypeScript, Python, MERN Stack,Next JS]
5 | date: 2024-09-02
6 | author: Developer-Utkarsh
7 | featuredImage: https://avatars.githubusercontent.com/u/128823414?s=400&u=84399792b7ad20c08d527467d9aea4f8ae561b44&v=4
8 | ---
9 |
10 | # Hi I'm Utkarsh Tiwari
11 | A passionate Full Stack developer from India | Skilled MERN Stack Developer | Crafting High-Quality, User-Friendly Web Apps | Passionate About AI Projects That Drive Impact
12 |
13 |
14 | #### Full Stack Web Developer | Skilled in MERN Stack | Passionate about Success & AI Projects
15 |
16 | Thank You For Viewing my profile
17 |
18 | #
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/utils/create-tags-collection.js:
--------------------------------------------------------------------------------
1 | import { formatSlug } from './format-slug';
2 |
3 | export const createTagsCollection = (collections) => {
4 | return collections
5 | .map((collection) => {
6 | const tags = collection.data?.tags || [];
7 |
8 | return tags
9 | .map((tag) => {
10 | const slug = formatSlug(tag) || '';
11 | return {
12 | name: tag || '',
13 | slug,
14 | };
15 | })
16 | .flat();
17 | })
18 | .flat()
19 | .filter((item, index, self) => {
20 | const { name } = item;
21 | return name && index === self.findIndex((obj) => obj.name === name);
22 | })
23 | .sort((a, b) => a.name.localeCompare(b.name));
24 | };
25 |
--------------------------------------------------------------------------------
/src/components/new-label.tsx:
--------------------------------------------------------------------------------
1 | import { component$, useSignal, useTask$ } from '@builder.io/qwik';
2 | import isNewContent from '../utils/is-new-content';
3 |
4 | interface Props {
5 | date: Date;
6 | }
7 |
8 | const NewLabel = component$(({ date }) => {
9 | const isNew = useSignal(false);
10 |
11 | useTask$(() => {
12 | isNew.value = isNewContent(date);
13 | });
14 |
15 | return (
16 |
21 | );
22 | });
23 |
24 | export default NewLabel;
25 |
--------------------------------------------------------------------------------
/src/components/list-top-ten-cities.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { data } = Astro.props;
3 |
4 | const listData = data.sort((a, b) => b.total - a.total).slice(0, 10);
5 | ---
6 |
7 |
24 |
--------------------------------------------------------------------------------
/src/components/table-of-contents.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { headings } = Astro.props;
3 | ---
4 |
5 | {
6 | headings.length > 0 ? (
7 |
8 |
on this page
9 |
10 | {headings.map((heading) => {
11 | const { depth, slug, text } = heading;
12 |
13 | const getPaddingDepth = {
14 | [2]: '4',
15 | [3]: '6',
16 | [4]: '8',
17 | [5]: '10',
18 | [6]: '12',
19 | };
20 |
21 | return (
22 |
23 |
24 | {text}
25 |
26 |
27 | );
28 | })}
29 |
30 |
31 | ) : null
32 | }
33 |
--------------------------------------------------------------------------------
/src/components/list-popular.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { data } = Astro.props;
3 | ---
4 |
5 |
6 | {
7 | data.map((item, index) => {
8 | const { slug, title, total } = item;
9 |
10 | return (
11 |
12 |
13 | {index + 1}
14 |
15 |
16 |
21 | {`x${total}`}
22 |
23 | );
24 | })
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/pages/tags.astro:
--------------------------------------------------------------------------------
1 | ---
2 | export const prerender = true;
3 |
4 | import Main from '../layouts/main.astro';
5 | import Aside from '../components/aside.astro';
6 | import ProfileCard from '../components/profile-card.astro';
7 | import SearchTags from '../components/search-tags';
8 |
9 | import { createTagsCollection } from '../utils/create-tags-collection';
10 |
11 | import { collections } from '../utils/all-collections';
12 |
13 | const tags = createTagsCollection(collections);
14 | ---
15 |
16 |
17 | Tags
19 | {`x${tags.length}`}
20 |
21 | Tags Search
22 | {tags ? : null}
23 |
26 |
27 |
--------------------------------------------------------------------------------
/src/pages/profiles.astro:
--------------------------------------------------------------------------------
1 | ---
2 | export const prerender = true;
3 |
4 | import Main from '../layouts/main.astro';
5 | import CollectionsList from '../components/collections-list.astro';
6 | import Aside from '../components/aside.astro';
7 | import ProfileCard from '../components/profile-card.astro';
8 |
9 |
10 | import { profiles } from '../utils/all-collections';
11 |
12 |
13 | ---
14 |
15 |
16 | Profiles
18 | {`x${profiles.length}`}
19 |
20 | Users Profiles
21 |
22 | View some users profiles here, and feel free to explore further by reading their profile post.
23 |
24 |
25 |
28 |
29 |
--------------------------------------------------------------------------------
/src/content/profiles/rohitshah09.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | base: posts
3 | title: Rohit Shah
4 | tags: [Javascript, Python, HTML]
5 | date: 2024-10-20
6 | author: rohitshah09
7 | featuredImage: https://avatars.githubusercontent.com/u/167185738?v=4
8 | ---
9 |
10 | Discord Bot Developer
11 |
12 |
13 | Hi, I am Rohit:
14 |
15 | I began my coding journey in year 7 with basic python code in pycharm. I expanded my coding skills by starting to learn HTMl - CSS - Javascript. I started to create different projects with different complexities using basic HTML. I continued practicing Python by making different projects such as face recognistion and voice recognition.
16 |
17 | Now I am learning more languages while continuing to work on my projects. I aim to learn more about open source and how to contribute to different projects through git and github. If you have any open source projects which I can contribute to, feel free to send them through my discord (vk_goat).
18 |
19 | Thanks for viewing my profile and reading about my journey!
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/style.yml:
--------------------------------------------------------------------------------
1 |
2 | name: 👯♂️ Style Changing Request
3 | description: Suggest a style designs
4 | title: '[style]: '
5 | labels: ['enhancement']
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Thanks for taking the time to fill out this template!
11 | - type: textarea
12 | id: style-idea
13 | attributes:
14 | label: What's the style idea?
15 | placeholder: Add descriptions
16 | value: 'We need to improve '
17 | validations:
18 | required: true
19 | - type: textarea
20 | id: screenshots
21 | attributes:
22 | label: Add screenshots
23 | description: Add screenshots to see the demo
24 | placeholder: Add screenshots
25 | value: 'Add screenshots'
26 | - type: checkboxes
27 | id: terms
28 | attributes:
29 | label: Code of Conduct
30 | description: By submitting this issue, you agree to follow our Code of Conduct
31 | options:
32 | - label: I agree to follow this project's Code of Conduct
33 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ## Fixes Issue
5 |
6 |
7 |
8 |
9 |
10 | ## Changes proposed
11 |
12 |
13 |
14 |
15 |
21 |
22 | ## Check List (Check all the applicable boxes)
23 |
24 | - [ ] My Changes follow the Code of Conduct of this Project.
25 | - [ ] My Post or Change does not contain any **Plagarized** Content.
26 | - [ ] The title of the PR is a short description of the Changes made.
27 |
28 | ## Note to reviewers
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/components/list-top-referrers.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { data } = Astro.props;
3 |
4 | const listData = data.sort((a, b) => b.total - a.total).slice(0, 10);
5 | ---
6 |
7 |
8 | {
9 | listData.map((item, index) => {
10 | const { referrer, total } = item;
11 |
12 | return (
13 |
14 |
15 | {index + 1}
16 |
17 |
18 |
23 |
24 | {`x${total}`}
25 |
26 | );
27 | })
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/src/components/tags-list.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import { formatSlug } from '../utils/format-slug';
3 |
4 | const { tags, className = 'mb-8', highlighted, link = false } = Astro.props;
5 | ---
6 |
7 |
8 | {
9 | tags.map((tag) => {
10 | const isHighlighted = formatSlug(tag) === highlighted ? true : false;
11 | return (
12 |
15 | {link ? (
16 |
20 | {tag}
21 |
22 | ) : (
23 | {tag}
24 | )}
25 |
26 | );
27 | })
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Hemang Yadav
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/components/search-trigger.tsx:
--------------------------------------------------------------------------------
1 | import { component$ } from '@builder.io/qwik';
2 |
3 | interface Props {
4 | handleModal: () => void;
5 | }
6 |
7 | const SearchTrigger = component$(({ handleModal }) => {
8 | return (
9 |
14 |
15 |
16 |
17 |
18 | Search
19 |
20 |
21 |
22 |
23 | ⌘
24 |
25 | K
26 |
27 |
28 | );
29 | });
30 |
31 | export default SearchTrigger;
32 |
--------------------------------------------------------------------------------
/src/components/stackblitz-embed.tsx:
--------------------------------------------------------------------------------
1 | import { component$, useVisibleTask$ } from '@builder.io/qwik';
2 |
3 | interface Props {
4 | id: string;
5 | file: string;
6 | view?: 'editor' | 'preview' | null;
7 | hideExplorer?: boolean;
8 | height?: number;
9 | theme?: 'dark' | 'light' | 'default' | null;
10 | clickToLoad?: boolean;
11 | }
12 |
13 | const StackBlitz = component$(
14 | ({ id, file, view = null, hideExplorer = false, height = 600, theme = 'dark', clickToLoad = false }) => {
15 | useVisibleTask$(async () => {
16 | const sdk = (await import('@stackblitz/sdk')).default;
17 |
18 | sdk.embedProjectId('stackblitz-embed', id, {
19 | forceEmbedLayout: true,
20 | openFile: file,
21 | view: view,
22 | hideExplorer: hideExplorer,
23 | hideNavigation: true,
24 | height: height,
25 | theme: theme,
26 | clickToLoad: clickToLoad,
27 | });
28 | });
29 |
30 | return (
31 |
34 | );
35 | }
36 | );
37 |
38 | export default StackBlitz;
39 |
--------------------------------------------------------------------------------
/src/components/featured-image-card.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import AstroImage from '../components/astro-image.astro';
3 |
4 | const { alt, thumbnail, text } = Astro.props;
5 | ---
6 |
7 |
27 |
--------------------------------------------------------------------------------
/src/components/search-input.tsx:
--------------------------------------------------------------------------------
1 | import { component$ } from '@builder.io/qwik';
2 |
3 | interface Props {
4 | handleModal?: () => void;
5 | handleInput: (event: any) => void;
6 | showEsc?: boolean;
7 | }
8 |
9 | const SearchInput = component$(({ handleModal, handleInput, showEsc = false }) => {
10 | return (
11 |
12 |
13 |
14 |
15 |
22 | {showEsc ? (
23 |
29 | esc
30 |
31 | ) : null}
32 |
33 | );
34 | });
35 |
36 | export default SearchInput;
37 |
--------------------------------------------------------------------------------
/.github/workflows/greetings.yml:
--------------------------------------------------------------------------------
1 |
2 | name: Greetings
3 |
4 | on:
5 | pull_request:
6 | types: [opened]
7 | issues:
8 | types: [opened]
9 |
10 | permissions:
11 | issues: write
12 | pull-requests: write
13 |
14 | jobs:
15 | greet:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Greet on PRs and Issues
19 | uses: actions/github-script@v7
20 | with:
21 | script: |
22 | try {
23 | const isPR = context.payload.pull_request !== undefined;
24 | const number = isPR ? context.payload.pull_request.number : context.payload.issue.number;
25 | const commentBody = isPR
26 | ? `Welcome, @${{ github.actor }}! Thanks for raising the issue!`
27 | : `Great job, @${{ github.actor }}! Thanks for creating the pull request`;
28 |
29 | await github.rest.issues.createComment({
30 | owner: context.repo.owner,
31 | repo: context.repo.repo,
32 | issue_number: number,
33 | body: commentBody
34 | });
35 |
36 | console.log('Comment successfully created.');
37 | } catch (error) {
38 | console.error('Error creating comment:', error);
39 | // Do not mark the step as failed; continue with the workflow.
40 | }
41 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/documentation.yml:
--------------------------------------------------------------------------------
1 |
2 | name: 🔖 Documentation update
3 | description: Improve Documentation
4 | title: '[Docs]: '
5 | labels: ['documentation']
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Thanks for taking the time to fill out this documentation update template!
11 | - type: textarea
12 | id: improve-docs
13 | attributes:
14 | label: What's wrong with the current Documentation?
15 | description: What Issue are you facing?
16 | placeholder: Add descriptions
17 | value: 'Briefly Describe the Issue you are facing'
18 | validations:
19 | required: true
20 | - type: textarea
21 | id: screenshots
22 | attributes:
23 | label: Add screenshots
24 | description: Add Screenshots if Possible
25 | placeholder: Add screenshots
26 | value: 'Add Screenshots here'
27 | - type: checkboxes
28 | id: self-grab
29 | attributes:
30 | label: Self - Grab
31 | description: By checking this box, you acknowledge that you can fix this Documentation Error
32 | options:
33 | - label: I would like to work on this issue
34 | id: terms
35 | attributes:
36 | label: Code of Conduct
37 | description: By submitting this issue, you agree to follow our Code of Conduct
38 | options:
39 | - label: I agree to follow this project's Code of Conduct
40 |
--------------------------------------------------------------------------------
/src/components/nav-link.tsx:
--------------------------------------------------------------------------------
1 | import { component$ } from '@builder.io/qwik';
2 |
3 | interface Props {
4 | title: string;
5 | icon: string;
6 | stroke: boolean;
7 | slug: string;
8 | isActive: boolean;
9 | newCount: number;
10 | }
11 |
12 | const NavLink = component$(({ title, icon, stroke, slug, isActive, newCount }) => {
13 | return (
14 |
20 |
28 |
29 |
30 | {newCount ? (
31 |
32 | {newCount}
33 |
34 | ) : null}
35 | {title}
36 |
37 | );
38 | });
39 |
40 | export default NavLink;
41 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug.yml:
--------------------------------------------------------------------------------
1 |
2 | name: 🐞 Bug Report
3 | description: File a bug report
4 | title: '[Bug]: '
5 | labels: ['bug']
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Thanks for taking the time to fill out this bug report!
11 | - type: textarea
12 | id: what-happened
13 | attributes:
14 | label: What happened?
15 | description: Also tell us, what did you expect to happen?
16 | placeholder: Add descriptions
17 | value: 'Briefly Describe the bug you found'
18 | validations:
19 | required: true
20 | - type: textarea
21 | id: screenshots
22 | attributes:
23 | label: Add screenshots
24 | description: Add screenshots to see the problems
25 | placeholder: Add screenshots
26 | value: 'Add screenshots'
27 | - type: dropdown
28 | id: browsers
29 | attributes:
30 | label: What browsers are you seeing the problem on?
31 | multiple: true
32 | options:
33 | - Firefox
34 | - Chrome
35 | - Safari
36 | - Microsoft Edge
37 | - Brave
38 | - Other
39 | - type: checkboxes
40 | id: self-grab
41 | attributes:
42 | label: Self - Grab
43 | description: By checking this box, you can fix this bug
44 | options:
45 | - label: I would like to work on this issue
46 | id: terms
47 | attributes:
48 | label: Code of Conduct
49 | description: By submitting this issue, you agree to follow our Code of Conduct
50 | options:
51 | - label: I agree to follow this project's Code of Conduct
--------------------------------------------------------------------------------
/src/pages/index.astro:
--------------------------------------------------------------------------------
1 | ---
2 | export const prerender = true;
3 |
4 | import Main from '../layouts/main.astro';
5 |
6 | import Aside from '../components/aside.astro';
7 | import ProfileCard from '../components/profile-card.astro';
8 | import CollectionsList from '../components/collections-list.astro';
9 | import CtaInternal from '../components/cta-internal.astro';
10 |
11 | import { profiles } from '../utils/all-collections';
12 | ---
13 |
14 |
15 | DISCOVER & CONNECT WITH DEVELOPERS
16 | ZemProfiles
17 |
18 | ZemProfiles stands as an open-source platform, providing users with the opportunity to connect seamlessly with fellow developers.
19 | This connectivity is fostered through the simple act of adding one's Profile to the platform,
20 | thus creating a digital hub where like-minded individuals can engage, collaborate, and
21 | share insights within the expansive realm of software development. With its user-friendly interface and inclusive community ethos,
22 | ZemProfiles serves as a dynamic space where connections are forged, ideas are exchanged, and innovation thrives.
23 |
24 |
25 |
26 | Latest Profiles
27 | Latest profiles published on ZemProfiles 👇
28 |
29 | {`See All ${profiles.length} Profiles`}
30 |
31 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/loading.tsx:
--------------------------------------------------------------------------------
1 | import { component$ } from '@builder.io/qwik';
2 |
3 | interface Props {
4 | classNames?: string;
5 | }
6 |
7 | const Loading = component$(({ classNames }) => {
8 | return (
9 |
10 |
17 |
21 |
25 |
26 |
Loading...
27 |
28 | );
29 | });
30 |
31 | export default Loading;
32 |
--------------------------------------------------------------------------------
/src/components/click-to-copy-email.jsx:
--------------------------------------------------------------------------------
1 | import { component$, useSignal, $ } from '@builder.io/qwik';
2 |
3 | const ClickToCopyEmail = component$(() => {
4 | const defaultMessage = 'Click to Copy';
5 |
6 | const message = useSignal(defaultMessage);
7 |
8 | const handleClick = $(async (event) => {
9 | const text = event.target.innerHTML;
10 |
11 | try {
12 | await navigator.clipboard.writeText(text);
13 | message.value = 'Copied!';
14 | } catch (error) {
15 | console.error('Failed to copy: ', error);
16 | }
17 | });
18 |
19 | const handleMouseOut = $(() => {
20 | setTimeout(() => {
21 | message.value = defaultMessage;
22 | }, 200);
23 | });
24 |
25 | return (
26 |
27 |
34 |
39 |
40 |
41 | ZemerikY@gmail.com
42 |
43 |
44 | {message.value}
45 |
46 |
47 | );
48 | });
49 |
50 | export default ClickToCopyEmail;
51 |
--------------------------------------------------------------------------------
/src/components/audio-feed-embed.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { audioFeedId } = Astro.props;
3 | import Loading from './loading';
4 | ---
5 |
6 |
10 |
11 |
12 |
13 |
58 |
--------------------------------------------------------------------------------
/src/components/search-tags.tsx:
--------------------------------------------------------------------------------
1 | import { component$, useSignal, $, useVisibleTask$ } from '@builder.io/qwik';
2 | import SearchInput from './search-input';
3 |
4 | interface tagProps {
5 | name: string;
6 | slug: string;
7 | }
8 |
9 | interface Props {
10 | tags: tagProps[];
11 | }
12 |
13 | const SearchTags = component$(({ tags }) => {
14 | const all = tags;
15 | const filtered = useSignal(tags);
16 |
17 | const handleInput = $(async (event) => {
18 | const FuseModule = await import('fuse.js');
19 | const Fuse = FuseModule.default;
20 | const {
21 | target: { value },
22 | } = event;
23 | const fuse = new Fuse(all, {
24 | threshold: 0.5,
25 | keys: ['name'],
26 | });
27 | const results = fuse.search(value).map((data: any) => {
28 | const {
29 | item: { name, slug },
30 | } = data;
31 | return {
32 | name,
33 | slug,
34 | };
35 | });
36 | if (value) {
37 | filtered.value = results;
38 | } else {
39 | filtered.value = all;
40 | }
41 | });
42 |
43 | useVisibleTask$(() => {
44 | document.getElementById('input').focus();
45 | });
46 |
47 | return (
48 |
49 |
50 |
51 | {filtered.value.map((item) => {
52 | const { name, slug } = item;
53 | return (
54 |
55 |
59 | {name}
60 |
61 |
62 | );
63 | })}
64 |
65 |
66 | );
67 | });
68 |
69 | export default SearchTags;
70 |
--------------------------------------------------------------------------------
/src/pages/tags/[...tag].astro:
--------------------------------------------------------------------------------
1 | ---
2 | export const prerender = true;
3 |
4 | import Main from '../../layouts/main.astro';
5 | import Aside from '../../components/aside.astro';
6 | import ProfileCard from '../../components/profile-card.astro';
7 | import CollectionsList from '../../components/collections-list.astro';
8 |
9 | import { collections } from '../../utils/all-collections';
10 | import { createTagsCollection } from '../../utils/create-tags-collection';
11 |
12 | interface Props {
13 | name: string;
14 | collection: { data: { tags: string[] } }[];
15 | }
16 |
17 | export async function getStaticPaths() {
18 | const tags = createTagsCollection(collections);
19 |
20 | return tags.map((tag: { name: string; slug: string }) => {
21 | const { name, slug } = tag;
22 |
23 | return {
24 | params: {
25 | tag: slug,
26 | },
27 | props: {
28 | name: name,
29 | collection: collections.filter((item) => item.data.tags.includes(name)),
30 | },
31 | };
32 | });
33 | }
34 |
35 | const { tag } = Astro.params;
36 | const site = Astro.site.href;
37 |
38 | const { name, collection } = Astro.props;
39 |
40 | const ogImage = `${site}/tags/${tag}/og.png`;
41 | ---
42 |
43 |
44 | {name}
46 | {`x${collection.length}`}
47 |
48 | {`${name} Developers`}
49 |
50 | Here you'll find {collection.length}
51 | {collection.length > 1 ? 'developers' : 'developer'} who {collection.length > 1 ? 'are' : 'is'} familiar with
52 | {name} .
53 |
54 |
55 |
58 |
59 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zemprofiles",
3 | "version": "1.0.0",
4 | "description": "Discover & Connect with Developers",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "astro dev",
8 | "start": "astro dev",
9 | "build": "astro build",
10 | "preview": "astro preview",
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/Zemerik/ZemProfiles.git"
16 | },
17 | "keywords": [],
18 | "author": "",
19 | "license": "ISC",
20 | "bugs": {
21 | "url": "https://github.com/Zemerik/ZemProfiles/issues"
22 | },
23 | "homepage": "https://zemprofiles.vercel.app",
24 | "dependencies": {
25 | "@astrojs/mdx": "^4.3.10",
26 | "@astrojs/partytown": "^2.1.0",
27 | "@astrojs/rss": "^4.0.5",
28 | "@astrojs/sitemap": "^3.1.6",
29 | "@astrojs/tailwind": "^5.1.5",
30 | "@astrojs/vercel": "^9.0.0",
31 | "@builder.io/qwik": "^1.9.0",
32 | "@fontsource/inconsolata": "^5.0.8",
33 | "@google-analytics/data": "^4.7.0",
34 | "@neondatabase/serverless": "^0.6.0",
35 | "@qwikdev/astro": "^0.5.2",
36 | "@stackblitz/sdk": "^1.9.0",
37 | "@vercel/edge": "^1.1.0",
38 | "astro": "^5.15.9",
39 | "astro-auto-import": "^0.4.5",
40 | "astro-embed": "^0.7.4",
41 | "dotenv": "^16.4.5",
42 | "fuse.js": "^7.0.0",
43 | "globe.gl": "^2.32.4",
44 | "markdown-it": "^14.1.0",
45 | "mdx": "^0.3.1",
46 | "octokit": "^4.1.1",
47 | "og-img": "^0.2.1",
48 | "rehype-autolink-headings": "^7.1.0",
49 | "rehype-external-links": "^3.0.0",
50 | "rehype-slug": "^6.0.0",
51 | "sanitize-html": "^2.13.0",
52 | "slugify": "^1.6.6",
53 | "tailwindcss": "^3.4.1",
54 | "three": "0.161.0",
55 | "typescript": "^5.3.2",
56 | "zemprofilees": "file:",
57 | "zemprofiles": "file:"
58 | },
59 | "devDependencies": {
60 | "@tailwindcss/typography": "^0.5.10",
61 | "@types/markdown-it": "^13.0.1"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/pages/posts/[...slug].astro:
--------------------------------------------------------------------------------
1 | ---
2 | export const prerender = true;
3 |
4 | import Main from '../../layouts/main.astro';
5 | import Aside from '../../components/aside.astro';
6 | import TagsList from '../../components/tags-list.astro';
7 | import FeaturedImageCard from '../../components/featured-image-card.astro';
8 | import TableOfContents from '../../components/table-of-contents.astro';
9 |
10 | import { formatDate } from '../../utils/format-date';
11 | import { createExcerpt } from '../../utils/create-excerpt';
12 |
13 | import { profiles } from '../../utils/all-collections';
14 |
15 | export async function getStaticPaths() {
16 | return profiles.map((post) => {
17 | return {
18 | params: {
19 | slug: post.slug,
20 | },
21 | props: {
22 | post,
23 | },
24 | };
25 | });
26 | }
27 |
28 | const {
29 | post,
30 | post: {
31 | slug,
32 | data: { title, author, date, tags, featuredImage, draft },
33 | },
34 | } = Astro.props;
35 |
36 | const excerpt = `${createExcerpt(post.body).substring(0, 70)}...`;
37 |
38 | const { Content, headings } = await post.render();
39 | ---
40 |
41 |
42 | {
43 | draft ? (
44 |
45 | Status: Unpublished
46 |
47 | ) : null
48 | }
49 |
50 | {formatDate(date)}
51 | {`By ${author}`}
52 |
53 | {title}
54 |
55 |
56 |
60 |
61 |
--------------------------------------------------------------------------------
/src/content/config.js:
--------------------------------------------------------------------------------
1 | import { z, defineCollection } from 'astro:content';
2 |
3 | export const collections = {
4 | posts: defineCollection({
5 | type: 'content',
6 | schema: z.object({
7 | draft: z.boolean().optional(),
8 | audioFeedId: z.string().optional(),
9 | base: z.string(),
10 | title: z.string(),
11 | tags: z.array(z.string()).optional(),
12 | date: z.date(),
13 | author: z.string(),
14 | featuredImage: z.string(),
15 | }),
16 | }),
17 | articles: defineCollection({
18 | type: 'content',
19 | schema: z.object({
20 | audioFeedId: z.string().optional(),
21 | base: z.string(),
22 | title: z.string(),
23 | tags: z.array(z.string()).optional(),
24 | date: z.date(),
25 | url: z.string(),
26 | publication: z.string(),
27 | author: z.string(),
28 | logo: z.string(),
29 | featuredImage: z.string().optional(),
30 | }),
31 | }),
32 | streams: defineCollection({
33 | type: 'content',
34 | schema: z.object({
35 | base: z.string(),
36 | title: z.string(),
37 | tags: z.array(z.string()).optional(),
38 | date: z.date(),
39 | url: z.string(),
40 | show: z.string(),
41 | role: z.string(),
42 | logo: z.string(),
43 | }),
44 | }),
45 | demos: defineCollection({
46 | type: 'content',
47 | schema: z.object({
48 | base: z.string(),
49 | title: z.string(),
50 | tags: z.array(z.string()).optional(),
51 | date: z.date(),
52 | author: z.string(),
53 | featuredImage: z.string(),
54 | }),
55 | }),
56 | opensource: defineCollection({
57 | type: 'content',
58 | schema: z.object({
59 | base: z.string(),
60 | title: z.string(),
61 | tags: z.array(z.string()).optional(),
62 | date: z.date(),
63 | author: z.string(),
64 | featuredImage: z.string(),
65 | }),
66 | }),
67 | ghosts: defineCollection({
68 | type: 'content',
69 | schema: z.object({
70 | base: z.string(),
71 | title: z.string(),
72 | tags: z.array(z.string()).optional(),
73 | date: z.date(),
74 | url: z.string(),
75 | publication: z.string(),
76 | author: z.string(),
77 | logo: z.string(),
78 | }),
79 | }),
80 | };
81 |
--------------------------------------------------------------------------------
/astro.config.mjs:
--------------------------------------------------------------------------------
1 | import { defineConfig, passthroughImageService } from 'astro/config';
2 | import tailwind from '@astrojs/tailwind';
3 | import mdx from '@astrojs/mdx';
4 | import AutoImport from 'astro-auto-import';
5 | import vercel from '@astrojs/vercel/serverless';
6 | import qwikdev from '@qwikdev/astro';
7 | import rehypeSlug from 'rehype-slug';
8 | import rehypeAutolinkHeadings from 'rehype-autolink-headings';
9 | import rehypeExternalLinks from 'rehype-external-links';
10 | import partytown from '@astrojs/partytown';
11 | import sitemap from '@astrojs/sitemap';
12 | const isProd = import.meta.env.PROD;
13 |
14 | // https://astro.build/config
15 | export default defineConfig({
16 | site: isProd ? 'https://zemprofiles.vercel.app' : 'http://localhost:4321',
17 | output: 'server',
18 | adapter: vercel({
19 | edgeMiddleware: true,
20 | }),
21 | image: {
22 | domains: ['res.cloudinary.com'],
23 | service: passthroughImageService(),
24 | },
25 | integrations: [
26 | tailwind(),
27 | qwikdev(),
28 | AutoImport({
29 | imports: [
30 | {
31 | './src/components/cta-external.astro': [['default', 'CtaExternal']],
32 | },
33 | {
34 | './src/components/code-sandbox.astro': [['default', 'CodeSandbox']],
35 | },
36 | {
37 | './src/components/astro-image.astro': [['default', 'AstroImage']],
38 | },
39 | {
40 | './src/components/video-player.astro': [['default', 'VideoPlayer']],
41 | },
42 | {
43 | './src/components/stackblitz-embed.tsx': [['default', 'StackBlitz']],
44 | },
45 | {
46 | 'astro-embed': ['Tweet', 'Vimeo', 'YouTube'],
47 | },
48 | {
49 | 'astro:assets': ['Image'],
50 | },
51 | ],
52 | }),
53 | mdx({
54 | syntaxHighlight: 'prism',
55 | rehypePlugins: [
56 | rehypeSlug,
57 | [
58 | rehypeAutolinkHeadings,
59 | {
60 | behavior: 'wrap',
61 | },
62 | ],
63 | [
64 | rehypeExternalLinks,
65 | {
66 | rel: ['nofollow'],
67 | target: ['_blank'],
68 | },
69 | ],
70 | ],
71 | }),
72 | partytown({
73 | config: {
74 | forward: ['dataLayer.push'],
75 | },
76 | }),
77 | sitemap(),
78 | ],
79 | vite: {
80 | build: {
81 | chunkSizeWarningLimit: 10000,
82 | },
83 | },
84 | });
85 |
--------------------------------------------------------------------------------
/src/components/line-chart-visits.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { data } = Astro.props;
3 |
4 | const chartData = data.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
5 |
6 | const chartWidth = 600;
7 | const chartHeight = 300;
8 | const offsetY = 40;
9 | const offsetX = 10;
10 | const paddingX = 40;
11 | const paddingY = 50;
12 |
13 | const maxY = data ? Math.max(...data.map((item) => item.total)) : null;
14 | const guides = [...Array(8).keys()];
15 |
16 | const properties = chartData.map((property, index) => {
17 | const { day, month, total } = property;
18 | const ratio = (index / chartData.length) * (chartWidth - offsetX * 2);
19 | const x = ratio + paddingX / 2;
20 | const y = chartHeight - offsetY - (total / maxY) * (chartHeight - (paddingY + offsetY)) - paddingY + offsetY;
21 | return {
22 | total: total,
23 | date: `${month}•${day}`,
24 | x: x,
25 | y: y,
26 | };
27 | });
28 |
29 | const points = properties
30 | .map((point) => {
31 | const { x, y } = point;
32 | return `${x},${y}`;
33 | })
34 | .toString();
35 | ---
36 |
37 |
38 |
39 | {
40 | guides.map((_, index) => {
41 | const ratio = index / guides.length;
42 | const y = chartHeight - paddingY - chartHeight * ratio;
43 |
44 | return (
45 |
51 | );
52 | })
53 | }
54 |
55 |
56 |
57 | {
58 | properties.map((property) => {
59 | const { total, date, x, y } = property;
60 | return (
61 |
62 |
63 |
64 | {`x${total}`}
65 |
66 |
71 | {date}
72 |
73 |
74 | );
75 | })
76 | }
77 |
78 |
79 |
--------------------------------------------------------------------------------
/src/content/profiles/zemerik.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | base: posts
3 | title: Hemang Yadav
4 | tags: [Typescript, Javascript, Astro, Python, HTML, CSS, NodeJS, ReactJS, NextJS, MongoDB, Open-Source, Content Creator]
5 | date: 2024-05-06
6 | author: Hemang Yadav
7 | featuredImage: https://avatars.githubusercontent.com/u/133865660?v=4
8 | ---
9 |
10 |
11 | 💻Passionate Developer + 💪Expertise in Web-Development + 🎓Open-Source Enthusiast + 🏆Content Creator
12 |
13 |
14 | ## About Me:
15 |
16 | As a 15-year-old high school student, I am driven by an unwavering passion for pursuing a career as a front-end software developer.
17 | With a knack for transforming concepts into tangible realities, I possess a strong command of Frontend / Backend development, along with different API's
18 | enabling me to bring ideas to life through coding expertise.
19 |
20 | - Learn more about me through my [Terminal](https://zemeriksterminal.vercel.app)
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | ## How I Started?
29 |
30 | I began my coding journey with JavaScript, creating a simple "hello Zemerik" output. I initially focused on building Discord bots using Node.js, which sparked an interest in web development. This led me to explore and master various frameworks and technologies within the field.
31 |
32 | - Learn more about my Journey on [LinkedIn](https://linkedin.com/in/zemerik)
33 |
34 | ## Projects:
35 |
36 | - ZemPosts: Post & Connect with Developers
37 | - https://zemposts.vercel.app
38 | - https://github.com/Zemerik/ZemPosts
39 |
40 | - ZemShowcase: Showcase & Connect with Developers
41 | - https://zemshowcase.vercel.app
42 | - https://github.com/Zemerik/ZemShowcase
43 |
44 | ## Blogging:
45 |
46 | I often write blogs on my [Personal Blog Site](https://zemerik.hashnode.dev) and [DevTo](https://dev.to/Zemerik) sharing my coding journey, to connect with other developers around the globe.
47 |
48 | ## Youtube Jorney:
49 |
50 | Other than Hashnode, DevTo, and X (Twitter), I utilize my [Youtube Channel](https://www.youtube.com/@Zemerik) as a marketing tool for my projects. In my videos, I explore different projects and try to provide some feedback for the developers to enhnace their projects.
51 |
52 | > - You can submit your Open - Source Project to be reviewed by me through my socials!
53 |
54 | ## Want to Connect?
55 |
56 | Feel free to reach out to me through my socials below
57 |
58 | - [Instagram](https://instagram.com/Zemerik_Insta)
59 | - [X (Twitter)](https://x.com/Zemerik_X)
60 | - [Discord](https://discordapp.com/users/1018816958587748383)
61 | - [Email](mailto:ZemerikY@gmail.com)
62 |
63 | ## Thanks for Visiting
64 |
--------------------------------------------------------------------------------
/public/prism-dracula.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Dracula Theme originally by Zeno Rocha [@zenorocha]
3 | * https://draculatheme.com/
4 | *
5 | * Ported for PrismJS by Albert Vallverdu [@byverdu]
6 | */
7 |
8 | code[class*='language-'],
9 | pre[class*='language-'] {
10 | color: #f8f8f2;
11 | background: none;
12 | text-shadow: 0 1px rgba(21, 34, 212, 0.3);
13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
14 | text-align: left;
15 | white-space: pre;
16 | word-spacing: normal;
17 | word-break: normal;
18 | word-wrap: normal;
19 | line-height: 1.5;
20 | -moz-tab-size: 4;
21 | -o-tab-size: 4;
22 | tab-size: 4;
23 | -webkit-hyphens: none;
24 | -moz-hyphens: none;
25 | -ms-hyphens: none;
26 | hyphens: none;
27 | }
28 |
29 | /* Code blocks */
30 | pre[class*='language-'] {
31 | padding: 1em;
32 | margin: 0.5em 0;
33 | overflow: auto;
34 | border-radius: 0.3em;
35 | }
36 |
37 | :not(pre) > code[class*='language-'],
38 | pre[class*='language-'] {
39 | background: #1c0cca;
40 | border: 1px solid #232140;
41 | }
42 |
43 | /* Inline code */
44 | :not(pre) > code[class*='language-'] {
45 | padding: 0.1em;
46 | border-radius: 0.3em;
47 | white-space: normal;
48 | }
49 |
50 | .token.comment,
51 | .token.prolog,
52 | .token.doctype,
53 | .token.cdata {
54 | color: #1746d4;
55 | }
56 |
57 | .token.punctuation {
58 | color: #f8f8f2;
59 | }
60 |
61 | .namespace {
62 | opacity: 0.7;
63 | }
64 |
65 | .token.property,
66 | .token.tag,
67 | .token.constant,
68 | .token.symbol,
69 | .token.deleted {
70 | color: #1fcfc7;
71 | }
72 |
73 | .token.boolean,
74 | .token.number {
75 | color: #2614c4;
76 | }
77 |
78 | .token.selector,
79 | .token.attr-name,
80 | .token.string,
81 | .token.char,
82 | .token.builtin,
83 | .token.inserted {
84 | color: #50fa7b;
85 | }
86 |
87 | .token.operator,
88 | .token.entity,
89 | .token.url,
90 | .language-css .token.string,
91 | .style .token.string,
92 | .token.variable {
93 | color: #f8f8f2;
94 | }
95 |
96 | .token.atrule,
97 | .token.attr-value,
98 | .token.function,
99 | .token.class-name {
100 | color: #f1fa8c;
101 | }
102 |
103 | .token.keyword {
104 | color: #8be9fd;
105 | }
106 |
107 | .token.regex,
108 | .token.important {
109 | color: #ffb86c;
110 | }
111 |
112 | .token.important,
113 | .token.bold {
114 | font-weight: bold;
115 | }
116 |
117 | .token.italic {
118 | font-style: italic;
119 | }
120 |
121 | .token.entity {
122 | cursor: help;
123 | }
124 |
125 | /* Custom styles */
126 |
127 | .token.inserted-sign.inserted > .token.line {
128 | color: #50fa7b;
129 | }
130 |
131 | .token.deleted-sign.deleted > .token.line {
132 | color: #fe3745;
133 | }
134 | .token.deleted-sign.deleted > .token.prefix.deleted {
135 | color: #fe3745;
136 | }
137 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 | .pnpm-debug.log*
9 |
10 | # Diagnostic reports (https://nodejs.org/api/report.html)
11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # Snowpack dependency directory (https://snowpack.dev/)
46 | web_modules/
47 |
48 | # TypeScript cache
49 | *.tsbuildinfo
50 |
51 | # Optional npm cache directory
52 | .npm
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Optional stylelint cache
58 | .stylelintcache
59 |
60 | # Microbundle cache
61 | .rpt2_cache/
62 | .rts2_cache_cjs/
63 | .rts2_cache_es/
64 | .rts2_cache_umd/
65 |
66 | # Optional REPL history
67 | .node_repl_history
68 |
69 | # Output of 'npm pack'
70 | *.tgz
71 |
72 | # Yarn Integrity file
73 | .yarn-integrity
74 |
75 | # dotenv environment variable files
76 | .env
77 | .env.development.local
78 | .env.test.local
79 | .env.production.local
80 | .env.local
81 |
82 | # parcel-bundler cache (https://parceljs.org/)
83 | .cache
84 | .parcel-cache
85 |
86 | # Next.js build output
87 | .next
88 | out
89 |
90 | # Astro / Vercel build out
91 | .vercel
92 |
93 | # Nuxt.js build / generate output
94 | .nuxt
95 | dist
96 |
97 | # Gatsby files
98 | .cache/
99 | # Comment in the public line in if your project uses Gatsby and not Next.js
100 | # https://nextjs.org/blog/next-9-1#public-directory-support
101 | # public
102 |
103 | # vuepress build output
104 | .vuepress/dist
105 |
106 | # vuepress v2.x temp and cache directory
107 | .temp
108 | .cache
109 |
110 | # Docusaurus cache and generated files
111 | .docusaurus
112 |
113 | # Serverless directories
114 | .serverless/
115 |
116 | # FuseBox cache
117 | .fusebox/
118 |
119 | # DynamoDB Local files
120 | .dynamodb/
121 |
122 | # TernJS port file
123 | .tern-port
124 |
125 | # Stores VSCode versions used for testing VSCode extensions
126 | .vscode-test
127 |
128 | # yarn v2
129 | .yarn/cache
130 | .yarn/unplugged
131 | .yarn/build-state.yml
132 | .yarn/install-state.gz
133 | .pnp.*
134 |
135 | #custom
136 | fauna
137 | src/pages/test.astro
138 | .tmp*/
139 | tmp*/
140 | db_backups
--------------------------------------------------------------------------------
/src/layouts/nav-links.ts:
--------------------------------------------------------------------------------
1 | export const siteLinks = [
2 | {
3 | title: 'Home',
4 | link: '/',
5 | icon: 'M12 5.432l8.159 8.159c.03.03.06.058.091.086v6.198c0 1.035-.84 1.875-1.875 1.875H15a.75.75 0 01-.75-.75v-4.5a.75.75 0 00-.75-.75h-3a.75.75 0 00-.75.75V21a.75.75 0 01-.75.75H5.625a1.875 1.875 0 01-1.875-1.875v-6.198a2.29 2.29 0 00.091-.086L12 5.43z',
6 | stroke: false,
7 | },
8 | {
9 | title: 'Profiles',
10 | link: '/profiles/',
11 | icon: 'M5.566 4.657A4.505 4.505 0 016.75 4.5h10.5c.41 0 .806.055 1.183.157A3 3 0 0015.75 3h-7.5a3 3 0 00-2.684 1.657zM2.25 12a3 3 0 013-3h13.5a3 3 0 013 3v6a3 3 0 01-3 3H5.25a3 3 0 01-3-3v-6zM5.25 7.5c-.41 0-.806.055-1.184.157A3 3 0 016.75 6h10.5a3 3 0 012.683 1.657A4.505 4.505 0 0018.75 7.5H5.25z',
12 | stroke: false,
13 | },
14 | {
15 | title: ' + Profile',
16 | link: 'https://github.com/Zemerik/ZemProfiles',
17 | icon: 'M21.731 2.269a2.625 2.625 0 00-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 000-3.712zM19.513 8.199l-3.712-3.712-12.15 12.15a5.25 5.25 0 00-1.32 2.214l-.8 2.685a.75.75 0 00.933.933l2.685-.8a5.25 5.25 0 002.214-1.32L19.513 8.2z',
18 | stroke: false,
19 | },
20 | ];
21 |
22 | export const socialLinks = [
23 | {
24 | url: 'https://x.com/Zemerik_X',
25 | title: 'Twitter/X',
26 | icon: 'M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z',
27 | stroke: false,
28 | rel: 'me',
29 | },
30 | {
31 | url: 'https://github.com/Zemerik',
32 | title: 'GitHub',
33 | icon: 'M11.88,0.6C5.5,0.6,0.3,5.8,0.3,12.18c0,5.44,3.78,10.05,8.86,11.23c0-0.12-0.12-0.35-0.12-0.59V20.8c-0.47,0-1.3,0-1.42,0c-0.83,0-1.54-0.35-1.89-0.95c-0.35-0.71-0.47-1.77-1.42-2.48C4.08,17.14,4.2,16.9,4.55,16.9c0.59,0.12,1.06,0.59,1.54,1.18c0.47,0.59,0.71,0.71,1.54,0.71c0.47,0,1.06,0,1.65-0.12c0.35-0.83,0.83-1.54,1.54-1.89c-3.9-0.35-5.67-2.36-5.67-4.96c0-1.18,0.47-2.25,1.3-3.19c-0.35-0.59-0.71-2.48,0-3.19c1.77,0,2.84,1.18,3.07,1.42c0.83-0.35,1.77-0.47,2.84-0.47s2.01,0.12,2.84,0.47c0.24-0.35,1.3-1.42,3.07-1.42c0.71,0.71,0.35,2.6,0.12,3.55c0.83,0.95,1.3,2.01,1.3,3.07c0,2.6-1.89,4.49-5.67,4.96c1.06,0.59,1.89,2.13,1.89,3.31v2.6c0,0.12,0,0.12,0,0.24c4.49-1.54,7.8-5.91,7.8-10.99C23.46,5.8,18.26,0.6,11.88,0.6z',
34 | stroke: false,
35 | rel: 'me',
36 | },
37 | {
38 | url: 'https://linkedin.com/in/Zemerik',
39 | title: 'LinkedIn',
40 | icon: 'M21.4,0.64H2.72c-1.14,0-2.02,0.88-2.02,2.02v18.55c0,1.26,0.88,2.15,2.02,2.15h18.55c1.14,0,2.02-0.88,2.02-2.02V2.66C23.42,1.52,22.53,0.64,21.4,0.64z M7.89,19.19H4.86V9.48h3.03C7.89,9.48,7.89,19.19,7.89,19.19z M6.38,8.09c-1.01,0-1.77-0.76-1.77-1.77s0.76-1.89,1.77-1.89s1.77,0.76,1.77,1.77S7.26,8.09,6.38,8.09z M19.25,19.19h-3.03v-4.67c0-1.14,0-2.65-1.64-2.65s-1.77,1.26-1.77,2.52v4.8H9.79V9.48h2.9v1.26l0,0c0.38-0.76,1.39-1.64,2.9-1.64c3.03,0,3.66,2.02,3.66,4.67C19.25,13.89,19.25,19.19,19.25,19.19z',
41 | stroke: false,
42 | rel: '',
43 | },
44 | ];
45 |
--------------------------------------------------------------------------------
/src/components/donut-chart-tags.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { data, dataLength } = Astro.props;
3 |
4 | import colors from '../utils/colors';
5 | import { formatSlug } from '../utils/format-slug';
6 |
7 | const chartSize = 100;
8 | const chartData = data.sort((a, b) => b.total - a.total).slice(0, 5);
9 | const max = chartData.reduce((a, b) => a + b.total, 0);
10 |
11 | const convertToPercent = (num) => Math.round((num / max) * 100);
12 | const convertToDegrees = (num) => Math.round((num / 100) * 360);
13 |
14 | const gradient = chartData
15 | .reduce((items, item, index, array) => {
16 | items.push(item);
17 |
18 | item.count = item.count || 0;
19 | item.count += array[index - 1]?.count || item.count;
20 | item.start_value = array[index - 1]?.count ? array[index - 1].count : 0;
21 | item.end_value = item.count += item.total;
22 | item.start_percent = convertToPercent(item.start_value);
23 | item.end_percent = convertToPercent(item.end_value);
24 | item.start_degrees = convertToDegrees(item.start_percent);
25 | item.end_degrees = convertToDegrees(item.end_percent);
26 |
27 | return items;
28 | }, [])
29 | .map((chart, index) => {
30 | const { start_degrees, end_degrees } = chart;
31 | return ` var(--color-brand-${colors[index]}) ${start_degrees}deg ${end_degrees}deg`;
32 | })
33 | .join();
34 | ---
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | Tags Analytics
43 | {`Displaying ${chartData.length} of ${dataLength}`}
46 |
47 |
53 |
54 |
55 |
56 |
57 |
58 | {
59 | chartData.map((item, index) => {
60 | const { tag, total } = item;
61 |
62 | return (
63 |
64 |
65 |
66 | {tag}
67 |
68 | {`x${total}`}
69 |
70 | );
71 | })
72 | }
73 |
74 |
75 |
--------------------------------------------------------------------------------
/src/pages/tags/[tag]/og.png.ts:
--------------------------------------------------------------------------------
1 | export const prerender = true;
2 |
3 | import { ImageResponse, html } from 'og-img';
4 | import fs from 'fs';
5 | import path from 'path';
6 |
7 | import { collections } from '../../../utils/all-collections';
8 | import { createTagsCollection } from '../../../utils/create-tags-collection';
9 |
10 | export async function GET({ props }) {
11 | const { name, collection } = props;
12 |
13 | return new ImageResponse(
14 | html`
15 |
16 |
17 |
18 |
21 |
22 | Tagged with ${name}
23 |
24 |
25 | Here you'll find ${collection.length} all developers
26 | about ${name} .
27 |
28 |
29 |
ZemProfiles
30 |
|
31 |
32 | ${`zemprofiles.vercel.app/tags/${name}`}
33 |
34 |
35 |
36 |
`,
37 | {
38 | width: 1200,
39 | height: 600,
40 | fonts: [
41 | {
42 | name: 'Roboto Regular',
43 | data: fs.readFileSync(path.resolve('./public/fonts/Roboto-Regular.ttf')),
44 | weight: 400,
45 | style: 'normal',
46 | },
47 | {
48 | name: 'Inconsolata Bold',
49 | data: fs.readFileSync(path.resolve('./public/fonts/Inconsolata-Bold.ttf')),
50 | weight: 600,
51 | style: 'normal',
52 | },
53 | {
54 | name: 'Inconsolata Black',
55 | data: fs.readFileSync(path.resolve('./public/fonts/Inconsolata-Black.ttf')),
56 | weight: 900,
57 | style: 'normal',
58 | },
59 | ],
60 | }
61 | );
62 | }
63 |
64 | export async function getStaticPaths() {
65 | const tags = createTagsCollection(collections);
66 |
67 | return tags.map((tag: { name: string; slug: string }) => {
68 | const { name, slug } = tag;
69 |
70 | return {
71 | params: {
72 | tag: slug,
73 | },
74 | props: {
75 | name: name,
76 | collection: collections.filter((item) => item.data.tags.includes(name)),
77 | },
78 | };
79 | });
80 | }
81 |
--------------------------------------------------------------------------------
/src/components/profile-card.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import { Image } from 'astro:assets';
3 | import ClickToCopyEmail from './click-to-copy-email';
4 |
5 | const locations = [
6 | // {
7 | // name: 'United Kingdom',
8 | // flag: '🇬🇧',
9 | // current: true,
10 | // },
11 | // {
12 | // name: 'Panama City, Panama',
13 | // flag: '🇵🇦',
14 | // current: true,
15 | // },
16 | // {
17 | // name: 'Medellín, Colombia',
18 | // flag: '🇨🇴',
19 | // current: false,
20 | // },
21 | // {
22 | // name: 'Los Angeles, USA',
23 | // flag: '🇺🇲',
24 | // current: false,
25 | // },
26 | // {
27 | // name: 'New Orleans, USA',
28 | // flag: '🇺🇲',
29 | // current: false,
30 | // },
31 | // {
32 | // name: 'Montreal, Canada',
33 | // flag: '🇨🇦',
34 | // current: false,
35 | // },
36 | // {
37 | // name: 'Toronto, Canada',
38 | // flag: '🇨🇦',
39 | // current: false,
40 | // },
41 | ];
42 | ---
43 |
44 |
45 |
52 |
53 |
54 |
55 | HEMANG YADAV
56 |
57 |
58 |
FOUNDER + MAINTAINER
59 |
60 |
💻Passionate Developer + 💪Expertise in Web-Development + 🎓Open-Source Enthusiast + 🏆Content Creator
61 |
62 |
80 |
81 |
82 |
83 |
89 |
96 | Zemerik_X
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/src/components/collections-list.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import { Image } from 'astro:assets';
3 | import AstroImage from './astro-image.astro';
4 |
5 | import NewLabel from './new-label';
6 | import TagsList from './tags-list.astro';
7 |
8 | import { formatDate } from '../utils/format-date';
9 | import { createExcerpt } from '../utils/create-excerpt';
10 |
11 | const { collections, slice, highlighted } = Astro.props;
12 | ---
13 |
14 |
15 | {
16 | collections
17 | .sort((a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime())
18 | .slice(0, slice || collections.length)
19 | .filter((item) => item.data.draft !== true)
20 | .map((collection) => {
21 | const {
22 | slug,
23 | data: { base, featuredImage, logo, publication, title, date, tags },
24 | } = collection;
25 |
26 | const excerpt = collection.body ? createExcerpt(collection.body) : '';
27 | const isGhost = base === 'ghosts';
28 |
29 | return (
30 |
33 |
76 |
77 | );
78 | })
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/src/components/happy-all-cities.tsx:
--------------------------------------------------------------------------------
1 | import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik';
2 | import { formatNumber } from '../utils/format-number';
3 |
4 | import Loading from './loading';
5 |
6 | interface Props {
7 | period: number;
8 | }
9 |
10 | const HappyAllCities = component$(({ period }) => {
11 | const data = useSignal(null);
12 |
13 | useVisibleTask$(async () => {
14 | try {
15 | const response = await fetch('/api/happy-by-city', {
16 | method: 'POST',
17 | body: JSON.stringify({ period: period }),
18 | });
19 |
20 | if (response.status !== 200) {
21 | throw new Error();
22 | }
23 |
24 | const result = await response.json();
25 |
26 | data.value = result.data;
27 | } catch (error) {
28 | console.error(error);
29 | }
30 | });
31 |
32 | return (
33 |
34 |
35 |
36 | {data.value ? (
37 | <>
38 | {data.value.length ? (
39 |
40 |
41 |
42 |
43 | City
44 | Country
45 | Total
46 |
47 |
48 |
49 | {data.value.map((row, index) => {
50 | const { city, country, flag, total } = row;
51 | return (
52 |
53 |
54 |
62 |
63 | {city}
64 |
65 |
66 |
67 | {flag}
68 | {country}
69 |
70 | {`x${formatNumber(total)}`}
71 |
72 | );
73 | })}
74 |
75 |
76 |
77 | ) : (
78 |
79 | No happy cities to display
80 |
81 | )}
82 | >
83 | ) : (
84 |
85 |
86 |
87 | )}
88 |
89 |
90 |
91 | );
92 | });
93 |
94 | export default HappyAllCities;
95 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ZemProfiles
15 |
16 |
17 |
18 | Discover & Connect with Developers
19 |
20 |
21 |
22 |
23 |
24 |
25 | ## ➕ Adding your Profile:
26 |
27 | 1. Fork a copy of this Repository on your Github account by clicking below,
28 |
29 | - [Fork](https://github.com/Zemerik/ZemProfiles/fork)
30 |
31 | 2. Clone your Forked Repository by using the following `GIT` command:
32 |
33 | ```bash
34 | git clone https://github.com/[YOUR GITHUB USERNAME]/ZemProfiles.git
35 | ```
36 |
37 | 3. Navigate into the Project's `Directory` by using the command below:
38 |
39 | ```bash
40 | cd ZemProfiles
41 | ```
42 |
43 | 4. Initialize a Remote to the original Repository by the following `GIT` command:
44 |
45 | ```bash
46 | git remote add upstream https://github.com/Zemerik/ZemProfiles
47 | ```
48 |
49 | 5. Create a new `branch` in which you can make your desired changes:
50 |
51 | ```bash
52 | git checkout -b newprofile
53 | ```
54 |
55 | 6. Create a new file in the `src/content/profiles` directory and name it `[YOUR GITHUB USERNAME].mdx`
56 |
57 | 
58 |
59 | 7. After Creating the file, paste the code snippet below and enter **Your** Details:
60 |
61 | ```md
62 | ---
63 | base: posts
64 | title: Your Name
65 | tags: [Skill 1, Skill 2, Skill 3, ...]
66 | date: Today's Date
67 | author: Name / Github Username
68 | featuredImage: Image address of your Profile Picture
69 | ---
70 |
71 | Add a short description of yourself here
72 |
73 |
74 | Customize your Profile Post as you like using Markdown or HTML here.
75 |
76 | ```
77 |
78 | > [!Tip]
79 | > You can refer to `zemerik.mdx` file for help or inspiration if required.
80 |
81 | 
82 |
83 | 8. After you are happy with your Profile Post, add all your files to the Staging Area:
84 |
85 | ```bash
86 | git add --all
87 | ```
88 |
89 | 9. Commit your Changes:
90 |
91 | ```bash
92 | git commit -m "Profile Addition: [Your Name]"
93 | ```
94 |
95 | > [!Note]
96 | > Remember to have a good commit message!
97 |
98 | 10. Push all your Changes:
99 |
100 | ```bash
101 | git push origin newprofile
102 | ```
103 |
104 | 11. Create a new Pull - Request on the Original Repository
105 |
106 | > Your Pull Request will be merged / reviewed as soon as possible
107 |
108 | - > Don't Forget to Check out [ZemShowcase](https://github.com/Zemerik/ZemShowcase) & [ZemPosts](https://github.com/Zemerik/ZemPosts)
109 |
110 | ## 🐞Bug/Issue/Feedback/Feature Request:
111 |
112 | - If you would like to report a bug, a issue, implement any feedack, or request any feature, you are free to do so by opening a issue on this repository. Remember to give a detailed explanation of what you are trying to say, and how it will help the website.
113 |
114 | ## 💁 Support:
115 |
116 | For any kind of support or inforrmation, you are free to join our **Discord Server**,
117 |
118 |
119 |
120 |
121 |
122 |
123 | Thanks for Visiting🙏
124 |
125 |
126 |
127 | Don't forget to leave a ⭐
128 |
129 | Made with 💖 by Hemang Yadav (Zemerik)
130 |
131 |
--------------------------------------------------------------------------------
/src/layouts/main.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import Layout from './layout';
3 | import { search } from '../utils/all-collections';
4 |
5 | import '@fontsource/inconsolata/300.css';
6 | import '@fontsource/inconsolata/400.css';
7 | import '@fontsource/inconsolata/500.css';
8 | import '@fontsource/inconsolata/700.css';
9 | import '@fontsource/inconsolata/900.css';
10 |
11 | const name = 'ZemProfiles';
12 | const siteUrl = 'https://zemprofiles.vercel.app';
13 | const keywords = [
14 | 'Developer Advocate',
15 | 'Technical Writing',
16 | 'Product Marketing'
17 | ];
18 |
19 | const { type, title, description, slug, image, tags, fullWidth = false, canonical } = Astro.props;
20 |
21 | const htmlTitle = `${name} | ${title}`;
22 | const canonicalHref = canonical ? canonical : `${siteUrl}${slug}`;
23 |
24 | const ogImage = image ? image : `${siteUrl}`;
25 | const seoKeywords = tags ? tags : keywords;
26 |
27 | const isProduction = import.meta.env.PROD;
28 | ---
29 |
30 |
31 |
32 |
33 |
34 |
35 | {htmlTitle}
36 |
37 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | {
75 | isProduction ? (
76 |
77 |
86 | ) : null
87 | }
88 |
89 |
90 | {
91 | isProduction ? (
92 |
100 | ) : null
101 | }
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/src/components/search-modal.tsx:
--------------------------------------------------------------------------------
1 | import { component$, useSignal, $, useVisibleTask$ } from '@builder.io/qwik';
2 |
3 | import SearchInput from './search-input';
4 |
5 | import { formatDate } from '../utils/format-date';
6 |
7 | interface searchProps {
8 | date: string;
9 | title: string;
10 | base: string;
11 | path: string;
12 | }
13 |
14 | interface Props {
15 | search: searchProps[];
16 | isModalOpen: Boolean;
17 | handleModal: () => void;
18 | }
19 |
20 | const SearchModal = component$(({ search, isModalOpen, handleModal }) => {
21 | const all = useSignal(search);
22 | const filtered = useSignal(search);
23 |
24 | const handleBackdrop = $((event) => {
25 | if (event.target.localName === 'dialog') {
26 | handleModal();
27 | }
28 | });
29 |
30 | const handleInput = $(async (event) => {
31 | const FuseModule = await import('fuse.js');
32 | const Fuse = FuseModule.default;
33 |
34 | const {
35 | target: { value },
36 | } = event;
37 |
38 | const fuse = new Fuse(all.value, {
39 | threshold: 0.5,
40 | keys: ['title', 'date'],
41 | });
42 |
43 | const results = fuse.search(value).map((data: any) => {
44 | const {
45 | item: { base, path, title, date },
46 | } = data;
47 |
48 | return {
49 | title,
50 | date,
51 | path,
52 | base,
53 | };
54 | });
55 |
56 | if (value) {
57 | filtered.value = results;
58 | } else {
59 | filtered.value = all.value;
60 | }
61 | });
62 |
63 | useVisibleTask$(({ track }) => {
64 | track(() => isModalOpen);
65 | if (isModalOpen) {
66 | document.getElementById('input').focus();
67 | document.body.classList.add('overflow-hidden');
68 | } else {
69 | document.body.classList.remove('overflow-hidden');
70 | filtered.value = all.value;
71 | }
72 | });
73 |
74 | return (
75 | <>
76 | {isModalOpen ? (
77 |
81 |
82 |
83 |
{`${
84 | filtered.value.length > 0 ? filtered.value.length : 0
85 | } results`}
86 |
119 |
120 |
121 | ) : null}
122 | >
123 | );
124 | });
125 |
126 | export default SearchModal;
127 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | ZemProfiles
16 |
17 |
18 |
19 | Discover & Connect with Developers
20 |
21 |
22 |
23 |
24 |
25 |
26 | ## ❗About:
27 |
28 | ZemProfiles stands as an open-source platform, providing users with the opportunity to connect seamlessly with fellow developers. This connectivity is fostered through the simple act of adding one's Profile to the platform, thus creating a digital hub where like-minded individuals can engage, collaborate, and share insights within the expansive realm of software development. With its user-friendly interface and inclusive community ethos, ZemProfiles serves as a dynamic space where connections are forged, ideas are exchanged, and innovation thrives.
29 |
30 | - > Read out Official Docs on [ZemDocs](https://zemdocs.vercel.app/en/zemprofiles/introduction)
31 |
32 | ## 🎥 Youtube Video:
33 |
34 | - Feel free to watch our Youtube Video by clicking below 👇
35 |
36 |
37 |
38 | [](https://www.youtube.com/watch?v=5XyGaH9f0wA)
39 |
40 |
41 |
42 |
43 | ## ⭐ Features:
44 |
45 | - User Friendly UI/UX
46 | - Customizable Profile Post
47 | - Use markdown or html for styling
48 | - Search for Developers using Tags
49 | - List of all Developers
50 | - Profile Card for Maintainers
51 |
52 | Want to see any other features? Open an [issue](https://github.com/Zemerik/ZemProfiles/issues) and let us know!
53 |
54 | ## 💬 Fonts:
55 |
56 | - [x] Inconsolata-Black
57 | - [x] Inconsolata-Black
58 | - [x] Roboto-Regular
59 |
60 | ## 🏃♂️ Locally Running:
61 |
62 | - This project can be locally executed on your machine in 4 simple steps!
63 |
64 | > [!Tip]
65 | > [NodeJS](https://nodejs.org/) needs to be installed on your machine.
66 |
67 |
68 | 1. Make a `Copy` of this Repository on your machine by using the following `git command` in your terminal:
69 |
70 | ```
71 | git clone https://github.com/Zemerik/ZemProfiles
72 | ```
73 |
74 | 2. `Navigate` into the Project's `directory` by entering the following `command` in your terminal:
75 |
76 | ```
77 | cd ZemProfiles
78 | ```
79 |
80 | 3. `Install` the required `Dependencies` by using `NPM`:
81 |
82 | ```nodejs
83 | npm i
84 | ```
85 |
86 | 4. Start the `Development Server` through the following `command`:
87 |
88 | ```nodejs
89 | npm run dev
90 | ```
91 |
92 | ## 🚀 Project Structure
93 |
94 | ```text
95 | ├── public/
96 | │ ├── fonts/
97 | │ └── images/
98 | ├── src/
99 | │ ├── components/
100 | │ ├── content/
101 | │ ├── layouts/
102 | │ └── pages/
103 | │ └── services/
104 | │ └── util/
105 | ├── .gitignore
106 | ├── astro.config.mjs
107 | ├── CODE_OF_CONDUCT.md
108 | ├── CONTRIBUTING.md
109 | ├── LICENCE
110 | ├── package-lock.json
111 | ├── package.json
112 | ├── README.md
113 | ├── SECURITY.md
114 | ├── tailwind.config.cjs
115 | ├── yarn.lock
116 | └── tsconfig.json
117 | ```
118 |
119 | ## 🤝 Contributing:
120 |
121 | Contributions are always welcome and appreciated! **Kindly visit the [CONTRIBUTING.md](https://github.com/Zemerik/ZemProfiles/blob/main/CONTRIBUTING.md) file for more information**
122 |
123 |
124 | ## 💁 Support:
125 |
126 | For any kind of support or inforrmation, you are free to join our **Discord Server**,
127 |
128 |
129 |
130 |
131 |
132 | ## 🥳 Contributers:
133 |
134 | Thanks to all Contributers!
135 |
136 | 
137 |
138 |
139 | Thanks for Visiting🙏
140 |
141 |
142 |
143 | Don't forget to leave a ⭐
144 |
145 | Made with 💖 by Hemang Yadav (Zemerik)
146 |
147 |
--------------------------------------------------------------------------------
/src/pages/dashboard.astro:
--------------------------------------------------------------------------------
1 | ---
2 | export const prerender = false;
3 |
4 | import Main from '../layouts/main.astro';
5 |
6 | import Aside from '../components/aside.astro';
7 | import ProfileCard from '../components/profile-card.astro';
8 | import ListPopular from '../components/list-popular.astro';
9 | import DonutChartTags from '../components/donut-chart-tags.astro';
10 | import PoweredByMdx from '../components/powered-by-mdx.astro';
11 | import HappyAllCities from '../components/happy-all-cities';
12 |
13 | let analyticsData = null;
14 | let reactionsData = null;
15 | const period = 30;
16 |
17 | ---
18 |
19 |
20 | Dashboard
21 | Built-in Analytics
22 |
23 | The data visualizations on this page have been created using data from local MDX files and a custom web analytics
24 | solution powered by Vercel Edge Functions and a Neon Serverless Postgres database. The recent GitHub activity list
25 | has been created by using the GitHub REST API.
26 |
27 |
28 | {
29 | analyticsData && reactionsData ? (
30 | <>
31 |
32 | Totals by Year and Month
33 | All content
34 |
35 |
36 |
37 | Totals by Year and Day
38 | All content
39 |
40 |
41 |
42 |
43 | Totals by reaction
44 | Recent reactions
45 |
46 |
47 | Totals by Tag
48 | Recent tags
49 |
51 |
52 |
53 |
54 |
55 |
56 | Totals by publisher
57 | All publishers
58 |
59 |
60 |
61 | Totals by site visits
62 | Recent site visits
63 |
64 |
65 |
66 | Totals by referrer
67 | Top Ten referrers
68 |
69 |
70 |
71 |
72 |
73 |
Totals by city
74 |
Recent city visits
75 |
76 |
77 |
78 | Location visualization
79 | Recent geolocation visits
80 |
84 |
85 |
86 |
87 |
88 | Happiest Cities
89 | Top ten happiest cities
90 |
91 |
92 |
93 |
94 | Popular Posts
95 | Top Ten Post views
96 |
98 |
99 |
100 |
101 | Popular Articles
102 | Top Ten Article views
103 |
105 |
106 | >
107 | ) : null
108 | }
109 |
110 |
111 | GtiHub Activity
112 | Recent GitHub events
113 |
114 |
115 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributor Covenant Code of Conduct
3 |
4 | ## Our Pledge
5 |
6 | We as members, contributors, and leaders pledge to make participation in our
7 | community a harassment-free experience for everyone, regardless of age, body
8 | size, visible or invisible disability, ethnicity, sex characteristics, gender
9 | identity and expression, level of experience, education, socio-economic status,
10 | nationality, personal appearance, race, religion, or sexual identity
11 | and orientation.
12 |
13 | We pledge to act and interact in ways that contribute to an open, welcoming,
14 | diverse, inclusive, and healthy community.
15 |
16 | ## Our Standards
17 |
18 | Examples of behavior that contributes to a positive environment for our
19 | community include:
20 |
21 | * Demonstrating empathy and kindness toward other people
22 | * Being respectful of differing opinions, viewpoints, and experiences
23 | * Giving and gracefully accepting constructive feedback
24 | * Accepting responsibility and apologizing to those affected by our mistakes,
25 | and learning from the experience
26 | * Focusing on what is best not just for us as individuals, but for the
27 | overall community
28 |
29 | Examples of unacceptable behavior include:
30 |
31 | * The use of sexualized language or imagery, and sexual attention or
32 | advances of any kind
33 | * Trolling, insulting or derogatory comments, and personal or political attacks
34 | * Public or private harassment
35 | * Publishing others' private information, such as a physical or email
36 | address, without their explicit permission
37 | * Other conduct which could reasonably be considered inappropriate in a
38 | professional setting
39 |
40 | ## Enforcement Responsibilities
41 |
42 | Community leaders are responsible for clarifying and enforcing our standards of
43 | acceptable behavior and will take appropriate and fair corrective action in
44 | response to any behavior that they deem inappropriate, threatening, offensive,
45 | or harmful.
46 |
47 | Community leaders have the right and responsibility to remove, edit, or reject
48 | comments, commits, code, wiki edits, issues, and other contributions that are
49 | not aligned to this Code of Conduct, and will communicate reasons for moderation
50 | decisions when appropriate.
51 |
52 | ## Scope
53 |
54 | This Code of Conduct applies within all community spaces, and also applies when
55 | an individual is officially representing the community in public spaces.
56 | Examples of representing our community include using an official e-mail address,
57 | posting via an official social media account, or acting as an appointed
58 | representative at an online or offline event.
59 |
60 | ## Enforcement
61 |
62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
63 | reported to the community leaders responsible for enforcement at
64 | zemerikY@gmail.com.
65 | All complaints will be reviewed and investigated promptly and fairly.
66 |
67 | All community leaders are obligated to respect the privacy and security of the
68 | reporter of any incident.
69 |
70 | ## Enforcement Guidelines
71 |
72 | Community leaders will follow these Community Impact Guidelines in determining
73 | the consequences for any action they deem in violation of this Code of Conduct:
74 |
75 | ### 1. Correction
76 |
77 | **Community Impact**: Use of inappropriate language or other behavior deemed
78 | unprofessional or unwelcome in the community.
79 |
80 | **Consequence**: A private, written warning from community leaders, providing
81 | clarity around the nature of the violation and an explanation of why the
82 | behavior was inappropriate. A public apology may be requested.
83 |
84 | ### 2. Warning
85 |
86 | **Community Impact**: A violation through a single incident or series
87 | of actions.
88 |
89 | **Consequence**: A warning with consequences for continued behavior. No
90 | interaction with the people involved, including unsolicited interaction with
91 | those enforcing the Code of Conduct, for a specified period of time. This
92 | includes avoiding interactions in community spaces as well as external channels
93 | like social media. Violating these terms may lead to a temporary or
94 | permanent ban.
95 |
96 | ### 3. Temporary Ban
97 |
98 | **Community Impact**: A serious violation of community standards, including
99 | sustained inappropriate behavior.
100 |
101 | **Consequence**: A temporary ban from any sort of interaction or public
102 | communication with the community for a specified period of time. No public or
103 | private interaction with the people involved, including unsolicited interaction
104 | with those enforcing the Code of Conduct, is allowed during this period.
105 | Violating these terms may lead to a permanent ban.
106 |
107 | ### 4. Permanent Ban
108 |
109 | **Community Impact**: Demonstrating a pattern of violation of community
110 | standards, including sustained inappropriate behavior, harassment of an
111 | individual, or aggression toward or disparagement of classes of individuals.
112 |
113 | **Consequence**: A permanent ban from any sort of public interaction within
114 | the community.
115 |
116 | ## Attribution
117 |
118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119 | version 2.0, available at
120 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
121 |
122 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
123 | enforcement ladder](https://github.com/mozilla/diversity).
124 |
125 | [homepage]: https://www.contributor-covenant.org
126 |
127 | For answers to common questions about this code of conduct, see the FAQ at
128 | https://www.contributor-covenant.org/faq. Translations are available at
129 | https://www.contributor-covenant.org/translations.
130 |
--------------------------------------------------------------------------------
/src/components/line-chart-years.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { data } = Astro.props;
3 | import colors from '../utils/colors';
4 | import months from '../utils/months';
5 | import years from '../utils/years';
6 |
7 | const totalByYearAndMonth = Object.keys(data).reduce((acc, year) => {
8 | const groupedByYear = data[year];
9 | Object.keys(groupedByYear).forEach((month) => {
10 | const monthCount = groupedByYear[month].length;
11 |
12 | if (!acc[year]) {
13 | acc[year] = [];
14 | }
15 |
16 | acc[year].push({
17 | month: month,
18 | total: monthCount,
19 | });
20 | });
21 |
22 | // Add months with 0 count
23 | months.forEach((month) => {
24 | if (!acc[year].some((item) => item.month === month)) {
25 | acc[year].push({
26 | month: month,
27 | total: 0,
28 | });
29 | }
30 | });
31 | return acc;
32 | }, {});
33 |
34 | const chartWidth = 600;
35 | const chartHeight = 300;
36 | const offsetY = 40;
37 | const paddingX = 50;
38 | const paddingY = 50;
39 |
40 | const maxY = Math.max(
41 | ...Object.values(totalByYearAndMonth).flatMap((yearData: any) => yearData.map((month) => month.total))
42 | );
43 | const guides = [...Array(8).keys()];
44 |
45 | const properties = Object.values(totalByYearAndMonth).map((property: any) => {
46 | return {
47 | total: property.reduce((items, item) => items + item.total, 0),
48 | data: property
49 | .sort((a, b) => months.indexOf(a.month) - months.indexOf(b.month))
50 | .map((entry, index) => {
51 | const { total } = entry;
52 |
53 | const x = (index / months.length) * chartWidth + paddingX / 2;
54 | const y = chartHeight - offsetY - (total / maxY) * (chartHeight - (paddingY + offsetY)) - paddingY + offsetY;
55 |
56 | return {
57 | total: total,
58 | x: x,
59 | y: y,
60 | };
61 | }),
62 | };
63 | });
64 |
65 | const points = properties.map((point): any => {
66 | return point.data.map((p) => {
67 | const { x, y } = p;
68 | return `${x},${y}`;
69 | });
70 | });
71 |
72 | const ticks = months.map((month, index) => {
73 | const x = (index / months.length) * chartWidth + paddingX / 2;
74 | return {
75 | month: month,
76 | x: x,
77 | };
78 | });
79 | ---
80 |
81 |
107 |
108 |
109 |
110 | {
111 | guides.map((_, index) => {
112 | const ratio = index / guides.length;
113 | const y = chartHeight - offsetY - chartHeight * ratio;
114 |
115 | return (
116 |
122 | );
123 | })
124 | }
125 | {
126 | points.map((point, index) => {
127 | return (
128 |
134 | );
135 | })
136 | }
137 | {
138 | properties.map((property, index) => {
139 | return property.data.map((p) => {
140 | const { total, x, y } = p;
141 |
142 | return (
143 |
144 |
151 | {total > 0 ? (
152 |
159 | {`x${total}`}
160 |
161 | ) : null}
162 |
163 | );
164 | });
165 | })
166 | }
167 | {
168 | ticks.map((tick) => {
169 | const { month, x } = tick;
170 |
171 | return (
172 |
179 | {month}
180 |
181 | );
182 | })
183 | }
184 |
185 |
186 |
187 | {
188 | years.map((year: string, index: number) => {
189 | return (
190 |
191 |
195 | {year}
196 |
197 |
198 | );
199 | })
200 | }
201 |
202 |
203 |
208 |
--------------------------------------------------------------------------------
/src/components/bar-chart-days.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const { data } = Astro.props;
3 | import colors from '../utils/colors';
4 | import days from '../utils/days';
5 | import years from '../utils/years';
6 |
7 | const totalByDayAndYear = Object.keys(data).reduce((acc, day) => {
8 | const groupedByDay = data[day];
9 |
10 | Object.keys(groupedByDay).forEach((year) => {
11 | const yearCount = groupedByDay[year].length;
12 |
13 | if (!acc[day]) {
14 | acc[day] = [];
15 | }
16 |
17 | acc[day].push({
18 | day: day,
19 | year: year,
20 | total: yearCount,
21 | });
22 | });
23 |
24 | // Add years with 0 count
25 | years.forEach((year) => {
26 | if (!acc[day].some((item) => item.year === year)) {
27 | acc[day].push({
28 | day: day,
29 | year: year,
30 | total: 0,
31 | });
32 | }
33 | });
34 |
35 | acc[day].sort((a, b) => a.year - b.year);
36 |
37 | return acc;
38 | }, {});
39 |
40 | const dayOrder = [...days.slice(1), 'Sun'];
41 |
42 | const totalByDayAndYearOrdered = dayOrder.reduce((result, day) => {
43 | result[day] = totalByDayAndYear[day];
44 | return result;
45 | }, {});
46 |
47 | const chartWidth = 600;
48 | const chartHeight = 300;
49 | const barWidth = 10;
50 | const barGap = 3;
51 | const offsetY = 40;
52 | const paddingX = 30;
53 | const paddingY = 50;
54 | const maxY = Math.max(
55 | ...Object.values(totalByDayAndYearOrdered).flatMap((yearData: any) => yearData.map((year) => year.total))
56 | );
57 |
58 | const guides = [...Array(8).keys()];
59 |
60 | const properties = Object.values(totalByDayAndYearOrdered).map((property: any, index: number) => {
61 | const x = (index / days.length) * chartWidth + paddingX / 2;
62 | const day = property[0].day;
63 |
64 | const data = property
65 | .sort((a, b) => years.indexOf(a.year) - years.indexOf(b.year))
66 | .map((entry, i) => {
67 | const { day, total } = entry;
68 | const height =
69 | chartHeight - offsetY - (total / maxY) * (chartHeight - (paddingY + offsetY)) - paddingY + offsetY * 2;
70 | const y = chartHeight - offsetY;
71 | return {
72 | day: day,
73 | year: years[i],
74 | total: total,
75 | height: total > 0 ? chartHeight - height : 1,
76 | x: x + (barWidth + barGap) * i,
77 | y: y,
78 | };
79 | });
80 |
81 | return {
82 | day: day,
83 | x: x,
84 | data: data,
85 | };
86 | });
87 |
88 | const ticks = dayOrder.map((day, index) => {
89 | const x = (index / days.length) * chartWidth + paddingX / 2;
90 | return {
91 | day: day,
92 | x: x,
93 | };
94 | });
95 | ---
96 |
97 |
124 |
125 |
126 |
127 | {
128 | guides.map((_, index) => {
129 | const ratio = index / guides.length;
130 | const y = chartHeight - offsetY - chartHeight * ratio;
131 |
132 | return (
133 |
139 | );
140 | })
141 | }
142 |
143 | {
144 | properties.map((property) => {
145 | const { x, data } = property;
146 |
147 | return (
148 |
149 | {data.map((d, index) => {
150 | const { x, y, height, total, day } = d;
151 | const _y = y - height;
152 |
153 | return (
154 |
155 |
165 | {total > 0 ? (
166 |
173 | {`x${total}`}
174 |
175 | ) : null}
176 |
177 | );
178 | })}
179 |
180 | );
181 | })
182 | }
183 |
184 | {
185 | ticks.map((tick) => {
186 | const { day, x } = tick;
187 |
188 | return (
189 |
196 | {day}
197 |
198 | );
199 | })
200 | }
201 |
202 |
203 |
204 | {
205 | years.map((year: string, index: number) => {
206 | return (
207 |
208 |
212 | {year}
213 |
214 |
215 | );
216 | })
217 | }
218 |
219 |
--------------------------------------------------------------------------------
/.astro/types.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'astro:content' {
2 | interface Render {
3 | '.mdx': Promise<{
4 | Content: import('astro').MarkdownInstance<{}>['Content'];
5 | headings: import('astro').MarkdownHeading[];
6 | remarkPluginFrontmatter: Record;
7 | }>;
8 | }
9 | }
10 |
11 | declare module 'astro:content' {
12 | interface Render {
13 | '.md': Promise<{
14 | Content: import('astro').MarkdownInstance<{}>['Content'];
15 | headings: import('astro').MarkdownHeading[];
16 | remarkPluginFrontmatter: Record;
17 | }>;
18 | }
19 | }
20 |
21 | declare module 'astro:content' {
22 | type Flatten = T extends { [K: string]: infer U } ? U : never;
23 |
24 | export type CollectionKey = keyof AnyEntryMap;
25 | export type CollectionEntry = Flatten;
26 |
27 | export type ContentCollectionKey = keyof ContentEntryMap;
28 | export type DataCollectionKey = keyof DataEntryMap;
29 |
30 | type AllValuesOf = T extends any ? T[keyof T] : never;
31 | type ValidContentEntrySlug = AllValuesOf<
32 | ContentEntryMap[C]
33 | >['slug'];
34 |
35 | /** @deprecated Use `getEntry` instead. */
36 | export function getEntryBySlug<
37 | C extends keyof ContentEntryMap,
38 | E extends ValidContentEntrySlug | (string & {}),
39 | >(
40 | collection: C,
41 | // Note that this has to accept a regular string too, for SSR
42 | entrySlug: E,
43 | ): E extends ValidContentEntrySlug
44 | ? Promise>
45 | : Promise | undefined>;
46 |
47 | /** @deprecated Use `getEntry` instead. */
48 | export function getDataEntryById(
49 | collection: C,
50 | entryId: E,
51 | ): Promise>;
52 |
53 | export function getCollection>(
54 | collection: C,
55 | filter?: (entry: CollectionEntry) => entry is E,
56 | ): Promise;
57 | export function getCollection(
58 | collection: C,
59 | filter?: (entry: CollectionEntry) => unknown,
60 | ): Promise[]>;
61 |
62 | export function getEntry<
63 | C extends keyof ContentEntryMap,
64 | E extends ValidContentEntrySlug | (string & {}),
65 | >(entry: {
66 | collection: C;
67 | slug: E;
68 | }): E extends ValidContentEntrySlug
69 | ? Promise>
70 | : Promise | undefined>;
71 | export function getEntry<
72 | C extends keyof DataEntryMap,
73 | E extends keyof DataEntryMap[C] | (string & {}),
74 | >(entry: {
75 | collection: C;
76 | id: E;
77 | }): E extends keyof DataEntryMap[C]
78 | ? Promise
79 | : Promise | undefined>;
80 | export function getEntry<
81 | C extends keyof ContentEntryMap,
82 | E extends ValidContentEntrySlug | (string & {}),
83 | >(
84 | collection: C,
85 | slug: E,
86 | ): E extends ValidContentEntrySlug
87 | ? Promise>
88 | : Promise | undefined>;
89 | export function getEntry<
90 | C extends keyof DataEntryMap,
91 | E extends keyof DataEntryMap[C] | (string & {}),
92 | >(
93 | collection: C,
94 | id: E,
95 | ): E extends keyof DataEntryMap[C]
96 | ? Promise
97 | : Promise | undefined>;
98 |
99 | /** Resolve an array of entry references from the same collection */
100 | export function getEntries(
101 | entries: {
102 | collection: C;
103 | slug: ValidContentEntrySlug;
104 | }[],
105 | ): Promise[]>;
106 | export function getEntries(
107 | entries: {
108 | collection: C;
109 | id: keyof DataEntryMap[C];
110 | }[],
111 | ): Promise[]>;
112 |
113 | export function reference(
114 | collection: C,
115 | ): import('astro/zod').ZodEffects<
116 | import('astro/zod').ZodString,
117 | C extends keyof ContentEntryMap
118 | ? {
119 | collection: C;
120 | slug: ValidContentEntrySlug;
121 | }
122 | : {
123 | collection: C;
124 | id: keyof DataEntryMap[C];
125 | }
126 | >;
127 | // Allow generic `string` to avoid excessive type errors in the config
128 | // if `dev` is not running to update as you edit.
129 | // Invalid collection names will be caught at build time.
130 | export function reference(
131 | collection: C,
132 | ): import('astro/zod').ZodEffects;
133 |
134 | type ReturnTypeOrOriginal = T extends (...args: any[]) => infer R ? R : T;
135 | type InferEntrySchema = import('astro/zod').infer<
136 | ReturnTypeOrOriginal['schema']>
137 | >;
138 |
139 | type ContentEntryMap = {
140 | "articles": Record;
146 | render(): Render[".md"];
147 | }>;
148 | "demos": Record;
154 | render(): Render[".md"];
155 | }>;
156 | "ghosts": Record;
162 | render(): Render[".md"];
163 | }>;
164 | "opensource": Record;
170 | render(): Render[".md"];
171 | }>;
172 | "posts": Record;
178 | render(): Render[".md"];
179 | }>;
180 | "profiles": {
181 | "Developer-Utkarsh.mdx": {
182 | id: "Developer-Utkarsh.mdx";
183 | slug: "developer-utkarsh";
184 | body: string;
185 | collection: "profiles";
186 | data: any
187 | } & { render(): Render[".mdx"] };
188 | "axorax.mdx": {
189 | id: "axorax.mdx";
190 | slug: "axorax";
191 | body: string;
192 | collection: "profiles";
193 | data: any
194 | } & { render(): Render[".mdx"] };
195 | "calllme-shadow.mdx": {
196 | id: "calllme-shadow.mdx";
197 | slug: "calllme-shadow";
198 | body: string;
199 | collection: "profiles";
200 | data: any
201 | } & { render(): Render[".mdx"] };
202 | "harrysingh100.mdx": {
203 | id: "harrysingh100.mdx";
204 | slug: "harrysingh100";
205 | body: string;
206 | collection: "profiles";
207 | data: any
208 | } & { render(): Render[".mdx"] };
209 | "zemerik.mdx": {
210 | id: "zemerik.mdx";
211 | slug: "zemerik";
212 | body: string;
213 | collection: "profiles";
214 | data: any
215 | } & { render(): Render[".mdx"] };
216 | };
217 | "streams": Record;
223 | render(): Render[".md"];
224 | }>;
225 |
226 | };
227 |
228 | type DataEntryMap = {
229 |
230 | };
231 |
232 | type AnyEntryMap = ContentEntryMap & DataEntryMap;
233 |
234 | export type ContentConfig = typeof import("./../src/content/config.js");
235 | }
236 |
--------------------------------------------------------------------------------
/src/layouts/layout.tsx:
--------------------------------------------------------------------------------
1 | import { Slot, component$, useSignal, $, useOnDocument } from '@builder.io/qwik';
2 |
3 | import Logo from '../components/logo';
4 | import NavLink from '../components/nav-link';
5 | import SearchModal from '../components/search-modal';
6 | import QuickSearch from '../components/search-trigger';
7 |
8 | import isNewContent from '../utils/is-new-content';
9 |
10 | import { siteLinks, socialLinks } from './nav-links.ts';
11 |
12 | interface Props {
13 | fullWidth: boolean;
14 | slug: string;
15 | search: any;
16 | }
17 |
18 | const Layout = component$(({ fullWidth, slug, search }) => {
19 | const isModalOpen = useSignal(false);
20 | const isNavOpen = useSignal(false);
21 |
22 | const newItems = search
23 | .map((item) => {
24 | const { date, base } = item;
25 |
26 | return {
27 | base: base,
28 | date: new Date(date),
29 | };
30 | })
31 | .filter((item) => {
32 | const { date } = item;
33 | if (isNewContent(date)) {
34 | return item;
35 | }
36 | })
37 | .reduce((items, item) => {
38 | const base = item.base;
39 | items[base] = (items[base] || 0) + 1;
40 | return items;
41 | }, {});
42 |
43 | const handleNav = $(() => {
44 | isNavOpen.value = !isNavOpen.value;
45 | });
46 |
47 | const handleModal = $(() => {
48 | isModalOpen.value = !isModalOpen.value;
49 | });
50 |
51 | useOnDocument(
52 | 'keydown',
53 | $((event) => {
54 | if (event.key === 'k' && (event.metaKey || event.ctrlKey)) {
55 | handleModal();
56 | }
57 | if (event.key === 'Escape' && isModalOpen.value) {
58 | handleModal();
59 | }
60 | })
61 | );
62 |
63 | return (
64 | <>
65 |
100 |
101 |
102 |
112 |
113 |
114 |
170 |
171 |
174 |
175 |
176 |
177 |
181 |
182 |
183 |
184 |
185 | >
186 | );
187 | });
188 |
189 | export default Layout;
190 |
--------------------------------------------------------------------------------
/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | const defaultTheme = require('tailwindcss/defaultTheme');
3 |
4 | module.exports = {
5 | content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
6 | safelist: [
7 | // These are for the modal
8 | 'backdrop-blur',
9 | // These are for the TOC
10 | 'pl-4',
11 | 'pl-5',
12 | 'pl-6',
13 | 'pl-7',
14 | 'pl-8',
15 | // These are for the charts
16 | 'stroke-brand-teal',
17 | 'stroke-brand-mauve',
18 | 'stroke-brand-salmon',
19 | 'stroke-brand-yellow',
20 | 'stroke-brand-lime',
21 | 'stroke-brand-blood',
22 | 'stroke-brand-starfleet',
23 | 'stroke-brand-electric',
24 | 'stroke-brand-pink',
25 | 'stroke-brand-fuchsia',
26 | 'stroke-brand-secondary',
27 |
28 | 'fill-brand-teal',
29 | 'fill-brand-mauve',
30 | 'fill-brand-salmon',
31 | 'fill-brand-yellow',
32 | 'fill-brand-lime',
33 | 'fill-brand-blood',
34 | 'fill-brand-starfleet',
35 | 'fill-brand-electric',
36 | 'fill-brand-pink',
37 | 'fill-brand-fuchsia',
38 | 'fill-brand-secondary',
39 |
40 | 'bg-brand-teal',
41 | 'bg-brand-mauve',
42 | 'bg-brand-salmon',
43 | 'bg-brand-yellow',
44 | 'bg-brand-lime',
45 | 'bg-brand-blood',
46 | 'bg-brand-starfleet',
47 | 'bg-brand-electric',
48 | 'bg-brand-pink',
49 | 'bg-brand-fuchsia',
50 | 'bg-brand-secondary',
51 |
52 | 'text-brand-teal',
53 | 'text-brand-mauve',
54 | 'text-brand-salmon',
55 | 'text-brand-yellow',
56 | 'text-brand-lime',
57 | 'text-brand-blood',
58 | 'text-brand-starfleet',
59 | 'text-brand-electric',
60 | 'text-brand-pink',
61 | 'text-brand-fuchsia',
62 | 'text-brand-secondary',
63 |
64 | // This is for the GitHub Activity
65 | 'bg-brand-starfleet',
66 | 'bg-brand-electric',
67 | 'bg-red-500',
68 |
69 | // These are for the Ghosts collections cards
70 | 'cursor-not-allowed',
71 | ],
72 | theme: {
73 | extend: {
74 | colors: {
75 | brand: {
76 | text: '#d9dbdf',
77 | primary: '#f056c7',
78 | secondary: '#a4a0fb',
79 | tertiary: '#58e6d9',
80 | muted: '#605c9d',
81 | salmon: '#ff6090',
82 | mauve: '#4871e3',
83 | teal: '#00bcd4',
84 | lime: '#8bc34a',
85 | yellow: '#ffc107',
86 | fuchsia: '#7B1FA2',
87 | blood: '#fc5656',
88 | starfleet: '#0091f7',
89 | electric: '#b900f7',
90 | pink: '#0096FF',
91 | background: '#131127',
92 | outline: '#232140',
93 | surface: '#16142c',
94 | guide: '#2d2a58',
95 | radar: '#57538c',
96 | },
97 | },
98 | fontFamily: {
99 | sans: ['Inconsolata', ...defaultTheme.fontFamily.sans],
100 | },
101 | maxWidth: {
102 | '8xl': '90rem',
103 | },
104 | backgroundImage: {
105 | 'x-icon': "url('https://cdn.icon-icons.com/icons2/4029/PNG/512/twitter_x_new_logo_x_rounded_icon_256078.png')",
106 | },
107 | typography: (theme) => ({
108 | DEFAULT: {
109 | css: {
110 | '*:not(h1, h2, h3, h4, h5, h6, a, code)': {
111 | color: theme('colors.brand.text'),
112 | },
113 |
114 | h1: {
115 | color: theme('colors.brand.text'),
116 | margin: '2rem 0',
117 | fontWeight: 900,
118 | },
119 | 'h2, h3, h4, h5, h6': {
120 | color: theme('colors.brand.salmon'),
121 | fontWeight: 900,
122 | a: {
123 | fontWeight: 900,
124 | textDecoration: 'none',
125 | color: theme('colors.brand.salmon'),
126 | },
127 | },
128 | p: {
129 | fontFamily: 'system-ui',
130 | strong: {
131 | fontWeight: 700,
132 | },
133 | },
134 | button: {
135 | fontFamily: 'system-ui',
136 | fontWeight: 700,
137 | },
138 | a: {
139 | color: theme('colors.brand.secondary'),
140 | cursor: 'pointer',
141 | wordBreak: 'break-word',
142 | '&:hover': {
143 | color: theme('colors.brand.text'),
144 | },
145 | p: {
146 | margin: 0,
147 | color: 'inherit',
148 | },
149 | },
150 | ol: {
151 | li: {
152 | '&::marker': {
153 | color: theme('colors.brand.salmon'),
154 | },
155 | },
156 | },
157 | ul: {
158 | li: {
159 | '&::marker': {
160 | color: theme('colors.brand.salmon'),
161 | },
162 | },
163 | },
164 | 'a, small, time': {
165 | fontWeight: 300,
166 | },
167 | 'pre[class*="language-"]': {
168 | margin: '2.5rem 0px!important',
169 | },
170 | code: {
171 | color: theme('colors.brand.tertiary'),
172 | wordBreak: 'break-word',
173 | '&::before': {
174 | content: '"" !important',
175 | },
176 | '&::after': {
177 | content: '"" !important',
178 | },
179 | },
180 |
181 | blockquote: {
182 | background: theme('colors.brand.surface'),
183 | padding: '1.2em',
184 | borderLeftColor: theme('colors.brand.yellow'),
185 | borderRadius: '.2em',
186 | p: {
187 | margin: 0,
188 | },
189 | },
190 | dl: {
191 | marginTop: '1.25em',
192 | marginBottom: '1.25em',
193 | paddingLeft: '1.625em',
194 | dt: {
195 | fontSize: '1.25rem',
196 | color: theme('colors.brand.text'),
197 | paddingLeft: '0.375em',
198 | },
199 | dd: {
200 | display: 'list-item',
201 | listStyleType: 'disc',
202 | marginTop: '0.5em',
203 | marginBottom: '0.5em',
204 | paddingLeft: '0.375em',
205 | '&::marker': {
206 | color: theme('colors.brand.salmon'),
207 | },
208 | },
209 | },
210 | '.twitter-tweet': {
211 | '&::before': {
212 | content: "''",
213 | display: 'block',
214 | background: theme('backgroundImage.x-icon'),
215 | width: 24,
216 | height: 24,
217 | marginBottom: 16,
218 | },
219 | borderColor: '#232140!important',
220 | padding: '32px!important',
221 | background: theme('colors.brand.surface'),
222 | borderRadius: '4px',
223 | color: theme('colors.brand.text'),
224 | },
225 | '.event-color-PushEvent': {
226 | backgroundColor: theme('colors.brand.starfleet'),
227 | },
228 | '.event-color-CreateEvent': {
229 | backgroundColor: theme('colors.brand.lime'),
230 | },
231 | '.event-color-ForkEvent': {
232 | backgroundColor: theme('colors.brand.mauve'),
233 | },
234 | '.event-color-WatchEvent': {
235 | backgroundColor: theme('colors.brand.electric'),
236 | },
237 | '.event-color-DeleteEvent': {
238 | backgroundColor: theme('colors.red.500'),
239 | },
240 |
241 | '.event-color-IssueCommentEvent': {
242 | backgroundColor: theme('colors.brand.yellow'),
243 | },
244 | '.event-color-PullRequestReviewCommentEvent': {
245 | backgroundColor: theme('colors.brand.yellow'),
246 | },
247 |
248 | '.event-color-PullRequestEvent': {
249 | backgroundColor: theme('colors.brand.teal'),
250 | },
251 | '.event-color-PullRequestReviewEvent': {
252 | backgroundColor: theme('colors.brand.teal'),
253 | },
254 | },
255 | },
256 | }),
257 | },
258 | },
259 | plugins: [
260 | require('@tailwindcss/typography'),
261 | function ({ addBase, theme }) {
262 | function extractColorVars(colorObj, colorGroup = '') {
263 | return Object.keys(colorObj).reduce((vars, colorKey) => {
264 | const value = colorObj[colorKey];
265 |
266 | const newVars =
267 | typeof value === 'string'
268 | ? { [`--color${colorGroup}-${colorKey}`]: value }
269 | : extractColorVars(value, `-${colorKey}`);
270 |
271 | return { ...vars, ...newVars };
272 | }, {});
273 | }
274 |
275 | addBase({
276 | ':root': extractColorVars(theme('colors')),
277 | });
278 | },
279 | ],
280 | };
281 |
--------------------------------------------------------------------------------