# Jazz ## Documentation ### Getting started #### Introduction Welcome to the Jazz documentation! The Jazz docs are currently heavily work in progress, sorry about that! ## Quickstart Run the following command to create a new Jazz project from one of our example apps: ```sh npx create-jazz-app@latest ``` Or set up Jazz yourself, using the following instructions for your framework of choice: - [React](/docs/react/project-setup) - [Next.js](/docs/react/project-setup#nextjs) - [React Native](/docs/react-native/project-setup) - [Vue](/docs/vue/project-setup) - [Svelte](/docs/svelte/project-setup) Or you can follow this [React step-by-step guide](/docs/react/guide) where we walk you through building an issue tracker app. ## Example apps You can also find [example apps](/examples) with code most similar to what you want to build. These apps make use of different features such as auth, file upload, and more. ## Sync and storage Sync and persist your data by setting up a [sync and storage infrastructure](/docs/sync-and-storage) using Jazz Cloud, or do it yourself. ## Collaborative values Learn how to structure your data using [collaborative values](/docs/schemas/covalues). ## API Reference Many of the packages provided are documented in the [API Reference](/api-reference). ## LLM Docs We support the [llms.txt](https://llmstxt.org/) convention for making documentation available to large language models and the applications that make use of them. We currently have: - [/llms.txt](/llms.txt) - A overview listing of the available packages and their documentation - [/llms-full.txt](/llms-full.txt) - Full documentation for our packages ## Get support If you have any questions or need assistance, please don't hesitate to reach out to us on [Discord](https://discord.gg/utDMjHYg42). We would love to help you get started. #### Guide ### react Implementation # React guide This is a step-by-step tutorial where we'll build an issue tracker app using React. You'll learn how to set up a Jazz app, use Jazz Cloud for sync and storage, create and manipulate data using Collaborative Values (CoValues), build a UI and subscribe to changes, set permissions, and send invites. ## Project setup 1. Create a project called "circular" from a generic Vite starter template: {/* prettier-ignore */} ```bash npx degit gardencmp/vite-ts-react-tailwind circular cd circular npm install npm run dev ``` You should now have an empty app running, typically at [localhost:5173](http://localhost:5173).
(If you make changes to the code, the app will automatically refresh.) 2. Install `jazz-tools` and `jazz-react`
(in a new terminal window): {/* prettier-ignore */} ```bash cd circular npm install jazz-tools jazz-react ``` 3. Modify `src/main.tsx` to set up a Jazz context: {/* prettier-ignore */} ```tsx import React from "react"; // old import ReactDOM from "react-dom/client"; // old import App from "./App.tsx"; // old import "./index.css"; // old import { JazzProvider, useDemoAuth, DemoAuthBasicUI, } from "jazz-react"; // old function JazzAndAuth({ children }: { children: React.ReactNode }) { const [auth, authState] = useDemoAuth(); return ( <> {children} ); } // old ReactDOM.createRoot(document.getElementById("root")!).render( // old // old // old ); // old ``` This sets Jazz up and wraps our app in the provider. {/* TODO: explain Auth */} ## Intro to CoValues Let's learn about the **central idea** behind Jazz: **Collaborative Values.** What if we could **treat distributed state like local state?** That's what CoValues do. We can - **create** CoValues, anywhere - **load** CoValues by `ID`, from anywhere else - **edit** CoValues, from anywhere, by mutating them like local state - **subscribe to edits** in CoValues, whether they're local or remote ### Declaring our own CoValues To make our own CoValues, we first need to declare a schema for them. Think of a schema as a combination of TypeScript types and runtime type information. Let's start by defining a schema for our most central entity in Circular: an **Issue.** Create a new file `src/schema.ts` and add the following: ```ts export class Issue extends CoMap { title = co.string; description = co.string; estimate = co.number; status? = co.literal("backlog", "in progress", "done"); } ``` {/* TODO: explain what's happening */} ### Reading from CoValues CoValues are designed to be read like simple local JSON state. Let's see how we can read from an Issue by building a component to render one. Create a new file `src/components/Issue.tsx` and add the following: {/* prettier-ignore */} ```tsx export function IssueComponent({ issue }: { issue: Issue }) { return (

{issue.title}

{issue.description}

Estimate: {issue.estimate}

Status: {issue.status}

); } ```
Simple enough! ### Creating CoValues To actually see an Issue, we have to create one. This is where things start to get interesting... Let's modify `src/App.tsx` to prepare for creating an Issue and then rendering it: {/* prettier-ignore */} ```tsx // old function App() {// old const [issue, setIssue] = useState(); // old if (issue) { return ; } else { return ; } } // old // old export default App; // old ``` Now, finally, let's implement creating an issue: {/* prettier-ignore */} ```tsx // old function App() {// old const [issue, setIssue] = useState(); // old // old const createIssue = () => { const newIssue = Issue.create( { title: "Buy terrarium", description: "Make sure it's big enough for 10 snails.", estimate: 5, status: "backlog", }, ); setIssue(newIssue); }; // old if (issue) {// old return ; // old } else { // old return ; } // old } // old // old export default App; // old ``` 🏁 Now you should be able to create a new issue by clicking the button and then see it rendered!
Preview

Buy terrarium

Make sure it's big enough for 10 snails.

Estimate: 5

Status: backlog

We'll already notice one interesting thing here: - We have to create every CoValue with an `owner`! - this will determine access rights on the CoValue, which we'll learn about in "Groups & Permissions" - here the `owner` is set automatically to a group managed by the current user because we have not declared any **Behind the scenes, Jazz not only creates the Issue in memory but also automatically syncs an encrypted version to the cloud and persists it locally. The Issue also has a globally unique ID.** We'll make use of both of these facts in a bit, but for now let's start with local editing and subscribing. ### Editing CoValues and subscribing to edits Since we're the owner of the CoValue, we should be able to edit it, right? And since this is a React app, it would be nice to subscribe to edits of the CoValue and reactively re-render the UI, like we can with local state. This is exactly what the `useCoState` hook is for! - Note that `useCoState` doesn't take a CoValue directly, but rather a CoValue's schema, plus its `ID`. - So we'll slightly adapt our `useState` to only keep track of an issue ID... - ...and then use `useCoState` to get the actual issue Let's modify `src/App.tsx`: {/* prettier-ignore */} ```tsx // old function App() { // old const [issueID, setIssueID] = useState>(); // old const issue = useCoState(Issue, issueID); // old const createIssue = () => {// old const newIssue = Issue.create(// old { // old title: "Buy terrarium", // old description: "Make sure it's big enough for 10 snails.", // old estimate: 5, // old status: "backlog", // old }, // old ); // old setIssueID(newIssue.id); }; // old // old if (issue) { // old return ; // old } else { // old return ; // old } // old } // old // old export default App; // old ``` And now for the exciting part! Let's make `src/components/Issue.tsx` an editing component. {/* prettier-ignore */} ```tsx // old export function IssueComponent({ issue }: { issue: Issue }) { // old return ( // old
// old { issue.title = event.target.value }}/>