# Astro's monorepo ships twenty packages on independent version lines, and the recommended install is a scaffolder

> A read of withastro/astro: the two install commands and what only one of them creates, why the release list pairs astro@7.3.5 with an adapter on version 11, the pnpm and turbo setup that contributors use while the docs say npm, and the formatting and test scripts that decide whether a change is cheap to run locally.

**withastro/astro** — GitHub describes it as The web framework for content-driven websites. ⭐️ Star to support our work!. The repository metadata lists TypeScript as its primary language. The metadata lists the NOASSERTION license. This article stays within the project description and details documented in the GitHub repository README.

- Repository: https://github.com/withastro/astro
- Website: https://astro.build
- Stars: 62,920 · Forks: 3,819
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-08-13 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/withastro-astro

## Two install commands, and only one of them builds you a project

The install section offers exactly two commands and marks one of them recommended. The first is the scaffolding route:

```bash
npm create astro@latest
```

The second is a bare dependency add:

```bash
npm install astro
```

The difference is not the version you get, since the second path also takes the latest, it is what exists in your directory afterwards. The first command runs a project creator, and the directory table shows a package called create-astro with its own release notes, so the recommended path is a generator that asks questions and writes a working layout. The second installs the framework and stops there, leaving you to create the configuration file, the page directory, the TypeScript setup, and the scripts that run the dev server and the build yourself. Nothing in the readme enumerates what the creator writes or which answers it asks, which is the practical gap here: someone choosing the manual path has to know the expected project shape from the docs, while someone choosing the creator has to review what it wrote. The readme points both cases at the Getting Started guide and at astro.new for a starter opened directly in the browser.

## Twenty packages on separate version lines, so astro 7 and vercel 11 sit side by side

The directory table is the single most useful thing in this readme, because it shows that the repository publishes far more than the framework. Alongside `astro` and `create-astro` sit five UI integrations (react, preact, solid-js, svelte, vue), an Alpine.js integration, four adapters (node, vercel, cloudflare, netlify), content pieces (mdx, rss, sitemap), partytown, and four editor and language tooling packages (check, language-server, ts-plugin, astro-vscode). Each row points at its own changelog under packages/.

The versioning consequence is visible in the three most recent releases. Two are the core, astro@7.3.5 on 2026-09-24 and astro@7.3.4 on 2026-09-22, and the third is an adapter, @astrojs/vercel at version 11.0.11 on the same day as the second core release. The numbers are unrelated lines. The adapter you deploy with is not locked to the framework's major version, so an upgrade of astro does not carry the deployment target with it, and a project that pins its adapter in a lockfile can end up on a different adapter version than its framework without anyone changing a number deliberately. Each package's own changelog under packages/ is where to read what moved.

## Contributors run pnpm and turbo while the install docs say npm

The tree tells you which package manager the maintainers actually use. A pnpm-workspace.yaml and a pnpm-lock.yaml sit at the root next to turbo.json, and every root script is a pnpm script: release is `pnpm run build && changeset publish`, dev is `turbo run dev` with `--concurrency=40 --parallel`, and the test entry point chains three filtered suites. So the published install command for users is npm, while the development loop for contributors is a pnpm workspace orchestrated by turbo, with every build and dev run filtered by package name, including a filter for the benchmark packages.

That split is not a problem in itself, but it does mean a contributor who installs with npm will not reproduce the lockfile, and a user who follows a contributor issue thread will not reproduce the install. Two other files mark the same boundary. The .nvmrc pins a Node version for the repository, and a .devcontainer plus .gitpod directory and config exist for a ready environment, so the intended way to work is inside a prepared container rather than on a bare laptop. For a reader deciding whether to contribute, that is the difference between cloning and running versus cloning and assembling a toolchain.

## biome and prettier both write files, then eslint config sits beside them

Formatting here is two tools in a fixed order, and the order is in the root scripts. The code format step is `biome format --write && prettier -w "**/*" --ignore-unknown --cache`, so biome formats and then prettier runs across the whole tree with a cache, skipping unknown file types. Import order is handled separately, with `biome check --formatter-enabled=false --write`, which runs biome as a linter with formatting disabled so it can sort imports without touching whitespace. The continuous integration variants are the same commands with a check flag, so a mismatch fails the pipeline rather than being fixed on the fly.

Sitting next to all of that is eslint.config.js, plus biome.jsonc, prettier.config.mjs, and a .prettierignore. Three configuration surfaces for one repository is a real cost for a first contribution: a rule you set in the eslint config may not be the rule that fires, because biome runs first for formatting and imports. The repository also ships STYLE_GUIDE.md and knip.js, which suggests an additional check beyond linting. A contributor who runs only their editor's formatter will produce diffs that the format scripts rewrite, and the churn lands in the review.

