Skip to content

Conversation

@mcanouil
Copy link
Contributor

Introduce a new blog post highlighting the integration of Quarto with GitHub Codespaces.

@cscheid
Copy link
Collaborator

cscheid commented May 16, 2025

Thank you! I like the structure. I have a number of edits and suggestions that I will make on a separate file and I'll return them to you.

Copy link
Collaborator

@cscheid cscheid left a comment

Choose a reason for hiding this comment

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

Here's a new version with a number of edits:

---
author:
  - name: "Mickaël CANOUIL, _Ph.D._"
    orcid: "0000-0002-3396-4549"
    url: "https://mickael.canouil.fr"
title: "How to use GitHub CodeSpaces to simplify your Quarto workshops"
description: |
  In this post, I'll teach you the basics of GitHub Codespaces and how to use them to make it easier to teach using Quarto.
date: "2025-05-16"
categories:
  - GitHub Codespaces
  - Teaching
  - Dev Container
image: featured.png
image-alt: |
  Quarto icon and text above GitHub Codespaces.
lang: en-GB
---

## What Is GitHub Codespaces?

[GitHub Codespaces](https://github.com/features/codespaces) is a cloud-powered, on-demand development environment that runs either in your browser or in Visual Studio Code via the [GitHub Codespaces extension](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces).
It eliminates the need for lengthy local setup by providing a fully configured development container, complete with all necessary dependencies and tools.
This means that whether you're an instructor or a developer, you can start coding immediately with a consistent environment tailored to your specific project, right on your web browser.

More importantly, the participants of your workshops can use GitHub Codespaces just as easily as you can. With Codespaces, you and your participants all work on identical environments, minimising the "it doesn't work on my machine" problems we are all too aware of.

In this post, I am assuming the case of a workshop instructor and a room full of participants with different laptops and operating systems.
Codespaces are also useful for development, though, as you will notice reading on.

## The Power of Combining Quarto CLI with Codespaces

Imagine a world where your participants are instantly equipped with the same environment with all the tools, libraries, and sample projects ready to go in the cloud.
That's the magic of using Codespaces:

1. **Immediate Onboarding:** Workshop participants or students can bypass the hassle of local setup.
   They simply launch a Codespace (running on their web browser of choice, independently of operating system), and the pre-configured environment is available immediately.

1. **A Consistent Environment:** Ensuring that everyone has the same tools and dependencies can be challenging.
   Codespaces lets you pre-define your environment with container configurations, reducing the risk of discrepancies in software versions or settings.

1. **Cloud-Powered Productivity:** Running computations or rendering complex documents doesn't rely on your local machine's power, or theirs.
   Codespaces leverages cloud resources, providing a responsive and efficient platform for tasks.

1. **Reproducible Workflows:** Whether you're teaching a data science workshop or collaborating on a research paper, reproducibility is crucial.
   Because GitHub Codespaces uses the [Dev Container specification](https://containers.dev/), you can ensure that your code can be run in the same environment.
   When participants are ready to run their projects locally, they can use Codespace to building an equivalent Docker container.

GitHub provides ["deep link"](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) to Codespaces, allowing you to create a link you can share with your students or workshop participants.
The link can include a specific branch, a particular file, or even a specific line in a file.
By doing nothing more than clicking that one link, participants create or resume an existing execution environment.

[![](https://github.com/codespaces/badge.svg)](https://codespaces.new/mcanouil/quarto-codespaces?quickstart=1&devcontainer_path=.devcontainer%2Fdevcontainer.json)

:::: {.dark-content}
:::: {layout-ncol="2"}
![](quarto-codespaces-new-001-dark.png){fig-alt="GitHub Codespaces interface showing the 'Create codespace' page. The page includes a section with the repository 'mcanouil/quarto-codespaces' and a message stating 'No codespace to resume'. There are two buttons: 'Change options' and 'Create new codespace'."}

![](quarto-codespaces-new-002-dark.png){fig-alt="image_url" alt="Screenshot of Visual Studio Code interface showing a GitHub Codespace for a project named 'quarto-codespaces'. The left sidebar contains a file explorer with folders and files such as .devcontainer, .github, init-env.sh, LICENSE, and README.md. The terminal at the bottom displays logs related to configuring the codespace, including commands and their outcomes. The right sidebar has a section titled 'Edit with Copilot' explaining how to use Copilot in agent mode."}
:::
:::

:::: {.light-content}

:::: {layout-ncol="2"}
![](quarto-codespaces-new-001-light.png){fig-alt="GitHub Codespaces interface showing the 'Create codespace' page. The page includes a section with the repository 'mcanouil/quarto-codespaces' and a message stating 'No codespace to resume'. There are two buttons: 'Change options' and 'Create new codespace'."}

![](quarto-codespaces-new-002-light.png){fig-alt="image_url" alt="Screenshot of Visual Studio Code interface showing a GitHub Codespace for a project named 'quarto-codespaces'. The left sidebar contains a file explorer with folders and files such as .devcontainer, .github, init-env.sh, LICENSE, and README.md. The terminal at the bottom displays logs related to configuring the codespace, including commands and their outcomes. The right sidebar has a section titled 'Edit with Copilot' explaining how to use Copilot in agent mode."}
:::
:::

## Setting Up Your Own Quarto-Codespaces Environment

If you're considering using Codespaces with Quarto CLI for your next workshop or teaching module, here's how to get started:

### Fork the `quarto-codespaces` Repository

Leverage the example provided by the [`quarto-codespaces` repository](https://github.com/mcanouil/quarto-codespaces) or [create your own Codespaces using the default](https://github.com/codespaces/new/).
This repository includes the Dev Container configuration file (*i.e.*, `devcontainer.json`) that instruct Codespaces on how to set up an environment complete with Quarto CLI and other essential tools.

### Configure the Development Container 

Inside the repository, the `.devcontainer/devcontainer.json` file serves as the blueprint for your Codespace.
This configuration ensures that every instance of your Codespace is identical, capturing everything from the Quarto CLI version to additional libraries or extensions you might need.

```json
{
	"name": "Quarto",
	// "image": "buildpack-deps:jammy-curl", // <1>
	"build": {
		"dockerfile": "./Dockerfile",
		"context": ".",
		"args": {
			"VARIANT": "jammy"
		}
	},
	"remoteUser": "vscode",
	"features": { // <2>
		"./quarto-computing-dependencies": { // <3>
			"rDeps": "rmarkdown,languageserver,nx10/httpgd@v2.0.3,prompt,lintr",
			"pythonDeps": "jupyter,papermill",
			"juliaDeps": "IJulia"
		},
		"./uv": { // <4>
			"version": "latest"
		},
		"ghcr.io/rocker-org/devcontainer-features/quarto-cli:1": { // <5>
			"version": "release",
			"installTinyTex": "true",
			"installChromium": "false"
		}
	},
	"customizations": { // <6>
		"vscode": {
			"extensions": [
				"quarto.quarto",
				"mcanouil.quarto-wizard",
				"REditorSupport.r",
				"Posit.air-vscode"
			],
			"settings": {
				"r.rterm.option": [
					"--no-save",
					"--no-restore-data",
					"--quiet"
				],
				"[r]": {
					"editor.defaultFormatter": "Posit.air-vscode",
					"editor.formatOnSave": true
				}
			}
		}
	}
}
```

1. The `image` field specifies the base image for the container.
   You can customise this to suit your needs.
2. The `features` section allows you to add additional tools or libraries.
   See the [Dev Container Features available](https://containers.dev/features/) for a comprehensive list of available features.
3. The `quarto-computing-dependencies` feature is a "local" custom feature that installs the computing dependencies: R, Python, and Julia.
   This is a great way to ensure that your Codespace has everything it needs to run Quarto documents.
4. The `uv` feature installs the [`uv` tool](https://docs.astral.sh/uv/) to manage Python packages and project dependencies.
5. The `quarto-cli` feature installs the Quarto CLI.
   You can specify the version you want to install, and it will be automatically downloaded and installed in your Codespace.
   You can see the code for this feature in the source repository: <https://github.com/rocker-org/devcontainer-features/tree/main/src/quarto-cli>.
6. The `customizations` section allows you to specify settings and extensions for Visual Studio Code.

The `quarto-codespaces` repository is a great starting point as it provides a prebuilt Docker image with the latest Quarto CLI, Python, R, and Julia installed.
You can also add additional features to the `.devcontainer/devcontainer.json` to suit your needs or start directly using the image as is in your `.devcontainer/devcontainer.json` file.

```json
{
	"name": "My Workshop Setup",
	"image": "ghcr.io/mcanouil/quarto-codespaces:latest", // <1>
	"remoteUser": "vscode",
	"customizations": {
		"vscode": {
			"extensions": [
				"quarto.quarto", // <2>
				"mcanouil.quarto-wizard" // <3>
			]
		}
	}
}
```

1. The Docker image is specified in the `image` field.
   It's built using a Dev Container specification that you can find in [`.github/.devcontainer`](https://github.com/mcanouil/quarto-codespaces/tree/main/.github/.devcontainer).
2. The [`quarto` extension](https://github.com/quarto-dev/quarto) for Visual Studio Code / Positron to provide support for Quarto documents.
3. The [`quarto-wizard` extension](https://github.com/mcanouil/quarto-wizard) for Visual Studio Code / Positron to provide assistance in managing Quarto extensions

## Benefits for Workshops and Teaching

When it comes to educational sessions, consistency and ease-of-use are paramount.
Pairing Codespaces with Quarto CLI brings many direct benefits to a teaching environment:

- **Streamlined Onboarding:** Students and workshop attendees can get right to work without spending time installing and configuring local environments.
- **Live, Interactive Sessions:** Instructors can demonstrate live edits to Quarto documents.
  Changes can be rendered instantly and reflect in each participant's environment: perfect for a hands-on, interactive learning experience.
- **Collaboration and Version Control:** All changes can be recorded in Git, making it easy to track progress, handle peer reviews, and manage collaborative projects, all within a single hosted environment.
- **Elimination of "Dependency Hell":** With containerised development, all attendees work from the same baseline, ensuring that version conflicts or missing libraries don't derail a session.

## Final Thoughts and Future Directions

Whether you're running a workshop, teaching a class, or collaborating on research, using Codespaces can reduce setup hassles, foster reproducibility, and encourage interactive learning.

In addition to the benefits mentioned above, other features further enhance your experience with Codespaces and Quarto CLI:

- **Automated Pipelines:** Integrating CI/CD tools to automatically validate Quarto document renders and catch errors using the exact same environment.
  See [GitHub Actions: Running jobs in a container](https://docs.github.com/en/actions/writing-workflows/choosing-where-your-workflow-runs/running-jobs-in-a-container)
- **Real-Time Co-Editing Features:** Enhancing collaborative sessions with simultaneous multi-user editing directly in Codespaces.
  See [GitHub Codespaces: Real-time collaboration](https://docs.github.com/en/codespaces/developing-in-a-codespace/working-collaboratively-in-a-codespace)

This post covered the basics of using Codespaces and Quarto together, but there's much more to Codespaces.
Learn more by [consulting their documentation](https://docs.github.com/en/codespaces).
Happy teaching!


@mcanouil mcanouil changed the title feat: Codespaces and Quarto CLI: A Perfect Partnership for Workshops, Teaching, and Development feat: How to use GitHub CodeSpaces to simplify your Quarto workshops May 16, 2025
@mcanouil
Copy link
Contributor Author

Thanks, I've added your edits.

@mcanouil
Copy link
Contributor Author

I wonder if the following information (as appendix) should be added:

Codespaces is available for free to students as part of the GitHub Student Developer Pack. Learn more about how to sign up and start using Codespaces and other GitHub products (GitHub Education Pack).

Codespaces is free for individual use up to 60 hours a month and comes with simple, pay-as-you-go pricing after that. It’s also available for organizations with pay-as-you-go pricing and has pricing controls so any company or team can determine how much they want to spend a month. Learn more about Codespaces pricing for organizations (GitHub Codespaces Billing).

@mcanouil mcanouil changed the title feat: How to use GitHub CodeSpaces to simplify your Quarto workshops feat: How to use GitHub Codespaces to simplify your Quarto workshops May 16, 2025
Copy link
Collaborator

@juliasilge juliasilge left a comment

Choose a reason for hiding this comment

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

I'm really glad you are putting this resource together! 🙌

@coatless
Copy link
Contributor

Thank you for writing this up! I've been meaning to make a post about GitHub Codespaces & Cloud options for teaching DS. As someone who uses Codespaces extensively for various development projects, I'd like to offer some suggestions to enhance your approach:

Storage Optimization

  1. Consider container size carefully: Large omnibus containers can quickly consume your individual storage/organization's shared storage quota. Instead, try to leverage the default dev container configurations and only add essential technologies.

  2. Minimize VS Code extensions: Keep extensions to the necessary minimum as they also count against storage limits.

Implementation Details

  1. Document link construction: It would be helpful to show how to create Codespaces links at a surface level, e.g.
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/<USER>/<REPO>?quickstart=1)
  1. Show configuration selection: For repositories with multiple dev container configurations:
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/<USER>/<REPO>?devcontainer_path=.devcontainer%2Fvs-code%2Fdevcontainer.json)
  1. Auto-open files: For repositories with many different files, you may want to auto open them:
"customizations": {
  "codespaces": {
    "openFiles": [
      "README.md",
      "quarto-ex1.qmd"
    ]
  }
}

Educational Context

  1. Consider GitHub Classroom integration: For educational settings, I recommend using GitHub Classroom with Codespaces.
    • For large courses, contact GitHub support to extend classroom hours and storage limits
    • Adjust the retention policy from 30 days to approximately 8 days to manage storage more effectively

Repository Organization

  1. Consider official organization placement: If this is meant to be an official resource, consider placing containers under the quarto-dev organization rather than a personal account.

Real-world Challenges

For context, here's what happens when you hit shared storage limits:

Shared limit e-mail hit

@mcanouil
Copy link
Contributor Author

Thanks for the feedbacks.

  • "Storage Optimization": You don't need to pre-build and store the Docker image out of the Dev Container. I did it for efficiency and to allow reuse in GitHub Actions, etc.
    The goal of this blog post is not to teach how to use or create efficient Docker image, which is a subject on its own. (for instance, you would use builder with dependencies, then deploy a lightweight image such as what I described in https://mickael.canouil.fr/posts/2023-05-07-quarto-docker/)
    The image I built is quite heavy because the goal was to have everything that works with Quarto to allow me to test various Quarto versions in a controlled environment without having to setup dependencies all the time.
    • ghcr.io/mcanouil/quarto-codespaces is 6.07GB
    • ghcr.io/quarto-dev/quarto-full is 2.28GB
    • ghcr.io/rocker-org/devcontainer/r-ver is 2.47GB
  • "Implementation Details": link to "deep link" documentation is provided. I don't think it brings much value to the blog post. The GitHub documentation is quite good for the users wanting to know more.
  • "Auto-open files": I mentioned this to Julia on Slack but forgot to talk about it. I will add this as it's really useful since you cannot really clean up your repository when starting a Dev Container or Codespace.
  • "Educational Context": I don't think the various GitHub Plans should be discussed in this blog post. If users/organisations want to use it, regardless of GitHub Plans being discussed or not, they should read the documentation about the product and the billing.
  • "Repository Organization": the repository I'm mentioning and using is a personal initiative not supported, paid, or endorsed by Posit (I'm not a Posit employee). Quarto/Posit Docker images are hosted on the Quarto CLI repository: https://github.com/orgs/quarto-dev/packages?repo_name=quarto-cli. This is also why I mentioned it in the blog post as an example rather than a resource for others to use as is.

@cscheid
Copy link
Collaborator

cscheid commented May 17, 2025

Thanks @coatless for the feedback! I agree with Mickael on the substance of the points, though.

Mickael, what do you think about linking to this discussion here in the post as part of the "for more" section?

@mcanouil
Copy link
Contributor Author

mcanouil commented May 17, 2025

I think that's a good idea to link to @coatless comment.

I have a question about the "repository organisation" point which relates to @juliasilge comment (#1667 (comment)).
I don't mind making my prebuilt image a resource but in some aspects it means that Quarto/Posit "recommends" it. While currently it's really just an example that you can use.

@cscheid
Copy link
Collaborator

cscheid commented May 17, 2025

I don't mind making my prebuilt image a resource but in some aspects it means that Quarto/Posit "recommends" it. While currently it's really just an example that you can use.

That's a very good point.

Speaking as a Posit employee - my main concern here is that I want to avoid the situation where the reward for your good contribution is additional work that you have to do to support that prebuilt image, which would benefit Posit. That's not the way to build a healthy community and it would be a nontrivial injustice on our part to do something we knew would cause that.

Concretely speaking, I don't know what language you would prefer to use to emphasize that this is not an officially-supported Posit product, but I trust your judgment on picking your preference. In addition, if it turns out that in the future this image becomes so popular to the point that it's becoming laborious for you to host it, Quarto and Posit should help you move that into something that Posit supports. (I of course can't predict exactly how that would go, but I can give you my word that I will strongly support this action if it comes to it.)

@coatless
Copy link
Contributor

@mcanouil
The note on the omnibus container was to warn that the storage billable limit with large containers not built off the default image will be more heavily penalized if left after use, e.g. GB / HoursInMonth = GB / (24 * 30) = ?? GB-Month < 15 GB-Month. When a user multiple comes into play, this increases quickly. So, if the container can be built off of the Universal devcontainer, mcr.microsoft.com/devcontainers/universal:2-focal, storage cost is 0GB + file size. With more targeted builds going to user use, e.g. r-ver (+ Python) / julia / Observable, would lower the storage size.

Sure you can't show the code for the click-to-launch container button here?

https://github.com/quarto-dev/quarto-web/pull/1667/files#diff-6dd09b48e840822c819462e74db0c3ab7c8f208a9072601d37fe2c7f5a24f999R55

You may want to link to:

https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-codespaces/about-billing-for-github-codespaces#reporting-storage-usage for the storage calculation (inactive & active)

https://docs.github.com/en/codespaces/troubleshooting/troubleshooting-included-usage#storage-usage-for-your-base-dev-container (universal container cost)

@mcanouil
Copy link
Contributor Author

I am aware of that but the universal image is way bigger than the buildpack I'm using which make the image not usable for GitHub Actions or local usage via Dev Containers.

  • buildpack-deps 136MB
  • mcr.microsoft.com/devcontainers/universal 3.81GB

Sure you can't show the code for the click-to-launch container button here?

Sure, I can show the code to the button, but not details how to make one. It's all written in the documentation linked just before.

@coatless
Copy link
Contributor

coatless commented May 17, 2025

@mcanouil I get that; but, the focus is more on workshops with newbies &, thus, my push.

Something like:

For example, we can instantly open a GitHub Codespace by clicking on this badge:

To create the badge, add this markdown to your repository's README.md:

[![](https://github.com/codespaces/badge.svg)](https://codespaces.new/mcanouil/quarto-codespaces?quickstart=1&devcontainer_path=.devcontainer%2Fdevcontainer.json)

Replace mcanouil/quarto-codespaces with your username/repository and adjust the devcontainer_path if needed.

Going to step out now. Thanks again for the awesome write up @mcanouil!

@mcanouil
Copy link
Contributor Author

mcanouil commented May 17, 2025

For the badge, I'm adding it while changing a bit the structure about the "base image" and adding the "open files" configuration.

@mcanouil I get that; but, the focus is more on workshops with newbies &, thus, my push.

I don't disagree. My take/experience on this is to tell participants to delete the Codespace after the workshop regardless of how and from what it was built.
FYI, I'm making a special Dev Container configuration that uses the universal base image1 but to benefit from the free storage policy it means all the features needs to be install for every new Codespaces.

Footnotes

  1. it's not building for now ... Now it's working.

@mcanouil
Copy link
Contributor Author

@coatless @juliasilge @cscheid I made several changes based on all your feedbacks. I think they address your main concerns.

Copy link
Collaborator

@juliasilge juliasilge left a comment

Choose a reason for hiding this comment

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

This looks great, @mcanouil! Thank you for working on it 🙌

@cscheid
Copy link
Collaborator

cscheid commented May 18, 2025

Same here - this is great.

@icarusz
Copy link
Collaborator

icarusz commented May 19, 2025

This looks great, thanks @mcanouil !

@cscheid cscheid merged commit 8b2afa8 into quarto-dev:main May 19, 2025
3 checks passed
github-actions bot pushed a commit that referenced this pull request May 19, 2025
…1667)

* feat: Codespaces and Quarto CLI: A Perfect Partnership for Workshops, Teaching, and Development

* style: use inline code markup

* fix: add link to Codespaces feature page

* refactor: @cscheid edits + few minor ones

* style: lightbox and center Codespaces button

* fix: typo

* fix: remove content not really relevant

* fix: add code for Codespaces deep link as suggested by @coatless

* refactor: use image workflow first, then customise and show postStartCommand

* chore: add disclaimer

* chore: minor wording changes

* fix: change cross-ref and add paragraph break

* fix: add acknowledgments

* fix: ackowlegment as appendix

* fix: use full names

* chore: bump date to 19th of may

(cherry picked from commit 8b2afa8)
@github-actions
Copy link
Contributor

Successfully created backport PR for prerelease:

cscheid pushed a commit that referenced this pull request May 19, 2025
…1667) (#1670)

* feat: Codespaces and Quarto CLI: A Perfect Partnership for Workshops, Teaching, and Development

* style: use inline code markup

* fix: add link to Codespaces feature page

* refactor: @cscheid edits + few minor ones

* style: lightbox and center Codespaces button

* fix: typo

* fix: remove content not really relevant

* fix: add code for Codespaces deep link as suggested by @coatless

* refactor: use image workflow first, then customise and show postStartCommand

* chore: add disclaimer

* chore: minor wording changes

* fix: change cross-ref and add paragraph break

* fix: add acknowledgments

* fix: ackowlegment as appendix

* fix: use full names

* chore: bump date to 19th of may

(cherry picked from commit 8b2afa8)

Co-authored-by: Mickaël Canouil <8896044+mcanouil@users.noreply.github.com>
@mcanouil mcanouil deleted the feat/quarto-codespaces branch May 19, 2025 17:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants