Setting Up Sanity
The Vyuh Framework uses Sanity.io as its default supported CMS. This guide walks you through setting up Sanity, configuring the studio, and connecting it to your Flutter app.
Overview
The CMS (Content) is a flagship extension provided by the Vyuh Framework. It allows you to integrate with any headless CMS and have it control the app experience. The Content extension is supported by two types of classes: ContentExtensionDescriptor and ContentExtensionBuilder, which work in conjunction to extract the content extensions from various features and use them to render content in the final app.
Descriptors and Builders
The ContentExtensionDescriptor is used by individual features to export various content types, actions, conditions, and other kinds of configurations. The ContentExtensionBuilder compiles all these descriptors across the features and assembles a registry that is used to render content at runtime.
1. Setup the Sanity CMS
Sanity is a headless CMS that allows you to define your own schemas and content types entirely in code. This makes it easy to quickly build sophisticated schemas without wrestling with any drag-and-drop builders. It also includes a Studio which becomes the go-to UI tool for content editors.
Scaffold the Project
Set up a free Sanity project using the guides from Sanity.io or use the command line:
pnpm dlx create-sanity@latestWhile creating the Sanity project, select the project template as Clean project with no predefined schema types.
Scaffold Quickly
A faster way to scaffold a Vyuh project is with the vyuh_cli tool. The Vyuh CLI can generate a complete Vyuh project, a Flutter feature package, and an NPM schema package.
2. Configure the Studio
Add the following dependencies to your package.json and run pnpm install:
{
dependencies: {
'@vyuh/sanity-plugin-structure': '^1.16.2',
'@vyuh/sanity-schema-core': '^1.16.2',
'@vyuh/sanity-schema-system': '^1.16.2',
},
}Update the sanity.config.ts file:
import { defineConfig } from 'sanity'
import { vyuh } from '@vyuh/sanity-plugin-structure'
import { system } from '@vyuh/sanity-schema-system'
export default defineConfig([
{
name: 'default',
title: 'My Blog',
basePath: '/',
projectId: '<Your Sanity Project ID>',
dataset: 'production',
plugins: [
vyuh({
features: [
system,
// ... other features ...
],
}),
],
},
])The vyuh() Plugin
vyuh({ features: [] }) is a Sanity plugin that configures the studio. It takes an array of FeatureDescriptor instances that represent the features of your application. Each FeatureDescriptor contributes a set of content schemas available on the Studio. It also includes the standard Sanity plugins such as the Structure, Vision, and Media plugins.
Now run the project with pnpm dev. Your studio should include the standard document types of Route, Conditional Route, Category, and Region.
3. Explore the Sanity Studio
Create a simple route for a blog post with the path /blog. Add a region on the route and call it body. Inside this region, add the Portable Text block.
Create some text and format it to look like a real blog post. You can add a title, section headings, paragraphs, and images.
4. Create the Feature on the Flutter Side
Just like the FeatureDescriptor for setting up schemas in Sanity, there is an equivalent FeatureDescriptor on the Flutter side that handles rendering:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:vyuh_core/vyuh_core.dart';
import 'package:vyuh_feature_system/vyuh_feature_system.dart';
final feature = FeatureDescriptor(
name: 'blog',
title: 'My diary of travel blogs',
description: 'Chronicling my journeys across the world',
icon: Icons.pages,
routes: () async {
return [
GoRoute(
path: '/blog',
pageBuilder: defaultRoutePageBuilder,
),
];
},
);The defaultRoutePageBuilder is a standard page builder that knows how to work with CMS routes.
5. Setup the Vyuh App
Connect the content, feature, and the app. Add the required framework packages:
flutter pub add vyuh_feature_system vyuh_feature_developer vyuh_plugin_content_provider_sanityNow set up SanityContentProvider within the DefaultContentPlugin:
import 'package:flutter/material.dart';
import 'package:sanity_client/client.dart';
import 'package:vyuh_core/vyuh_core.dart' as vc;
import 'package:vyuh_extension_content/vyuh_extension_content.dart';
import 'feature.dart' as blog;
import 'package:vyuh_feature_system/vyuh_feature_system.dart' as system;
import 'package:vyuh_feature_developer/vyuh_feature_developer.dart'
as developer;
import 'package:vyuh_plugin_content_provider_sanity/vyuh_plugin_content_provider_sanity.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
vc.runApp(
initialLocation: '/blog',
features: () => [
system.feature,
developer.feature,
blog.feature,
],
plugins: PluginDescriptor(
content: DefaultContentPlugin(
provider: SanityContentProvider(
SanityClient(
SanityConfig(
dataset: 'your_dataset',
projectId: 'your_project_id',
token: 'your_token',
),
),
),
),
),
);
}- Use
/blogas theinitialRouteto load it as the starting page - The
project-idshould match the one used for the Studio setup - To get the token, visit the Manage console of the Sanity Project and create a Read Token
Running on the Web?
If you are running on the Web, make sure to update the CORS Origins in Sanity to include the port number you are using. You will also have to pass --web-port=8080 to ensure the browser launches on the correct port.
CMS-Side FeatureDescriptor
The FeatureDescriptor class on the CMS side has a well-defined structure:
class FeatureDescriptor {
name: string
title: string
description: string
contents: ContentDescriptor[]
contentSchemaBuilders: ContentSchemaBuilder[]
contentSchemaModifiers: ContentSchemaModifier[]
actions: SchemaTypeDefinition[]
conditions: SchemaTypeDefinition[]
}Each feature exports its schemas through this descriptor. The vyuh() plugin reads all FeatureDescriptor instances and assembles them into a single master schema for Sanity.
Flutter-Side Setup
A similar setup exists on the Flutter side, where you bootstrap the counterpart features of the content schemas:
import 'package:vyuh_core/vyuh_core.dart' as vc;
void main() async {
final plugins = await _getPlugins();
vc.runApp(
initialLocation: '/chakra',
features: () => [
system.feature,
developer.feature,
// ... other features ...
],
plugins: plugins,
);
}The main entry point calls runApp() from the vyuh_core library, taking in an array of features and plugins to bootstrap the Vyuh app.
Summary
This guide covered how to set up Sanity as your CMS, configure the Studio with Vyuh's schema plugins, and connect it to your Flutter app. With this setup, you can make changes on Sanity and have them rendered in real time.
Try exploring other content types such as Cards, Groups, and playing around with Actions and Conditions. Refer to the dedicated guides for more information: