Skip to content

Prerequisites

  • Sanity account (https://manage.sanity.io)
  • Project ID and a dataset (e.g., production)
  • A deploy token for CI (used by CLI deploy of Studio)

Environment

Create or update apps/marketing/.env.local (and CI variables):

bash
SANITY_STUDIO_PROJECT_ID=your_project_id
SANITY_STUDIO_DATASET=production
SANITY_STUDIO_API_VERSION=2025-09-07
SANITY_STUDIO_HOST=studio.your-domain.tld
# Optional for local CLI auth; not required at runtime
SANITY_STUDIO_API_TOKEN=your_token_optional

Local Development

To run Sanity Studio locally for development:

Prerequisites

  • Sanity CLI (available via npx, no installation needed)
  • Environment variables configured in apps/marketing/.env.local

Running Sanity Studio Locally

  1. Navigate to the marketing app directory:
bash
cd apps/marketing
  1. Start the Sanity Studio development server:
bash
npx sanity dev
  1. Access the Studio at http://localhost:3333 (default port)

Port conflict

If port 3333 is in use (e.g., by the AdonisJS server running on the host), Sanity will automatically try the next available port. To run the API server separately, use npm run dev -- --filter=server.

The Studio will automatically reload when you make changes to schemas or configuration files.

Environment Variables for Local Development

For local development, use a development dataset instead of production:

bash
SANITY_STUDIO_PROJECT_ID=your_project_id
SANITY_STUDIO_DATASET=dev  # Use 'dev' instead of 'production' for local work
SANITY_STUDIO_API_VERSION=2025-09-07
SANITY_STUDIO_HOST=studio.your-domain.tld
# Optional: Only needed for authenticated operations
SANITY_STUDIO_API_TOKEN=your_token_optional

Development Workflow

  • Local Studio: Use npx sanity dev for schema development and content editing during development
  • Hosted Studio: Deploy via CLI for team collaboration and production content management
  • Dataset Considerations: Use dev dataset locally to avoid affecting production content
  • Schema Changes: Schema modifications in apps/marketing/src/sanity/schemaTypes/ are automatically reflected in the local Studio

Troubleshooting

  • Port Conflicts: If port 3333 is in use, Sanity will automatically try the next available port
  • Authentication Issues: Ensure SANITY_STUDIO_API_TOKEN is set if you need authenticated operations
  • Environment Variable Errors: Verify all required variables are set in apps/marketing/.env.local

Studio (Hosted)

  • Config: apps/marketing/sanity.config.ts
  • Embedded Studio route has been removed from the marketing app to reduce bundle size.
  • Deploy hosted Studio via CLI (run inside apps/marketing):
bash
npx --yes sanity@latest deploy --non-interactive --tag <dev|qa|prod>
  • In CI/CD, authenticate non-interactively using a token env var:
bash
SANITY_AUTH_TOKEN=<token> npx --yes sanity@latest deploy --non-interactive --tag $ENVIRONMENT

Notes

  • The marketing site does not require the token at runtime for public, cached reads (next-sanity with useCdn: true).
  • Map your CI secret to the app variable when needed:
    • CLI reads: SANITY_AUTH_TOKEN
    • App config reads: SANITY_STUDIO_API_TOKEN (optional, only for authenticated tasks)

Schemas (already included)

  • author (name, slug, image, bio)
  • post (title, slug, author ref, mainImage, categories[], publishedAt, body)
  • category (title, slug, description)
  • blockContent (Portable Text)

Fetching content (helpers)

  • Post: getPostResource(slug)apps/marketing/src/utils/blog/posts.ts
    • Returns: Promise<{ data: TPost | null; error: string | null }>
  • Author: getAuthorResource(slug)apps/marketing/src/utils/blog/authors.ts
    • Returns: Promise<{ data: TAuthor | null; error: string | null }>
  • Category: getCategoryResource(slug)apps/marketing/src/utils/blog/categories.ts
    • Returns: Promise<{ data: TCategory | null; error: string | null }>

Frontend routes

  • Post: /blog/[slug]
  • Author: /blog/author/[slug]
  • Category: /blog/category/[slug]

Images

  • Next.js is configured for Sanity images: cdn.sanity.io is allowed in apps/marketing/next.config.ts.

Deployment notes

  • Cloudflare Pages Worker size limit (free plan) is 3 MiB. To stay under:

    • Remove embedded Studio (done) and deploy via CLI.
    • Avoid dynamic icon/OG routes that pull in next/og WASM.
    • Place static assets in apps/marketing/public/ (e.g., favicon.ico, icon.png, OG images) and reference them in metadata.
  • For read-only public data, only NEXT_PUBLIC_* vars are required.

  • If you need authenticated queries at build-time, set SANITY_STUDIO_API_TOKEN in CI secrets (optional) and keep it out of client bundles.

Built with ❤️ by the Jubiloop team