1. Overview
বাংলা পঞ্জিকা is a modern, interactive Bengali calendar web application that displays the Bengali (Bangla Sansan) calendar alongside Gregorian dates. It follows the Bisuddha Siddhanta system used in West Bengal, India.
The project has three distinct layers:
- Data Layer —
panjika_data.json(auto-scraped) +events.json(manually curated) - Automation Layer — Python scraper + GitHub Actions CI/CD
- Presentation Layer — Pure HTML/CSS/JS frontend deployed on Cloudflare Pages
2. Architecture
The system follows a static-first, data-driven architecture. No server is needed at runtime — the calendar runs entirely in the browser using pre-computed JSON data.
prokerala.com (source)
↓ (scraped annually via GitHub Actions)
generate_panjika.py
↓
panjika_data.json ←──── GitHub Private Repo ────→ events.json
↓ ↓
└───────────────── Frontend JS ────────────────────┘
↓
Cloudflare Pages (CDN)
3. Folder Structure
├── src/ # Web frontend
│ ├── index.html # Main HTML
│ ├── css/
│ │ └── style.css # All styles, themes, animations
│ └── js/
│ ├── data.js # Data loading & conversion
│ ├── calendar.js # State management
│ ├── ui.js # UI rendering
│ └── main.js # App bootstrap
├── data/ # All JSON data files
│ ├── panjika_data.json # Bengali month lengths (auto-scraped)
│ └── events.json # Festival & event data
├── scripts/ # Data maintenance
│ └── generate_panjika.py
├── docs/
│ └── documentation.html # This file
└── .github/workflows/
└── update_panjika.yml
4. Data Strategy
Collection Schedule
| Trigger | Action | Years Fetched |
|---|---|---|
| Annual (April 20) | GitHub Actions auto-run | Current + next 3 (4 total) |
| Manual dispatch | GitHub Actions manual trigger | Current + next 3 |
| 5-year batch | Run script locally with range arg | Any 5-year window |
| Fallback | VERIFIED_DATA table in script | Hardcoded safe values |
Why Bisuddha Siddhanta?
There are two systems for the Bengali calendar:
- Bisuddha Siddhanta — Used in West Bengal, India. Month lengths vary (29–32 days). Astronomical basis.
- Bangla Academy — Used in Bangladesh. Fixed month lengths (first 6 months = 31 days, rest = 30). Standardized in 1987.
This project uses Bisuddha Siddhanta data sourced from prokerala.com.
5. Panjika Data JSON
File: data/panjika_data.json
{
"1433": {
"b1": "2026-04-15", // Gregorian date of Boishakh 1 (Poila Boishakh)
"m": [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30]
// ↑ Boishakh ↑ Asharh ↑ Poush ↑ Choitro
// 12 values = 12 Bengali months
}
}
Conversion Algorithm
To find the Bengali date for any Gregorian date:
- Find which BS year range contains the target Gregorian date (using
b1of year N and year N+1) - Starting from
b1, walk month by month using themarray - Stop when the cursor exceeds the target date — the previous month was the Bengali month
- The day number is
target - monthStart + 1
6. Events Data JSON
File: data/events.json
Events are stored in three categories:
a) Recurring Bengali Date Events
Events that occur on the same Bengali month/day every year (e.g., Pohela Boishakh = Boishakh 1):
{
"recurring": [
{
"bMonth": 1, "bDay": 1,
"name": "পহেলা বৈশাখ — বাংলা নববর্ষ",
"nameEn": "Pohela Boishakh — Bengali New Year",
"type": "national", // religious | national | cultural | seasonal
"emoji": "🎊",
"desc": "বাংলা নববর্ষের প্রথম দিন।"
}
]
}
b) Fixed Gregorian Events
Events on fixed Gregorian dates (e.g., Christmas = December 25):
{
"fixed_gregorian": [
{ "gregMonth": 12, "gregDay": 25, "name": "বড়দিন", ... }
]
}
c) Year-Specific Events
One-off events for a specific BS year:
{
"year_specific": {
"1433": [
{ "bMonth": 4, "bDay": 22, "name": "বিশেষ অনুষ্ঠান", ... }
]
}
}
7. Scraping Script
File: scripts/generate_panjika.py
Dependencies
pip install requests beautifulsoup4
How It Works
Scan monthly pages
For each BS year, fetches prokerala.com/calendar/bengalicalendar-{month}-{year}.html for ~14 months (April of year N to May of year N+1).
Parse calendar grid
Reads the HTML <table> and finds cells where the Bengali date resets to 1 — these are month-start dates.
Compute month lengths
Collects 13 consecutive month-start dates (Boishakh of year N → Boishakh of year N+1). Differences between consecutive starts = month lengths.
Sanity checks
Validates: Boishakh 1 falls Apr 13–16, all 12 months present, each month 28–33 days, total 359–367 days.
Fallback
If scraping fails, uses hardcoded VERIFIED_DATA table (manually sourced, always correct).
Save JSON
Merges with existing data and saves panjika_data.json (sorted by BS year, no duplicate writes if unchanged).
8. GitHub Actions Automation
File: .github/workflows/update_panjika.yml
Schedule
cron: "0 6 20 1 *" # Runs January 20 at 06:00 UTC every year
"0 6 20 4 *" (April 20, after Poila Boishakh) so new year data is available before the festival.
Workflow Steps
- Checkout repository
- Setup Python 3.11
- Install
requestsandbeautifulsoup4 - Run
generate_panjika.py - If
panjika_data.jsonchanged — commit and push
9. Frontend Architecture
The frontend is pure vanilla HTML/CSS/JS — no build tools, no frameworks, no bundlers. It loads directly in any browser.
| File | Responsibility |
|---|---|
data.js | Data loading, Bengali↔Gregorian conversion, events lookup, formatting helpers |
calendar.js | App state management, navigation logic, keyboard shortcuts |
ui.js | DOM rendering — grid, nav, events panel, modals, particle canvas |
main.js | Bootstrap, event binding, touch gesture handling |
style.css | All visual styles, CSS variables (light/dark), animations, responsive layout |
10. Features
| Feature | Description | Status |
|---|---|---|
| Bengali Calendar Grid | Full month grid with Bengali numerals | ✓ Live |
| Gregorian Date Sync | Each cell shows corresponding English date | ✓ Live |
| Today Highlight | Current day highlighted with pulsing animation | ✓ Live |
| Events Panel | Monthly events list with type filtering | ✓ Live |
| Day Detail Modal | Click any day for full event details | ✓ Live |
| Dark Mode | Full dark/light theme toggle | ✓ Live |
| Hard Mode | Blurs English dates — test your Bengali calendar knowledge | ✓ Live |
| Language Toggle | Bengali / English interface switch | ✓ Live |
| Year Navigation | Browse any year from 1429–1450 BS | ✓ Live |
| Month Tabs | Quick jump to any month | ✓ Live |
| Swipe Gestures | Mobile swipe left/right to change months | ✓ Live |
| Keyboard Shortcuts | Arrow keys, T, D, H, Esc | ✓ Live |
| Floating Particles | Animated Bengali characters in background | ✓ Live |
| Persistent Theme | Theme preference saved in localStorage | ✓ Live |
11. Deployment on Cloudflare Pages
Push to GitHub
Push the entire project to a private GitHub repository (e.g., dr-susovon/bangla-calendar).
Connect to Cloudflare Pages
Go to Cloudflare Pages → Create a project → Connect to GitHub → Select your repo.
Build Settings
Build command: (leave blank — no build step)
Output directory: src
Root directory: / (project root)
Data file paths
In data.js, the fetch paths use ../data/ relative to src/. Cloudflare will serve data/ from project root — paths will resolve correctly.
Custom domain (optional)
Add a custom domain in Cloudflare Pages settings. DNS propagates in minutes.
Auto-deploy on push
Every time GitHub Actions commits updated panjika_data.json, Cloudflare Pages automatically redeploys — zero manual work needed.
12. Keyboard Shortcuts
| Key | Action |
|---|---|
← | Previous month |
→ | Next month |
↑ | Previous year |
↓ | Next year |
T | Jump to today |
D | Toggle dark mode |
H | Toggle hard mode |
Esc | Close modal |
13. Extending the Project
Add new events
Edit data/events.json — add entries to recurring, fixed_gregorian, or year_specific sections. No code changes needed.
Add new years (manual)
Add entries to VERIFIED_DATA dict in generate_panjika.py, then run the script.
Fetch 5 years at once
Modify the targets list in main() of the script:
targets = list(range(this_bs, this_bs + 5))
Add more event types
Add a new type value in events.json, then add corresponding CSS class in style.css (for the dot color and badge color).
Localize to other languages
Add a new language to data.js (MONTHS_XX, WEEKDAYS_XX), add a toggle option in main.js.