This documentation contains everything required to manage the Malang website and its supporting tools. It includes guides for updating website content, using internal utilities, managing broadcasts, and maintaining workflows used by the Malang core team.
-
Site
-
Updation
-
Events
-
Galleries
-
Members
-
-
Management
- Site Structure
- Variables
-
Workflows
-
-
Broadcasts
- Go to
/resrc/data/events.jsonand add events like:
[
{
"name": "EVENT NAME",
"date": "EVENT DATE",
"location": "EVENT VENUE",
"description": "EVENT DESCRIPTION",
"image": "[/resrc/images/misc/IMAGE] || IMAGE URL",
"buttons": [
{
"text": "ALTERNATE BUTTON TEXT",
"link": "REDIRECTION LINK",
"focus": false
},
{
"text": "PRIMARY BUTTON TEXT",
"link": "REDIRECTION LINK",
"focus": true
}
]
}
]- Go to
/resrc/data/timeline.jsonand add events like:
{
"title": "EVENT TITLE",
"date": "EVENT DATE",
"description": "EVENT DESCRIPTION",
"images": [
list of paths of images to be added
]
}- Go to
/resrc/data/artworks.jsonand add artwork like:
"0": {
"title": "ARTWORK TITLE",
"artist": "ARTIST'S NAME",
"type": "ARTWORK TYPE"
}Caution
Artwork image must be in .webp format.
The JSON key must be unique, continued series of existing keys and must match the image name.
Note
Don't forget to add artwork image in resrc\images\artworks folder.
Update the artwork count in src/scripts/gallery.js:
// artwork count and photograph count
const total = mode === 'artworks' ? 68 : 42;
^- Go to
/resrc/data/photographs.jsonand add artwork like:
"0": {
"title": "PHOTOGRAPH TITLE",
"artist": "PHOTOGRAPHER'S NAME",
"type": "PHOTOGRAPH TYPE"
}Caution
Phogograph must be in .webp format.
The JSON key must be unique, continued series of existing keys and must match the image name.
Note
Don't forget to add photograph in resrc\images\photographs folder.
Update the photograph count in src/scripts/gallery.js:
// artwork count and photograph count
const total = mode === 'artworks' ? 68 : 42;
^Active core team members are managed in resrc/data/core.json.
The structure groups members by their generation and academic year.
- Go to
/resrc/data/core.jsonand add/update members in the current generation:
[
{
"year": "2026-2027",
"generation": "Gen VIII",
"members": [
{
"name": "Member Name",
"role": "Role Title",
"image": "image_name.webp",
"branch": "Branch Name",
"linkedin": "https://linkedin.com/in/...",
"github": "https://github.com/..."
}
]
}
]Caution
Member images must be placed in the resrc/images/members/ directory.
Past core members who have graduated or completed their tenure are recorded in resrc/data/alumni.json.
- Go to
/resrc/data/alumni.jsonand append a new generation block exactly like the core members format above when a batch passes out.
Associates are active club contributors whose data is loaded dynamically via a CSV file hosted in the media repository.
- To update the Associates list, edit the
members.csvfile in the MalangBvp/media repository. - Required Columns:
Name,Position,Year,Branch,Division. - Changes made to the CSV will automatically reflect on the Associates page.
This section covers the internal tools restricted to authorized members. Access is strictly managed.
The Account portal serves as the gateway to restricted utilities. Authentication is managed in two ways:
- Firebase Authentication: Members must sign in with Google. To grant a new member access, add their email address to the array in
/resrc/data/member-emails.json. - Passcodes: Some pages (like Treasury, Media Kit, and Drafts) require a specific passcode. Passcodes are base64-encoded and verified inside
src/scripts/authentication.js.
The Claims page allows members to submit bills for reimbursement.
- Process: Members submit their name, the bill amount, and attach an image/PDF of the bill.
- Backend: The form encodes the file to Base64 and sends a POST request to a configured Google Apps Script endpoint which logs the claim into a Google Sheet with a "Pending" status.
The Redirector allows the core team to create shortened, custom links (malangbvp.in/[slug]).
- Process: Entering a long URL and a custom slug (
postfix) directly modifies the redirects JSON file. - Backend: It uses the Vercel serverless function
api/create-redirect.js, which fetches the existingr/redirects.jsonvia the GitHub API, checks for duplicates, appends the new redirect, and commits it directly to the repository using a securely storedPERSONAL_PAT.
The Treasury dashboard tracks all Malang expenses and funds.
- Process: Members log transactions by selecting a category header (e.g., Bharatiyam, Funds) and inputting a positive or negative amount.
- Backend: It communicates with a Google Apps Script to log transactions to a master Google Sheet. The page dynamically fetches the data from the sheet to render real-time balance and expense charts using
Chart.js.
A built-in QR Code Generator helps create scan-able QR codes for any link (e.g., for event registration posters).
- Note: This is an independent utility and is not related to the separate Attendance QR Tool.
M-ArUCo is an augmented reality scanner built into the site.
- Process: It scans physical ArUCo markers and maps their specific IDs to designated redirect links.
- Update Mapping: To change where a marker leads, update the ID mapping in
/resrc/data/aruco.json:
{
"1": "https://tejasgupta.work",
"2": "https://malangbvp.in/events"
}The Media Kit provides access to official logos and branding assets for Malang.
- It is a passcode-protected page accessible via the Account portal.
The project is organized into several key directories:
src/: Contains the source code for the site.components/: Reusable HTML components (Navbar, Footer, etc.).pages/: Individual HTML pages.scripts/: Client-side JavaScript logic.styles/: CSS stylesheets.
resrc/: Contains resources like images, icons, and JSON data files (resrc/data/) that power the site content.api/: Contains Vercel serverless backend functions (e.g.,create-redirect.js).variables/: Configuration files and parameters.
The variables/ directory contains configuration parameters used across different tools.
- Currently, it holds
utils.json, which defines paths to structural text files (e.g.,structure_path_txt).
A GitHub Action (.github/workflows/update-search-data.yml) runs automatically every Sunday at midnight (or can be triggered manually) to parse the site's HTML files.
- It executes a Python script (
generate_search_data.py) to build an up-to-datesearch.json(for the site-wide search bar) andsitemap.xml(for SEO). - It then commits and pushes these changes directly to the
mainbranch.
A GitHub Action (.github/workflows/update-structure.yml) maintains an up-to-date representation of the project's directory tree.
- It runs a Python script to generate a text-based tree structure of the repository.
- The output is saved to
/documentation/structure/structure.txt, ensuring developers always have a clear map of the codebase.
| Tool | CSV Requirements | How to use? |
|---|---|---|
| Certificate Tool | name | Read |
| Contact Tool | contact no. | Read |
| Mail Tool | name, email | Read |
For creating bulk certificated with custom names and font-style.
# sample configuration -----------------------------------------------------------------------
output_dir = "Certificate-tool/certificates"
# Certificate template (PNG/JPG)
template_path = "Certificate-tool/certificate_template.jpg"
#font style
pdfmetrics.registerFont(TTFont('NoticiaText', 'Certificate-tool/NoticiaText-BoldItalic.ttf'))
# size
PAGE_WIDTH, PAGE_HEIGHT = landscape(A4)
# position of the name on the certificate
NAME_X = PAGE_WIDTH / 1.6
NAME_Y = PAGE_HEIGHT / 1.8
FONT_SIZE = 42
data="Mail-tool/shortlisted.csv"
#--------------------------------------------------------------------------------------------- output_dir: path of directory where certificates are saved
- template_path: path of certificate template.
Caution
Template must be .png or .jpg.
- Store
.ttffile inCertificate-tool/for custom font and refer it here
#font style
pdfmetrics.registerFont(TTFont('NoticiaText', 'Certificate-tool/NoticiaText-BoldItalic.ttf'))- Set NAME_X and NAME_Y for position of name on the certificate.
- FONT_SIZE: Sets the size of name text.
- data: Is the path to the file containing names.
For saving bulk contacts to Google contacts, generally useful for adding multiple people to Whatsapp group.
- Install dependencies
pip install google-auth google-auth-oauthlib google-auth-httplib2 google-api-python-client- Enable Google People API
-
Create a project in Google Cloud Console.
-
Enable Google People API.
-
Create OAuth credentials (Desktop app) and replace
credentials.json.
# configurations ---------------------------------------------------
contacts_file = 'Contact-tool/contacts.csv' # CSV file path
prefix = "malang2025@" # Contact name prefix
#-------------------------------------------------------------------contacts.csv→ one phone number per line, like:
8279843949,
1234567890,- Contacts will be created as:
malang2025@1,malang2025@2, etc.
Used for sending bulk emails with customised names, template and attachments.
Note
email_template.html is the customizable design template of the email to be sent.
Important
Always use media like images, posters, etc. from this repo using links like:
https://raw.githubusercontent.com/MalangBvp/media/refs/heads/main/images/malang.webp
# ------------- sample configurations --------------
subject = "Malang: Welcome to the club! 🥳"
csv_path = "Mail-tool/shortlisted.csv"
attachment_dir = "Certificate-tool/certificates"
#---------------------------------------------------- subject: Subject of the emails to be sent.
- csv_path: Path of file that contains names and emails.
- attachment_dir: Path of directory where attachments are stored.
Send E-mails to newsletter subscribers via Mail Tool.