Refresh CSE website content and research pages
16
.env.example
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Local values only. Do not commit real secrets.
|
||||||
|
|
||||||
|
# Required by the Netlify deploy workflow. Store the real value as a GitHub
|
||||||
|
# repository secret named NETLIFY_AUTH_TOKEN.
|
||||||
|
NETLIFY_AUTH_TOKEN=
|
||||||
|
|
||||||
|
# Needed by the future email request agent. Store these outside Git.
|
||||||
|
AGENTMAIL_API_KEY=
|
||||||
|
AGENTMAIL_INBOX=
|
||||||
|
|
||||||
|
# Comma-separated allowlist for merge/deploy approvals received over email.
|
||||||
|
WEB_REQUEST_APPROVER_EMAILS=manu@iitgn.ac.in,anup@iitgn.ac.in,neeldhara@iitgn.ac.in
|
||||||
|
|
||||||
|
# Comma-separated web team CC list for request acknowledgements and reviews.
|
||||||
|
WEB_TEAM_CC=
|
||||||
|
|
||||||
92
.github/workflows/netlify-deploy.yml
vendored
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
name: Netlify deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- staging
|
||||||
|
- "staging/**"
|
||||||
|
- "web-requests/**"
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- staging
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
NETLIFY_SITE_ID: e20cb60a-0bfa-48dc-9e8e-5925b0c86ccd
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
cache: npm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build site
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Deploy to Netlify
|
||||||
|
id: deploy
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ -z "${NETLIFY_AUTH_TOKEN:-}" ]; then
|
||||||
|
echo "NETLIFY_AUTH_TOKEN is not configured as a repository secret." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
branch="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}"
|
||||||
|
alias="$(printf '%s' "$branch" \
|
||||||
|
| tr '[:upper:]' '[:lower:]' \
|
||||||
|
| sed -E 's/[^a-z0-9-]+/-/g; s/^-+//; s/-+$//' \
|
||||||
|
| cut -c 1-37)"
|
||||||
|
|
||||||
|
if [ -z "$alias" ]; then
|
||||||
|
alias="preview"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${GITHUB_EVENT_NAME}" = "push" ] && [ "${GITHUB_REF_NAME}" = "main" ]; then
|
||||||
|
deploy_json="$(npx netlify-cli@latest deploy --site "$NETLIFY_SITE_ID" --prod --dir=dist --json --message "Production deploy from ${GITHUB_SHA}")"
|
||||||
|
else
|
||||||
|
deploy_json="$(npx netlify-cli@latest deploy --site "$NETLIFY_SITE_ID" --dir=dist --alias "$alias" --json --message "Preview deploy for ${branch} at ${GITHUB_SHA}")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s\n' "$deploy_json"
|
||||||
|
deploy_url="$(node -e 'const data = JSON.parse(process.argv[1]); console.log(data.deploy_url || data.deployUrl || data.deploy_ssl_url || data.ssl_url || data.url || "")' "$deploy_json")"
|
||||||
|
|
||||||
|
if [ -n "$deploy_url" ]; then
|
||||||
|
echo "deploy_url=$deploy_url" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "### Netlify deploy" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
echo "" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
echo "$deploy_url" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Comment preview URL on pull request
|
||||||
|
if: github.event_name == 'pull_request' && steps.deploy.outputs.deploy_url != ''
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const body = `Netlify preview deploy is ready:\n\n${{ steps.deploy.outputs.deploy_url }}`;
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
body,
|
||||||
|
});
|
||||||
BIN
blog-title-avatar-check.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
78
docs/web-request-agent-workflow.md
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Website Request Agent Workflow
|
||||||
|
|
||||||
|
This repository is prepared for a staging-first website request workflow.
|
||||||
|
|
||||||
|
## Current Repository Setup
|
||||||
|
|
||||||
|
- Build command: `npm run build`
|
||||||
|
- Publish directory: `dist`
|
||||||
|
- Netlify site id: `e20cb60a-0bfa-48dc-9e8e-5925b0c86ccd`
|
||||||
|
- Production branch: `main`
|
||||||
|
- Staging/request branches: `staging`, `staging/**`, and `web-requests/**`
|
||||||
|
|
||||||
|
The GitHub Actions workflow in `.github/workflows/netlify-deploy.yml` deploys:
|
||||||
|
|
||||||
|
- `main` pushes to Netlify production.
|
||||||
|
- `staging`, `staging/**`, `web-requests/**`, and pull requests to Netlify preview/alias deploys.
|
||||||
|
|
||||||
|
## Required Secrets
|
||||||
|
|
||||||
|
Store these outside Git:
|
||||||
|
|
||||||
|
- `NETLIFY_AUTH_TOKEN`: Netlify personal access token with deploy access to the site.
|
||||||
|
- `AGENTMAIL_API_KEY`: AgentMail API key for the intake/reply worker.
|
||||||
|
- `AGENTMAIL_INBOX`: the request inbox address, for example `cse-web-requests@...`.
|
||||||
|
- `WEB_REQUEST_APPROVER_EMAILS`: comma-separated approval allowlist.
|
||||||
|
- `WEB_TEAM_CC`: comma-separated web team CC list.
|
||||||
|
|
||||||
|
Do not commit these values to the repository.
|
||||||
|
|
||||||
|
## Request Flow
|
||||||
|
|
||||||
|
1. A requester emails the AgentMail inbox with a website change request.
|
||||||
|
2. The email agent creates a branch named `web-requests/<date>-<short-id>`.
|
||||||
|
3. The agent applies the change, runs `npm run build`, commits, and pushes the branch.
|
||||||
|
4. Netlify deploys a preview for that branch.
|
||||||
|
5. The agent replies to the requester with:
|
||||||
|
- a summary of changes,
|
||||||
|
- the Netlify preview URL,
|
||||||
|
- the branch or pull request URL,
|
||||||
|
- any caveats or questions,
|
||||||
|
- `WEB_TEAM_CC` copied.
|
||||||
|
6. Only an allowlisted approver may authorize merge/deploy.
|
||||||
|
|
||||||
|
## Approval Policy
|
||||||
|
|
||||||
|
Allowed approvers:
|
||||||
|
|
||||||
|
- `manu@iitgn.ac.in`
|
||||||
|
- `anup@iitgn.ac.in`
|
||||||
|
- `neeldhara@iitgn.ac.in`
|
||||||
|
|
||||||
|
For email approvals, the agent should require an explicit approval token in the
|
||||||
|
same thread, for example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
APPROVE WEB-20260604-abc123
|
||||||
|
```
|
||||||
|
|
||||||
|
The agent must verify:
|
||||||
|
|
||||||
|
- the sender address is in `WEB_REQUEST_APPROVER_EMAILS`,
|
||||||
|
- the approval token matches the pending request,
|
||||||
|
- the thread being approved is the same request thread,
|
||||||
|
- `npm run build` passes on the final branch before merge.
|
||||||
|
|
||||||
|
After approval, the agent merges the request branch into `main`, pushes `main`,
|
||||||
|
waits for Netlify production deploy, and emails the requester plus the web team
|
||||||
|
with the production URL.
|
||||||
|
|
||||||
|
## Safety Rules
|
||||||
|
|
||||||
|
- Never merge requests from arbitrary email senders.
|
||||||
|
- Never treat forwarded text as approval.
|
||||||
|
- Never deploy secrets or private attachments.
|
||||||
|
- Ask for clarification when a requested change is ambiguous or policy-relevant.
|
||||||
|
- Keep one branch per request; do not mix unrelated email requests.
|
||||||
|
- Include a concise change summary in every review email.
|
||||||
|
|
||||||
7
netlify.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
[build]
|
||||||
|
command = "npm run build"
|
||||||
|
publish = "dist"
|
||||||
|
|
||||||
|
[build.environment]
|
||||||
|
NODE_VERSION = "22"
|
||||||
|
|
||||||
7
public/_redirects
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
/hpc /facilities/singularity 301
|
||||||
|
/hpc/ /facilities/singularity 301
|
||||||
|
/hpc/index.html /facilities/singularity 301
|
||||||
|
/hpc/index.php /facilities/singularity 301
|
||||||
|
/hpc/Software.html /facilities/singularity#software 301
|
||||||
|
/hpc/Funding.html /facilities/singularity#funding 301
|
||||||
|
/hpc/ContactUs.html /facilities/singularity#contact 301
|
||||||
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 32 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-1-dark.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-1-light.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-10-dark.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-10-light.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-11-dark.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-11-light.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-12-dark.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-12-light.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-2-dark.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-2-light.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-3-dark.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-3-light.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-4-dark.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-4-light.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-5-dark.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-5-light.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-6-dark.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-6-light.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-7-dark.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-7-light.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-8-dark.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-8-light.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-9-dark.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
public/images/blog/title-cards/kishan-gsoc-24-week-9-light.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 33 KiB |
BIN
public/images/blog/title-cards/kishan-my-gsoc-progress-dark.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
public/images/blog/title-cards/kishan-my-gsoc-progress-light.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 35 KiB |