From 951e514103d63c8aa6e195956e1ebd6b4dab74d9 Mon Sep 17 00:00:00 2001 From: punjitha <132387971+algotyrnt@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:53:20 +0530 Subject: [PATCH 1/5] Add Privacy Policy component with modal dialog and content --- src/components/sections/Privacy.tsx | 269 ++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 src/components/sections/Privacy.tsx diff --git a/src/components/sections/Privacy.tsx b/src/components/sections/Privacy.tsx new file mode 100644 index 0000000..3f8fe0b --- /dev/null +++ b/src/components/sections/Privacy.tsx @@ -0,0 +1,269 @@ +'use client' +import { useState } from 'react' +import Dialog from '@mui/material/Dialog' +import DialogContent from '@mui/material/DialogContent' +import DialogTitle from '@mui/material/DialogTitle' +import Box from '@mui/material/Box' +import Typography from '@mui/material/Typography' +import Link from '@mui/material/Link' + +interface PrivacyProps { + open: boolean + onClose: () => void +} + +export function Privacy({ open, onClose }: PrivacyProps) { + return ( + + + + + Privacy Policy + + + + Last updated: March 9, 2026 + + + + + + *:not(:last-child)': { mb: 3 }, + '& h2': { + fontSize: '1.125rem', + fontWeight: 600, + mt: 3, + mb: 2, + color: 'text.primary', + }, + '& p': { + fontSize: '0.9rem', + lineHeight: 1.7, + letterSpacing: '0.005em', + color: 'text.secondary', + textAlign: 'justify', + hyphens: 'auto', + }, + '& ul': { + pl: 3, + '& li': { + fontSize: '0.9rem', + lineHeight: 1.6, + letterSpacing: '0.005em', + color: 'text.secondary', + mb: 1, + }, + }, + '& a': { + color: 'text.primary', + textDecorationColor: 'rgba(0,0,0,0.25)', + textUnderlineOffset: 3, + fontWeight: 450, + '&:hover': { textDecorationColor: 'text.primary' }, + }, + }} + > + + This privacy policy describes how ("we", "us", + or "our") collects, uses, and shares your information when + you visit our website. + + + + Information We Collect + + + + We collect minimal information about your visit through third-party + services: + + + +
  • + Analytics Data: We use{' '} + + Vercel Analytics + {' '} + to collect anonymous usage statistics including page views, + referrers, device type, and general location (country/city). +
  • +
  • + Performance Data: We use{' '} + + Vercel Speed Insights + {' '} + to collect performance metrics to improve site loading times. +
  • +
    + + + We do not: + + + +
  • Collect personally identifiable information
  • +
  • Use advertising trackers or cookies
  • +
  • Store user accounts or login information
  • +
  • Share your data with advertisers
  • +
  • Track you across other websites
  • +
    + + + How We Use Your Information + + + + The anonymous analytics data we collect is used solely to: + + + +
  • Understand how visitors use our website
  • +
  • Improve site content and user experience
  • +
  • Optimize website performance and loading speeds
  • +
  • Identify and fix technical issues
  • +
    + + + Third-Party Services + + + + We use the following third-party services that may collect + information: + + + +
  • + Vercel: Hosts our website and provides analytics + services. View{' '} + + Vercel's Privacy Policy + + . +
  • +
  • + GitHub: We display public repository information + from GitHub. No personal data is collected through this + integration. +
  • +
  • + Medium: We display public blog posts from Medium. + No personal data is collected through this integration. +
  • +
    + + + Data Retention + + + + Analytics data is retained according to Vercel's data retention + policies, typically for a period of up to 90 days. We do not store + any personal data on our own servers. + + + + Changes to This Policy + + + + We may update this privacy policy from time to time. Changes will be + posted on this page with an updated revision date. + + + + This website is open source. View the code at{' '} + + github.com/algotyrnt/nova + + . + +
    +
    +
    + ) +} + +export function usePrivacyModal() { + const [open, setOpen] = useState(false) + + const openModal = () => setOpen(true) + const closeModal = () => setOpen(false) + + return { open, openModal, closeModal } +} From a6ca09e041622e5b18733e1bc4da8d2fb678ef7a Mon Sep 17 00:00:00 2001 From: punjitha <132387971+algotyrnt@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:53:33 +0530 Subject: [PATCH 2/5] Add Privacy Policy link to footer and integrate modal functionality --- src/components/layout/footer.tsx | 141 ++++++++++++++++++------------- 1 file changed, 83 insertions(+), 58 deletions(-) diff --git a/src/components/layout/footer.tsx b/src/components/layout/footer.tsx index 92a43a7..b1f7cd8 100644 --- a/src/components/layout/footer.tsx +++ b/src/components/layout/footer.tsx @@ -3,77 +3,102 @@ import Box from '@mui/material/Box' import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' import Link from '@mui/material/Link' +import { Privacy, usePrivacyModal } from '@/components/sections/Privacy' export function Footer() { const currentYear = new Date().getFullYear() + const { open, openModal, closeModal } = usePrivacyModal() return ( - - + - - © {currentYear}{' '} - - algotyrnt - - . - + © {currentYear}{' '} + + algotyrnt + + . + - - Released under the{' '} - - MIT License - - - - + Released under the{' '} + + MIT License + + {' | '} + + Privacy Policy + + + + + + + ) } From 597489775e0f20086d3dc98a76abbbb5f7063fae Mon Sep 17 00:00:00 2001 From: punjitha <132387971+algotyrnt@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:53:44 +0530 Subject: [PATCH 3/5] Update README.md to enhance project description, features, and configuration details --- README.md | 225 +++++++++++++++++++++++------------------------------- 1 file changed, 96 insertions(+), 129 deletions(-) diff --git a/README.md b/README.md index 154f62b..2762669 100644 --- a/README.md +++ b/README.md @@ -1,193 +1,160 @@ # Nova -A minimal, fast, and fully customizable personal portfolio site. Built with Next.js (App Router), MUI, and Framer Motion. Pulls live data from GitHub (pinned repos) and Medium (latest posts). +A minimal, fast, and fully customizable personal portfolio site built with `Next.js` (App Router), `TypeScript`, `MUI`, and `Framer Motion`. +It can render your pinned GitHub repositories and latest Medium posts at build/runtime with ISR. -**Live:** [algotyrnt.com](https://algotyrnt.com) +Live site: [algotyrnt.com](https://algotyrnt.com) ---- -## Preview +## Features -![Site Preview](.github/assets/preview.png) - ---- +- App Router + React Server Components +- Structured, env-driven content (no CMS required) +- GitHub pinned projects via GraphQL API +- Medium posts via RSS feed +- SEO basics included (`sitemap.xml`, `robots.txt`, Open Graph image) +- Vercel Analytics + Speed Insights integration ## Tech Stack -| | | -| ------------- | ----------------------------------------------------------------------------------------------------------- | -| Framework | [Next.js](https://nextjs.org/) (App Router, React Server Components) | -| Language | TypeScript | -| UI Components | [Material UI (MUI)](https://mui.com/) | -| Animations | [Framer Motion](https://www.framer.com/motion/) | -| Analytics | [Vercel Analytics](https://vercel.com/analytics) + [Speed Insights](https://vercel.com/docs/speed-insights) | - ---- +| Area | Tooling | +| --------- | ---------------------------------------------------------------------------------------------------------- | +| Framework | [Next.js](https://nextjs.org/) 16 | +| Language | TypeScript | +| UI | [Material UI (MUI)](https://mui.com/) + Emotion | +| Animation | [Framer Motion](https://www.framer.com/motion/) | +| Analytics | [Vercel Analytics](https://vercel.com/analytics), [Speed Insights](https://vercel.com/docs/speed-insights) | ## Project Structure -``` +```text src/ -├── app/ # Next.js App Router -│ ├── layout.tsx # Root layout (fonts, metadata, theme provider) -│ ├── page.tsx # Home page — composes all sections -│ ├── error.tsx # Error boundary -│ ├── not-found.tsx # 404 page -│ ├── robots.ts # robots.txt -│ └── sitemap.ts # sitemap.xml +├── app/ # Next.js routes, metadata, robots, sitemap ├── components/ -│ ├── layout/ # Header and Footer -│ ├── sections/ # Page sections: About, Work, Projects, Blogs, Connect -│ ├── ThemeRegistry/ # MUI theme + Emotion SSR cache setup -│ └── ui/ # Animation primitives: FadeIn, Stagger +│ ├── layout/ # Header, footer +│ ├── sections/ # About, Work, Projects, Blogs, Connect, Privacy +│ ├── ThemeRegistry/ # MUI + Emotion integration +│ └── ui/ # Animation primitives ├── lib/ -│ ├── config.ts # Configuration (loads from environment variables) -│ └── api/ -│ ├── github.ts # GitHub GraphQL API — fetches pinned repos -│ └── medium.ts # Medium RSS feed — fetches latest posts -└── types/ - └── index.ts # Shared TypeScript types +│ ├── api/ # GitHub + Medium fetchers +│ └── config.ts # Env parsing and typed config exports +└── types/ # Shared TypeScript types ``` ---- - ## Getting Started ### Prerequisites - Node.js 20+ -- A GitHub personal access token (for the Projects section) +- npm +- Optional: GitHub personal access token for Projects section -### 1. Clone the repo +### 1. Clone ```bash git clone https://github.com/algotyrnt/nova.git cd nova ``` -### 2. Install dependencies +### 2. Install ```bash npm install ``` -### 3. Set environment variables +### 3. Configure environment ```bash cp .env.example .env.local ``` -Then open `.env.local` and configure your variables: - -```env -# Required for GitHub integration -GITHUB_TOKEN=your_github_personal_access_token - -# Site configuration -EMAIL=your-email@example.com -WEBSITE_URL=https://yourwebsite.com -SITE_NAME=Your Name - Your Title -SITE_DESCRIPTION=Your professional description here. -ABOUT_TEXT=Your about text describing your background and interests. - -# JSON arrays (all must be valid JSON) -SITE_KEYWORDS=["keyword1","keyword2","Software Engineer"] -WORK_EXPERIENCE=[{"company":"Company Name","title":"Job Title","start":"YYYY MMM","end":"present","link":"https://company.com/","id":"work1"}] -SOCIAL_LINKS=[{"label":"Github","link":"https://github.com/yourusername"},{"label":"LinkedIn","link":"https://www.linkedin.com/in/yourusername"}] +Update `.env.local` with your content. -# External integrations -GITHUB_USERNAME=yourgithubusername -MEDIUM_USERNAME=yourmediumusername -``` +Important notes: -> The GitHub token only needs `read:user` scope. Without it, the Projects section will be gracefully hidden. +- `SITE_KEYWORDS`, `WORK_EXPERIENCE`, and `SOCIAL_LINKS` must be valid JSON. +- `GITHUB_TOKEN` is optional in code. If not set (or invalid), the Projects section simply returns no items. +- `MEDIUM_USERNAME` controls the Medium feed endpoint. -### 4. Start the dev server +### 4. Run locally ```bash npm run dev ``` -Open [http://localhost:3000](http://localhost:3000). - ---- - -## Configuration - -All configuration is managed through environment variables (see `.env.example`). For statically generated pages, Next.js reads these from `process.env` at build time, so changing them requires a rebuild (or restarting the dev server) for changes to take effect. +Open `http://localhost:3000`. + +## Configuration Reference + +All values come from environment variables in `src/lib/config.ts`. + +| Variable | Purpose | +| ------------------ | ------------------------------------------ | +| `EMAIL` | Contact email used in Connect/footer areas | +| `WEBSITE_URL` | Canonical site URL for metadata/sitemap | +| `SITE_NAME` | Site title and branding | +| `SITE_DESCRIPTION` | Meta description | +| `ABOUT_TEXT` | About section body text | +| `SITE_KEYWORDS` | JSON array for SEO keywords | +| `WORK_EXPERIENCE` | JSON array of work entries | +| `SOCIAL_LINKS` | JSON array of social links | +| `GITHUB_USERNAME` | Username used for pinned repos query | +| `GITHUB_TOKEN` | Token used to call GitHub GraphQL API | +| `MEDIUM_USERNAME` | Username used for Medium RSS feed | + +Example JSON values: + +```json +{ + "SITE_KEYWORDS": ["portfolio", "software engineer", "nextjs"], + "WORK_EXPERIENCE": [ + { + "company": "Example Inc", + "title": "Software Engineer", + "start": "2023 Jan", + "end": "present", + "link": "https://example.com", + "id": "exp-1" + } + ], + "SOCIAL_LINKS": [ + { "label": "Github", "link": "https://github.com/yourname" }, + { "label": "LinkedIn", "link": "https://linkedin.com/in/yourname" } + ] +} +``` -**Configuration variables:** +## Customizing Sections -- `EMAIL` — Contact email -- `WEBSITE_URL` — Site URL -- `SITE_NAME` — Site title -- `SITE_DESCRIPTION` — Meta description -- `SITE_KEYWORDS` — JSON array of keywords -- `ABOUT_TEXT` — About section text -- `WORK_EXPERIENCE` — JSON array of work history -- `SOCIAL_LINKS` — JSON array of social links -- `GITHUB_USERNAME` — GitHub username (for Projects section) -- `MEDIUM_USERNAME` — Medium username (for Blogs section) +The homepage section order is defined in `src/app/page.tsx`. +Add, remove, or reorder section components there. -**To remove a section**, delete its import from `src/app/page.tsx`. +## Available Scripts ---- +```bash +npm run dev # Start development server +npm run build # Build for production +npm run start # Start production server +npm run lint # Run ESLint +``` ## Deployment -The site is a standard Next.js application and can be deployed to any platform that supports Next.js: +This is a standard Next.js app and can be deployed on Vercel or any Node-capable platform. -1. **Build the project:** +### Vercel (recommended) - ```bash - npm run build - ``` +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/algotyrnt/nova) -2. **Set environment variables** on your hosting platform (all variables from `.env.example`) +Set the same environment variables from `.env.example` in the Vercel project settings. -3. **Deploy** the built application - -**Requirements:** - -- Node.js 20+ -- All environment variables must be set -- `GITHUB_TOKEN` is required for the Projects section to work - -### Deploying to Vercel - -This project includes Vercel Analytics and Speed Insights. To deploy to Vercel: - -1. **One-click deploy:** - - [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/algotyrnt/nova) - -2. **Or using Vercel CLI:** - - ```bash - npm i -g vercel - vercel - ``` - -3. **Set environment variables** in Vercel dashboard: - - Go to **Project Settings → Environment Variables** - - Add all variables from `.env.example` - - Redeploy for changes to take effect - -> Vercel Analytics and Speed Insights are automatically enabled when deployed to Vercel. - ---- - -## Scripts +### Generic deployment flow ```bash -npm run dev # Start development server (http://localhost:3000) -npm run build # Production build -npm run start # Start production server -npm run lint # Run ESLint +npm run build +npm run start ``` ---- - ## License -MIT — free to use as a template for your own personal site. +MIT From ccbb12ea650709b1d422d2e9c23de9d551802f9a Mon Sep 17 00:00:00 2001 From: Punjitha Bandara <132387971+algotyrnt@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:10:12 +0530 Subject: [PATCH 4/5] Apply code review suggestions Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/components/sections/Privacy.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/sections/Privacy.tsx b/src/components/sections/Privacy.tsx index 3f8fe0b..968ed5a 100644 --- a/src/components/sections/Privacy.tsx +++ b/src/components/sections/Privacy.tsx @@ -12,6 +12,8 @@ interface PrivacyProps { onClose: () => void } +const PRIVACY_POLICY_LAST_UPDATED = 'March 9, 2026' + export function Privacy({ open, onClose }: PrivacyProps) { return ( - Last updated: March 9, 2026 + Last updated: {PRIVACY_POLICY_LAST_UPDATED} From 02b98756a218e4286f25b48cde042566058ef356 Mon Sep 17 00:00:00 2001 From: Punjitha Bandara <132387971+algotyrnt@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:10:35 +0530 Subject: [PATCH 5/5] Apply code review suggestions Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2762669..223d566 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ Example JSON values: } ], "SOCIAL_LINKS": [ - { "label": "Github", "link": "https://github.com/yourname" }, + { "label": "GitHub", "link": "https://github.com/yourname" }, { "label": "LinkedIn", "link": "https://linkedin.com/in/yourname" } ] }