diff --git a/docs/src/content/config.ts b/docs/src/content/config.ts
new file mode 100644
index 0000000..45f60b0
--- /dev/null
+++ b/docs/src/content/config.ts
@@ -0,0 +1,6 @@
+import { defineCollection } from 'astro:content';
+import { docsSchema } from '@astrojs/starlight/schema';
+
+export const collections = {
+ docs: defineCollection({ schema: docsSchema() }),
+};
diff --git a/docs/src/content/docs/guides/binary-packages.mdx b/docs/src/content/docs/guides/binary-packages.mdx
new file mode 100644
index 0000000..250d46e
--- /dev/null
+++ b/docs/src/content/docs/guides/binary-packages.mdx
@@ -0,0 +1,41 @@
+---
+title: Using Binary Packages
+description: Learn how to use binary packages.
+---
+
+A **binary package** is a package that contains a binary export.
+
+Binary packages can be run like a normal program. There are several ways to use
+binary packages with pesde.
+
+## Using `pesde x`
+
+The `pesde x` command can be used to run a one-off binary package. This is
+useful for running a binary package without installing it or outside of a pesde
+project.
+
+```sh
+pesde x pesde/hello
+# Hello, pesde! (pesde/hello@1.0.0, lune)
+```
+
+## Installing a binary package
+
+Binary packages can be installed using the `pesde add` and `pesde install`
+commands.
+
+This requires a `pesde.toml` file to be present in the current directory, and
+will add the binary package to the `dependencies` section of the file.
+
+```sh
+pesde add pesde/hello
+pesde install
+```
+
+This will add the binary package to your `PATH`, meaning that it can be run
+anywhere!
+
+```sh
+hello
+# Hello, pesde! (pesde/hello@1.0.0, lune)
+```
\ No newline at end of file
diff --git a/docs/src/content/docs/guides/dependencies.mdx b/docs/src/content/docs/guides/dependencies.mdx
new file mode 100644
index 0000000..8fafc79
--- /dev/null
+++ b/docs/src/content/docs/guides/dependencies.mdx
@@ -0,0 +1,170 @@
+---
+title: Specifying Dependencies
+description: Learn how to specify dependencies in your pesde project.
+---
+
+import { Aside, FileTree, LinkCard } from "@astrojs/starlight/components"
+
+The `[dependencies]` section of your `pesde.toml` file is where you specify the
+dependencies of your project.
+
+pesde supports multiple types of dependencies.
+
+## pesde Dependencies
+
+The most common type of dependency are pesde dependencies. These are
+dependencies on packages published to a [pesde registry](https://pesde.daimond113.com).
+
+```toml title="pesde.toml"
+[indices]
+default = "https://github.com/daimond113/pesde-index"
+
+[dependencies]
+hello = { name = "pesde/hello", version = "^1.0.0" }
+```
+
+In this example, we're specifying a dependency on the `pesde/hello` package on
+the official pesde registry with a version constraint of `^1.0.0`.
+
+You can also add a dependency by running the following command:
+
+```sh
+pesde add pesde/hello
+```
+
+## Git Dependencies
+
+Git dependencies are dependencies on packages hosted on a Git repository.
+
+```toml title="pesde.toml"
+[dependencies]
+acme = { repo = "acme/package", rev = "main" }
+```
+
+In this example, we're specifying a dependency on the package contained within
+the `acme/package` GitHub repository at the `main` branch.
+
+You can also use a URL to specify the Git repository and a specific commit.
+
+```toml title="pesde.toml"
+[dependencies]
+acme = { repo = "https://git.acme.local/package.git", rev = "aeff6" }
+```
+
+You can also specify a path if the package is not at the root of the repository.
+
+
+
+- acme/package.git
+ - pkgs/
+ - **foo/**
+ - pesde.toml
+ - ...
+
+
+
+```toml title="pesde.toml"
+[dependencies]
+foo = { repo = "acme/package", rev = "main", path = "pkgs/foo" }
+```
+
+The path specified by the Git dependency must either be a valid pesde package or
+a [Wally][wally] package.
+
+You can also add a Git dependency by running the following command:
+
+```sh
+# From Git URL
+pesde add https://git.acme.local/package.git#aeff6
+
+# From GitHub repository
+pesde add gh#acme/package#main
+```
+
+## Wally Dependencies
+
+Wally dependencies are dependencies on packages published to a
+[Wally registry][wally]. Wally is a package manager for Roblox and thus Wally
+dependencies should only be used in Roblox projects.
+
+```toml title="pesde.toml"
+[wally_indices]
+default = "https://github.com/UpliftGames/wally-index"
+
+[dependencies]
+foo = { wally = "acme/package", version = "^1.0.0" }
+```
+
+In this example, we're specifying a dependency on the `acme/package` package
+on the official Wally registry with a version constraint of `^1.0.0`.
+
+
+
+You can also add a Wally dependency by running the following command:
+
+```sh
+pesde add wally#acme/package
+```
+
+[wally]: https://wally.run/
+
+## Workspace Dependencies
+
+Packages within a workspace can depend on each other. For example, if `foo`
+and `bar` are both packages in the same workspace, you can add a dependency to
+`bar` in the `foo/pesde.toml` file:
+
+```toml title="foo/pesde.toml"
+[dependencies]
+bar = { workspace = "acme/bar", version = "^" }
+```
+
+You can also add a workspace dependency by running the following command:
+
+```sh
+pesde add workspace:acme/bar
+```
+
+
+
+## Peer Dependencies
+
+Peer dependencies are dependencies that are not installed automatically when
+used by another package. They need to be installed by the user of the package.
+
+```toml title="pesde.toml"
+[peer_dependencies]
+foo = { name = "acme/foo", version = "^1.0.0" }
+```
+
+You can add a peer dependency by passing `--peer` to the `pesde add` command:
+
+```sh
+pesde add --peer acme/foo
+```
+
+## Dev Dependencies
+
+Dev dependencies are dependencies that are only used during development. They
+are not installed when the package is used as a dependency.
+
+```toml title="pesde.toml"
+[dev_dependencies]
+foo = { name = "acme/foo", version = "^1.0.0" }
+```
+
+You can add a dev dependency by passing `--dev` to the `pesde add` command:
+
+```sh
+pesde add --dev acme/foo
+```
diff --git a/docs/src/content/docs/guides/overrides.mdx b/docs/src/content/docs/guides/overrides.mdx
new file mode 100644
index 0000000..fc28c1c
--- /dev/null
+++ b/docs/src/content/docs/guides/overrides.mdx
@@ -0,0 +1,80 @@
+---
+title: Overriding Dependencies
+description: Learn how to override and patch dependencies in pesde.
+---
+
+import { Aside } from '@astrojs/starlight/components'
+
+pesde has several ways to override or patch dependencies in your project.
+
+## Dependency Overrides
+
+Dependency overrides allow you to replace a dependency of a dependency with a
+different version or package.
+
+Let's say you have a project with the following dependencies:
+
+```toml title="pesde.toml"
+[dependencies]
+foo = { name = "acme/foo", version = "^1.0.0" }
+```
+
+But `foo` depends on `bar` 1.0.0, and you want to use `bar` 2.0.0 instead. You
+can override the `bar` dependency in your `pesde.toml` file:
+
+```toml title="pesde.toml"
+[dependencies]
+foo = { name = "acme/foo", version = "^1.0.0" }
+
+[overrides]
+"foo>bar" = { name = "acme/bar", version = "^2.0.0" }
+```
+
+Now, when you run `pesde install`, `bar` 2.0.0 will be used instead of 1.0.0.
+
+You can learn more about the syntax for dependency overrides in the
+[reference](/reference/manifest#overrides).
+
+## Patching Dependencies
+
+Patching allows you to modify the source code of a dependency.
+
+To patch a dependency, you can use the `pesde patch` and `pesde patch-commit`
+commands.
+
+Let's say you have the following dependency in your `pesde.toml` file:
+
+```toml title="pesde.toml"
+[target]
+environment = "luau"
+
+[dependencies]
+foo = { name = "acme/foo", version = "^1.0.0" }
+```
+
+And you want to patch `foo` to fix a bug. You can run the following command:
+
+```sh
+pesde patch "acme/foo@1.0.0 luau"
+
+# done! modify the files in the directory, then run `pesde patch-commit /x/y/z`
+# to apply.
+# warning: do not commit these changes
+# note: the pesde.toml file will be ignored when patching
+```
+
+pesde will copy the source code of `foo` to a temporary directory, in this case
+`/x/y/z`. You can then modify the files in this directory. Once you're done,
+run `pesde patch-commit /x/y/z` to apply the changes.
+
+This will create a patch within the `patches` directory of your project, and
+add an entry to `[patches]`. Then, next time you run `pesde install`, the patch
+will be applied to the dependency.
+
+
+
diff --git a/docs/src/content/docs/guides/publishing.mdx b/docs/src/content/docs/guides/publishing.mdx
new file mode 100644
index 0000000..e111f31
--- /dev/null
+++ b/docs/src/content/docs/guides/publishing.mdx
@@ -0,0 +1,94 @@
+---
+title: Publishing Packages
+description: Learn how to publish packages to the pesde registry.
+---
+
+## Configuration
+
+Before you can publish a package, you must configure the required fields in your
+`pesde.toml` file.
+
+### `includes`
+
+The `includes` field is a list of files and directories that should be included
+in the package.
+
+```toml
+includes = [
+ "pesde.toml",
+ "README.md",
+ "LICENSE",
+ "init.luau",
+]
+```
+
+### `target`
+
+The `target` field defines the environment where the package can be run.
+
+Here, you must also specify the `lib` and/or `bin` fields to indicate the path
+of the exported library or binary.
+
+```toml
+[target]
+environment = "luau"
+lib = "init.luau"
+```
+
+#### Roblox
+
+`bin` is not supported in Roblox packages. You must also specify a list of
+`build_files`. These are the files that should be synced into Roblox. They are
+passed to the `roblox_sync_config_generator` script.
+
+For more information, see [Roblox](/guides/roblox).
+
+```toml
+[target]
+environment = "roblox"
+lib = "init.luau"
+build_files = ["init.luau"]
+```
+
+## Authentication
+
+Before you can publish a package, you must authenticate with your GitHub account.
+
+```sh
+pesde auth login
+```
+
+You will be given a code and prompted to open the GitHub authentication page in
+your browser. You must enter the code to authenticate.
+
+## Publishing
+
+To publish a package, run the following command:
+
+```sh
+pesde publish
+```
+
+You will be prompted to confirm the package details before publishing.
+
+Once a package is published, others will be able to install it. You may not
+remove a package once it has been published. You may not publish a package with
+an already existing version.
+
+## Multi-target Packages
+
+You may publish packages under the same name and version but with different
+targets. This allows you to publish a package that can be used in multiple
+environments.
+
+For example, you may publish a package that can be used in both Roblox and
+Luau environments by publishing two versions of the package, one for each
+environment.
+
+## Documentation
+
+The `README.md` file in the root of the package will be displayed on the
+[pesde registry website](https://pesde.daimond113.com/).
+
+If you have a `docs` directory in the root of the package, they will be
+hosted by pesde and be accessible on the pesde website.
diff --git a/docs/src/content/docs/guides/roblox.mdx b/docs/src/content/docs/guides/roblox.mdx
new file mode 100644
index 0000000..b35517e
--- /dev/null
+++ b/docs/src/content/docs/guides/roblox.mdx
@@ -0,0 +1,36 @@
+---
+title: Roblox
+description: Using pesde in a Roblox project.
+---
+
+pesde can be used in Roblox projects, however this requires some extra setup.
+Namely, you need to specify a `roblox_sync_config_generator` script in order
+to generate the adequate configuration for the sync tool you are using.
+
+The [`pesde-scripts`](https://github.com/daimond113/pesde-scripts)
+repository contains a list of scripts for different sync tools. If the tool
+you are using is not supported, you can write your own script and submit a PR
+to get it added.
+
+These scripts are automatically cloned into the `~/.pesde/scripts` folder and
+kept up to date when you use pesde.
+
+## Usage with Rojo
+
+[Rojo](https://rojo.space/) is a popular tool for syncing files into Roblox
+Studio.
+
+Running `pesde init` will prompt you to select a target, select
+`roblox` or `roblox_server` in this case. This will setup the configuration
+needed to use pesde in a project using Rojo.
+
+## Usage with other tools
+
+If you are using a different sync tool, you should look for it's scripts in the
+pesde-scripts repository. If you cannot find them, you can write your own and
+optionally submit a PR to help others using the same tool as you get started
+quicker.
+
+Scaffold your project with `pesde init`, select the `roblox` or `roblox_server`
+target, and then replace the `.pesde/roblox_sync_config_generator.luau` script
+with the one you want to use.
diff --git a/docs/src/content/docs/guides/self-hosting-registries.mdx b/docs/src/content/docs/guides/self-hosting-registries.mdx
new file mode 100644
index 0000000..dc8c3bf
--- /dev/null
+++ b/docs/src/content/docs/guides/self-hosting-registries.mdx
@@ -0,0 +1,204 @@
+---
+title: Self Hosting Registries
+description: Learn how to self host registries for pesde.
+---
+
+You can self host registries for pesde. This is useful if you want a private
+registry or if you a separate registry for other reasons.
+
+## Making the index repository
+
+The index is a repository that contains metadata about all the packages in the
+registry.
+
+An index contains a `config.toml` file with configuration options.
+
+To create an index, create a new repository and add a `config.toml` file with
+the following content:
+
+```toml title="config.toml"
+# The URL of the registry API
+api = "https://registry.acme.local/"
+
+# Package download URL (optional)
+download = "{API_URL}/v0/packages/{PACKAGE}/{PACKAGE_VERSION}/{PACKAGE_TARGET}"
+
+# the client ID of the GitHub OAuth app (optional)
+github_oauth_client_id = "a1d648966fdfbdcd9295"
+
+# whether to allow packages with Git dependencies (default: false)
+git_allowed = true
+
+# whether to allow packages which depend on packages from other registries
+# (default: false)
+other_registries_allowed = true
+
+# whether to allow packages with Wally dependencies (default: false)
+wally_allowed = false
+
+# the maximum size of the archive in bytes (default: 4MB)
+max_archive_size = 4194304
+```
+
+- **api**: The URL of the registry API. See below for more information.
+
+- **download**: The URL to download packages from. This is optional and
+ defaults to the correct URL for the official pesde registry implementation.
+ You only need this if you are using a custom registry implementation.
+
+ This string can contain the following placeholders:
+
+ - `{API_URL}`: The API URL (as specified in the `api` field).
+ - `{PACKAGE}`: The package name.
+ - `{PACKAGE_VERSION}`: The package version.
+ - `{PACKAGE_TARGET}`: The package target.
+
+ Defaults to `{API_URL}/v0/packages/{PACKAGE}/{PACKAGE_VERSION}/{PACKAGE_TARGET}`.
+
+- **github_oauth_client_id**: This is required if you use GitHub OAuth for
+ authentication. See below for more information.
+
+- **git_allowed**: Whether to allow packages with Git dependencies. This is
+ optional and defaults to `false`.
+
+- **other_registries_allowed**: Whether to allow packages which depend on
+ packages from other registries. This is optional and defaults to `false`.
+
+- **wally_allowed**: Whether to allow packages with Wally dependencies. This is
+ optional and defaults to `false`.
+
+- **max_archive_size**: The maximum size of the archive in bytes. This is
+ optional and defaults to `4194304` (4MB).
+
+You should then push this repository to [GitHub](https://github.com/).
+
+## Configuring the registry
+
+The registry is a web server that provides package downloads and the ability to
+publish packages.
+
+The official registry implementation is available in the
+[pesde GitHub repository](https://github.com/daimond113/pesde/tree/0.5/registry).
+
+Configuring the registry is done using environment variables. In order to allow
+the registry to access the index repository, you must use a personal access
+token of a GitHub account that has access to the index repository. We recommend
+using a separate GitHub account for this purpose.
+
+For instructions on how to create a personal access token, see the
+[GitHub documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).
+The access token must have read and write access to the index repository.
+
+### General configuration
+
+- **INDEX_REPO_URL**: The URL of the index repository. This is required.\
+ Example: `https://github.com/daimond113/pesde-index.git`
+
+- **GITHUB_USERNAME**: The username of the GitHub account that has access to the
+ index repository. This is required.
+
+- **GITHUB_PAT**: The personal access token of the GitHub account specified by
+ `GITHUB_USERNAME`. This is required.
+
+- **COMMITTER_GIT_NAME**: The name to use for the committer when updating the
+ index repository.\
+ Example: `pesde index updater`
+
+- **COMMITTER_GIT_EMAIL**: The email to use for the committer when updating the
+ index repository.\
+ Example: `pesde@localhost`
+
+- **ADDRESS**: The address to bind the server to.\
+ Default: `127.0.0.1`
+
+- **PORT**: The port to bind the server to.\
+ Default: `8080`
+
+### Authentication configuration
+
+The registry supports multiple authentication methods, which are documented
+below.
+
+#### General configuration
+
+- **READ_NEEDS_AUTH**: If set to any value, reading data requires
+ authentication. If not set, anyone can read from the registry.
+ This is optional.
+
+#### Single token authentication
+
+Allows read and write access to the registry using a single token.
+
+- **ACCESS_TOKEN**: The token to use for authentication.
+
+#### Multiple token authentication
+
+Allows read and write access to the registry using different tokens.
+
+- **READ_ACCESS_TOKEN**: The token that grants read access.
+- **WRITE_ACCESS_TOKEN**: The token that grants write access.
+
+#### GitHub OAuth authentication
+
+Allows clients to get read and write access to the registry using GitHub OAuth.
+This requires a GitHub OAuth app, instructions to create one can be found
+in the [GitHub documentation](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app).
+
+- **GITHUB_CLIENT_SECRET**: The client secret of the GitHub OAuth app.
+
+#### No authentication
+
+If none of the above variables are set, **anyone** will be able to read and
+write to the registry.
+
+### Storage configuration
+
+The registry supports multiple storage backends, which are documented below.
+
+#### File system storage
+
+Stores packages on the file system.
+
+- **FS_STORAGE_ROOT**: The root directory where packages are stored.
+
+#### S3 storage
+
+Stores packages on an S3 compatible storage service, such as
+[Amazon S3](https://aws.amazon.com/s3/) or
+[Cloudflare R2](https://www.cloudflare.com/r2/).
+
+- **S3_ENDPOINT**: The endpoint of the S3 bucket to store packages in.
+- **S3_BUCKET_NAME**: The name of the bucket.
+- **S3_REGION**: The region of the bucket.
+- **S3_ACCESS_KEY**: The access key to use.
+- **S3_SECRET_KEY**: The secret key to use.
+
+### Sentry configuration
+
+The registry supports [Sentry](https://sentry.io/) for error tracking.
+
+- **SENTRY_DSN**: The DSN of the Sentry instance.
+
+## Running the registry
+
+First clone the repository and navigate to the repository directory:
+
+```sh
+git clone https://github.com/daimond113/pesde.git
+cd pesde
+```
+
+You can then build the registry using the following command:
+
+```sh
+cargo build --release -p pesde-registry
+```
+
+This will build the registry. The resulting binary will be located at
+`target/release/pesde-registry` or `target/release/pesde-registry.exe`.
+
+After setting the environment variables, you can run the registry using the
+by executing the binary.
+
+The registry must be exposed at the URL specified in the `api` field of the
+index repository configuration.
diff --git a/docs/src/content/docs/guides/workspaces.mdx b/docs/src/content/docs/guides/workspaces.mdx
new file mode 100644
index 0000000..4b7bb52
--- /dev/null
+++ b/docs/src/content/docs/guides/workspaces.mdx
@@ -0,0 +1,100 @@
+---
+title: Workspaces
+description: Learn how to use workspaces in pesde.
+---
+
+import { FileTree, LinkCard } from "@astrojs/starlight/components"
+
+Workspaces allow you to work with multiple pesde projects within a single
+repository. Packages within a workspace can depend on each other. And you can
+run commands like install or publish on every package in the workspace at once.
+
+Let's say you have a repository with the following structure:
+
+
+
+- pesde.toml
+- pkgs/
+ - foo/
+ - pesde.toml
+ - ...
+ - bar/
+ - pesde.toml
+ - ...
+
+
+
+Within the root `pesde.toml` file, we can define a workspace:
+
+```toml title="pesde.toml"
+name = "acme/root"
+version = "0.0.0"
+private = "true"
+
+workspace_members = ["pkgs/*"]
+
+[target]
+environment = "luau"
+```
+
+Now, each folder within the `pkgs/` directory is considered a package in the
+workspace. You can run commands like `pesde install` or `pesde publish` from
+the root of the repository to run them on every package in the workspace.
+
+## Workspace Dependencies
+
+Packages within a workspace can depend on each other. For example, if `foo`
+depends on `bar`, you can add a dependency to `bar` in the `foo/pesde.toml` file:
+
+```toml title="pkgs/foo/pesde.toml"
+name = "acme/foo"
+version = "1.0.0"
+
+[dependencies]
+bar = { workspace = "acme/bar", version = "^" }
+```
+
+Workspace dependencies are replaced with normal pesde dependencies when
+publishing.
+
+The `version` field can either contain `^`, `*`, `=`, `~`, or a specific version
+requirement, such as `^1.0.0`. If you use `^`, `=`, or `~`, it will be replaced
+with the version of the package in the workspace when publishing.
+
+For example, if you had the following:
+
+```toml title="pesde.toml"
+[dependencies]
+bar = { workspace = "acme/bar", version = "^" }
+qux = { workspace = "acme/qux", version = "=" }
+qar = { workspace = "acme/qar", version = "~" }
+zoo = { workspace = "acme/zoo", version = "^2.1.0" }
+baz = { workspace = "acme/baz", version = "*" }
+```
+
+If `bar`, `baz`, `qux`, `qar`, and `zoo` are all at version `2.1.5` in the
+workspace, the `pesde.toml` file will be transformed into the following when
+publishing.
+
+```toml title="pesde.toml"
+[dependencies]
+bar = { name = "acme/bar", version = "^2.1.5" }
+qux = { name = "acme/qux", version = "=2.1.5" }
+qar = { name = "acme/qar", version = "~2.1.5" }
+zoo = { name = "acme/zoo", version = "^2.1.0" }
+baz = { name = "acme/baz", version = "*" }
+```
+
+A `target` field can be added to the `dependencies` table to specify a target
+environment for the dependency.
+
+```toml title="pesde.toml"
+[dependencies]
+bar = { workspace = "acme/bar", version = "^", target = "luau" }
+```
+
+
diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx
new file mode 100644
index 0000000..45255fc
--- /dev/null
+++ b/docs/src/content/docs/index.mdx
@@ -0,0 +1,32 @@
+---
+title: What is pesde?
+description: A package manager for the Luau programming language, supporting multiple runtimes including Roblox and Lune.
+---
+
+pesde is a package manager for the Luau programming language.
+
+## Why use pesde?
+
+When you write code, you often want to use libraries or frameworks that others
+have written. Manually downloading and managing these can be cumbersome.
+
+These libraries or frameworks can be distributed as packages. You can then
+easily install and use these packages using pesde. pesde will automatically
+download and manage the packages, and their dependencies, for you.
+
+## Multi-target support
+
+Luau can run in a lot of different places, such as on [Roblox][roblox], or in
+[Lune][lune].
+
+pesde is designed to work with all of these runtimes. Packages can publish
+multiple versions of themselves, each tailored to a specific runtime.
+
+[registry]: https://pesde.daimond113.com/
+[roblox]: https://www.roblox.com/
+[lune]: https://lune-org.github.io/docs
+
+## The pesde registry
+
+The [pesde registry][registry] is where anyone can publish their packages for
+others to use.
diff --git a/docs/src/content/docs/installation.mdx b/docs/src/content/docs/installation.mdx
new file mode 100644
index 0000000..3cb8f8c
--- /dev/null
+++ b/docs/src/content/docs/installation.mdx
@@ -0,0 +1,89 @@
+---
+title: Installation
+description: Install pesde
+---
+
+import { Aside, Steps, TabItem, Tabs } from "@astrojs/starlight/components"
+
+## Prerequisites
+
+pesde requires [Lune](https://lune-org.github.io/docs) to be installed on your
+system in order to function properly.
+
+You can follow the installation instructions in the
+[Lune documentation](https://lune-org.github.io/docs/getting-started/1-installation).
+
+## Installing pesde
+
+
+
+1. Go to the [GitHub releases page](https://github.com/daimond113/pesde/releases/latest).
+
+2. Download the corresponding archive for your operating system. You can choose
+ whether to use the `.zip` or `.tar.gz` files.
+
+3. Extract the downloaded archive to a folder on your computer.
+
+4. Open a terminal and locate the path of the extracted `pesde` binary.
+
+
+
+
+ If you extracted the archive to `C:\Users\User\Downloads`, the path to the
+ `pesde` binary would be `C:\Users\User\Downloads\pesde.exe`.
+
+ You can then run the `self-install` command:
+
+ ```ps
+ C:\Users\User\Downloads\pesde.exe self-install
+ ```
+
+ pesde should now be installed on your system. You may need to restart your
+ computer for the changes to take effect.
+
+
+
+
+ If you extracted the archive to `~/Downloads`, the path to the `pesde`
+ binary would be `~/Downloads/pesde`.
+
+ You must then add execute permissions and run the `self-install` command:
+
+ ```sh
+ chmod +x ~/Downloads/pesde
+ ~/Downloads/pesde self-install
+ ```
+
+ pesde should now be installed on your system. You will need to update your
+ shell configuration file to add the pesde binary to your `PATH`
+ environment variable.
+
+ ```sh title=".zshrc"
+ export PATH = "$PATH:/home/user/.pesde/bin"
+ ```
+
+ You should then be able to run `pesde` after restarting your shell.
+
+
+
+
+ 5. Verify that pesde is installed by running the following command:
+
+ ```sh
+ pesde -v
+ ```
+
+ This command should output the version of pesde that you installed.
+
+
+
+
diff --git a/docs/src/content/docs/quickstart.mdx b/docs/src/content/docs/quickstart.mdx
new file mode 100644
index 0000000..10ce4d9
--- /dev/null
+++ b/docs/src/content/docs/quickstart.mdx
@@ -0,0 +1,142 @@
+---
+title: Quickstart
+description: Start using pesde
+---
+
+import { FileTree } from "@astrojs/starlight/components"
+
+Let's make a simple Luau program that uses the `pesde/hello` package to print
+hello to the terminal.
+
+## Scaffolding the project
+
+In your terminal, run the following commands to create a folder and navigate
+into it.
+
+```sh
+mkdir hello-pesde
+cd hello-pesde
+```
+
+Then, we'll use `pesde init` to scaffold a new pesde project. The command will
+ask you a few questions to set up the project. Our project will be named
+`/hello_pesde`, replace `` with a username of your choice.
+The name may only contain lowercase letters, numbers, and underscores. The
+environment we're targeting is `luau`.
+
+```sh
+pesde init
+
+# What is the name of the project? /hello_pesde
+# What is the description of the project? (leave empty for none)
+# Who are the authors of this project? (leave empty for none, comma separated)
+# What is the repository URL of this project? (leave empty for none)
+# What is the license of this project? (leave empty for none) MIT
+# What environment are you targeting for your package? luau
+# Would you like to setup a default roblox_sync_config_generator script? No
+```
+
+The command will create a `pesde.toml` file in the current folder. Go ahead
+and open this file in your text editor of choice.
+
+## Adding a main script
+
+Under the `[target]` section, we're going to add a `bin` field to specify
+the path to the main script of our package.
+
+```diff lang="toml" title="pesde.toml"
+ name = "/hello_pesde"
+ version = "0.1.0"
+ license = "MIT"
+
+ [target]
+ environment = "luau"
++ bin = "main.luau"
+
+ [indices]
+ default = "https://github.com/daimond113/pesde-index"
+```
+
+Don't forget to save the file after making the changes.
+
+Now, lets create a `main.luau` file in the project folder and add the following
+code to it.
+
+```luau title="main.luau"
+print("Hello, pesde!")
+```
+
+## Running the script
+
+Then, we can run the following command to run the script.
+
+```sh
+pesde run
+```
+
+You should see `Hello, pesde!` printed to the terminal.
+
+## Install a dependency
+
+Let's use the `pesde/hello` package instead of printing ourselves.
+
+Run the following command to add the package to `pesde.toml`.
+
+```sh
+pesde add pesde/hello
+```
+
+You should see that `pesde.toml` has been updated with the new dependency.
+
+```diff lang="toml" title="pesde.toml"
+ name = "lukadev_0/hello_pesde"
+ version = "0.1.0"
+ license = "MIT"
+
+ [target]
+ environment = "luau"
+ bin = "main.luau"
+
+ [indices]
+ default = "https://github.com/daimond113/pesde-index"
+
++ [dependencies]
++ hello = { name = "pesde/hello", version = "^1.0.0" }
+```
+
+Run the following command to install the new dependency.
+
+```sh
+pesde install
+```
+
+You should see that pesde has created a `luau_packages` folder containing the
+newly installed package. It has alsoo created a `pesde.lock` file, this file
+contains the exact versions of the dependencies that were installed so that
+they can be installed again in the future.
+
+
+
+- luau_packages/
+ - hello.luau
+ - ...
+- main.luau
+- pesde.lock
+- pesde.toml
+
+
+
+Let's update the `main.luau` file to use the `pesde/hello` package.
+
+```luau title="main.luau"
+local hello = require("./luau_packages/hello")
+
+hello()
+```
+
+If we run the script again, we should see something printed to the terminal.
+
+```sh
+pesde run
+# Hello, pesde! (pesde/hello@1.0.0, luau)
+```
\ No newline at end of file
diff --git a/docs/src/content/docs/reference/cli.mdx b/docs/src/content/docs/reference/cli.mdx
new file mode 100644
index 0000000..48fdea3
--- /dev/null
+++ b/docs/src/content/docs/reference/cli.mdx
@@ -0,0 +1,188 @@
+---
+title: pesde CLI
+description: Reference for the pesde CLI.
+---
+
+import { LinkCard } from "@astrojs/starlight/components"
+
+The pesde CLI is the primary way to interact with pesde projects. It provides
+commands for installing dependencies, running scripts, and more.
+
+## `pesde auth`
+
+Authentication-related commands.
+
+- `-i, --index`: The index of which token to manipulate. May be a URL or an alias.
+ Defaults to the default
+ index of the current project or the default index set in the config.
+
+### `pesde auth login`
+
+Sets the token for the index.
+
+- `-t, --token`: The token to set.
+
+If no token is provided, you will be prompted to authenticate with GitHub. A
+code will be provided that you can paste into the GitHub authentication prompt.
+
+### `pesde auth logout`
+
+Removes the stored token for the index.
+
+### `pesde auth whoami`
+
+Prints the username of the currently authenticated user of the index. Only
+works if the token is a GitHub token.
+
+## `pesde config`
+
+Configuration-related commands.
+
+### `pesde config default-index`
+
+```sh
+pesde config default-index [INDEX]
+```
+
+Configures the default index. If no index is provided, the current default index
+is printed.
+
+- `-r, --reset`: Resets the default index.
+
+The default index is [`pesde-index`](https://github.com/daimond113/pesde-index).
+
+### `pesde config scripts-repo`
+
+```sh
+pesde config scripts-repo [REPO]
+```
+
+Configures the scripts repository. If no repository is provided, the current
+scripts repository is printed.
+
+- `-r, --reset`: Resets the scripts repository.
+
+The default scripts repository is [`pesde-scripts`](https://github.com/daimond113/pesde-scripts).
+
+## `pesde init`
+
+Initializes a new pesde project in the current directory.
+
+## `pesde run`
+
+Runs a script from the current project using Lune.
+
+```sh
+pesde run [SCRIPT] [ -- ...]
+```
+
+If no script is provided, it will run the script specified by `target.bin`
+in `pesde.toml`.
+
+If a path is provided, it will run the script at that path.
+
+If a script defined in `[scripts]` is provided, it will run that script.
+
+If a package name is provided, it will run the script specified by `target.bin`
+in that package.
+
+Arguments can be passed to the script by using `--` followed by the arguments.
+
+```sh
+pesde run foo -- --arg1 --arg2
+```
+
+## `pesde install`
+
+Installs dependencies for the current project.
+
+- `-t, --threads`: The number of threads to use for downloading dependencies.
+- `--locked`: Whether to error if the lockfile is out of date.
+- `--prod`: Whether to skip installing dev dependencies.
+
+## `pesde publish`
+
+Publishes the current project to the pesde registry.
+
+- `-d, --dry-run`: Whether to perform a dry run. This will output a
+ tarball containing the package that would be published, but will not actually
+ publish it.
+- `-y, --yes`: Whether to skip the confirmation prompt.
+
+## `pesde self-install`
+
+Performs the pesde installation process. This should be the first command run
+after downloading the pesde binary.
+
+## `pesde self-upgrade`
+
+Upgrades the pesde binary to the latest version.
+
+## `pesde patch`
+
+```sh
+pesde patch
+```
+
+Prepares a patching environment for a package. This will copy the source code of
+the package to a temporary directory.
+
+The package specified must be in the format `@`.
+
+
+
+## `pesde patch-commit`
+
+```sh
+pesde patch-commit
+```
+
+Applies the changes made in the patching environment created by `pesde patch`.
+
+## `pesde add`
+
+```sh
+pesde add
+```
+
+Adds a package to the dependencies of the current project.
+
+- `-i, --index `: The index in which to search for the package.
+- `-t, --target `: The target environment for the package.
+- `-a, --alias `: The alias to use for the package, defaults to the
+ package name.
+- `-p, --peer`: Adds the package as a peer dependency.
+- `-d, --dev`: Adds the package as a dev dependency.
+
+The following formats are supported:
+
+```sh
+pesde add pesde/hello
+pesde add gh#acme/package#main
+pesde add https://git.acme.local/package.git#aeff6
+```
+
+## `pesde update`
+
+Updates the dependencies of the current project.
+
+- `-t, --threads`: The number of threads to use for downloading dependencies.
+
+## `pesde x`
+
+Runs a one-off binary package.
+
+```sh
+pesde x
+```
+
+This is useful for running a binary package without installing it or outside of
+a pesde project.
+
+```sh
+pesde x pesde/hello
+```
diff --git a/docs/src/content/docs/reference/manifest.mdx b/docs/src/content/docs/reference/manifest.mdx
new file mode 100644
index 0000000..9156e00
--- /dev/null
+++ b/docs/src/content/docs/reference/manifest.mdx
@@ -0,0 +1,405 @@
+---
+title: pesde.toml
+description: Reference for `pesde.toml`
+---
+
+import { LinkCard } from "@astrojs/starlight/components"
+
+`pesde.toml` is the manifest file for a pesde package. It contains metadata about
+the package and its dependencies.
+
+## Top-level fields
+
+```toml
+name = "acme/package"
+version = "1.2.3"
+description = "A package that does foo and bar"
+license = "MIT"
+authors = ["John Doe (https://acme.local)"]
+repository = "https://github.com/acme/package"
+```
+
+### `name`
+
+The name of the package. This is used to identify the package in the registry.
+
+The name consists of a scope and a package name, separated by a slash (`/`). It
+may only contain lowercase letters, numbers, and underscores.
+
+The first one to publish to a given scope gets to own it. If you want multiple
+people to be able to publish to the same scope, you can send a pull request to
+the [pesde-index GitHub repository](https://github.com/daimond113/pesde-index)
+and add the GitHub user ID of the other person to the `owners` field of the
+`scope.toml` file of the given scope. For more information, see
+[policies](/registry/policies#package-ownership).
+
+### `version`
+
+The version of the package. This must be a valid [SemVer](https://semver.org/)
+version, such as `1.2.3`.
+
+### `description`
+
+A short description of the package. This is displayed on the package page in the
+registry.
+
+### `license`
+
+The license of the package. It is recommended to use a
+[SPDX license identifier](https://spdx.org/licenses/), such as `MIT` or
+`Apache-2.0`.
+
+### `authors`
+
+A list of authors of the package. Each author is a string containing the name of
+the author, optionally followed by an email address in angle brackets, and a
+website URL in parentheses. For example:
+
+```toml
+authors = ["John Doe (https://acme.local)"]
+```
+
+### `repository`
+
+The URL of the repository where the package is hosted. This is displayed on the
+package page in the registry.
+
+### `private`
+
+A boolean indicating whether the package is private. If set to `true`, the
+package cannot be published to the registry.
+
+### `includes`
+
+List of top-level files and directories to include in the package when
+publishing. Files not listed here will not be published.
+
+```toml
+includes = [
+ "pesde.toml",
+ "README.md",
+ "LICENSE",
+ "init.luau",
+ "docs",
+]
+```
+
+### `pesde_version`
+
+The version of pesde to use within this project. The `pesde` CLI will look at
+this field and run the correct version of pesde for this project.
+
+### `workspace_members`
+
+A list of globs containing the members of this workspace.
+
+
+
+
+## `[target]`
+
+The `[target]` section contains information about the target platform for the
+package.
+
+```toml
+[target]
+environment = "luau"
+lib = "init.luau"
+```
+
+### `environment`
+
+The target environment for the package. This can be one of the following:
+
+- `luau`: Standalone Luau code that can be run using the `luau` CLI.
+- `lune`: Luau code that requires the Lune runtime.
+- `roblox`: Luau code that must be run in Roblox.
+- `roblox_server`: Same as `roblox`, but only for server-side code.
+
+### `lib`
+
+**Allowed in:** `luau`, `lune`, `roblox`, `roblox_server`
+
+The entry point of the library exported by the package. This file is what will
+be required when the package is loaded using `require`.
+
+### `bin`
+
+**Allowed in:** `luau`, `lune`
+
+The entry point of the binary exported by the package. This file is what will be
+run when the package is executed as a binary.
+
+
+
+### `build_files`
+
+**Allowed in:** `roblox`, `roblox_server`
+
+A list of files that should be synced to Roblox when the package is installed.
+
+```toml
+build_files = [
+ "init.luau",
+ "foo.luau",
+]
+```
+
+These files are passed to [`roblox_sync_config_generator`](#roblox_sync_config_generator)
+when the package is installed in order to generate the necessary configuration.
+
+## `[scripts]`
+
+The `[scripts]` section contains scripts that can be run using the `pesde run`
+command. These scripts are run using [Lune](https://lune-org.github.io/docs).
+
+```toml
+[scripts]
+build = "sripts/build.luau"
+test = "scripts/test.luau"
+```
+
+There are also a few special scripts that are run in certain cases by pesde.
+
+### `roblox_sync_config_generator`
+
+This is responsible for generating adequate configuration files for Roblox
+sync tools.
+
+`process.args` will contain the directory containing the package, and the list
+of files specified within the [`target.build_files`](#build_files) of the
+package.
+
+You can find template scripts inside the
+[`pesde-scripts` repository](https://github.com/daimond113/pesde-scripts)
+for various sync tools.
+
+
+
+
+
+### `sourcemap_generator`
+
+This is responsible for generating source maps for packages that are installed.
+This is required to get proper types support when using
+[Wally dependencies](/guides/dependencies/#wally-dependencies).
+
+The script will receive the path to the package directory as the first argument
+through `process.args`.
+
+
+
+## `[indices]`
+
+The `[indices]` section contains a list of pesde indices where packages can be
+installed from.
+
+```toml
+[indices]
+default = "https://github.com/daimond113/pesde-index"
+acme = "https://github.com/acme/pesde-index"
+```
+
+These can then be referenced in the [`dependencies`](#dependencies) of the
+package. The `default` index is used if no index is specified.
+
+```toml
+[dependencies]
+foo = { name = "acme/foo", version = "1.2.3", index = "acme" }
+```
+
+## `[wally_indices]`
+
+The `[wally_indices]` section contains a list of Wally indices where packages
+can be installed from. This is used for
+[Wally dependencies](/guides/dependencies/#wally-dependencies).
+
+```toml
+[wally_indices]
+default = "https://github.com/UpliftGames/wally-index"
+acme = "https://github.com/acme/wally-index"
+```
+
+These can then be referenced in the [`dependencies`](#dependencies) of the
+package. The `default` index is used if no index is specified.
+
+```toml
+[dependencies]
+foo = { wally = "acme/foo", version = "1.2.3", index = "acme" }
+```
+
+## `[overrides]`
+
+The `[overrides]` section contains a list of overrides for dependencies. This
+allows you to replace certain dependencies with different versions or even
+different packages.
+
+```toml
+[overrides]
+"bar>baz" = { name = "acme/baz", version = "1.0.0" }
+"foo>bar,baz>bar" = { name = "acme/bar", version = "2.0.0" }
+```
+
+The above example will replace the `baz` dependency of the `bar` package with
+version `1.0.0`, and the `bar` and `baz` dependencies of the `foo` package with
+version `2.0.0`.
+
+Each key in the overrides table is a comma-separated list of package paths. The
+path is a list of package names separated by `>`. For example, `foo>bar>baz`
+refers to the `baz` dependency of the `bar` package, which is a dependency of
+the `foo` package.
+
+
+
+## `[patches]`
+
+The `[patches]` section contains a list of patches for dependencies. This allows
+you to modify the source code of dependencies.
+
+```toml
+[patches]
+"acme/foo" = { "1.0.0 luau" = "patches/acme+foo-1.0.0+luau.patch" }
+```
+
+The above example will patch version `1.0.0` with the `luau` target of the
+`acme/foo` package using the `patches/acme+foo-1.0.0+luau.patch` file.
+
+Each key in the patches table is the package name, and the value is a table
+where the keys are the version and target, and the value is the path to the
+patch.
+
+The patches can be generated using the `pesde patch` command.
+
+
+
+## `[place]`
+
+This is used in Roblox projects to specify where packages are located in the
+Roblox datamodel.
+
+```toml
+[place]
+shared = "game.ReplicatedStorage.Packages"
+server = "game.ServerScriptService.Packages"
+```
+
+## `[dependencies]`
+
+The `[dependencies]` section contains a list of dependencies for the package.
+
+```toml
+[dependencies]
+foo = { name = "acme/foo", version = "1.2.3" }
+bar = { wally = "acme/bar", version = "2.3.4" }
+baz = { git = "acme/baz", rev = "main" }
+```
+
+Each key in the dependencies table is the name of the dependency, and the value
+is a dependency specifier.
+
+There are several types of dependency specifiers.
+
+### pesde
+
+```toml
+[dependencies]
+foo = { name = "acme/foo", version = "1.2.3", index = "acme", target = "lune" }
+```
+
+**pesde dependencies** contain the following fields:
+
+- `name`: The name of the package.
+- `version`: The version of the package.
+- `index`: The [pesde index](#indices) to install the package from. If not
+ specified, the `default` index is used.
+- `target`: The target platform for the package. If not specified, the target
+ platform of the current package is used.
+
+### Wally
+
+```toml
+[dependencies]
+foo = { wally = "acme/foo", version = "1.2.3", index = "acme" }
+```
+
+**Wally dependencies** contain the following fields:
+
+- `wally`: The name of the package.
+- `version`: The version of the package.
+- `index`: The [Wally index](#wally_indices) to install the package from. If not
+ specified, the `default` index is used.
+
+### Git
+
+```toml
+[dependencies]
+foo = { git = "acme/packages", rev = "main", path = "foo" }
+```
+
+**Git dependencies** contain the following fields:
+
+- `git`: The URL of the Git repository.
+ This can either be `/` for a GitHub repository, or a full URL.
+- `rev`: The Git revision to install. This can be a branch, tag, or commit hash.
+- `path`: The path within the repository to install. If not specified, the root
+ of the repository is used.
+
+## `[peer_dependencies]`
+
+The `[peer_dependencies]` section contains a list of peer dependencies for the
+package. These are dependencies that are required by the package, but are not
+installed automatically. Instead, they must be installed by the user of the
+package.
+
+```toml
+[peer_dependencies]
+foo = { name = "acme/foo", version = "1.2.3" }
+```
+
+## `[dev_dependencies]`
+
+The `[dev_dependencies]` section contains a list of development dependencies for
+the package. These are dependencies that are only required during development,
+such as testing libraries or build tools. They are not installed when the
+package is used by another package.
+
+```toml
+[dev_dependencies]
+foo = { name = "acme/foo", version = "1.2.3" }
+```
+
+
+
+
diff --git a/docs/src/content/docs/registry/policies.md b/docs/src/content/docs/registry/policies.md
new file mode 100644
index 0000000..707d467
--- /dev/null
+++ b/docs/src/content/docs/registry/policies.md
@@ -0,0 +1,96 @@
+---
+title: Policies
+description: Policies for the pesde registry
+---
+
+The following policies apply to the [official public pesde registry](https://registry.pesde.daimond113.com)
+and its related services, such as the index repository or websites.
+They may not apply to other registries. By using the pesde registry, you agree
+to these policies.
+
+If anything is unclear, please [contact us](#contact-us), and we will be happy
+to help.
+
+## Contact Us
+
+You can contact us at [pesde@daimond113.com](mailto:pesde@daimond113.com). In
+case of a security issue, please prefix the subject with `[SECURITY]`.
+
+## Permitted content
+
+The pesde registry is a place for Luau-related packages. This includes:
+
+- Libraries
+- Frameworks
+- Tools
+
+The following content is forbidden:
+
+- Malicious, vulnerable code
+- Illegal, harmful content
+- Miscellaneous files (doesn't include configuration files, documentation, etc.)
+
+pesde is not responsible for the content of packages, the scope owner is. It
+is the responsibility of the scope owner to ensure that the content of their
+packages is compliant with the permitted content policy.
+
+If you believe a package is breaking these requirements, please [contact us](#contact-us).
+
+## Package removal
+
+pesde does not support removing packages for reasons such as abandonment. A
+package may only be removed for the following reasons:
+
+- The package is breaking the permitted content policy
+- The package contains security vulnerabilities
+- The package must be removed for legal reasons (e.g. DMCA takedown)
+
+In case a secret has been published to the registry, it must be invalidated.
+If you believe a package should be removed, please [contact us](#contact-us).
+We will review your request and take action if necessary.
+
+If we find that a package is breaking the permitted content policy, we will
+exercise our right to remove it from the registry without notice.
+
+pesde reserves the right to remove any package from the registry at any time for
+any or no reason, without notice.
+
+## Package ownership
+
+Packages are owned by scopes. Scope ownership is determined by the first person
+to publish a package to the scope. The owner of the scope may send a pull request
+to the index repository adding team members' user IDs to the scope's `scope.toml`
+file to give them access to the scope, however at least one package must be
+published to the scope before this can be done. The owner may also remove team
+members from the scope.
+
+A scope's true owner's ID must appear first in the `owners` field of the scope's
+`scope.toml` file. Ownership may be transferred by the current owner sending a
+pull request to the index repository, and the new owner confirming the transfer.
+
+Only the owner may add or remove team members from the scope.
+
+pesde reserves the right to override scope ownership in the case of a dispute,
+such as if the original owner is unresponsive or multiple parties claim ownership.
+
+## Scope squatting
+
+Scope squatting is the act of creating a scope with the intent of preventing
+others from using it, without any intention of using it yourself. This is
+forbidden and can result in the removal (release) of the scope and its packages
+from the registry without notice.
+
+If you believe a scope is being squatted, please [contact us](#contact-us).
+We will review your request and take action if necessary.
+
+## API Usage
+
+The pesde registry has an API for querying, downloading, and publishing packages.
+Only non-malicious use is permitted. Malicious uses include:
+
+- **Service Degradation**: this includes sending an excessive amount of requests
+ to the registry in order to degrade the service
+- **Exploitation**: this includes trying to break the security of the registry
+ in order to gain unauthorized access
+- **Harmful content**: this includes publishing harmful (non-law compliant,
+ purposefully insecure) content
diff --git a/docs/src/env.d.ts b/docs/src/env.d.ts
new file mode 100644
index 0000000..acef35f
--- /dev/null
+++ b/docs/src/env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/docs/src/tailwind.css b/docs/src/tailwind.css
new file mode 100644
index 0000000..a5ca780
--- /dev/null
+++ b/docs/src/tailwind.css
@@ -0,0 +1,11 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root[data-theme="light"] {
+ --sl-color-bg: rgb(255 245 230);
+}
+
+:root[data-theme="light"] .sidebar-pane {
+ background-color: var(--sl-color-bg);
+}
diff --git a/docs/tailwind.config.ts b/docs/tailwind.config.ts
new file mode 100644
index 0000000..32bae0d
--- /dev/null
+++ b/docs/tailwind.config.ts
@@ -0,0 +1,36 @@
+import starlightPlugin from "@astrojs/starlight-tailwind"
+import type { Config } from "tailwindcss"
+import defaultTheme from "tailwindcss/defaultTheme"
+
+export default {
+ content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
+
+ theme: {
+ extend: {
+ fontFamily: {
+ sans: ["Nunito Sans Variable", ...defaultTheme.fontFamily.sans],
+ },
+ colors: {
+ accent: {
+ 200: "rgb(241 157 30)",
+ 600: "rgb(120 70 10)",
+ 900: "rgb(24 16 8)",
+ 950: "rgb(10 7 4)",
+ },
+ gray: {
+ 100: "rgb(245 230 210)",
+ 200: "rgb(228 212 192)",
+ 300: "rgb(198 167 140)",
+ 400: "rgb(142 128 112)",
+ 500: "rgb(84 70 50)",
+ 600: "rgb(65 50 41)",
+ 700: "rgb(50 42 35)",
+ 800: "rgb(28 22 17)",
+ 900: "rgb(10 7 4)",
+ },
+ },
+ },
+ },
+
+ plugins: [starlightPlugin()],
+} as Config
diff --git a/docs/tsconfig.json b/docs/tsconfig.json
new file mode 100644
index 0000000..a3f6981
--- /dev/null
+++ b/docs/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "astro/tsconfigs/strict"
+}
diff --git a/registry/src/endpoints/publish_version.rs b/registry/src/endpoints/publish_version.rs
index d6a38ab..043f5ff 100644
--- a/registry/src/endpoints/publish_version.rs
+++ b/registry/src/endpoints/publish_version.rs
@@ -61,7 +61,7 @@ const ADDITIONAL_FORBIDDEN_FILES: &[&str] = &["default.project.json"];
struct DocEntryInfo {
#[serde(default)]
label: Option,
- #[serde(default)]
+ #[serde(default, alias = "position")]
sidebar_position: Option,
#[serde(default)]
collapsed: bool,
diff --git a/website/.gitignore b/website/.gitignore
new file mode 100644
index 0000000..79518f7
--- /dev/null
+++ b/website/.gitignore
@@ -0,0 +1,21 @@
+node_modules
+
+# Output
+.output
+.vercel
+/.svelte-kit
+/build
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Env
+.env
+.env.*
+!.env.example
+!.env.test
+
+# Vite
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/website/.npmrc b/website/.npmrc
new file mode 100644
index 0000000..b6f27f1
--- /dev/null
+++ b/website/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/website/.prettierignore b/website/.prettierignore
new file mode 100644
index 0000000..ab78a95
--- /dev/null
+++ b/website/.prettierignore
@@ -0,0 +1,4 @@
+# Package Managers
+package-lock.json
+pnpm-lock.yaml
+yarn.lock
diff --git a/website/.prettierrc b/website/.prettierrc
new file mode 100644
index 0000000..4ebb478
--- /dev/null
+++ b/website/.prettierrc
@@ -0,0 +1,14 @@
+{
+ "useTabs": true,
+ "printWidth": 100,
+ "semi": false,
+ "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
+ "overrides": [
+ {
+ "files": "*.svelte",
+ "options": {
+ "parser": "svelte"
+ }
+ }
+ ]
+}
diff --git a/website/bun.lockb b/website/bun.lockb
new file mode 100755
index 0000000..db992e7
Binary files /dev/null and b/website/bun.lockb differ
diff --git a/website/eslint.config.js b/website/eslint.config.js
new file mode 100644
index 0000000..b36887c
--- /dev/null
+++ b/website/eslint.config.js
@@ -0,0 +1,33 @@
+import js from "@eslint/js"
+import ts from "typescript-eslint"
+import svelte from "eslint-plugin-svelte"
+import prettier from "eslint-config-prettier"
+import globals from "globals"
+
+/** @type {import('eslint').Linter.Config[]} */
+export default [
+ js.configs.recommended,
+ ...ts.configs.recommended,
+ ...svelte.configs["flat/recommended"],
+ prettier,
+ ...svelte.configs["flat/prettier"],
+ {
+ languageOptions: {
+ globals: {
+ ...globals.browser,
+ ...globals.node,
+ },
+ },
+ },
+ {
+ files: ["**/*.svelte"],
+ languageOptions: {
+ parserOptions: {
+ parser: ts.parser,
+ },
+ },
+ },
+ {
+ ignores: ["build/", ".svelte-kit/", "dist/"],
+ },
+]
diff --git a/website/package.json b/website/package.json
new file mode 100644
index 0000000..9a26eeb
--- /dev/null
+++ b/website/package.json
@@ -0,0 +1,70 @@
+{
+ "name": "website",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "vite preview",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "lint": "prettier --check . && eslint .",
+ "format": "prettier --write ."
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-vercel": "^5.4.6",
+ "@sveltejs/kit": "^2.7.3",
+ "@sveltejs/vite-plugin-svelte": "^4.0.0",
+ "@tailwindcss/typography": "^0.5.15",
+ "@types/eslint": "^9.6.1",
+ "@types/gunzip-maybe": "^1.4.2",
+ "@types/tar-stream": "^3.1.3",
+ "autoprefixer": "^10.4.20",
+ "eslint": "^9.13.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-svelte": "^2.46.0",
+ "globals": "^15.11.0",
+ "mdsvex": "^0.12.3",
+ "prettier": "^3.3.3",
+ "prettier-plugin-svelte": "^3.2.7",
+ "prettier-plugin-tailwindcss": "^0.6.8",
+ "svelte": "^5.1.4",
+ "svelte-check": "^4.0.5",
+ "tailwindcss": "^3.4.14",
+ "typescript": "^5.6.3",
+ "typescript-eslint": "^8.12.2",
+ "vite": "^5.4.10"
+ },
+ "type": "module",
+ "dependencies": {
+ "@fontsource-variable/nunito-sans": "^5.1.0",
+ "@shikijs/rehype": "^1.22.2",
+ "@types/hast": "^3.0.4",
+ "@types/unist": "^3.0.3",
+ "bits-ui": "next",
+ "date-fns": "^4.1.0",
+ "gunzip-maybe": "^1.4.2",
+ "hast-util-heading": "^3.0.0",
+ "hast-util-heading-rank": "^3.0.0",
+ "hast-util-to-text": "^4.0.2",
+ "lucide-svelte": "^0.446.0",
+ "rehype-infer-description-meta": "^2.0.0",
+ "rehype-raw": "^7.0.0",
+ "rehype-sanitize": "^6.0.0",
+ "rehype-slug": "^6.0.0",
+ "rehype-stringify": "^10.0.1",
+ "remark-frontmatter": "^5.0.0",
+ "remark-gemoji": "^8.0.0",
+ "remark-gfm": "^4.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.1.1",
+ "shiki": "^1.22.2",
+ "tar-stream": "^3.1.7",
+ "unified": "^11.0.5",
+ "unist-util-map": "^4.0.0",
+ "vfile": "^6.0.3"
+ },
+ "patchedDependencies": {
+ "@shikijs/rehype@1.22.0": "patches/@shikijs%2Frehype@1.22.0.patch"
+ }
+}
diff --git a/website/patches/@shikijs%2Frehype@1.22.0.patch b/website/patches/@shikijs%2Frehype@1.22.0.patch
new file mode 100644
index 0000000..a2e86a8
--- /dev/null
+++ b/website/patches/@shikijs%2Frehype@1.22.0.patch
@@ -0,0 +1,26 @@
+@shikis/rehype doesn't use the `fallbackLanguage` if `lazy` is used.
+
+--- a/dist/core.mjs
++++ b/dist/core.mjs
+@@ -1,6 +1,8 @@
+ import { visit } from 'unist-util-visit';
+ import { toString } from 'hast-util-to-string';
+
++import { bundledLanguages } from 'shiki';
++
+ const InlineCodeHandlers = {
+ "tailing-curly-colon": (_tree, node) => {
+ const raw = toString(node);
+@@ -90,8 +92,12 @@ function rehypeShikiFromHighlighter(highlighter, options) {
+ const languageQueue = [];
+ const queue = [];
+ function getLanguage(lang) {
+ if (!lang)
+ return defaultLanguage;
++
++ if (!(lang in bundledLanguages))
++ return fallbackLanguage;
++
+ if (highlighter.getLoadedLanguages().includes(lang))
+ return lang;
+ if (lazy) {
diff --git a/website/postcss.config.js b/website/postcss.config.js
new file mode 100644
index 0000000..1a52624
--- /dev/null
+++ b/website/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/website/src/app.css b/website/src/app.css
new file mode 100644
index 0000000..0883f6a
--- /dev/null
+++ b/website/src/app.css
@@ -0,0 +1,92 @@
+@import "tailwindcss/base";
+@import "tailwindcss/components";
+@import "tailwindcss/utilities";
+
+:root {
+ --color-background: 255 245 230;
+ --color-card: 245 230 210;
+ --color-card-hover: 240 225 205;
+ --color-border: 200 180 160;
+ --color-header: 250 234 215;
+
+ --color-body: 84 70 50;
+ --color-heading: 70 55 35;
+ --color-light: 0 0 0;
+
+ --color-input-bg: 245 230 210;
+ --color-input-border: 180 160 140;
+ --color-placeholder: 130 90 40;
+
+ --color-primary: 120 70 10;
+ --color-primary-hover: 255 172 42;
+ --color-primary-bg: 241 157 30;
+ --color-primary-fg: 10 7 4;
+
+ --shiki-foreground: rgb(var(--color-heading));
+ --shiki-background: rgb(var(--color-card));
+ --shiki-token-constant: color-mix(in srgb, rgb(120 140 230), rgb(var(--color-light)) 50%);
+ --shiki-token-string: rgb(var(--color-heading));
+ --shiki-token-comment: rgb(var(--color-body));
+ --shiki-token-keyword: color-mix(in srgb, rgb(var(--color-primary)), rgb(var(--color-light)) 50%);
+ --shiki-token-parameter: rgb(var(--color-heading));
+ --shiki-token-function: rgb(var(--color-primary));
+ --shiki-token-string-expression: color-mix(
+ in srgb,
+ rgb(120 230 140),
+ rgb(var(--color-light)) 50%
+ );
+ --shiki-token-punctuation: rgb(var(--color-heading));
+ --shiki-token-link: rgb(var(--color-primary));
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --color-background: 10 7 4;
+ --color-card: 28 22 17;
+ --color-card-hover: 40 32 25;
+ --color-border: 28 22 17;
+ --color-header: 20 16 12;
+
+ --color-body: 198 167 140;
+ --color-heading: 227 213 200;
+ --color-light: 255 255 255;
+
+ --color-input-bg: 20 13 8;
+ --color-input-border: 78 60 40;
+ --color-placeholder: 169 147 128;
+
+ --color-primary: 241 157 30;
+ --color-primary-hover: 255 172 42;
+ --color-primary-bg: 241 157 30;
+ --color-primary-fg: 10 7 4;
+ }
+}
+
+html {
+ scroll-padding-top: theme(spacing.24);
+ color-scheme: light dark;
+}
+
+body {
+ background-color: theme(colors.background);
+ color: theme(colors.body);
+}
+
+@keyframes cursor-blink {
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0;
+ }
+}
+
+.hide-scrollbar::-webkit-scrollbar {
+ display: none;
+}
+
+.hide-scrollbar {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
diff --git a/website/src/app.d.ts b/website/src/app.d.ts
new file mode 100644
index 0000000..f70d0e1
--- /dev/null
+++ b/website/src/app.d.ts
@@ -0,0 +1,13 @@
+// See https://kit.svelte.dev/docs/types#app
+// for information about these interfaces
+declare global {
+ namespace App {
+ // interface Error {}
+ // interface Locals {}
+ // interface PageData {}
+ // interface PageState {}
+ // interface Platform {}
+ }
+}
+
+export {}
diff --git a/website/src/app.html b/website/src/app.html
new file mode 100644
index 0000000..77a5ff5
--- /dev/null
+++ b/website/src/app.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+