Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ Every time you add commits to the Pull Request, Netlify will automatically updat

Once approved, a maintainer will merge your PR. If your changes need revision, follow their instructions and update your PR.

## Editing the home page FAQ

The Frequently Asked Questions section on the home page is generated from a single data file: [`data/faq.yaml`](./data/faq.yaml). To add, edit, reorder, or remove a question, edit that file directly via the GitHub web UI (no template or layout changes are needed for ordinary content edits). The file's header comment documents the schema; for a longer walkthrough see [`docs/maintaining-faq.md`](./docs/maintaining-faq.md).

## Local Development

To set up a local development environment:
Expand Down
3 changes: 3 additions & 0 deletions content/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,6 @@ A national biotechnology development center dedicated to developing tools and se
subtitle="Why reproducible neuroimaging"
>}}
{{< /rn-buttons >}}

<!-- FAQ content lives in data/faq.yaml — see docs/maintaining-faq.md for the editing guide. -->
{{< rn-faq >}}
66 changes: 66 additions & 0 deletions data/faq.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Home page Frequently Asked Questions
#
# Each item under `entries:` becomes one expandable question on the home page.
# Order in this list = order on the page. To add, edit, or remove a question,
# just edit this file and commit.
#
# Schema:
# - question: Short question text (plain text, ends with "?").
# answer: |
# Multi-line Markdown answer. Use the "|" pipe so newlines and
# lists are preserved. Links and **emphasis** work normally.
# id: (optional) explicit URL anchor for deep-linking, e.g.
# "fellowship-apply". Use lowercase, kebab-case. If you set
# this once, you can later reword the question without
# breaking external links to it.
#
# Anchors auto-generated from the question (when no `id:` is set) take the
# form "faq-<slugified-question>", e.g. "faq-how-do-i-get-started". Share
# https://repronim.org/#faq-how-do-i-get-started to deep-link directly.
#
# Detailed maintainer guide: docs/maintaining-faq.md

entries:
- question: What is ReproNim?
answer: |
ReproNim is a national biotechnology development center dedicated to
developing tools and services that increase efficiency, rigor,
reproducibility, transparency, and FAIRness in neuroimaging. See the
[About page](/about/) for the center's history, team, and mission.

- question: Who is ReproNim for?
answer: |
Researchers, students, data managers, and institutions working with
neuroimaging data — at any stage of a project. If you produce, share,
analyze, or steward MRI/EEG/MEG datasets and want to make that work
more reproducible, ReproNim's tools and guidance are aimed at you.

- question: How do I get started?
answer: |
The [Getting Started](/resources/getting-started/) page is the best
entry point. From there you can branch into specific
[tools](/resources/tools/) and [tutorials](/resources/) depending on
what you're trying to do.

- question: Where can I find ReproNim's tools?
answer: |
All recommended tools are catalogued on the
[Tools page](/resources/tools/), with links to documentation, tutorials,
and community help forums for each one.

- question: How can I participate in the ReproNim community?
answer: |
Visit the [Participate page](/participate/) for current opportunities —
working groups, hackathons, webinars, and ways to contribute to ongoing
projects.

- question: Where can I get help or attend office hours?
answer: |
Email [info@repronim.org](mailto:info@repronim.org) anytime. Virtual
drop-in office hours run on the first Thursday of every month — see the
[Help page](/help/) for details and additional support resources.

- question: How do I apply to the ReproNim Fellowship?
answer: |
Application timelines, eligibility, and current cycle details live on
the [Fellowship page](/fellowship/).
85 changes: 85 additions & 0 deletions docs/maintaining-faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Maintaining the home page FAQ

**Audience**: ReproNim maintainers (anyone already comfortable editing site Markdown via GitHub)
**Time to add a new entry**: ~5 minutes

The Frequently Asked Questions section on the home page is generated from a single data file. This guide walks through adding, editing, reordering, and removing entries — all without touching any layout or template code.

## TL;DR

To add an FAQ entry, edit one file: **`data/faq.yaml`** in the repo. Append a new list item under `entries:`, commit, and the question appears on the home page after the next Netlify deploy.

## Step-by-step: add a new FAQ entry

1. **Open `data/faq.yaml`** on GitHub. The "Edit this page" workflow that already works for site Markdown also works for data files — open the file in the GitHub UI and click the pencil icon.

2. **Append a new list item** under `entries:`. Use this template:

```yaml
- question: Your question goes here?
answer: |
Your answer goes here. You can use **Markdown**:
- Lists work.
- [Links](/resources/) work.
- `Inline code` works.
```

