Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
22 changes: 22 additions & 0 deletions .cursor/rules/performance-seo.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
description: Core Web Vitals, LCP/CLS/INP, and SEO rules for all UI work in this app
globs:
- src/**/*
- index.html
- public/**/*
alwaysApply: false
---

# Performance & SEO

Before changing layout, images, fonts, routing, or page content, read and follow **[docs/WebPerformanceSEO.md](../docs/WebPerformanceSEO.md)**.

## Non-negotiables

- **LCP** ≤ 2.5 s — preload only the true LCP candidate (logo or hero slide 1); never lazy-load above-the-fold heroes.
- **CLS** ≤ 0.1 — every `<img>` needs `width` + `height` (or `aspect-ratio`); reserve space for fonts and embeds.
- **INP** ≤ 200 ms — lazy routes, no heavy sync work on click handlers.
- Register image paths in **`src/constants/images.ts`**; copy text to page **`constants/`** modules.
- Pair with **[docs/HTMLSemantics.md](../docs/HTMLSemantics.md)** and **[docs/DesignGuidelines.md](../docs/DesignGuidelines.md)**.

Do not copy WordPress/Elementor patterns that hurt vitals (multi-MB images, blocking scripts, duplicate nav DOM).
66 changes: 66 additions & 0 deletions .fallowrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json",
"entry": ["src/main.{ts,tsx,js,jsx}"],
"ignoreDependencies": [
"immer",
"eslint-config-prettier",
"eslint-plugin-import",
"eslint-import-resolver-typescript",
"eslint-plugin-node",
"@typescript-eslint/eslint-plugin",
"@typescript-eslint/parser",
"@testing-library/jest-native",
"@testing-library/react-native",
"vite-tsconfig-paths",
"@types/jest",
"jest",
"cross-env",
"src/assets/*",
"globals"
],
"ignorePatterns": [
"src/features/**/tests/**",
"src/shared/**/tests/**",
"src/tests/**",
"**/tests/**",
"**/__tests__/**",
"**/*.test.ts",
"**/*.test.tsx",
"**/*.spec.ts",
"**/*.spec.tsx",
"jest.config.js",
"jest.setup.js",
"api/payment/webhook-test.js",
"api/payment/webhook.js"
],
"duplicates": {
"minOccurrences": 3,
"ignore": [
"**/lib/**",
"**/dist/**",
"**/node_modules/**",
"**/docs/**",
"src/features/**/tests/**",
"src/shared/**/tests/**",
"src/tests/**",
"**/tests/**",
"**/*.test.ts",
"**/*.test.tsx",
"src/appStore/*"
],
"mode": "mild"
},
"health": {
"ignore": [
"src/features/**/tests/**",
"src/shared/**/tests/**",
"src/tests/**",
"**/tests/**",
"**/*.test.ts",
"**/*.test.tsx"
]
},
"rules": {
"circular-dependencies": "error"
}
}
57 changes: 57 additions & 0 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Security Audit

on:
push:
paths:
- 'package.json'
- 'bun.lock'
pull_request:
paths:
- 'package.json'
- 'bun.lock'

jobs:
audit:
name: Dependency Security Audit
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies (frozen lockfile)
run: bun install --frozen-lockfile

- name: Run security audit
run: bun audit

- name: Check for new postinstall scripts
run: |
node -e "
const fs = require('fs');
const path = require('path');
const nm = './node_modules';
const ALLOWED = ['esbuild', 'protobufjs', 'core-js', 'unrs-resolver'];
let violations = [];
fs.readdirSync(nm).forEach(pkg => {
try {
const p = JSON.parse(fs.readFileSync(path.join(nm, pkg, 'package.json'), 'utf8'));
const s = p.scripts || {};
if ((s.postinstall || s.preinstall || s.install) && !ALLOWED.includes(pkg)) {
violations.push({ pkg, scripts: s });
}
} catch {}
});
if (violations.length > 0) {
console.error('UNEXPECTED INSTALL SCRIPTS DETECTED:');
console.error(JSON.stringify(violations, null, 2));
process.exit(1);
} else {
console.log('All install scripts are from known-safe packages.');
}
"
26 changes: 24 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
.venv/
__pycache__/
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
bun-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules/
dist
index.html
build/
tailwind.config.ts
src/index.css
11 changes: 11 additions & 0 deletions .prettierrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// .prettierrc.cjs
module.exports = {
arrowParens: 'avoid',
bracketSameLine: true,
bracketSpacing: false,
singleQuote: true,
trailingComma: 'all',
endOfLine: 'lf',
plugins: ['prettier-plugin-tailwindcss'],
printWidth: 80,
};
167 changes: 140 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,159 @@
# Pratima Chandra Foundation Scraper
# Pratima Chandra Foundation — React Web App

