Skip to content
Draft
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
81 changes: 81 additions & 0 deletions docs/blog/posts/2026-03-10-1.9-release/_contribs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
[CoryMcCartan](https://github.com/CoryMcCartan),
[Data-Wise](https://github.com/Data-Wise),
[FrankwaP](https://github.com/FrankwaP),
[Joao-O-Santos](https://github.com/Joao-O-Santos),
[LukasDSauer](https://github.com/LukasDSauer),
[MBe-iUS](https://github.com/MBe-iUS),
[MarcoPortmann](https://github.com/MarcoPortmann),
[MariaBarrioSchez](https://github.com/MariaBarrioSchez),
[MateusMolina](https://github.com/MateusMolina),
[Selbosh](https://github.com/Selbosh),
[ThePurox](https://github.com/ThePurox),
[TucoFernandes](https://github.com/TucoFernandes),
[aecoleman](https://github.com/aecoleman),
[amirhome61](https://github.com/amirhome61),
[andrewheiss](https://github.com/andrewheiss),
[azankl](https://github.com/azankl),
[bensoltoff](https://github.com/bensoltoff),
[bruvellu](https://github.com/bruvellu),
[byzheng](https://github.com/byzheng),
[cbrnr](https://github.com/cbrnr),
[chendaniely](https://github.com/chendaniely),
[chi-raag](https://github.com/chi-raag),
[christopherkenny](https://github.com/christopherkenny),
[coatless](https://github.com/coatless),
[cynthiahqy](https://github.com/cynthiahqy),
[darwindarak](https://github.com/darwindarak),
[davidskalinder](https://github.com/davidskalinder),
[dmenne](https://github.com/dmenne),
[fconil](https://github.com/fconil),
[fkgruber](https://github.com/fkgruber),
[fkohrt](https://github.com/fkohrt),
[fredguth](https://github.com/fredguth),
[gadenbuie](https://github.com/gadenbuie),
[github-actions[bot]](https://github.com/apps/github-actions),
[gsathler-vi](https://github.com/gsathler-vi),
[hamgamb](https://github.com/hamgamb),
[herosi](https://github.com/herosi),
[icarusz](https://github.com/icarusz),
[jeremy886](https://github.com/jeremy886),
[jkrumbiegel](https://github.com/jkrumbiegel),
[jmcphers](https://github.com/jmcphers),
[jonas37](https://github.com/jonas37),
[jorherre](https://github.com/jorherre),
[jreades](https://github.com/jreades),
[jromanowska](https://github.com/jromanowska),
[jtbayly](https://github.com/jtbayly),
[juleswg23](https://github.com/juleswg23),
[juliasilge](https://github.com/juliasilge),
[kathsherratt](https://github.com/kathsherratt),
[kusnezoff-alexander](https://github.com/kusnezoff-alexander),
[lrrichter](https://github.com/lrrichter),
[lwjohnst86](https://github.com/lwjohnst86),
[maelle](https://github.com/maelle),
[matthiasbaitsch](https://github.com/matthiasbaitsch),
[mipmip](https://github.com/mipmip),
[mstrms2000](https://github.com/mstrms2000),
[multimeric](https://github.com/multimeric),
[mvuorre](https://github.com/mvuorre),
[mykolaskrynnyk](https://github.com/mykolaskrynnyk),
[nichtich](https://github.com/nichtich),
[nithinmkp](https://github.com/nithinmkp),
[nrichers](https://github.com/nrichers),
[orbsmiv](https://github.com/orbsmiv),
[paytonej](https://github.com/paytonej),
[petrelharp](https://github.com/petrelharp),
[phongphuhanam](https://github.com/phongphuhanam),
[pm-gusmano](https://github.com/pm-gusmano),
[posit-snyk-bot](https://github.com/posit-snyk-bot),
[prosoitos](https://github.com/prosoitos),
[rabyj](https://github.com/rabyj),
[sasja-san](https://github.com/sasja-san),
[sbwiecko](https://github.com/sbwiecko),
[serialc](https://github.com/serialc),
[spaette](https://github.com/spaette),
[spraetor](https://github.com/spraetor),
[stragu](https://github.com/stragu),
[szimmer](https://github.com/szimmer),
[the-solipsist](https://github.com/the-solipsist),
[thomasp85](https://github.com/thomasp85),
[yyzeng](https://github.com/yyzeng),
[zhe00a](https://github.com/zhe00a).
68 changes: 68 additions & 0 deletions docs/blog/posts/2026-03-10-1.9-release/get-contribs.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Run using `quarto run get-contribs.R`

library(tidyverse)
library(gh)
library(glue)

last_release <- "2025-09-05T00:00:00Z"
milestone <- "v1.9"

quarto_staff_vec <-
c("allenmanning", "cderv", "cscheid", "cwickham", "dragonstyle",
"jjallaire", "jooyoungseo", "kevinushey", "mcanouil",
"rich-iannone", "gordonwoodhull", "tarleb", "vezwork", "mine-cetinkaya-rundel")

# Get milestone number -----

milestones <- gh("/repos/{owner}/{repo}/milestones",
owner = "quarto-dev",
repo = "quarto-cli")

milestone_number <- map_int(milestones, "number")[map_chr(milestones, "title") == milestone]

# Get cli issues tagged with current milestone -----

quarto_issues <-
gh(
endpoint = "/repos/quarto-dev/quarto-cli/issues",
.limit = 2000,
.progress = FALSE,
.params = list(
state = "all",
milestone = milestone_number
)
)

quarto_issues_tbl <- map(quarto_issues, \(x) data.frame(login = x$user$login, html_url = x$user$html_url)) |>
list_rbind()

# Get web issues since last release -----

quarto_web_issues <-
gh(
endpoint = "/repos/quarto-dev/quarto-web/issues",
.limit = 1500,
.progress = FALSE,
.params = list(
state = "all",
since = last_release
)
)

quarto_web_issues_tbl <- map(quarto_web_issues, \(x) data.frame(login = x$user$login, html_url = x$user$html_url)) |>
list_rbind()

# Put together, exclude staff and write to file -----

cli_and_web_users <- bind_rows(quarto_web_issues_tbl, quarto_issues_tbl) |>
filter(!(login %in% quarto_staff_vec)) |>
arrange(login) |>
distinct()

strings <- cli_and_web_users |>
glue_data("[{login}]({html_url}), ")

strings[length(strings)] <- str_c(str_sub(strings[length(strings)], 1, -3), ".")

strings |> write_lines("_contribs.md")

176 changes: 176 additions & 0 deletions docs/blog/posts/2026-03-10-1.9-release/index.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
---
title: Quarto 1.9
description: |
Quarto 1.9 adds publishing to Posit Connect Cloud, LLM-friendly website output, major Typst improvements, experimental PDF accessibility standards, and list tables for complex table content.
categories:
- Quarto 1.9
- Releases
author: Charlotte Wickham
date: "2026-03-10"
image: thumbnail.png
image-alt: "Quarto 1.9"
---

Quarto 1.9 is out! You can get the current release from the [download page](/docs/download/index.qmd).

Sharing your work just got easier with integrated Posit Connect Cloud publishing. Typst users will appreciate book project support and article layouts, while experimental PDF accessibility standards bring PDF/A and PDF/UA compliance to both LaTeX and Typst. This release also introduces LLM-friendly output for websites, the `quarto use brand` command for keeping your brand assets in sync, and list tables for authoring complex tables with familiar bullet syntax.

You can read about these improvements and some other highlights below. You can find all the changes in this version in the [Release Notes](/docs/download/changelog/1.9/).

## Publish to Posit Connect Cloud

You can now publish documents and websites to [Posit Connect Cloud](https://connect.posit.cloud) directly from the command line.
For example, publish your Quarto website project with:

```{.bash filename="Terminal"}
quarto publish posit-connect-cloud
```

Posit Connect Cloud is a hosted platform for sharing data applications and documents without managing your own infrastructure. It includes a free tier for unlimited static document publishing.
Read more in [Publishing > Posit Connect Cloud](/docs/publishing/posit-connect-cloud.qmd).

## Improvements to Typst Support

Quarto 1.9 brings substantial improvements to Typst output, including book project support via the bundled `orange-book` extension, article layout options for margins and side notes, new typography options, and theorem styling with four appearance options.

There's so much new, we've already written up the details in a separate [Typst improvements blog post](TODO-LINK-TO-TYPST-BLOG-POST).

## PDF Accessibility (Experimental)

We're rolling out experimental support for PDF accessibility standards in 1.9. The new `pdf-standard` option enables PDF/A archival formats and PDF/UA accessibility compliance for both LaTeX and Typst outputs. Alt text from `fig-alt` attributes now passes through to PDF for screen reader support, and Typst gains support for alt text on cross-referenced equations.

Not everything works yet---look for a blog post and patch release in the coming weeks with more details and improvements.

Read more in the documentation for [LaTeX](/docs/output-formats/pdf-basics.qmd#pdf-accessibility-standards) and [Typst](/docs/output-formats/typst.qmd#pdf-accessibility-standards).

## Output for LLMs

Quarto can now generate [llms.txt](https://llmstxt.org/) format output for your website, making your content more accessible to large language models and AI-powered tools.

Enable it in your website configuration:

```{.yaml filename="_quarto.yml"}
website:
title: "My Documentation"
llms-txt: true
```

When you render your site, Quarto creates:

- An `llms.txt` index file at the root of your site listing all pages
- A `.llms.md` markdown file alongside each HTML page (e.g., `guide.html` gets `guide.llms.md`)

The markdown files contain clean versions of your content---navigation, sidebars, and scripts are stripped out; tables, code blocks, and callouts are converted to standard markdown.

Read more, including how to customize what appears in LLM output, in [Websites > Output for LLMs](/docs/websites/website-llms.qmd).

## `quarto use brand` Command

Keep your project's brand assets in sync with an external source using the new `quarto use brand` command:

```{.bash filename="Terminal"}
quarto use brand myorg/shared-brand
```

The command copies brand files from a GitHub repository, local directory, or zip archive into your project's `_brand/` directory. Quarto walks you through each step---confirming trust for remote sources, creating the directory if needed, and asking whether to overwrite or remove files.

See [Guide > Brand](/docs/authoring/brand.qmd#quarto-use-brand) for `--dry-run`, `--force`, and other options.

## List Tables

List tables provide a new syntax for creating tables with complex content---multiple paragraphs, code blocks, or nested lists---using familiar bullet syntax instead of grid table formatting:

::: {layout-ncol="2"}

:::: {}

```` markdown
::: {.list-table}
- - Function
- Description

- - `sum()`
- Add values:

```python
sum([1, 2, 3])
```

- - `len()`
- Count items:

- Works on lists
- Works on strings
:::
````

::::

:::: {}

::: {.list-table}
- - Function
- Description

- - `sum()`
- Add values:

```python
sum([1, 2, 3])
```

- - `len()`
- Count items:

- Works on lists
- Works on strings
:::

::::

:::

Each top-level bullet represents a row; nested bullets represent cells. This syntax is much easier to maintain than grid tables, especially when cells contain code or other block elements.

List tables support all the usual table features: captions, cross-references, column widths, and alignment. Thanks to Martin Fischer for the original development, with contributions from Albert Krewinkel and William Lupton.

Find all the details in [Guide > Tables](/docs/authoring/tables.qmd#list-tables).

## Other Highlights

- Privacy-focused features for websites:

- [A privacy-first default for cookie consent](/docs/websites/website-tools.qmd#cookie-consent): The default for cookie consent has changed to `type: express`, providing opt-in consent that blocks cookies until users explicitly agree. This privacy-conscious default is designed with modern privacy regulations in mind.

- [Algolia Search Insights avoids cookies](/docs/websites/website-search.qmd#cookie-consent-and-user-tracking): Use Algolia Insights now uses persistent cookies only if `cookie-consent` is active, and the user has opted-in.

- [Use Plausible Analytics](/docs/websites/website-tools.qmd#plausible-analytics): Add privacy-friendly Plausible Analytics to websites via the `plausible-analytics` configuration option.

- [`aria-label` for videos](/docs/authoring/videos.qmd#accessibility-label): Improve accessibility of embedded videos by providing custom descriptive labels for screen readers instead of the default "Video Player" label.

- [New `syntax-highlighting` Option](/docs/output-formats/pdf-basics.qmd#syntax-highlighting): Replaces the deprecated `highlight-style` (Pandoc 3.8). Supports style names, custom `.theme` files, `none`, or `idiomatic` for format-native highlighting.

- Metadata and brand extensions now work without a `_quarto.yml` project. A temporary default project is created in memory.

- [Engine extensions](/docs/extensions/engine.qmd) allow replacement of the execution engine:
- Julia is now a bundled extension instead of being built-in.
- **quarto-marimo** will soon change from a filter extension to an engine extension.
- New `quarto create extension engine` command.
- New `quarto call build-ts-extension` command.
- New **Quarto API** for engine extensions to use. (This is in flux and will not be documented for the next few releases, but there will be a dev blog post about it.)

Dependency updates:

- `pandoc` updated to 3.8.3
- `typst` updated to 0.14.2
- `esbuild` updated to 0.25.10
- `deno` updated to 2.4.5
- `mermaid` updated to 11.12.0

## Acknowledgements

We'd like to say a huge thank you to everyone who contributed to this release by opening issues and pull requests:

{{< include _contribs.md >}}

The airplane departure emoji in the [listing and social card image](thumbnail.png) for this post comes from [OpenMoji](https://openmoji.org/){.external}– the open-source emoji and icon project. License: [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/#){.external}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.