## Changesets cut the release, so version numbers and changelogs arrive together

Releases are not typed by hand here. The root has a .changeset directory, and the release script is `pnpm run build && changeset publish`: a filtered turbo build of the core, the creator, every @astrojs package, the VS Code extension, and the benchmarks, followed by changesets publishing whatever the accumulated change files describe. The practical meaning for anyone on the other side of the package is that a version bump is a consequence of a merged change, and its notes are generated, so the changelog is the record of what a given number did.

Two costs follow. First, a change that touches the core and an integration can land as two version moves, which is exactly what the recent release list shows with astro@7.3.4 and @astrojs/vercel@11.0.11 on 2026-09-22. Second, because publishing is driven by pending change files, a repository that has not been given them has nothing to publish, so anyone tracking releases should read the per-package changelog under packages/ rather than infer a change from the version number alone. The version string itself follows npm scope conventions, with the scope prefix on the adapter and integration packages and none on the core.

## Test scripts select affected packages and force concurrency down to one

The three test entries are worth reading before a contributor runs anything. The aggregate test script chains test:astro, test:integrations, and test:language-tools, so a single command runs all three groups. Each of them is not a plain suite invocation: test:astro is `node ./scripts/turbo-run-affected.js test --concurrency=1 --filter=astro --only`, integrations add `--filter=create-astro` and `--filter="@astrojs/*"` while excluding the language-tools path, and the language-tools group is a turbo run filtered to that directory. The wrapper script name is the important part, since it selects affected packages rather than running everything, and the exclusions are the reason the three groups do not overlap.

`--concurrency=1` in every group is a deliberate choice, and it means a full local run is serial. Contributors are expected to use the filtered form. A second cost shows up in the build scripts, since `build:examples` runs turbo filtered to `@example/*`, so a change in the core is exercised by building the example projects. The examples directory is large, with named cases for each framework integration, for framework-multiple, with-mdx, with-markdoc, with-nanostores, with-tailwindcss, container-with-vitest, with-vitest, toolbar-app, advanced-routing, ssr, hackernews, blog, portfolio, component, basics, minimal, integration and starlog, so the practical feedback loop for a core change is the examples, not the unit tests alone.

## The compiler and Starlight are versioned elsewhere, and the licence field disagrees with the licence link

Two things a project depends on are not in this repository. The readme states that several official projects are maintained outside it, and names two: withastro/compiler, which is the piece that compiles the framework's own template syntax, and Starlight, the documentation site project. Both have their own repositories and their own release cadence, so the framework's behaviour and a docs site's version are governed by other release trains. Anything pinned in a lockfile for a project that uses Starlight therefore has two version lines to watch, and this repository's changelog will not record the other one.

The licensing signal is contradictory in a way worth resolving before shipping. The repository metadata carries no licence assertion at all, while the readme links a LICENSE file labelled MIT, and LICENSE exists at the root. With twenty separate published packages, the top-level field is a poor place to answer what licence applies to the one package you are installing, so each package's own metadata is the place to check. Two files settle the process side: GOVERNANCE.md records open governance and voting, which is the document to read before depending on internals that could change, and CONTRIBUTING.md plus SECURITY.md and SECURITY_CONTACTS cover how changes and vulnerability reports enter the project.

## Conclusion

A content site that wants a build step and little client side JavaScript fits the tool, and the fastest start is the scaffolding command rather than the bare dependency. Before adopting, check which @astrojs adapter your host needs and what version of that adapter you are pinning, read GOVERNANCE.md if you depend on internals, and treat the compiler and Starlight as separately versioned pieces, because the repository licence field disagrees with the licence the readme links.

## FAQ

### What is Astro, the build tool?

It is a website build tool for the modern web from the withastro organisation, written in TypeScript, whose stated aim is a developer experience paired with lightweight output, with docs at docs.astro.build.

### How do I install Astro?

The recommended way is `npm create astro@latest`, which scaffolds a project, and the manual alternative is `npm install astro`, which only adds the dependency and leaves the project layout to you.

### How do I use Astro after installing it?

Follow the Getting Started guide at docs.astro.build, or open a starter project in the browser at astro.new, since the readme points both routes there rather than documenting day to day usage itself.

### Is Astro still active?

Yes. The last push to the repository landed on 2026-09-29, with astro@7.3.5 published on 2026-09-24 and astro@7.3.4 on 2026-09-22, and the releases are published continuously from the monorepo.

## Sources

- [Official documentation](https://astro.build)
- [Official README](https://github.com/withastro/astro#readme)
- [Project repository](https://github.com/withastro/astro)
- [Release notes](https://github.com/withastro/astro/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/withastro-astro