This project scrapes public data from `https://pratimachandrafoundation.org/` and writes it in usable formats:
Modern React rebuild of [pratimachandrafoundation.org](https://pratimachandrafoundation.org/) — faster, accessible, and aligned with [Core Web Vitals](https://web.dev/vitals/), while preserving foundation brand and content.

- `site_data.json`: complete structured data
- `website_data.md`: human-readable website content
- `pages.csv`: page-level summary
- `images.csv`: discovered image URLs
- `assets_manifest.csv`: downloaded asset index
- `assets_manifest.json`: downloaded asset index
- `assets/`: downloaded images, CSS, JS, icons, PDFs, fonts, and other same-site assets
> **Status:** Phase 0–1 complete. **Phase 2 home (partial):** hero, about, partners strip, and gallery teaser are shipped. **Recent events** (6 cards) and full inner-page content are still pending — see [Next up](#next-up).

## Setup
---

## Repository & branches

Everything lives in **[Ax108/pcc-foundation](https://github.com/Ax108/pcc-foundation)** (one repo, two branches):

| Branch | Contents |
| ------ | -------- |
| **`master`** | Python scraper + scraped data under `data/pratima_chandra_foundation/` |
| **`react-app-master`** | This Vite React app (`src/`, `public/`, `docs/`, …) at **repo root** |

> **Local folder name** (e.g. `pcc-foundation-react-app`) is only a clone directory — on GitHub the app files are at the clone root on **`react-app-master`**, not in a subfolder.

### Pull scrape data while on the React branch

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
git fetch origin master
git checkout origin/master -- data/pratima_chandra_foundation
```

## Run
Copy selected files from `data/.../assets/images/` into `public/assets/` as pages are built. See [docs/MigrationPlan.md §2.4](./docs/MigrationPlan.md#24-image-assets-dataassetsimages).

---

## What's built

| Area | Status |
| ---- | ------ |
| Bootstrap (Vite, React 19, TS, Tailwind v4, theme tokens) | ✅ |
| Universal chrome — sticky `TopNavBar`, `Footer`, `SiteLayout` | ✅ |
| All 5 routes wired (lazy-loaded) | ✅ |
| Home — accessible hero carousel (4 slides) | ✅ |
| Home — about section (poster + PDF + Read More) | ✅ |
| Home — partners memorial-award strip | ✅ |
| Home — gallery teaser (8 photos → `/gallery`) | ✅ |
| Home — **recent events** (6 cards) | **TODO** — Phase 2; shares data with Phase 4 |
| Inner pages (Inspiration, Gallery, Events list, Contact) | Stubs only |

Full checklist: [docs/Tasks.md](./docs/Tasks.md) · Architecture: [docs/MigrationPlan.md](./docs/MigrationPlan.md)

---

## Next up

| Priority | Work | Docs |
| -------- | ---- | ---- |
| **1** | Home **`RecentEvents`** — 6 cards below gallery teaser | [Tasks.md § Phase 2](./docs/Tasks.md#phase-2--home-page-in-progress) |
| **2** | Shared **`src/content/events.ts`** from scrape (Bengali titles, dates, slugs) | [Tasks.md § Phase 4](./docs/Tasks.md#phase-4--events) |
| **3** | Inner routes — Inspiration, Gallery grid, Events archive, Contact | Phases 3–5 |

Home section order (locked): Hero → About → Partners → Gallery teaser → **Recent events** → footer (global).

---

## Stack

- **UI:** React 19, TypeScript, Vite 8, React Compiler (Babel)
- **Routing & state:** React Router 7, Zustand, Immer
- **Styling:** Tailwind CSS v4, Kodchasan (Google Fonts), design tokens in `src/theme.css`
- **Icons:** Custom Font Awesome subset (`src/app/utils/icons.ts`) — no FA npm packages
- **Tooling:** Bun, ESLint (flat config), Prettier, Fallow

---

## Setup

```bash
python scrape_pratima_chandra_foundation.py
git checkout react-app-master
bun install
bun run dev
```

The files are written to:
Dev server: [http://localhost:5173](http://localhost:5173)

---

```text
data/pratima_chandra_foundation/
## Scripts

| Command | Purpose |
| ------- | ------- |
| `bun run dev` | Start Vite dev server |
| `bun run build` | Typecheck + production build → `dist/` |
| `bun run preview` | Serve production build locally |
| `bun run lint` | ESLint |
| `bun run format` | Prettier (src) |
| `bun run tsc` | Typecheck only |

**Quality gate** (run after UI changes):

```bash
bun run lint && bun run build
```

Downloaded files are grouped under:
---

## Project layout

```text
data/pratima_chandra_foundation/assets/images/
data/pratima_chandra_foundation/assets/site-assets/
data/pratima_chandra_foundation/assets/documents/
data/pratima_chandra_foundation/assets/other/
```
src/
├── app/ hooks (useSEO), utils (icons), routing
├── navigationBars/ TopNavBar, Footer, SiteLayout, nav constants
├── pages/ route modules (home, gallery, events, …)
├── constants/ images.ts — centralized public asset paths
├── theme.css brand tokens (colors, container width)
└── index.css global utilities + section overrides

For a quick test run:
public/
├── assets/ static images, PDFs (served at /assets/…)
├── favicon.* PWA / favicon pack
└── robots.txt

```bash
python scrape_pratima_chandra_foundation.py --limit 3
docs/ migration plan, tasks, design & performance standards
.cursor/rules/ agent rules (e.g. Core Web Vitals)
```

Path aliases (`vite.config.ts` + `tsconfig.app.json`): `@src`, `@app`, `@navigationBars`, `@home`, `@inspiration`, `@gallery`, `@events`, `@contact`, `@public`.

Folder rules: [docs/FolderStructureRules.md](./docs/FolderStructureRules.md)

---

## Static assets (`public/assets/`)

Images and PDFs live under **`public/assets/`**, not `src/assets/`.

| Why `public/` | Detail |
| ------------- | ------ |
| Stable URLs | `/assets/home/slide-1-header-1.jpg` — used in `index.html` LCP preload and `src/constants/images.ts` |
| Scrape workflow | Copy compressed variants from `data/.../assets/images/` with predictable names |
| PDFs & OG | Direct links without import/hashing |

Register every UI asset path in **`src/constants/images.ts`** with explicit `width` / `height` for CLS. See [docs/WebPerformanceSEO.md](./docs/WebPerformanceSEO.md).

---

## Documentation

| Doc | Purpose |
| --- | ------- |
| [MigrationPlan.md](./docs/MigrationPlan.md) | WordPress → React plan, scrape workflow, asset mapping |
| [Tasks.md](./docs/Tasks.md) | Phased checklist with ✅ progress |
| [DesignGuidelines.md](./docs/DesignGuidelines.md) | Brand vs liberty bounds; reference-site patterns |
| [WebPerformanceSEO.md](./docs/WebPerformanceSEO.md) | **Core Web Vitals** (LCP, CLS, INP), SEO, image rules |
| [HTMLSemantics.md](./docs/HTMLSemantics.md) | Landmarks, headings, carousel a11y |
| [FolderStructureRules.md](./docs/FolderStructureRules.md) | Where code and files belong |

**Design principle:** Improve UX, performance, and accessibility using AstraX / PC Chandra patterns — keep PCF brand, copy, nav labels, and home section order from the live WordPress site.

---

## License

Proprietary. All rights reserved.
Loading
Loading