Notes:
- The `|` after `answer:` is YAML's literal block scalar. It lets you write multi-line Markdown naturally.
- Indent the answer body two spaces past the `answer:` key, as shown.

3. **(Optional) Set a stable anchor** by adding an explicit `id:` field. Recommended whenever you expect the question wording might change later but you want existing deep links to keep working.

```yaml
- id: fellowship-apply
question: How do I apply to the ReproNim Fellowship?
answer: |
See the [Fellowship page](/fellowship/).
```

Without `id:`, the anchor is auto-generated from the question slug — fine for stable wording, but a reworded question changes the URL.

4. **Commit and push.** Use a conventional-commit message such as `docs: add FAQ entry on fellowship deadlines`. A pull request triggers Netlify's preview deploy; merging to `main` triggers production.

5. **Verify.** After deploy:
- Open `https://repronim.org/` and scroll to the FAQ section.
- Click your new question; the answer should expand.
- Copy the URL of the question's anchor (right-click the question → "Copy link" works in most browsers, or check the rendered page source for the `<details id="...">`).
- Paste the deep-link URL in a new tab; confirm the page loads with your entry already expanded and scrolled into view.

## Step-by-step: edit or remove an entry

- **Edit**: Change `question` or `answer` in place. Reordering, formatting, and link changes are all in-place edits.
- **Reorder**: Move the list item up or down within `entries:`. Render order = YAML order.
- **Remove**: Delete the list item. If you anticipate that outstanding deep links exist (e.g., the question was linked from an email or another page), consider replacing it with a redirect-style answer that points to the new location instead of deleting outright.

## Anchor stability tips

- The auto-generated anchor for a question is `faq-` + the URL-friendly slug of the question. Example: `"How do I get started?"` → `faq-how-do-i-get-started`.
- To preserve a deep link across a rewording, set `id:` to the previous slug **before** changing the question text. Example: change to `id: faq-how-do-i-get-started`, then update `question:` freely.

## Common pitfalls

| Symptom | Cause | Fix |
|---------|-------|-----|
| New entry doesn't appear on the home page | YAML indentation is wrong (Netlify build will have failed) | Check the build log on Netlify for a YAML parse error; fix indentation so each list item starts with ` - question:`. |
| Answer renders as a single long line | Used `>` (folded scalar) instead of `|` (literal scalar) for `answer:` | Use `|` to preserve newlines. |
| Markdown link looks like raw text in the answer | The answer string is being treated as plain text | Confirm the YAML uses `answer: |` (with the pipe) and that the answer is indented correctly. The shortcode runs `markdownify` on the value. |
| Deep link doesn't open the entry | Hash in URL doesn't match any entry's id (typo, stale link, or entry was removed) | Verify the current id by inspecting the page or by checking `data/faq.yaml` for an `id:` override. |
| Duplicate ids warning in build log | Two questions slugify to the same anchor (e.g., differ only in punctuation) | Add an explicit `id:` to one of them. |

## Verifying accessibility (occasional check)

When the FAQ grows or styles change, run an accessibility check on the home page:

- **Lighthouse** (Chrome DevTools → Lighthouse → "Accessibility") — score should be ≥ 95 with no FAQ-related findings.
- **axe DevTools** browser extension — run on `/`; confirm no violations under the `.rn-faq` section.
- Keyboard test: Tab to a question; press Enter; press Tab again to confirm focus moves into the answer's links.

## Where the implementation lives

- Data: `data/faq.yaml`
- Shortcode template: `layouts/shortcodes/rn-faq.html`
- Invocation: `content/_index.md` (one `{{< rn-faq >}}` line below the `rn-buttons` block)

If you need to change the section heading, the styling, or the script, edit `layouts/shortcodes/rn-faq.html`. For everyday content edits, you only need `data/faq.yaml`.
131 changes: 131 additions & 0 deletions layouts/shortcodes/rn-faq.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
{{- with site.Data.faq -}}
{{- with .entries -}}
{{- $seen := slice -}}
<section class="rn-faq" aria-labelledby="rn-faq-heading">
<h2 id="rn-faq-heading">Frequently Asked Questions</h2>

