-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathportfolio.js
More file actions
120 lines (112 loc) · 5.79 KB
/
portfolio.js
File metadata and controls
120 lines (112 loc) · 5.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
* @typedef {Object} Project
* @property {string} title - The title of the project
* @property {string} description - Description of the project
* @property {string} link - URL link to the project
* @property {string} image - image URL for the project
* @property {string} [techStack] - Optional comma separated technologies used in the project
* @property {string} [icon] - Optional icon SVG code for the project link
*/
/** @type {Project[]} */
const projects = [
{
title: "ganji.me",
description: "This website. My personal blog and portfolio, built from scratch using only vanilla HTML, CSS, and JavaScript for responsiveness and fun. It used to look like the shelf in the image once but now it's much more minimalistic.",
// techStack: "HTML, CSS, JavaScript",
link: "https://ganji.me",
image: "./assets/shelf-screenshot.png",
},
{
title: "mindmap.io",
description: "A keyboard-first, super fast mindmapping tool with agentic capabilities. This is my first project using LLM agents with a UX that is intuitive and makes sense. I built this initially for the Google DeepMind hackathon (Gemini 3 competition on Kaggle) and later turned it into a product.",
// techStack: "LLM, AI Agents, UX",
link: "https://mindmap.io",
image: "./assets/mindmap-io.png",
},
{
title: "Braindump",
description: "An agent-friendly local memory CLI tool built in Go. It gives AI agents persistent, searchable memory across conversations using SQLite with FTS5 full-text search. Notes are stored as Markdown with YAML frontmatter, organized by category, and optimized for speed.",
// techStack: "Go, SQLite, CLI",
link: "https://github.com/MohGanji/braindump",
image: "./assets/braindump.png",
},
{
title: "SchemaIran Bot",
description: "I developed a Telegram bot for Schemairan clinic to conduct YSQ tests (Yonge Schema Questionnaire) online. We analyzed 10k+ test results over 4 years and conducted a quantitative analysis, published as a research paper.",
// techStack: "Python, Node.js, MongoDB, Telegram API",
link: "https://t.me/SchemaIran_Bot",
image: "./assets/schemairan.png",
},
{
title: "Credi",
description: "Credi is a content credibility analyzer. It can help you find out which voices you can trust on social media and avoid those who try to sell you something. I built this project during my participation in the Code with Kiro hackathon, and 99% of the code is generated by AI.",
// techStack: "Typescript, VSCode API",
link: "https://credicredi.com",
image: "./assets/credi.png",
},
{
title: "JScope",
description: "JScope is a VSCode extension that enables measuring and visualizing async code coverage criteria. I built it as part of my research \"code coverage criteria for asyncrhonous programs (ESEC/FSE 2023)\" during my master's at SFU",
// techStack: "Typescript, VSCode API",
link: "https://github.com/MohGanji/jscope",
image: "./assets/jscope.png",
},
{
title: "Daily Timeblock notion template",
description: "After reading 'Deep Work' by Cal Newport (great read btw), I was inspired to use his time blocking technique for my daily planning. So I built this notion template to help me timeblock and keep logs of my days for retrospection. The template available for free from the link below.",
// techStack: "Html, CSS, JavaScript",
link: "https://ganjim.gumroad.com/l/daily-timeblock",
image: "./assets/notion-timeblock.png",
},
{
title: "BlogFrog.xyz",
description: "Blogfrog is a blog post dispencer that takes user to a random blog post from my favorite writers. I created it to replace my doomscrolling on twitter and instagram with reading blogs.",
// techStack: "Html, CSS, JavaScript",
link: "http://blogfrog.xyz",
image: "./assets/blogfrog.png",
},
];
const DEFAULT_ICON = `<svg
role="img"
viewBox="0 0 24 24"
width="1.2rem" height="auto"
xmlns="http://www.w3.org/2000/svg"
>
<title>External Link</title>
<path fill="var(--url-color)" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/>
</svg>`;
/**
* Creates HTML markup for a project card
* @param {Project} project - The project object containing title, description, link etc.
* @returns {string} HTML string for the project card
*/
const createProjectCard = (project) => {
return `
<div class="portfolio-item">
<div class="content-media">
<img src="${project.image}" alt="">
<div class="hover-description">
<p>${project.description}</p>
${project.techStack ? `<p style="font-style: italic">${project.techStack}</p>` : ""}
</div>
</div>
<a class="content-link" href="${project.link}">
<span class="link-text">${project.title}</span>
${project.icon || DEFAULT_ICON}
</a>
</div>
`;
};
// Wait for DOM to be loaded
document.addEventListener('DOMContentLoaded', () => {
// Find portfolio items container
const portfolioContainer = document.querySelector('.portfolio-items');
if (!portfolioContainer) {
console.error('Could not find portfolio items container');
return;
}
// Generate HTML for each project
const projectCardsHTML = projects.map(project => createProjectCard(project)).join('\n');
// Append the project cards HTML to the existing content
portfolioContainer.insertAdjacentHTML('beforeend', projectCardsHTML);
});