
Research
Security News
Malicious PyPI Package Exploits Deezer API for Coordinated Music Piracy
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
@tinloof/sanity-studio
Advanced tools
A collection of studio plugins, fields, and components to boost your Sanity studio.
npm install @tinloof/sanity-studio
Pages is a plugin that wraps Presentation to display your website pages in a sitemap-like navigation and make it possible to create new ones.
import { pages } from "@tinloof/sanity-studio";
export default defineConfig({
// ... other Sanity Studio config
plugins: [
pages({
// Presentation's configuration
previewUrl: {
previewMode: {
enable: "/api/draft",
},
},
}),
],
});
pathname
field to page schemas using the definePage
helper:import { definePathname } from "@tinloof/sanity-studio";
export default defineType({
type: "document",
name: "modularPage",
fields: [
definePathname({
name: "pathname",
}),
],
});
Documents with a defined pathname
field value are now recognized as pages and are automatically grouped into directories in the pages navigator.
Like Sanity's native slug
type, the pathname
supports a source
option which can be used to generate the pathname from another field on the document, eg. the title:
import { definePathname } from "@tinloof/sanity-studio";
export default defineType({
type: "document",
name: "modularPage",
fields: [
definePathname({
name: "pathname",
options: {
source: "title",
},
}),
],
});
The source
can also be a function (which can be asynchronous), returning the generated pathname.
Use the creatablePages
option to define which schema types can be used to create pages.
When a page is created, it will automatically have the current folder in its pathname.
import { pages } from "@tinloof/sanity-studio";
export default defineConfig({
// ... other Sanity Studio config
plugins: [
pages({
// Add any documents you want to be creatable from the pages navigator
creatablePages: ["page"],
previewUrl: {
previewMode: {
enable: "/api/draft",
},
},
}),
],
});
The i18n
option can be used to support filtering pages by a locale
field and display internationalized URLs.
When page creation is enabled, the currently selected locale
is also used as an initial value to create new pages.
Pathnames are automatically validated to be unique accros locales.
import { pages } from "@tinloof/sanity-studio";
const i18nConfig = {
locales: [
{ id: "en", title: "English" },
{ id: "fr", title: "French" },
],
defaultLocaleId: "en",
};
export default defineConfig({
// ... other Sanity Studio config
plugins: [
pages({
i18n: i18nConfig,
previewUrl: {
previewMode: {
enable: "/api/draft",
},
},
}),
],
});
/**
* Don't forget to add i18n options and locale field to your document schema
*/
export default defineType({
type: "document",
name: "page",
fields: [
definePathname({
name: "pathname",
options: {
// Add i18n options
i18n: {
enabled: true,
defaultLocaleId: i18nConfig.defaultLocaleId,
},
},
}),
// Add locale field
defineField({
type: "string",
name: "locale",
hidden: true,
}),
],
});
By default, when internationalization is enabled, only pages whose locale
field matches the currently selected locale will be shown in the list. If you have page types that are not translated but you still want them to show up in the list, you can set the requireLocale
option to false in your i18n
config:
const i18nConfig = {
locales: [
{ id: "en", title: "English" },
{ id: "fr", title: "French" },
],
defaultLocaleId: "en",
requireLocale: false,
};
Now all documents with a pathname
field will show up in the list regardless of the filtered locale, even if they don't have a locale
field (or their locale
is null
).
By default, folders can be renamed. Set the folder.canUnlock
option to false
to disable this.
import { definePathname } from "@tinloof/sanity-studio";
export default defineType({
type: "document",
name: "modularPage",
fields: [
definePathname({
name: "pathname",
options: {
folder: {
canUnlock: false,
},
},
}),
],
});
Documents can have their preview customized on the pages navigator using the List Previews API:
export default {
name: "movie",
type: "document",
fields: [
{
title: "Title",
name: "title",
type: "string",
},
{
type: "image",
name: "image",
title: "Image",
},
],
// Preview information
preview: {
select: {
title: "title",
media: "image",
},
prepare({ title, image }) {
return {
title,
media: image,
};
},
},
};
By default, folders will have a folder icon and use the pathname/prefix capitalized as the title. You can customize this for individual folders using the folders
config option on the plugin:
export default defineConfig({
// ... other Sanity Studio config
plugins: [
pages({
previewUrl: {
previewMode: {
enable: "/api/draft",
},
},
folders: {
"/news": {
title: "Articles",
icon: NewspaperIcon,
},
},
}),
],
});
By default, the pathname
field comes with a "Preview" button which is used to navigate to the page within the Presentation iframe when the pathname changes. You can optionally disable this manual button and have the Presentation tool automatically navigate to the new pathname as it changes:
import { definePathname } from "@tinloof/sanity-studio";
export default defineType({
type: "document",
name: "modularPage",
fields: [
definePathname({
name: "pathname",
options: {
autoNavigate: true,
},
}),
],
});
The Presentation tool will now automatically navigate to the new pathname as the user types, with a 1 second debounce.
The defineSection
field lets you easily define a new section schema. Used in combination with the SectionsArrayInput
component, it will render a useful section picker in your Sanity documents.
// @/sanity/schemas/sections/banner.tsx
export const bannerSection = defineSection({
name: "block.banner",
title: "Banner",
type: "object",
options: {
variants: [
{
/**
* Will be used to display a preview image
* when opening the section picker
*/
assetUrl: "/images/blocks/hero.png",
},
],
},
fields: [
defineField({
name: "bannerSection",
type: "string",
}),
],
});
// @/sanity/schemas/sections/index.tsx
import { bannerSection } from "@/sanity/schemas/sections/banner";
export const sections = [bannerSection];
Here, the SectionsArrayInput
component is used to render a useful section picker in your Sanity documents.
// @/sanity/schemas/sections/index.tsx
import { sections } = "@/sanity/schemas/sections/index";
import { SectionsArrayInput } from "@tinloof/sanity-studio";
export default defineType({
name: "page",
type: "document",
// ... other fields
fields: [
defineField({
name: 'sectionPicker',
title: 'Section Picker',
type: 'array',
of: sections.map((section) => ({
type: section.name,
})),
components: {
input: SectionsArrayInput,
},
}),
]
})
export const sections = [bannerSection];
// @/sanity/schemas/index.tsx
import { sections } from "@sanity/schemas/index";
import page from "@/sanity/schemas/page";
const schemas = [page, ...sections];
export default schemas;
documentI18n
The documentI18n
plugin is an opinionated thin wrapper around Sanity's Document Internationalization that makes it possible to add internationalization without having to specify schema types.
documentI18n
enables internationalization on any schema with a locale
field.
Check the with-i18n
example for instructions on usage.
localizedItem
The localizedItem
utility helps create localized document lists in your Sanity Studio's structure. It creates a nested list structure that groups documents by locale, with an "All" option to view all documents regardless of locale.
import { localizedItem } from '@tinloof/sanity-studio';
import { StructureResolver } from 'sanity/structure';
const locales = [
{ id: 'en', title: 'English' },
{ id: 'fr', title: 'French' },
];
export const structure: StructureResolver = (S) => {
return S.list()
.title('Content')
.items([
localizedItem(S, 'blog.post', 'Blog posts', locales),
]);
S
: The Sanity Structure Builder instancename
: The document type name (string)title
: The display title for the list (string)locales
: An array of locale objects with id
and title
propertiesYou can include additional properties
const locales = [
{ id: "en", title: "English", countryCode: "US", isDefault: true },
{ id: "fr", title: "French", countryCode: "FR" },
];
localizedItem(S, "blog.post", "Blog posts", locales);
The utility will create a nested structure with:
locale
fielddefineIcon
Builds upon a string field with an options list to show a preview of the icon select as well as other options.
import { defineIcon } from "@tinloof/sanity-studio";
import { defineType } from "sanity";
export default defineType({
type: "document",
name: "page",
fields: [
{
type: "string",
name: "title",
},
defineIcon({
name: "icon",
options: {
list: [
{ title: "Calendar", value: "calendar" },
{ title: "Chat", value: "chat" },
{ title: "Clock", value: "clock" },
],
},
}),
],
});
options.list
: Uses the default string option list type of {title: string, value: string}[]
The ultility searches for icons within the folder /icons/select/[icon-value].svg
, if you have a Next.js embbedded setup then store them under /public/icons/select/[icon-value].svg
.
Plugin to disable the creation of doucments with the disableCreation
option set to true. The plugin does this by:
sanity.config.ts;
import { disableCreation } from "@tinloof/sanity-studio";
import schemas from "@/sanity/schemas";
export default defineConfig({
name: "studio",
title: "Studio",
projectId: "12345678",
dataset: "production",
schema: {
types: schemas,
},
plugins: [disableCreation({ schemas: ["home", "header", "footer"] })],
});
schemas
: String array of document typesoverrideDocumentActions
: The document actions to override, defaults to publish, discardChanges, restoreWhen using this plugin, make sure you placing it after the stucutureTool()
.
plugins: [
structureTool(),
visionTool(),
disableCreation({
schemaTypes: schemaTypes as SchemaTypeDefinition[],
}),
],
Check the /examples
folder.
MIT © Tinloof
This plugin uses @sanity/plugin-kit with default configuration for build & watch scripts.
See Testing a plugin in Sanity Studio on how to run this plugin with hotreload in the studio.
FAQs
A collection of Sanity studio plugins, fields, and components
The npm package @tinloof/sanity-studio receives a total of 1,423 weekly downloads. As such, @tinloof/sanity-studio popularity was classified as popular.
We found that @tinloof/sanity-studio demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.
Security News
Newly introduced telemetry in devenv 1.4 sparked a backlash over privacy concerns, leading to the removal of its AI-powered feature after strong community pushback.