{{- range $i, $entry := . }}
{{- $q := $entry.question | default "" -}}
{{- $a := $entry.answer | default "" -}}
{{- if not $q -}}
{{- warnf "rn-faq: skipping entry %d — missing or empty 'question' field" $i -}}
{{- else if not $a -}}
{{- warnf "rn-faq: skipping entry %q — missing or empty 'answer' field" $q -}}
{{- else -}}
{{- $rawId := "" -}}
{{- with $entry.id -}}
{{- $rawId = . -}}
{{- end -}}
{{- $id := "" -}}
{{- if $rawId -}}
{{- $idPattern := `^[a-z0-9][a-z0-9-]*$` -}}
{{- if findRE $idPattern $rawId -}}
{{- $id = $rawId -}}
{{- else -}}
{{- warnf "rn-faq: id %q for question %q is invalid (must match %s); falling back to auto-generated slug" $rawId $q $idPattern -}}
{{- $id = printf "faq-%s" (urlize $q) -}}
{{- end -}}
{{- else -}}
{{- $id = printf "faq-%s" (urlize $q) -}}
{{- end -}}
{{- /* duplicate-id detection: append -2, -3, ... if needed */ -}}
{{- $finalId := $id -}}
{{- $n := 2 -}}
{{- range $seen -}}
{{- if eq . $finalId -}}
{{- $finalId = printf "%s-%d" $id $n -}}
{{- $n = add $n 1 -}}
{{- end -}}
{{- end -}}
{{- if ne $finalId $id -}}
{{- warnf "rn-faq: duplicate anchor for question %q — using %q. Consider setting an explicit 'id:' field in data/faq.yaml." $q $finalId -}}
{{- end -}}
{{- $seen = $seen | append $finalId }}
<details class="rn-faq-item" id="{{ $finalId }}">
<summary>{{ $q }}</summary>
<div class="rn-faq-answer">
{{ $a | markdownify }}
</div>
</details>
{{- end -}}
{{- end }}

<style>
.rn-faq {
margin-top: 2.5rem;
margin-bottom: 1.5rem;
text-align: left;
}
.rn-faq h2#rn-faq-heading {
text-align: left;
margin-bottom: 1rem;
}
.rn-faq-item {
border-top: 1px solid rgba(127, 127, 127, 0.3);
padding: 0.75rem 0;
/* Offset deep-link scroll so the targeted entry lands below the
Hextra sticky navbar (--navbar-height) instead of behind it. */
scroll-margin-top: calc(var(--navbar-height, 4rem) + 0.5rem);
}
Comment on lines +63 to +69

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the site uses a sticky navigation bar, deep-linking to an FAQ entry (e.g., via /#faq-id) will cause the question to be partially obscured by the header. Adding scroll-margin-top ensures that the element is positioned with enough clearance when scrolled into view by the browser or the scrollIntoView script.

Suggested change
.rn-faq-item {
border-top: 1px solid rgba(127, 127, 127, 0.3);
padding: 0.75rem 0;
}
.rn-faq-item {
border-top: 1px solid rgba(127, 127, 127, 0.3);
padding: 0.75rem 0;
scroll-margin-top: 5rem;
}

.rn-faq-item:last-of-type {
border-bottom: 1px solid rgba(127, 127, 127, 0.3);
}
.rn-faq-item > summary {
cursor: pointer;
font-weight: 600;
list-style: none;
padding: 0.25rem 0;
position: relative;
padding-right: 1.5rem;
}
.rn-faq-item > summary::-webkit-details-marker {
display: none;
}
.rn-faq-item > summary::after {
content: "+";
position: absolute;
right: 0.25rem;
top: 50%;
transform: translateY(-50%);
font-weight: 400;
font-size: 1.25rem;
line-height: 1;
}
.rn-faq-item[open] > summary::after {
content: "\2212"; /* unicode minus */
}
.rn-faq-item > summary:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
border-radius: 2px;
}
.rn-faq-answer {
padding: 0.5rem 0 0.25rem;
line-height: 1.6;
}
.rn-faq-answer > :first-child { margin-top: 0; }
.rn-faq-answer > :last-child { margin-bottom: 0; }
</style>

<script>
(function () {
function openFromHash() {
Comment on lines +111 to +112

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If this shortcode is used multiple times on the same page, the hashchange event listener will be attached multiple times, leading to redundant execution of the openFromHash function. Adding a global guard ensures the initialization logic runs only once per page load.

Suggested change
(function () {
function openFromHash() {
(function () {
if (window.rnFaqInitialized) return;
window.rnFaqInitialized = true;
function openFromHash() {

var hash = window.location.hash;
if (!hash || hash.length < 2) return;
var el = document.getElementById(decodeURIComponent(hash.substring(1)));
if (el && el.tagName && el.tagName.toLowerCase() === "details" && el.classList.contains("rn-faq-item")) {
el.open = true;
el.scrollIntoView({ block: "start" });
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", openFromHash);
} else {
openFromHash();
}
window.addEventListener("hashchange", openFromHash);
})();
</script>
</section>
{{- end -}}
{{- end -}}
Loading