diff --git a/_quarto.yml b/_quarto.yml index 0d7381b..651719e 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -21,6 +21,7 @@ website: contents: - text: Welcome href: index.qmd + - pages/agenda/index.qmd - text: "Slides: Why make a website for your research?" href: pages/why/index.qmd - section: "Tutorial" @@ -33,6 +34,7 @@ website: - pages/media/index.qmd - pages/inline_html/index.qmd - pages/customising/index.qmd + - pages/hosting/index.qmd - pages/task/index.qmd - section: "Optional extras" contents: diff --git a/pages/agenda/index.qmd b/pages/agenda/index.qmd new file mode 100644 index 0000000..9fb6ad8 --- /dev/null +++ b/pages/agenda/index.qmd @@ -0,0 +1,48 @@ +--- +title: Workshop agenda +--- + +This is the companion website for the workshop. You will use it during the exercises, and you can refer back to it afterwards. It contains written instructions that match what we cover in the session, plus some extra material. + +To open this site go to: + + + +![](quarto2026-qr.png){fig-alt="QR code"} + +## Session plan + +1. **Introduction:** + Short talk and demo showing how Quarto can be used in research. + +2. **Practical set-up and first commit:** + - Create or log in to a GitHub account + - Open the Quarto template in GitHub Codespaces + - Render the site, make a small change, and commit it to Git + +3. **Break** + +4. **Guided exercises:** + Work through a series of short exercises to practice: + - Markdown basics + - Media (images, videos, documents) + - Customising the appearance of your site + - And a few other core features + + +5. **Hosting:** + Finally, we will explain how to host your site online via GitHub Pages. + +## What to expect + +We have a varied cohort: some of you may already have seen GitHub, Markdown, or Quarto, and for others this will all be completely new. The workshop is designed to be accessible if you are new to these tools, so please do not worry if the terminology is unfamiliar at first. + +If you find you move quickly through the core exercises, there are extra pages later in this site where you can explore some more advanced concepts including: + +- **Task listings** (e.g. blog‑style or gallery‑style listings) +- **Sass and CSS** +- Running and embedding **code** in Quarto. + +These are optional and aimed at those who already feel confident with the basics. + +You can also browse the **Examples** page, which shows a range of real Quarto sites. Each example has a link to the live site and, via the GitHub icon in the top right, a link to the source code so you can see how it was built. diff --git a/pages/agenda/quarto2026-qr.png b/pages/agenda/quarto2026-qr.png new file mode 100644 index 0000000..9ec20ff Binary files /dev/null and b/pages/agenda/quarto2026-qr.png differ diff --git a/pages/basic_structure/index.qmd b/pages/basic_structure/index.qmd index 9a246f2..452c858 100644 --- a/pages/basic_structure/index.qmd +++ b/pages/basic_structure/index.qmd @@ -80,7 +80,7 @@ book: chapters: - text: Overview href: index.qmd - - pages/TODO.qmd + - pages/pagename.qmd navbar: right: - icon: github @@ -98,11 +98,19 @@ A `.qmd` file is a **Quarto Markdown** document. It mixes metadata at the top, t > If you're familiar with R Markdown (`.Rmd`), these are similar, but `.qmd` is more flexible. -Each `.qmd` file begins with **YAML front matter**, enclosed by three dashes (`---`). This defines metadata such as the page title. Below that is the page. Here we just have one sentence: `This is my homepage.`. +Each `.qmd` file begins with **YAML front matter**, enclosed by three dashes (`---`). This defines metadata such as the page title, author information and date. Below that is the main content of the page. Here we just have one sentence: `This is my homepage.`. -```{.r} +```{.yaml} --- title: My homepage +author: + - name: Amy Heather + orcid: 0000-0002-6596-3479 + affiliations: University of Exeter + - name: Thomas Monks + orcid: 0000-0003-2631-4481 + affiliations: University of Exeter +date: 06-01-2026 --- diff --git a/pages/blog/examples/example1/butterfly.jpg b/pages/blog/examples/example1/butterfly.jpg new file mode 100644 index 0000000..f5ab171 Binary files /dev/null and b/pages/blog/examples/example1/butterfly.jpg differ diff --git a/pages/blog/examples/example1/index.qmd b/pages/blog/examples/example1/index.qmd new file mode 100644 index 0000000..6993e9d --- /dev/null +++ b/pages/blog/examples/example1/index.qmd @@ -0,0 +1,7 @@ +--- +title: Example 1 +--- + +This page has a picture of a butterfly. + +![Butterfly](butterfly.jpg) \ No newline at end of file diff --git a/pages/blog/examples/example2/index.qmd b/pages/blog/examples/example2/index.qmd new file mode 100644 index 0000000..b378fe1 --- /dev/null +++ b/pages/blog/examples/example2/index.qmd @@ -0,0 +1,7 @@ +--- +title: Example 2 +--- + +This page has a picture of a squirrel. + +![Squirrel](squirrel.jpg) \ No newline at end of file diff --git a/pages/blog/examples/example2/squirrel.jpg b/pages/blog/examples/example2/squirrel.jpg new file mode 100644 index 0000000..132f29f Binary files /dev/null and b/pages/blog/examples/example2/squirrel.jpg differ diff --git a/pages/blog/examples/example3/cat.jpg b/pages/blog/examples/example3/cat.jpg new file mode 100644 index 0000000..4422d3f Binary files /dev/null and b/pages/blog/examples/example3/cat.jpg differ diff --git a/pages/blog/examples/example3/index.qmd b/pages/blog/examples/example3/index.qmd new file mode 100644 index 0000000..4047bef --- /dev/null +++ b/pages/blog/examples/example3/index.qmd @@ -0,0 +1,7 @@ +--- +title: Example 3 +--- + +This page has a picture of a cat. + +![Cat](cat.jpg) \ No newline at end of file diff --git a/pages/blog/index.qmd b/pages/blog/index.qmd index 72a91e9..75ccd8b 100644 --- a/pages/blog/index.qmd +++ b/pages/blog/index.qmd @@ -1,6 +1,10 @@ --- title: Listings (e.g., blog) listing: + - id: simple + contents: examples + type: grid + grid-columns: 3 - id: links contents: links_real.yml template: links.ejs @@ -15,6 +19,93 @@ There are two ways to use listings: ## Listing of pages +### Simple listing of pages + +A common use case is a blog or "Projects" page that lists documents from a folder. We create it with `listing:` in the YAML. At a minimum, you specify `contents`, which determines which documents to include. + +For example, this will create a listing from files within the `pages/` folder: + +```{.markdown} +--- +title: Projects +listing: + contents: pages +--- +``` + +In this example, we have add more criteria: + +* `type:` how to display the items (for example, `default` list or `grid`). +* `grid-columns:` number of columns when using a grid layout. +* `fields:` which pieces of metadata to show for each item (for example, `title`, `subtitle`, `image`). +* `image-height:` how tall to show any image field. + +```{.markdown} +--- +title: Projects +listing: + contents: pages + type: grid + grid-columns: 3 + fields: [title, subtitle, image] + image-height: "100" +--- +``` + +Example: + +::: {#simple} +::: + +### Grouped listing of pages + +You can also define **multiple listings** on the same page and group them. + +This approach assumes that the pages in `pages/` have a `year:` field in their YAML. Each listing block uses `include:` to filter by `year`, and an `id` that matches a placeholder div later in the document. + +```{.markdown} +--- +title: Projects +listing: + - id: projects-2026 + contents: pages + include: + year: 2026 + fields: [title, subtitle, image] + + - id: projects-2025 + contents: pages + include: + year: 2025 + fields: [title, subtitle, image] + + - id: projects-2024 + contents: pages + include: + year: 2024 + fields: [title, subtitle, image] + +format: + html: + page-layout: article +--- + +## 2026 + +::: {#projects-2026} +::: + +## 2025 + +::: {#projects-2025} +::: + +## 2024 + +::: {#projects-2024} +::: +``` + ## Listing of external things **Note:** This is more advanced. The approach is based on `quarto-dev/quarto-web`'s gallery ([link](https://github.com/quarto-dev/quarto-web/blob/main/docs/gallery/gallery.ejs)). diff --git a/pages/blog/links.yml b/pages/blog/links.yml index dc12088..a5fc6ae 100644 --- a/pages/blog/links.yml +++ b/pages/blog/links.yml @@ -6,7 +6,7 @@ subtitle: "Self-paced training resource on creating discrete-event simulation models in Python and R as part of a reproducible analytical pipeline." href: "https://pythonhealthdatascience.github.io/des_rap_book/" thumbnail: /images/listings/des_rap_book.png - - title: "Testing in Research Workflow" + - title: "Testing in Research Workflows" subtitle: "Tutorial on testing in Python and R, accompanies HDR UK Futures training videos." href: "https://pythonhealthdatascience.github.io/stars-testing-intro/" thumbnail: /images/listings/testing_in_research.png diff --git a/pages/blog/links_real.yml b/pages/blog/links_real.yml index 7ca3f8a..6303782 100644 --- a/pages/blog/links_real.yml +++ b/pages/blog/links_real.yml @@ -6,7 +6,7 @@ subtitle: "Self-paced training resource on creating discrete-event simulation models in Python and R as part of a reproducible analytical pipeline." href: "https://pythonhealthdatascience.github.io/des_rap_book/" thumbnail: /pages/examples/des_rap_book.png - - title: "Testing in Research Workflow" + - title: "Testing in Research Workflows" subtitle: "Tutorial on testing in Python and R, accompanies HDR UK Futures training videos." href: "https://pythonhealthdatascience.github.io/stars-testing-intro/" thumbnail: /pages/examples/testing_in_research.png diff --git a/pages/code/index.qmd b/pages/code/index.qmd index 540b234..0a192d1 100644 --- a/pages/code/index.qmd +++ b/pages/code/index.qmd @@ -2,11 +2,493 @@ title: Code --- -code example -code task +## Code in Quarto pages -rstudio... r... +In a Quarto document, you can include **code cells** and choose whether they run when you render the site. -r code -make figure -r code annotation? \ No newline at end of file +### Executable code + +A **code cell** is a fenced block like: + +```{{python}} +print("Hello from Python") +``` + +If the cell has a language (for example `{python}`, `{r}`, `{bash}`), Quarto can **execute** it when you render. + +That means Quarto actually runs the code, captures the output (and any figures), and inserts those results into the page. This is powerful, because your website and your analysis stay in sync - if the code or data change, you just re‑render. + +Below are some examples from the Quarto documentation showing a map and an interactive Plotly plot: + + + +### Non-executable code + +If you just want to show code (not run it), you can either: + +1. Add a dot before the language. + +```{{.python}} +print("Hello from Python") +``` + +2. Make the cell as `eval: false`. + +```{{python}} +#| eval: false +print("Hello from Python") +``` + +3. Set all cells in a Quarto document to `eval: false` in the YAML: + +```{.yaml} +--- +title: "Title" +execute: + eval: false +--- +``` + +## Deploying your site with executable code + +As explained on the [Hosting](/pages/hosting/index.qmd), we can deploy a Quarto site using a GitHub Actions workflow, allowing us to host it on GitHub pages. + +If your pages contain executable code, the workflow must be amended to installed the required **programming language and dependencies**. + +### Python + +#### requirements.txt + +Use this pattern when you have a `requirements.txt` file listing your Python packages. + +This example file is from: . + +It is based on the [suggested file in the Quarto documentation](). + +```{.yaml} +name: Update GitHub pages +run-name: Render Quarto website and publish on GitHub pages + +# Source: https://quarto.org/docs/publishing/github-pages.html + +on: + push: + branches: main + workflow_dispatch: + +jobs: + build-deploy: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Quarto + uses: quarto-dev/quarto-actions/setup@v2 + + - name: Install python and dependencies + uses: actions/setup-python@v4 + with: + python-version: '3.10' + cache: 'pip' + - run: pip install -r requirements.txt + + - name: Render and publish to GitHub pages + uses: quarto-dev/quarto-actions/publish@v2 + with: + target: gh-pages + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +#### conda + +If you are using a Conda environment with an `environment.yml`/`environment.yaml` file, you can use this action. + +It is taken from: . + +```{.yaml} +name: Render quarto site and publish on GitHub pages +run-name: Render quarto site and publish on GitHub pages + +on: + push: + branches: main + workflow_dispatch: + +jobs: + build-deploy: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Quarto + uses: quarto-dev/quarto-actions/setup@v2 + + - name: Set up Conda environment + uses: conda-incubator/setup-miniconda@v3 + with: + environment-file: environment.yaml + activate-environment: ambdes + auto-activate-base: false + channels: conda-forge + + - name: Render and publish to GitHub pages + uses: quarto-dev/quarto-actions/publish@v2 + with: + target: gh-pages + path: docs + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +#### uv + +If you are using uv, you can use a file like below, which is from: . + +```{.yaml} +name: docs +run-name: Render Quarto website and publish on GitHub pages + +on: + push: + branches: main + workflow_dispatch: + +jobs: + build-deploy: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Quarto + uses: quarto-dev/quarto-actions/setup@v2 + + - name: Set up Python from .python-version + uses: actions/setup-python@v4 + with: + python-version-file: ".python-version" + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + enable-cache: true + + - name: Sync project from uv.lock + run: uv sync --locked --all-extras --dev + + - name: Quarto render + working-directory: docs + run: uv run quarto render + + - name: Quarto publish to gh-pages + if: github.ref == 'refs/heads/main' + working-directory: docs + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + uv run quarto publish gh-pages --no-prompt --no-browser +``` + +### R + +If you are using R with renv, you can use an action like below, which is [copied from the Quarto documentation](https://quarto.org/docs/publishing/github-pages.html#example-knitr-with-renv). + +```{.yaml} +on: + workflow_dispatch: + push: + branches: main + +name: Quarto Publish + +jobs: + build-deploy: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Quarto + uses: quarto-dev/quarto-actions/setup@v2 + + - name: Install R + uses: r-lib/actions/setup-r@v2 + with: + r-version: '4.2.0' + + - name: Install R Dependencies + uses: r-lib/actions/setup-renv@v2 + with: + cache-version: 1 + + - name: Render and Publish + uses: quarto-dev/quarto-actions/publish@v2 + with: + target: gh-pages + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +### Python and R + +For sites running both Python and R, we found the following approach to work: + +1. Build a Docker image that contains everything needed. +2. Push that image to the GitHub Container Registry (GHCR). +3. Run the Quarto render inside the Docker container. + +We have used this approach in two of our projects: the [DES RAP Book](https://github.com/pythonhealthdatascience/des_rap_book) and the Python package [vidigi](https://github.com/hsma-tools/vidigi). + +#### Workflow file + +```{.yaml} +name: Publish docker on GHCR and quarto on GitHub pages +run-name: Publish docker on GHCR and quarto on GitHub pages + +on: + push: + branches: [main] + workflow_dispatch: + inputs: + force_docker_build: + description: 'Force Docker build (skip change detection)' + required: true + type: boolean + default: false + skip_docker_build: + description: 'Skip Docker build (use last built image)' + required: true + type: boolean + default: false + +jobs: + publish-docker: + name: Publish docker + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check if Docker build needed + if: ${{ !inputs.skip_docker_build && !inputs.force_docker_build }} + id: changes + uses: dorny/paths-filter@v3 + with: + filters: | + docker: + - 'Dockerfile' + - 'environment.yaml' + - 'renv.lock' + - 'renv/**' + + - name: Login to GitHub Container Registry + if: > + (!inputs.skip_docker_build) && + (inputs.force_docker_build || steps.changes.outputs.docker == 'true') + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build the Docker image + if: > + (!inputs.skip_docker_build) && + (inputs.force_docker_build || steps.changes.outputs.docker == 'true') + uses: docker/build-push-action@v6 + with: + context: . + tags: | + ghcr.io/${{ github.repository_owner }}/des_rap_book:latest + push: true + build-args: | + GIT_PAT=${{ secrets.GITHUB_TOKEN }} + + build-deploy: + runs-on: ubuntu-latest + needs: [publish-docker] + container: + image: ghcr.io/${{ github.repository_owner }}/des_rap_book:latest + credentials: + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write + packages: read + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure Git safe directory + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + + - name: Update YAML date with last commit + run: bash ./update-quarto-date.sh + + - name: Render and publish to GitHub pages + uses: quarto-dev/quarto-actions/publish@v2 + with: + target: gh-pages + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +### Dockerfile + +```{.docker} +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive + +# ============================================================ +# STAGE 1: Install ALL system dependencies FIRST +# ============================================================ +# This must happen before Conda to ensure R compiles against +# system libraries, not conda libraries +RUN set -eux; \ + # retry apt-get update a few times in case mirrors are mid-sync + for i in 1 2 3; do \ + apt-get update && break; \ + echo "apt-get update failed, retrying ($i/3)..."; \ + sleep 5; \ + done; \ + apt-get install -y --no-install-recommends \ + # Basic utilities + wget ca-certificates gnupg software-properties-common \ + dirmngr locales git \ + # R compilation dependencies + build-essential gfortran \ + libxml2-dev \ + libglpk-dev \ + libgmp-dev \ + libblas-dev \ + liblapack-dev \ + libcurl4-openssl-dev \ + libssl-dev \ + libfontconfig1-dev \ + libfreetype6-dev \ + libharfbuzz-dev \ + libfribidi-dev \ + libpng-dev \ + libtiff5-dev \ + libjpeg-dev \ + # Chrome dependencies (for Kaleido/plotly) + fonts-liberation \ + libasound2t64 \ + libatk-bridge2.0-0 \ + libatk1.0-0 \ + libatspi2.0-0 \ + libcups2 \ + libdbus-1-3 \ + libgbm1 \ + libgtk-3-0 \ + libnspr4 \ + libnss3 \ + libvulkan1 \ + libxcomposite1 \ + libxdamage1 \ + libxkbcommon0 \ + libxrandr2 \ + xdg-utils && \ + locale-gen en_GB.UTF-8 && \ + rm -rf /var/lib/apt/lists/* + +# Set locale environment variables for Python and other tools +ENV LANG=en_GB.UTF-8 +ENV LC_ALL=en_GB.UTF-8 +ENV PYTHONIOENCODING=utf-8 + +# ============================================================ +# STAGE 2: Install R from CRAN +# ============================================================ +RUN wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | \ + gpg --dearmor -o /usr/share/keyrings/r-project.gpg && \ + echo "deb [signed-by=/usr/share/keyrings/r-project.gpg] https://cloud.r-project.org/bin/linux/ubuntu noble-cran40/" \ + > /etc/apt/sources.list.d/r-project.list && \ + apt-get update && \ + apt-get install -y --no-install-recommends r-base r-base-dev && \ + rm -rf /var/lib/apt/lists/* + +# ============================================================ +# STAGE 3: Install Quarto +# ============================================================ +RUN wget -qO /tmp/quarto.deb https://quarto.org/download/latest/quarto-linux-amd64.deb && \ + apt-get update && \ + apt-get install -y /tmp/quarto.deb && \ + rm /tmp/quarto.deb && \ + rm -rf /var/lib/apt/lists/* + +# ============================================================ +# STAGE 4: Install Google Chrome (required by Kaleido for plotly) +# ============================================================ +RUN wget -O /tmp/chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \ +apt-get update && \ +apt-get install -y --no-install-recommends /tmp/chrome.deb && \ +rm /tmp/chrome.deb && \ +rm -rf /var/lib/apt/lists/* + +# ============================================================ +# STAGE 5: Install Miniconda (use explicit paths, not PATH) +# ============================================================ +ENV CONDA_DIR=/opt/conda +RUN wget -qO /tmp/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && \ + bash /tmp/miniconda.sh -b -p "$CONDA_DIR" && \ + rm /tmp/miniconda.sh + +RUN $CONDA_DIR/bin/conda config --system --set always_yes yes && \ + $CONDA_DIR/bin/conda config --system --set changeps1 no + +# ============================================================ +# STAGE 6: Set up project and create conda environment +# ============================================================ +WORKDIR /workspace +COPY . /workspace +RUN rm -f /workspace/.Renviron + +# Accept Anaconda ToS for required channels (non-interactive) +RUN $CONDA_DIR/bin/conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main && \ + $CONDA_DIR/bin/conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r + +# Create conda environment using explicit path (NOT in PATH yet) +RUN $CONDA_DIR/bin/conda env create -f environment.yaml + +# ============================================================ +# STAGE 7: Install R packages WITHOUT conda in PATH +# ============================================================ +# CRITICAL: R package compilation must happen with system +# libraries, NOT conda libraries in PATH +ENV RENV_PATHS_LIBRARY=/workspace/renv/library + +RUN Rscript -e "install.packages('renv', repos = 'https://cloud.r-project.org')" && \ + Rscript -e "renv::restore()" + +# ============================================================ +# STAGE 8: Activate conda environment for RUNTIME only +# ============================================================ +# Now that R packages are installed, it's safe to add conda to PATH +ENV CONDA_DEFAULT_ENV=des-rap-book +ENV PATH="/opt/conda/envs/des-rap-book/bin:${PATH}" +ENV RETICULATE_PYTHON=/opt/conda/envs/des-rap-book/bin/python + +RUN echo "conda activate des-rap-book" >> /root/.bashrc + +CMD ["/bin/bash"] +``` \ No newline at end of file diff --git a/pages/examples/examples.yml b/pages/examples/examples.yml index ecfb2e7..3a27cf2 100644 --- a/pages/examples/examples.yml +++ b/pages/examples/examples.yml @@ -163,7 +163,7 @@ code: https://github.com/pythonhealthdatascience/des_rap_book thumbnail: des_rap_book.png categories: [University of Exeter] - - title: Testing in Research Workflow + - title: Testing in Research Workflows subtitle: Tutorial on testing in Python and R, accompanies HDR UK Futures training videos. href: https://pythonhealthdatascience.github.io/stars-testing-intro/ code: https://github.com/pythonhealthdatascience/stars-testing-intro diff --git a/pages/hosting/404_error.png b/pages/hosting/404_error.png new file mode 100644 index 0000000..ad67050 Binary files /dev/null and b/pages/hosting/404_error.png differ diff --git a/pages/hosting/about_pane.png b/pages/hosting/about_pane.png new file mode 100644 index 0000000..10afe52 Binary files /dev/null and b/pages/hosting/about_pane.png differ diff --git a/pages/hosting/action_triggered.png b/pages/hosting/action_triggered.png new file mode 100644 index 0000000..40bd4b0 Binary files /dev/null and b/pages/hosting/action_triggered.png differ diff --git a/pages/hosting/actions.png b/pages/hosting/actions.png new file mode 100644 index 0000000..180afdc Binary files /dev/null and b/pages/hosting/actions.png differ diff --git a/pages/hosting/enable.png b/pages/hosting/enable.png new file mode 100644 index 0000000..995af6f Binary files /dev/null and b/pages/hosting/enable.png differ diff --git a/pages/hosting/index.qmd b/pages/hosting/index.qmd new file mode 100644 index 0000000..fcae2ae --- /dev/null +++ b/pages/hosting/index.qmd @@ -0,0 +1,135 @@ +--- +title: Hosting +--- + +::: {.pale-blue} + +**On this page we will:** + +* Enable the GitHub action to automatically render and publish your site. +* Trigger a build and visit your live site. + +::: + +You can host your Quarto site for free using **GitHub Pages**. GitHub Pages takes the HTML files that Quarto creates and puts them on the web so that anyone with the link can see your site. + +## Go to Actions tab + +Open your fork of the `quarto-template` repository on GitHub. If you need to find it, go to GitHub → Repositories → `quarto-template`. + +Click on the **Actions** tab. + +![](actions.png){fig-alt="Screenshot of cursor hovering on Actions tab."} + +## Enable workflows + +GitHub will show a message that workflows aren't being run on this forked repository. + +This is just a safety check. We know what the workflow does (it builds and publishes the Quarto site), so it is safe to enable it for this workshop. + +Click the green button to enable Actions for this repository. + +![](enable.png){fig-alt="Screenshot of 'Workflows aren't being run' message."} + +After you click, you should see that Actions are now enabled: + +![](now_enabled.png){fig-alt="Screenshot of screen after clicking to enable actions."} + +## Set the GitHub Pages branch + +Next, tell GitHub Pages which branch to use for the website. + +In your repository on GitHub, click on the **Settings** tab. In the left sidebar, click **Pages**. + +Under **Branch**, change the source from `None` to `gh-pages`. Click **Save**. + +> **Why `gh-pages`?** +> +> A Git repository can have more than one **branch**. You can think of branches as different versions or lines of development in the same project. +> For this template, the main branch (`main`) holds your source files (the `.qmd` files, `_quarto.yml`, etc.), and the workflow puts the **built website** into a special branch called `gh-pages`. +> GitHub Pages is then told, "Use the files from the `gh-pages` branch as the live website."" + +![](settings.png){fig-alt="Screenshot of GitHub Pages settings page."} + +## Make a commit to trigger the build + +The workflow runs **each time you push a commit** to GitHub on the `main` branch. That is how your site will stay up to date. + +Go back to your Codespace and make a small change to your site (e.g., edit some text on the homepage), then **commit and push** you change. + +Then, return to your GitHub repository **Actions** tab, and you should see a new workflow run starting. + +![](action_triggered.png){fig-alt="Screenshot showing a workflow run in the Actions list."} + +Then click on the `build-deploy` job to watch the steps. Near the end of the "Render and publish to GitHub pages" step, you should see a line with the URL of your site. Click that link (or copy and paste it into your browser). + +![](view_action_running.png){fig-alt="Screenshot of a running workflow with build-deploy job."} + +Then click on the `build-deploy` job to watch the steps. Near the end, you should see a line with the URL of your site. Click that link (or copy and paste it into your browser). + +![](view_url.png){fig-alt="Screenshot showing the GitHub Pages URL in the workflow output."} + +Sometimes, you may briefly see a 404 error while GitHub finishes publishing. If that happens, wait a few moments and refresh the page. + +![](404_error.png){fig-alt="Screenshot of 404 error message."} + +## Update the repository "About" url + +To make the site easy to find later, add the GitHub Pages URL to the repository's "About" section. + +On the main page of your repository on GitHub, look at the **About** box on the right, and click the small **settings** (gear) icon next to it. + +![](about_pane.png){fig-alt="Screenshot of the About pane with the settings icon."} + +Paste your GitHub Pages URL into the **Website** field then click **save changes**. + +![](replace_url.png){fig-alt="Screenshot showing the Website field."} + +
+ +--- + +## How did that work? + +The publishing is handled by a **GitHub Actions workflow**. GitHub Actions is a service that can run steps for you in the cloud when certain events happen (for example, when you push a commit). + +The instructions live in a workflow file in `.github/workflows/`. For this template, it looks like: + + +```{.yaml} +name: Render quarto site and publish on GitHub pages # <1> +run-name: Render quarto site and publish on GitHub pages # <1> + +on: # <2> + push: # <2> + branches: main # <2> + +jobs: # <3> + build-deploy: # <3> + runs-on: ubuntu-latest # <4> + permissions: # <5> + contents: write # <5> + steps: # <6> + - name: Check out repository # <7> + uses: actions/checkout@v4 # <7> + + - name: Set up Quarto # <8> + uses: quarto-dev/quarto-actions/setup@v2 # <8> + + - name: Render and publish to GitHub pages # <9> + uses: quarto-dev/quarto-actions/publish@v2 # <9> + with: # <9> + target: gh-pages # <9> + env: # <9> + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # <9> +``` + +1. **name/run-name**: Labels for the workflow and its runs, so you can recognise them in the Actions tab. +2. **on: push: branches: main:** Tells GitHub to run this workflow whenever you push a commit to the `main` branch. +3. **jobs / build-deploy:** Defines a job called `build-deploy` that does the work. +4. **runs-on: ubuntu-latest:** Uses a fresh Linux (Ubuntu) virtual machine in the cloud to run the job. +5. **permissions: contents: write:** Allows the job to write back to the repository (needed to update the `gh-pages` branch). +6. **steps:** The list of actions to perform. +7. **Check out repository:** Downloads the code from your repository into the runner. +8. **Set up Quarto:** Installs Quarto so it can render the site. +9. **Render and publish to GitHub Pages:** Renders the Quarto project and pushes the built site to the `gh-pages` branch using the `quarto-actions/publish` action. `GITHUB_TOKEN` is a special token that GitHub provides so the workflow can authenticate and push to your repository securely. diff --git a/pages/hosting/now_enabled.png b/pages/hosting/now_enabled.png new file mode 100644 index 0000000..3c521cc Binary files /dev/null and b/pages/hosting/now_enabled.png differ diff --git a/pages/hosting/replace_url.png b/pages/hosting/replace_url.png new file mode 100644 index 0000000..c1ab371 Binary files /dev/null and b/pages/hosting/replace_url.png differ diff --git a/pages/hosting/settings.png b/pages/hosting/settings.png new file mode 100644 index 0000000..1a11b30 Binary files /dev/null and b/pages/hosting/settings.png differ diff --git a/pages/hosting/view_action_running.png b/pages/hosting/view_action_running.png new file mode 100644 index 0000000..499ecb3 Binary files /dev/null and b/pages/hosting/view_action_running.png differ diff --git a/pages/hosting/view_url.png b/pages/hosting/view_url.png new file mode 100644 index 0000000..802da9e Binary files /dev/null and b/pages/hosting/view_url.png differ diff --git a/pages/hosting/workflow_file.png b/pages/hosting/workflow_file.png new file mode 100644 index 0000000..64cf941 Binary files /dev/null and b/pages/hosting/workflow_file.png differ