Bilingual academic blog and publication portal for the DINA Laboratory.
Live Site · Publications · Members · Report a bug · Request a feature
DINA Lab Blog is the public web presence of the DINA Laboratory — Distributed Infrastructure for NextGen Applications — at Iran University of Science and Technology. The repository is a static Astro site that serves two audiences at once: lab members who publish research notes and announcements, and readers who follow the lab's publications and people.
The site is bilingual. Every post declares its own language in frontmatter, and the site chrome (navigation, footer, listings, search, labels) can be switched between English and Persian at runtime, with full right-to-left support for Persian. Content pillars are blog posts, publications, and lab members. The output is fully static and is deployed to GitHub Pages by a workflow on every push to main.
- Bilingual posts — language declared per-post via frontmatter (
lang: en | fa) - Runtime chrome-language toggle (English / Persian) with RTL support, persisted in localStorage
- Content-zone isolation: posts, cards, and publications follow their own language and direction regardless of the site chrome
- MDX posts with reusable components:
Figure,Tabs,VideoEmbed,AudioPlayer,JupyterNotebook - Distill-style layout for research articles (
distill: true) - KaTeX math, Mermaid, Vega-Lite, Chart.js, Plotly, TikZ, pseudocode, Typograms — all opt-in per post
- Build-time Jupyter notebook rendering (no Python at runtime)
- BibTeX-driven publications page with per-year grouping
- Live search across titles, authors, venues, years
- Badges: Google Scholar citation counts, Altmetric, Dimensions, InspireHEP (per-entry opt-in)
- Co-author link resolution via
coauthors.yml - Automatic citation-count refresh via weekly GitHub Action
- Full-text search with Pagefind (build-time index) and a keyboard-driven command palette
- Dark / light theme with system-preference detection
- Auto-generated Open Graph images via Satori
- Reading progress, table of contents, related posts, RSS, sitemap
- Medium-zoom for post images, reading-time estimates
- Strict TypeScript, ESLint flat config, Prettier, simple-import-sort
- Vitest for utilities, Playwright for smoke tests
- GitHub Actions CI (type-check, lint, unit tests, build) and CD
- Husky + lint-staged + commitlint for conventional commits
| Layer | Choice |
|---|---|
| Framework | Astro 6 (static output) |
| UI islands | React 19 |
| Styling | Tailwind CSS 4 + CSS custom properties |
| Content | Astro Content Collections + MDX |
| Search | Pagefind |
| Testing | Vitest (unit), Playwright (e2e) |
| Tooling | Yarn 4, ESLint, Prettier, Husky |
| Deployment | GitHub Pages |
- Node.js 24 or newer
- Yarn 4 (via Corepack — Node ships it)
corepack enable
git clone https://github.com/DINA-Lab-IUST/blog.git
cd blog
yarn install --immutable
cp .env.example .env
# edit .env — set ASTRO_SITE and ASTRO_BASE
yarn devThe dev server runs at http://localhost:4321. When ASTRO_BASE is set, pages are served under that prefix.
Only two variables are used, both consumed by astro.config.mjs and re-exported through src/config/site.ts:
| Variable | Purpose | Example |
|---|---|---|
ASTRO_SITE |
Public origin of the deployed site | https://dina-lab-iust.github.io |
ASTRO_BASE |
Base path for GitHub project pages | /blog |
Leave ASTRO_BASE empty for user/org pages; set it to /repo-name for project pages.
src/
components/ Reusable Astro + React components
layouts/ Base, Page, Post, Distill layouts
pages/ Route handlers (blog, members, publications, feeds)
content/ Post and people MDX/MD files
data/ BibTeX, citation counts, co-author links
config/ Single source of truth: site.ts
styles/ Global CSS, color tokens, typography
utils/ Pure helpers (bibtex, i18n, reading-time, search)
public/
assets/ Favicons, logos, JS shims, sample SVGs
scripts/ Content validation + citation refresh
e2e/ Playwright smoke tests
.github/ CI, Deploy, Citation refresh, Release-please
Create src/content/posts/<slug>.mdx (or .md for plain Markdown). Minimum frontmatter:
---
title: Your post title
date: 2026-01-15
description: One-line summary shown in listings and search.
tags: [tag-one, tag-two]
categories: [research]
lang: en # or 'fa' for Persian
authors: [member-slug]
---Optional fields (math, toc, relatedPosts, pinned, hidden, draft, robots, lastmod, redirect, image, distill, refs, and the per-post chart and render flags) are documented in src/content.config.ts.
Open src/data/papers.bib and append one BibTeX entry per publication. Required: title, author, year, and one of journal / booktitle / publisher. Strongly recommended:
abbr— short venue abbreviation shown as a pill on the cardabstract— enables the Abstract toggledoi— enables DOI link, DOI-based badges, citation countingpreview— thumbnail filename underpublic/assets/img/publication_preview/pdf— filename underpublic/assets/pdf/google_scholar_id— required for citation countsbibtex_show: true— enables the Bib toggle
Persian-language entries should set lang: fa and may provide author_fa for localized author display.
After editing, run:
yarn citations:update
yarn content:checkCreate src/content/people/<slug>.md where <slug> is what posts reference in authors. Minimum:
---
name: Full Name
role: PhD Student
group: current # 'supervisor' | 'current' | 'alumni'
photo: /assets/img/people/photo.jpg
focus: [federated-learning, llm-infrastructure]
website: https://example.com
github: username
---Optional Persian fields: nameFa, roleFa, descriptionFa. The members page renders bilingual blocks based on the visitor's chrome language.
yarn content:checkThis runs scripts/check-content.ts — a fast frontmatter validator that catches typos in authors, refs, lang, and image paths without a full build. It runs automatically in CI on content-only PRs.
| Command | Purpose |
|---|---|
yarn dev |
Start the dev server |
yarn build |
Static build + Pagefind index |
yarn preview |
Preview the production build locally |
yarn check |
Astro's type-check pass |
yarn test:types |
astro check + tsc --noEmit |
yarn lint |
ESLint with autofix |
yarn lint:ci |
ESLint without writes |
yarn format |
Prettier |
yarn test |
Vitest unit tests |
yarn test:watch |
Vitest in watch mode |
yarn test:e2e |
Playwright smoke tests |
yarn test:all |
Full gate: types, lint, unit, e2e |
yarn content:check |
Fast frontmatter validation |
yarn citations:update |
Refresh citation counts from OpenAlex |
- Unit tests (Vitest, happy-dom environment) cover pure utilities: BibTeX parsing, i18n helpers, reading time, search rank, copy buttons, author linking. Run with
yarn test. - End-to-end tests (Playwright, Chromium) cover critical paths: homepage, members, publications, dark-mode persistence, language switch, 404. Run with
yarn test:e2e. The config usesyarn previewagainst a fresh build. - CI splits into two jobs based on changed paths (
dorny/paths-filter):- Content-only PRs run
yarn content:checkonly (fast). - Template PRs run the full gate:
test:types→lint:ci→test→build.
- Content-only PRs run
Deployment is fully automated via .github/workflows/deploy.yml on every push to main:
- Checkout, install,
yarn buildwithASTRO_SITEandASTRO_BASEread from repository variables. - Commit updated
src/data/citations.ymlif the citation refresh produced changes. - Upload the
dist/artifact and deploy to GitHub Pages.
Repository variables to set (Settings → Secrets and variables → Actions → Variables):
ASTRO_SITE— e.g.https://dina-lab-iust.github.ioASTRO_BASE— e.g./blog(leave empty for user/org pages)
Falls back to the DINA Lab deployment defaults if the variables are unset.
-
Commit messages follow Conventional Commits — enforced by commitlint.
-
Pre-commit hook runs
lint-staged(ESLint on TS/TSX/Astro, Prettier on JSON/CSS/MD/YAML). -
Before opening a PR:
yarn test:types yarn lint:ci yarn test yarn test:e2e -
For content-only contributions (posts, people, bib entries), CI runs the fast
content:checkpath. -
Keep pull requests focused. One concern per PR.
Released under the MIT License — see LICENSE. The upstream theme's
copyright notice is retained in the same file.