# Build a content application https://www.sanity.io/learn/course/day-one-with-sanity-studio/create-a-content-application.md Go beyond the customization and configuration of Sanity Studio and build something specific to your unique content operations. Many teams will find Sanity Studio sufficient for most of their content operations. However, when teams become fragmented with unique needs or need to perform operations more specifically in bulk or integrated with other systems, reaching outside Sanity Studio and building your application may be best. Fortunately, Sanity App SDK provides almost all of Sanity Studio's CMS-like behavior as a set of headless React hooks for data fetching and mutation. This means you can build custom applications that live alongside your Sanity Studio in the "Dashboard." ## Initialize Let's build a (very simple) custom content application to list all events with a link to their ticket website—so authors can rapidly check, update and fix any incorrect URLs. ![Missing alt text](https://cdn.sanity.io/images/3do82whm/next/bf78b1bd23fe80cdb0a608c75e2efd048889092c-2240x1480.png) For this lesson you'll use the Sanity UI template, but as a headless data library you may use any front end library you prefer such as Tailwind, shadcn/ui, etc. 1. **Run** the following command at the root `/day-one` directory to initialize a new App SDK app ```sh # in /day-one pnpm dlx sanity@latest init --template app-sanity-ui --typescript --output-path apps/tickets ``` You'll be prompted to select an Organization, choose the same one in which you created your Sanity project. ### Workspace arrangement You should now have your Sanity Studio, Next.js app and App SDK app in three separate, adjacent folders. ```text day-one/ └── apps/ ├── studio/ -> Sanity Studio ├── tickets/ -> Sanity App SDK app └── web/ -> Next.js app ``` ### Configuration You'll notice in the terminal you're prompted to update the `App.tsx` file with the details of your Sanity project ID and dataset name. 1. **Update** `App.tsx` by copying `projectId` and `dataset` from your `sanity.config.ts` file ```typescript:apps/tickets/src/App.tsx const sanityConfigs: SanityConfig[] = [ { projectId: 'REPLACE_WITH_YOUR_PROJECT_ID', dataset: 'production', }, ]; ``` ## Running two apps By default, SDK Apps use the same port number (`3333`) as the Studio. To run the Studio and your applications simultaneously, you can update `sanity.cli.ts` of either one. Let's change the default port of the Studio. 1. **Update** the Sanity CLI config of the Sanity Studio ```typescript:apps/studio/sanity.cli.ts import {defineCliConfig} from 'sanity/cli' export default defineCliConfig({ server: { port: 3334, }, // ...all other settings }) ``` Restart your Studio's development server, you'll get a new development URL. Open the Studio in your browser and be asked to create a new CORS origin. You can follow the instructions in the browser, or create a new origin using Sanity CLI with the following command run from inside your `studio` folder. ```sh:Terminal # in apps/studio pnpm dlx sanity@latest cors add http://localhost:3334 --allow ``` 1. **Run** the following inside the `apps/tickets` folder to start the app's development server. ```sh # in apps/tickets pnpm run dev ``` 1. If you get an error about a mismatched Organization ID, you may have selected a different Organization to the one in which the project was created. Update `apps/tickets/sanity.cli.ts` to use the correct Organization ID. You'll see a URL in the terminal to open the App running from within the Sanity Dashboard. Dashboard is the default "home screen" where authors can move between deployed Studios and other applications—such as the one you're building right now. The Dashboard also provides authentication to your app. ![Sanity Dashboard showing a default welcome screen](https://cdn.sanity.io/images/3do82whm/next/a6eb36b396ac49d34e8805bbc6d2baeb192cffd4-2240x1480.png) ## Create components Sanity App SDK for React is a collection of hooks which are implemented individually into components. Create following component files to assemble the entire application. 1. Sanity App SDK hooks use [Suspense](https://react.dev/reference/react/Suspense), if you are not familiar with this component you may like to read the React documentation. 1. **Create** `Publish.tsx` to publish changes to documents when they are in a draft state. ```tsx:apps/tickets/src/Publish.tsx import { DocumentHandle, publishDocument, useApplyDocumentActions, useDocument, } from '@sanity/sdk-react' import {Button} from '@sanity/ui' export function Publish(props: DocumentHandle) { const {data: _id} = useDocument({...props, path: '_id'}) const isDraft = _id?.startsWith('drafts.') const apply = useApplyDocumentActions() const publish = () => apply(publishDocument(props)) return (