Jekyll website for the Aswendt Lab’s research on experimental stroke, neuroimaging, and neuromodulation.
Live website: https://aswendtlab.com/
Use a modern Ruby installation compatible with Bundler 2.5.10 (Ruby 3.1 or newer).
gem install bundler -v 2.5.10
bundle install
bundle exec jekyll serveOpen http://localhost:4000/. To check a production build:
JEKYLL_ENV=production bundle exec jekyll buildThe generated site is written to _site/, which is ignored by Git. Dependencies are pinned in Gemfile.lock; keep this file when updating the site.
index.md: homepage, research introduction, featured publication, and news highlights.reading-list.md: manuscripts shared in the lab's Telegram channel; the page is populated from_data/reading_list.json._data/partners.yml: collaborator names, institutions, and logos shown on the homepage.projects.md: research themes;software.md: AIDA tools, data workflows, tutorials, and poster downloads.opportunities.md: student inquiries and application guidance.paper.md,team.md,news.md: publications, team profiles, and news archive.contact.md,imprint.md: contact details and legal notice.assets/main.scss: shared black theme, responsive layouts, and accessible focus styles._includes/footer.html: footer navigation;_layouts/landing.html: homepage layout.
Use descriptive image alternative text. Add loading="lazy" to images below the first screen. Homepage news highlights and the featured-paper selection are curated manually. The latest-publication cards and Publications page update automatically from the report output.
The site uses GitHub Pages-compatible Jekyll dependencies. _config.yml sets url: https://aswendtlab.com and baseurl: "". Use Jekyll’s relative_url filter for internal links so links resolve correctly at the custom-domain root.
Deployment is managed through the repository’s GitHub Pages settings. Confirm the configured branch or workflow there before publishing; local edits alone do not deploy the site.
Open an issue or submit a pull request. Include a description and screenshots for visual changes. Before submitting, build the site and check navigation, mobile layouts, and links.
Explore the lab’s software repositories.
The Update publications GitHub Actions workflow runs Mondays at 05:23 UTC and can be run manually from the Actions tab. It also runs when its collector/configuration changes on main.
It runs a pinned revision of CitationsReport, reads the generated works_summary_*.csv, and updates:
_data/publications.json: publication list, citation counts, and annual citation history.data/publications.csv: downloadable bibliographic data from the report.pdf/citations-latest.pdf: detailed citation report.
The Publications page and homepage consume the same snapshot. The previous hand-written list remains in _includes/publications-fallback.md and is used only until the first complete successful refresh. New uncited papers are included in the list; the detailed PDF includes works with retrievable citing publications.
- Enable GitHub Actions for this repository and permit the workflow to write repository contents. Branch protection must allow its snapshot commits, or the workflow will stop without publishing.
- Add an
OPENALEX_API_KEYrepository Actions secret for a dedicated OpenAlex API budget. Without it, requests use OpenAlex’s shared unauthenticated IP budget and may fail on shared runners. Never put the key into tracked files. - This workflow preserves the existing Deploy from a branch GitHub Pages setup (
main,/). After committing a validated snapshot it explicitly requests a Pages rebuild, because commits made withGITHUB_TOKENdo not trigger one automatically. If Pages is configured to use a custom Actions deployment instead, adapt the final rebuild step to invoke that deployment. - Run Update publications → Run workflow and confirm both the update and Pages build succeed.
The author is fixed to OpenAlex A5088353298 and ORCID 0000-0003-1423-0934 in scripts/publications-config.json. The refresh verifies both and never searches by name. The export contains all works returned for that author, including work before the lab was established; this is not an aggregate bibliography of every lab member. display_types sets the published-work types displayed on the website. exclude_ids and exclusion_notes identify known conference abstracts misclassified by OpenAlex; these exclusions affect display only, never the complete CSV export.
The runner uses the original report generator with strict complete pagination, fixed author selection, and OpenAlex-only bibliographic metadata (optional per-citation Crossref enrichment is disabled to avoid thousands of extra requests). It stages output in a temporary directory and stops on incomplete downloads, malformed CSV, mismatched author identity, or a large drop in the existing publication list. A production Jekyll build must pass before the workflow commits anything. Failed runs leave the last published snapshot in place; check failed-run notifications in GitHub Actions.
Citation counts count links to the listed works, not unique citing papers; one citing paper can contribute more than one link. The downloadable CSV retains every fetched record, including preprints and conference contributions; the PDF provides detailed citation reports for cited works across all record types. The website list, homepage cards, publication count, citation count, and annual chart use published journal articles, reviews, data papers, books, and book chapters. Repository-only records, abstracts, presentations, and preprints are excluded from display. Duplicate DOIs, JoVE article/video pairs, and matching-title versions from the same venue and first author are counted once on the website while all source rows remain in the CSV. Annual history reflects the recent-year window supplied by OpenAlex. SCImago 2025 values are explicitly labelled citations per document (2 years), not official Clarivate JIFs; that bundled journal-metrics year does not refresh automatically.
To change the featured publication, edit its DOI in index.md. Recent publications below it are selected automatically. Bibliographic corrections should be made upstream in OpenAlex where possible.
Use Python 3.12 in a virtual environment, then:
pip install -r scripts/requirements-publications.txt
python -m unittest discover -s tests -v
python scripts/update_publications.py
JEKYLL_ENV=production bundle exec jekyll build --strict_front_matterSet OPENALEX_API_KEY through your environment or secret manager if needed. A complete report retrieves citing works for every cited publication and can take several minutes. The reporter revision is pinned in scripts/update_publications.py; update it deliberately when upgrading the tool.
Validation also checks internal links and anchors with bundle exec ruby scripts/check_links.rb and filter behavior with node --test tests/publications.test.js. The report adapter corrects PMID values read as floating-point numbers by pandas. The page distinguishes OpenAlex’s indexed citation counts from the report’s actually retrieved citation links.
The adapter embeds DejaVu Sans fonts from Matplotlib and normalizes typographic hyphens so author names and publication titles render correctly in the PDF.
The shared AIDA video and GitHub repository overview are defined in _includes/tools-feature.html and shown on both the homepage and Software & Data page. The feature displays img/AIDA-Tools-Animation.gif as an automatically looping image, with a pause/resume button. Visitors who prefer reduced motion see img/AIDA-Tools-Illustration.jpg instead. The MP4 remains the source asset for future GIF regeneration.
The Update reading list workflow checks Telegram every 15 minutes and adds PubMed-indexed journal articles and reviews to the Reading list page. Entries use plain-text PubMed-formatted citations, a Journal Club column, and a separate DOI link; other posts and private bot chats are ignored.
To connect the bot:
- In Telegram, open @BotFather, send
/newbot, choose a display name and a username ending inbot. Copy the token it gives you; treat it like a password. - Open the private channel's Manage channel → Administrators → Add administrator, find the bot by username, and add it. It does not need posting or editing rights. Keep this dedicated bot in this channel only.
- In the GitHub repository, open Settings → Secrets and variables → Actions → New repository secret. Name it
readinglistauto_botand paste the token as its value. Never put the token in a file, command, or chat. - Open Settings → Actions → General → Workflow permissions and select Read and write permissions.
- In Actions → Update reading list → Run workflow, run it once. The workflow will discover the channel and check for new posts every 15 minutes. A post's date is retained; the page lists the newest post first.
To import older posts once, use Telegram Desktop while signed into an account that can access the channel:
- Open the channel, use its ⋮ menu and choose Export chat history (or use Settings → Advanced → Export Telegram data and select the channel). Choose JSON and include text messages. Export locally; the export can contain private channel content.
- Find the exported JSON file containing the channel's
messagesarray (commonly namedmessages.jsonorresult.json). Do not put the export inside the repository. - From the website repository, run
python3 scripts/update_reading_list.py --history-export "/full/path/to/messages.json". The script reads it locally, extracts manuscript links and dates, merges DOI duplicates, and updates_data/reading_list.jsonin newest-first order. It does not send the export to Telegram or GitHub. - Review the generated reading list, then commit and push
_data/reading_list.json. The next scheduled workflow run will continue importing new posts without re-adding the historical DOI entries. - Delete the local export when you're done, subject to your lab's data-retention policy.
The Bot API cannot download channel history, so Desktop export is the one-time backfill route. The importer tracks the live Telegram update offset and discovered channel ID in _data/reading_list_state.json; the workflow commits that state with the data. Do not edit the offset manually. Telegram only retains uncollected bot updates for a limited time, so enable the workflow promptly after adding the bot.
Team profiles are stored in _data/team.yml. The Team page renders them as portrait tiles that start in color. On devices with mouse hover, hovering a tile turns all other portraits grayscale and reveals a small Info control below its name; leaving the tile restores the other portraits' color, including in grid gaps. Keyboard focus also reveals Info. Touch devices keep all portraits in color and always show Info on closed profiles. Only selecting Info opens a biography; hovering or selecting the portrait or name does not. Open biographies hide the Info control and have no close button. assets/team.js closes them when the mouse leaves the portrait tile, when a click or tap lands outside it, with Escape (returning focus to Info), or when focus leaves the tile. Touch and pen pointer-leave events do not close biographies. Opening focuses the scrollable text area for keyboard navigation and temporarily removes the hidden Info control from the tab order. Fields grow with their text up to half the portrait height, including a fixed 46px fade at the top. Only the heading and biography below that fade scroll, so text never enters the transparent transition.
The CSV adds type, source_type, and displayed_on_website columns so the full export can be audited against the filtered publication list. Source/type information and explicit conference exclusions are applied automatically on every refresh.
The custom domain is declared in CNAME (aswendtlab.com). DNS is managed through Namecheap BasicDNS. HTTPS certificates are provisioned by GitHub Pages; enable Enforce HTTPS in the repository’s Pages settings once certificate issuance completes.