This Astro integration downloads Sanity File Assets to your project's public/
directory on build which makes these files available in your dist/
directory without the Sanity CDN.
First, install the package using your package manager, for example:
npm install astro-sanity-assets
Then, apply the integration to your Astro config file using the integrations property:
import { defineConfig } from "astro/config";
import downloadSanityAssets from "astro-sanity-assets";
export default defineConfig({
// ...
integrations: [
downloadSanityAssets({
// see Configuration section below
}),
],
});
The configuration expects a Sanity client config as used for @sanity/client
as well as the GROQ query
to retrieve your files from Sanity and a directory
name to use for your files inside the public/
folder.
import { defineConfig } from "astro/config";
import downloadSanityAssets from "astro-sanity-assets";
export default defineConfig({
// ...
integrations: [
downloadSanityAssets({
projectId: "<YOUR-PROJECT-ID>",
dataset: "<YOUR-DATASET-NAME>",
query: `*[_type == "download"].file.asset->`,
directory: "directory",
}),
],
});
The plugin run on every Astro build, retrieve the list of files and will download them to public/<directory>
. So in the example above all attachments from the file
field in download
documents will be downloaded to public/downloads
and therefore land in the final dist/downloads
folder.
If the specified directory
does not exist in the public/
folder, the plugin will create the folder and delete it after the build, so that only the dist/
folder will contain the files after the build is done. The folder will not be deleted, if it already existed when the build was started.
Any GROQ query that will return an array of Sanity Asset objects as returned by the File field. The only required fields are assetId
, extension
and url
. You may also use a totally different query and tweak the data by using the handler
function.
The files by default will be named <assetId>.<extension>
.
Sometimes you may want to use a query
that does not return Sanity Assets and therefore have to tweak the query result a bit. For example:
import { defineConfig } from "astro/config";
import downloadSanityAssets from "astro-sanity-assets";
type FileAssetType = {
url: string;
originalFilename: string;
};
export default defineConfig({
// ...
integrations: [
downloadSanityAssets<FileAssetType>({
projectId: "<YOUR-PROJECT-ID>",
dataset: "<YOUR-DATASET-NAME>",
query: `*[_type == "fileType" && mimeType == "video/mp4"]`,
directory: "videos",
handler: (file) =>
file.url && file.originalFilename
? {
url: file.url, // URL of the file to download
filename: file.originalFilename, // local filename
}
: undefined,
}),
],
});
The handler
function receives every item from the array returned by the query
and must return an object containing the url
to download and the local filename
to use inside the directory
. If the file should be skipped just return undefined
or null
.
You can use the local files however you like. Since they are downloaded at start of the build process they are available early on. For example, you could check if the file exists locally like so:
---
import fs from "fs";
import { resolve } from "path";
import type { SanityFileAsset } from "@types/sanity.types";
interface Props {
title: string;
file: SanityFileAsset;
}
const { file } = Astro.props;
const src = `/downloads/${file.originalFilename}`;
const filePath = resolve("./public/downloads", file.originalFilename);
if (!fs.existsSync(filePath)) {
return null;
}
---
<a href={src}>{title}</a>
Copyright © kolossal. Released under MIT License.