You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+66-42Lines changed: 66 additions & 42 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@
4
4
5
5
This repository contains the complete source code and content for my personal portfolio website, built by Mit Patel. It's a fully static site generated using Python, Jinja2, and a custom build script, designed to be a living document of my projects, skills, and technical learnings.
6
6
7
-
The entire site is generated from a single, centralized [`JSON database`](portfolio-mit_v1.json), making it incredibly easy to maintain and update.
7
+
The entire site is generated from a single, centralized [`portfolio.json`](portfolio.json) database, making it incredibly easy to maintain and update.
@@ -21,33 +21,45 @@ This approach gives me the best of both worlds:
21
21
***Easy Maintenance:** To add a new project or blog post, I only need to update the JSON and Markdown files and re-run the script. No HTML editing is required.
22
22
***High Performance:** The final output is pure, lightweight static files, which are incredibly fast, secure, and can be hosted for free on platforms like GitHub Pages.
23
23
24
-
25
24
---
26
25
27
26
## Features
28
27
29
-
This portfolio is packed with features we've built from the ground up:
28
+
This portfolio is packed with features built from the ground up:
30
29
31
-
***Centralized Data Management:** All content (project details, blog posts, skills, etc.) is managed in a single [`updated-data.json`](future-work/updated-data.json) file, acting as a "single source of truth."
32
-
***Dynamic Site Generation:** A Python script ([`generate_portfolio_modified.py`](generate_portfolio_modified.py)) serves as the build engine.
30
+
***Centralized Data Management:** All content (project details, blog posts, skills, etc.) is managed in a single [`portfolio.json`](portfolio.json) file, acting as a "single source of truth." Projects and their associated blogs are grouped together under `projects_blog_db` — one place to update a GitHub URL, image, or summary.
31
+
***Dynamic Site Generation:** A Python script ([`generate_portfolio_modified.py`](generate_portfolio_modified.py)) serves as the build engine, deriving `featured_projects`, `projects`, and `blogs` lists at runtime from the unified database.
33
32
***Multi-Page Architecture:** Includes separate, fully-featured pages for:
34
-
***Homepage:** A personal introduction and high-level summary.
35
-
***Resume:** A clean, professional resume layout.
36
-
***Projects:** A beautiful, card-based gallery of my featured work.
33
+
***Homepage:** A personal introduction with "About Me" prose and an "At a Glance" sidebar.
34
+
***Resume:** A clean, professional resume layout with work experience, education, and technical skills.
35
+
***Projects:** A beautiful, card-based gallery of featured work with tech stack icons.
37
36
***Tech Stack:** A visual grid of all the technologies I'm proficient in.
38
-
***Blog:** A filterable list of all my technical articles.
39
-
***Contact:** A clear call-to-action page.
37
+
***Blog:** A filterable, paginated list of all my technical articles.
38
+
***Contact:** A direct contact form with Web3Forms (primary) + Formspree (fallback) plus social link cards.
40
39
***Markdown-Powered Blog:**
41
40
* Blog posts are written in simple Markdown files.
42
41
* The build script automatically converts them to styled HTML pages.
43
-
* Supports multi-part blog series with automatic "Part 1 / Part 2" linking.
42
+
* Supports multi-part blog series with automatic "Part 1 / Part 2 / Part 3" linking.
44
43
* Includes "Previous/Next Post" navigation to encourage reader engagement.
45
44
***Interactive UI & UX:**
46
45
***Light/Dark Theme Toggle:** A site-wide, persistent theme switcher with a floating icon.
47
46
***Themed Icons:** All SVG icons (for social links and tech stacks) are theme-aware, automatically changing color to match the light or dark mode.
48
-
***Interactive Filtering:** The blog page features a sidebar that allows users to filter posts by core technologies.
47
+
***Multi-Select OR Filters:** The blog page allows filtering by multiple technologies simultaneously using OR logic.
48
+
***Dynamic Post Counter:** The "Total Posts" counter updates in real-time based on active filters.
49
+
***Load More Pagination:** Blog posts load incrementally with smooth scroll-to-new-content behavior.
50
+
***Mobile Filter Panel:** On small screens, filters collapse into a toggleable icon panel with outside-click-to-close.
51
+
***Client-Side Search:** A floating search button (with ⌘K shortcut) opens a modal overlay to search across all blog post titles, summaries, and tags.
52
+
***Horizontal Progress Bar:** A reading progress indicator at the top of blog post pages.
53
+
***Table of Contents (TOC):** Auto-generated from blog post headings with a collapsible hamburger menu on mobile.
54
+
***Sticky Sidebar:** Post metadata and TOC remain fixed while scrolling through content.
49
55
***Responsive Design:** Custom CSS ensures the site looks great on both desktop and mobile devices.
50
-
***Deep Project-Blog Integration:** Each project card on the "Projects" page links directly to its corresponding detailed "Read the Story" blog post, creating a powerful narrative flow.
56
+
***SEO & Open Graph:** Auto-generated `meta_description`, `meta_keywords`, and `og:description` for every blog post, plus proper Open Graph tags on all pages.
57
+
***Sitemap & Robots.txt:** Automatically generated `sitemap.xml` (with all pages and blog posts) and `robots.txt` at build time.
58
+
***Automated Image Optimization:** The build script converts all images in `project_images/` and `posts_assets/` to WebP format with thumbnails.
59
+
***Deep Project-Blog Integration:** Each project card on the "Projects" page links directly to its corresponding detailed "Read the Story" blog post.
60
+
***Dual Contact Form:** A contact form using Web3Forms as the primary endpoint with an automatic Formspree fallback, client-side validation, loading states, success/error toasts, and honeypot anti-spam fields.
61
+
***CI/CD Pipeline:** A GitHub Actions workflow (`.github/workflows/deploy.yml`) that automatically builds and deploys the site to GitHub Pages on every push to `main`.
62
+
***Modular Codebase:** All inline CSS and JS has been extracted into dedicated external files (`css/blog.css`, `js/blog.js`, etc.) for improved maintainability and caching.
51
63
52
64
---
53
65
@@ -88,34 +100,17 @@ This portfolio is packed with features we've built from the ground up:
This project is a continuous work in progress. Here are some of the features and improvements planned for the future:
94
106
95
-
* `[ ]` **Integrate a CSS Framework (e.g., Bootstrap):** To further improve the responsive design and accelerate the addition of new UI components, I plan to refactor the custom CSS to use a professional framework. This will involve updating the HTML templates to use the framework's class system.
96
-
97
-
*`[ ]`**Implement a Direct Contact Form:** To provide an alternative to the `mailto:` link, I plan to integrate a third-party service (like Formspree) to handle direct message submissions from a form on the contact page. This will require setting up the service and adding a `<form>` element to the [`contact_template.html`](contact_template.html).
98
-
99
-
*`[ ]`**Content Expansion:**
100
-
* Add more projects to the [`json`](portfolio-mit_v1.json) file.
101
-
* Write more technical blog posts.
102
-
* Continue to expand and refine the `tech_stack` with new skills.
103
-
104
-
*`[ ]`**Update architecture diagram link in markdown file**
107
+
* `[ ]` **Update architecture diagram link in markdown file:**
105
108
* by simply adding `../` or `/` should work on local system, but that does not solve the problem in static `html` page
106
109
* the current approach solves the issue for `html` page but when previewing the `markdown` file, the **image** is not shown (both in **local** as well as in **github repos**)
107
110
108
-
*`[ ]`**Organise data inside `json` file:**
109
-
* Keep the data in a structured format so there are no duplicates.
110
-
* The data for a project/blog must be together ([`project_db`](future-work/project_db.json)) to make it easier to edit details like Github URLs, blog images, project card thumbnail, blog home page summary, etc, etc, etc.
111
-
* Follow the structure given in [`update-data.json`](future-work/updated-data.json) and [`project_db.json`](future-work/project_db.json) in [`future-work`](future-work/) folder.
112
-
113
111
* `[ ]` **Architecture diagram and video or a gif:**
114
112
* Add architecture diagram of the project or the blog or create a video doing a walkthrough of the project or a gif of the working ui.
115
113
116
-
*`[ ]`**Clean individual html files by removing extra white space:**
117
-
* Remove extra white space from individual html files to make them more readable. (see [`future-work/images/unclean-html-code-block.png`](future-work/images/unclean-html-code-block.png))
118
-
119
114
* `[x]` **Add a "Copy Code" Button to Code Blocks:** -- 27.02.2026
120
115
* A final layer of polish for the blog, allowing visitors to easily copy code snippets. This was originally attempted with Prism.js plugins, but has now been resolved directly using a custom Javascript implementation to sidestep the plugin issues.
121
116
@@ -130,25 +125,54 @@ This project is a continuous work in progress. Here are some of the features and
130
125
* Add horizontal progress scroll bar to the top of the page to make it easier for users to navigate the page.
131
126
132
127
* `[x]` **Add dynamic pagination for blog page:** -- 08.03.2026
133
-
* Add dynamic pagination for blog page to make it easier for users to navigate through the blog posts. -->`Load More Posts` button at the end of the blog page. (see [`future-work/images/dynamic-pagination.png`](future-work/images/dynamic-pagination.png))
128
+
* Add dynamic pagination for blog page to make it easier for users to navigate through the blog posts. --> `Load More Posts` button at the end of the blog page.
134
129
135
130
* `[x]` **Add heading sections inside blog post page:** -- 09.03.2026
136
-
* In the blog post page, add page headings and links for easy scrolling and navigating through the page.
137
-
* This also helps in giving a brief of the blog post page.
138
-
* See [`future-work/images/blog-post-page.png`](future-work/images/blog-post-page.png) for reference and [`future-work/images/reference-sample.png`](future-work/images/reference-sample.png)
131
+
* In the blog post page, add page headings and links for easy scrolling and navigating through the page.
139
132
140
133
* `[x]` **Add table of contents in posts page:** -- 09.03.2026
141
-
* Add table of contents in posts page to make it easier for users to navigate through the blog posts. (see [`future-work/images/table-of-content-2.png`](future-work/images/table-of-content-2.png) and [`future-work/images/table-of-content-3.png`](future-work/images/table-of-content-3.png))
134
+
* Add table of contents in posts page to make it easier for users to navigate through the blog posts.
142
135
143
136
* `[x]` **Modify the code such that the sidebar is fixed in the page while scrolling down (sticky positioning):** -- 09.03.2026
144
-
* where the sidebar (or an element) remains fixed in place while the rest of the page scrolls—is called "sticky positioning"in web design. (see [`future-work/images/sticky-positioning-highlight-01.png`](future-work/images/sticky-positioning-highlight-01.png) and [`future-work/images/sticky-positioning-highlight-02.png`](future-work/images/sticky-positioning-highlight-02.png))
137
+
* where the sidebar (or an element) remains fixed in place while the rest of the page scrolls—is called "sticky positioning" in web design.
145
138
146
139
* `[x]` **Keep 3 projects columns:**
147
-
* Need to make changes in [`project_template`](projects_template.html) to make sure it includes 3 project cards in each row. (see [`future-work/images/project-page.png`](future-work/images/project-page.png))
140
+
* Need to make changes in [`project_template`](projects_template.html) to make sure it includes 3 project cards in each row.
148
141
149
142
* `[x]` **Add read story section in project page:**
150
143
* In the project page, under the given project card, add a link to read the blog along with viewing it on github.
151
-
* The blog will be redirected to the 1st blog in the series.
152
144
153
-
*`[x]`**Add a section in blog page to show the number of posts:**
154
-
* Add a section in blog page to show the number of posts. (see `future-work/images/number-of-posts.png`)
* The "Total Posts" counter next to "Recent Posts" now updates in real-time based on the number of posts matching the currently selected filters.
153
+
154
+
* `[x]` **Multi-select OR filters for blog page:** -- 18.03.2026
155
+
* Users can select multiple technology tags simultaneously. Filtering uses "OR" logic — posts matching *any* selected tag are shown.
156
+
157
+
* `[x]` **Organise data inside `json` file:** -- 27.03.2026
158
+
* Migrated from scattered `portfolio-mit_v1.json` to a unified [`portfolio.json`](portfolio.json) with a `projects_blog_db` structure.
159
+
* Blogs inherit `github_url` from their parent project; no more redundant URLs.
160
+
* Updated `generate_portfolio_modified.py` to derive all template-compatible lists at runtime from the unified database.
161
+
162
+
* `[x]` **Implement a Direct Contact Form:** -- 27.03.2026
163
+
* Integrated dual contact form with Web3Forms (primary, 250/mo limit) + Formspree (fallback, 50/mo limit). Includes client-side validation, loading states, success/error toasts, and honeypot anti-spam fields for both services.
164
+
165
+
* `[x]` **Extract inline CSS/JS into external files & clean HTML templates:** -- 03.04.2026
166
+
* Extracted large `<style>` and `<script>` blocks from all templates into dedicated files (`css/blog.css`, `css/contact.css`, `css/post-layout.css`, `css/projects.css`, `css/tech-stack.css`, `js/blog.js`, `js/contact.js`, `js/post-toc.js`).
167
+
* Added `trim_blocks=True` and `lstrip_blocks=True` to Jinja2 Environment for cleaner HTML output.
168
+
* Removed all verbose HTML comments, duplicate script references (resume had app.js loaded 3x), and excess whitespace.
* Added `generate_sitemap()` and `generate_robots_txt()` functions to the build script.
172
+
* `sitemap.xml` includes all static pages and blog posts with `lastmod`, `changefreq`, and `priority`.
173
+
174
+
* `[x]` **Dynamic SEO & Open Graph Metadata:** -- 03.04.2026
175
+
* Auto-generates `meta_description` (truncated to 160 chars from post content), `meta_keywords` (from core_technologies + keywords), and `og:description` for every blog post at build time.
* Added Pillow-based image optimization to the build script. Converts all `.jpg`/`.png` images in `project_images/` and `posts_assets/` to WebP format (80% quality) with `_thumb.webp` thumbnails (400×400 max). Conversions are incremental — skipped when WebP is already up-to-date.
0 commit comments