# CedarJS > CedarJS is the full-stack web framework designed to help you grow from side project to startup. CedarJS features an end-to-end development workflow that weaves together the best parts of React, GraphQL, Prisma, TypeScript, Vitest, and Storybook. ## Introduction ### Introduction CedarJS is the full-stack web framework designed to help you grow from side project to startup. CedarJS features an end-to-end development workflow that weaves together the best parts of [React](https://react.dev/), [GraphQL](https://graphql.org/), [Prisma](https://www.prisma.io/), [TypeScript](https://www.typescriptlang.org/), [Jest](https://jestjs.io/), and [Storybook](https://storybook.js.org/). For full inspiration and vision, see CedarJS's [README](https://github.com/cedarjs/cedar/blob/main/README.md). Development on CedarJS happens in the [cedarjs/cedar repo on GitHub](https://github.com/cedarjs/cedar). The docs are [there too](https://github.com/cedarjs/cedar/tree/main/docs). While the [CedarJS Team](https://github.com/cedarjs/cedar#the-cedarjs-team) handle most of the high-priority items and the day-to-day, CedarJS wouldn't be where it is without [all its contributors](https://github.com/cedarjs/cedar/graphs/contributors)! #### Getting the Most out of CedarJS[​](#getting-the-most-out-of-cedarjs "Direct link to Getting the Most out of CedarJS") To get the most out of CedarJS, do two things: * [Start the tutorial](/docs/tutorial/foreword.md) * [Join the community on Discord](https://cedarjs.com/discord) The tutorial is the best way to start your CedarJS adventure. It's readable, feature-ful, and fun. You'll go all the way from `git clone` to deploying a full-stack app! And by the end, you should feel comfortable enough to start that side project. After you've read the tutorial and started your side project, come say hi and tell us all about it by joining the community. CedarJS wouldn't be where it is without the people who use and contribute to it. We warmly welcome you! #### How these Docs are Organized[​](#how-these-docs-are-organized "Direct link to How these Docs are Organized") As you can probably tell from the sidebar, CedarJS's docs are organized into sections, like: * [Tutorial](/docs/tutorial/foreword.md) * [Reference](/docs/reference.md) * [How To](/docs/how-to.md) The order isn't arbitrary. This is more or less the learning journey we have in mind for you. While we expect you to read the tutorial from top to bottom (maybe even more than once?), we of course don't expect you to read the Reference and How To sections that way. The content in those sections is there on an as-needed basis. You need to know about the Router? Check out the [Router](/docs/router.md) reference. You need to upload files? Check out the [File Uploads](/docs/how-to/file-uploads.md) how to. That said, there are some references you should consider reading at some point in your CedarJS learning journey. Especially if you want to become an advanced user. For example, [Services](/docs/services.md) are fundamental to CedarJS. It's worth getting to know them inside and out. And if you're not writing [tests](/docs/testing.md) and [stories](/docs/storybook.md), you're not using CedarJS to its full potential. > **We realize that the content doesn't always match the organization** > > For example, half the [Testing](/docs/testing.md) reference reads like a tutorial, and half the [Logger](/docs/logger.md) reference read like a how to. Till now, we've focused on coverage, making sure we had content on all of CedarJS's feature somewhere at least. We'll shift our focus to organization and pay more attention to how we can curate the experience. --- ## Quick Start ### Quick Start Prerequisites * CedarJS requires [Node.js](https://nodejs.org/en/) (=24.x) and [Yarn](https://yarnpkg.com/) (>=1.22.21) * Are you on Windows? For best results, follow our [Windows development setup](/docs/how-to/windows-development-setup.md) guide Create a Cedar project with `yarn create cedar-app`: ```text yarn create cedar-app my-cedar-project ``` Prefer TypeScript? CedarJS comes with full TypeScript support from the get-go: ```text yarn create cedar-app my-cedar-project --typescript ``` Then change into that directory, yarn install, and start the development server: ```text cd my-cedar-project yarn install yarn cedar dev ``` Your browser should automatically open to where you'll see the Welcome Page, which links out to many great resources: ![CedarJS Welcome Page](/img/quick-start-light-theme.png) ![CedarJS Welcome Page](/img/quick-start-dark-theme.png) Congratulations on running your first Cedar CLI command! From dev to deploy, the CLI is with you the whole way. And there's quite a few commands at your disposal: ```text yarn cedar --help ``` For all the details, see the [CLI reference](/docs/cli-commands.md). ##### Ona[​](#ona "Direct link to Ona") The fastest way to start a new Cedar project is to use Ona's (formerly Gitpod) cloud development environment ([additional documentation for working with Ona](/docs/how-to/using-ona.md)). [![Run in Ona](https://ona.com/run-in-ona.svg)](https://app.ona.com/#https://github.com/cedarjs/starter) #### Prisma and the database[​](#prisma-and-the-database "Direct link to Prisma and the database") CedarJS wouldn't be a full-stack framework without a database. It all starts with the schema. Open the `schema.prisma` file in `api/db` and replace the `UserExample` model with the following `Post` model: api/db/schema.prisma ```js model Post { id Int @id @default(autoincrement()) title String body String createdAt DateTime @default(now()) } ``` CedarJS uses [Prisma](https://www.prisma.io/), a next-gen Node.js and TypeScript ORM, to talk to the database. Prisma's schema offers a declarative way of defining your app's data models. And Prisma [Migrate](https://www.prisma.io/migrate) uses that schema to make database migrations hassle-free: ```text yarn cedar prisma migrate dev # ... ? Enter a name for the new migration: › create posts ``` You'll be prompted for the name of your migration. `create posts` will do. tip If you feel `yarn cedar` is too long to type out all the time, you can add `alias cedar='yarn cedar'` as an alias to your shell and then just use `cedar` ```text cedar prisma migrate dev cedar dev # etc ``` Now let's generate everything we need to perform all the CRUD (Create, Retrieve, Update, Delete) actions on our `Post` model: ```text yarn cedar generate scaffold post ``` Navigate to , fill in the title and body, and click "Save": ![Create a new post](https://user-images.githubusercontent.com/300/73028004-72262c00-3de9-11ea-8924-66d1cc1fceb6.png) Did we just create a post in the database? Yup! With `yarn cedar generate scaffold `, Cedar created all the pages, components, and services necessary to perform all CRUD actions on our posts table. #### Frontend first with Storybook[​](#frontend-first-with-storybook "Direct link to Frontend first with Storybook") Don't know what your data models look like? That's more than ok — Cedar integrates Storybook so that you can work on design without worrying about data. Mockup, build, and verify your React components, even in complete isolation from the backend: ```text yarn cedar storybook ``` Seeing "Couldn't find any stories"? That's because you need a `*.stories.{tsx,jsx}` file. The CedarJS CLI makes getting one easy enough — try generating a [Cell](/docs/cells.md), CedarJS's data-fetching abstraction: ```text yarn cedar generate cell examplePosts ``` The Storybook server should hot reload and now you'll have four stories to work with. They'll probably look a little bland since there's no styling. See if the CedarJS CLI's `setup ui` command has your favorite styling library: ```text yarn cedar setup ui --help ``` #### Testing with Vitest[​](#testing-with-vitest "Direct link to Testing with Vitest") It'd be hard to scale from side project to startup without a few tests. Cedar fully integrates Vitest with both the front- and back-ends, and makes it easy to keep your whole app covered by generating test files with all your components and services: ```text yarn cedar test ``` To make the integration even more seamless, CedarJS augments Vitest with database [scenarios](/docs/testing.md#scenarios) and [GraphQL mocking](/docs/testing.md#mocking-graphql-calls). #### Ship it[​](#ship-it "Direct link to Ship it") CedarJS is designed for both serverless deploy targets like Netlify and Vercel and serverful deploy targets like Render and AWS: ```text yarn cedar setup deploy --help ``` Don't go live without auth! Lock down your app with CedarJS's built-in, database-backed authentication system ([dbAuth](/docs/authentication.md#self-hosted-auth-installation-and-setup)), or integrate with the most popular third-party auth providers: ```text yarn cedar setup auth --help ``` #### Next Steps[​](#next-steps "Direct link to Next Steps") The best way to learn CedarJS is by going through the comprehensive [tutorial](/docs/tutorial/foreword.md) and joining the community on our [Discord server](https://cedarjs.com/discord)). --- ## Tutorial ### Afterword You made it! Get yourself some ice cream or a slice of pie: you definitely deserve it. Will there be a chapters 8+ of the tutorial? We've spent a lot of time getting our features working but not much time with optimization and polish. [Premature optimization is the root of all evil](http://wiki.c2.com/?PrematureOptimization), but once your site is live and you've got real users on it you'll get a sense of what could be faster, prettier or more efficient. That's when time spent optimizing can pay huge dividends. But, discovering the techniques and best practices for those optimizations...that's a whole different story. The kind of story that Cedar loves to help you write! So until next time, a bit of wisdom to help combat that next bout of every developer's nemesis, imposter syndrome: > *"There is nothing noble in being superior to your fellow man; true nobility is being superior to your former self."* — Ernest Hemingway #### What's Next[​](#whats-next "Direct link to What's Next") Want to add some more features to your app? Check out some of our how to's like [calling to a third party API](/docs/how-to/using-a-third-party-api.md) and [deploying an app without an API at all](/docs/how-to/disable-api-database.md). We've also got lots of [guides](https://cedarjs.com/docs/index) for more info on Cedar's internals. #### Roadmap[​](#roadmap "Direct link to Roadmap") Check out our [Roadmap](https://github.com/cedarjs/cedar#roadmap) to see where we're headed and how we're going to get there. If you're interested in helping with anything you see, just submit a pull request or open an issue on the [CedarJS GitHub](https://github.com/cedarjs/cedar) and we'll be happy to get you set up. If you need any help we're happy to chat on the [CedarJS Discord](https://cedarjs.com/discord). #### Help Us\![​](#help-us "Direct link to Help Us!") What do you think of Cedar? Is it the Next Step for JS frameworks? What can it do better? We've got a lot more planned. Want to help us build these upcoming features? * [Open a PR](https://github.com/cedarjs/cedar/pulls) * [Write some docs](https://cedarjs.com/docs/introduction) * [Join the community](https://cedarjs.com/discord) Thanks for following along. Now go out and build something amazing! --- ### What is CedarJS? *What follows is a high-level description of CedarJS and how it works. If you want to get right to the meat and potatoes of building something, skip ahead to [Chapter 1](/docs/tutorial/chapter1/prerequisites.md).* CedarJS is a React framework with lots of pre-installed packages and configuration that makes it easy to build full-stack web applications. Now that the elevator pitch is out of the way, what does that actually *mean*? At its core, CedarJS is React plus a bunch of stuff that makes your life as a developer easier. Some of that stuff includes: * GraphQL * Prisma * Vitest * Storybook * Vite * Typescript What do we mean when we say a "full-stack web application?" We're talking about your classic web app: a UI that's visible in the browser (the frontend), backed by a server and database (the backend). Until React Server Components came along (more on those later) React had no idea a server and/or database existed: it was up to you to somehow get data into your app. Maybe this was done with a `fetch()` or in a build step which would pre-bake some of the data needed right into your components. However the data got there, it wasn't an ideal solution. One of the core principles behind CedarJS was that getting data from the backend should be as simple as possible, going so far as to create conventions around it so that retrieving data for display in a component was as easy as adding a couple of lines of code directly into the component itself. Oh and while we're at it, CedarJS will automatically show a loading message while waiting for the data, a different state if there's an error, and even a separate message if the data returned from the server is empty (the classic "blank slate"). #### How a CedarJS App Works[​](#how-a-cedarjs-app-works "Direct link to How a CedarJS App Works") A CedarJS app is actually two apps: a frontend (that's the React part) and a backend, which is your server and talks to a database and other third party systems. Your app is technically a monorepo with two top-level directories: `web` containing the frontend code and `api` containing the backend. You can start them both with a single command: `yarn cedar dev` #### The Frontend[​](#the-frontend "Direct link to The Frontend") ##### The Router[​](#the-router "Direct link to The Router") When you open your web app in a browser, React does its thing initializing your app and monitoring the history for changes so that new content can be shown. CedarJS features a custom, declarative Router that lets you specify URLs and the requisite pages (just a React component) will be shown. A simple routes file may look something like: ```jsx import { Route, Router, Set, PrivateSet } from '@cedarjs/router' import ApplicationLayout from 'src/layouts/ApplicationLayout' import { useAuth } from './auth' const Routes = () => { return ( ) } ``` You can probably get a sense of how all of this works without ever having seen a Cedar route before! Some routes can be marked as `` and will not be accessible without being logged in. Others can be wrapped in a "layout" (again, just a React component) to provide common styling shared between pages in your app. ###### Prerender[​](#prerender "Direct link to Prerender") If you have content on your page that can be purely static (like public facing marketing-focused pages) you can simply add the `prerender` attribute to your route and that page will be completely rendered (no matter how deeply nested the internal components go) into an HTML page. This page loads instantly, but still contains the JS needed to include React. Once React loads, the page is rehydrated and becomes interactive. You can also prerender pages that contain variables pulled from the URL, like the `/products/{sku}` route above. Cedar will [iterate](/docs/prerender.md#dynamic-routes--route-hooks) through all available skus and generate a page for each. This is Cedar's version of static site generation, aka SSG. ###### Accessibility[​](#accessibility "Direct link to Accessibility") Cedar includes a couple of components to [aid screen readers](https://cedarjs.com/docs/accessibility) in properly navigating your app. The `` component tells a screen reader to read something aloud, even though it isn't visible in the browser. And the `` tells a reader to skip verbose navigation options at the top of a page and get to the content. ##### Authentication[​](#authentication "Direct link to Authentication") The `` route limits access to users that are authenticated, but how do they authenticate? Cedar includes integrations to many popular third party authentication hosts (including [Auth0](https://auth0.com/), [Supabase](https://supabase.com/docs/guides/auth) and [Clerk](https://clerk.com/)). You can also [host your own auth](https://cedarjs.com/docs/auth/dbauth), or write your own [custom authentication](https://cedarjs.com/docs/auth/custom) option. If going self-hosted, we include login, signup, and reset password pages, as well as the option to include TouchID/FaceID and third party biometric readers! Once authenticated, how do you know what a user is allowed to do or not do? Cedar includes helpers for [role-based access control](https://cedarjs.com/docs/how-to/role-based-access-control-rbac) that integrates on both the front- and backend. The homepage is accessible *without* being logged in, browsing to `/` will load the `HomePage` page (component) which itself is just composed of more React components, nothing special there. But, what if the homepage, say, displayed some testimonials from the database? Ahh, now things are getting interesting. Here's where Cedar's handpicked selection of technologies start to take the spotlight. ##### GraphQL[​](#graphql "Direct link to GraphQL") Cedar uses GraphQL as the glue between the front- and backends: whenever you want data from the server/database, you're going to retrieve it via GraphQL. Now, we could have just given you raw access to some GraphQL library and let you make those calls yourself. We use [Apollo Client](https://www.apollographql.com/apollo-client) on the frontend and Apollo provides hooks like [useQuery()](https://www.apollographql.com/tutorials/lift-off-part1/10-the-usequery-hook) and [useMutation()](https://www.apollographql.com/tutorials/lift-off-part4/08-the-usemutation-hook) to retrieve and set data, respectively. But Cedar has a much deeper integration. What if you could have a component that was not only responsible for its own display *but even its own data retrieval*? Meaning everything that component needed in order to display itself could all be self-contained. That includes the code to display while the data is loading, or if something goes wrong. These kinds of uber-components are real, and Cedar calls them "cells." ##### Cells[​](#cells "Direct link to Cells") A cell is still just a React component (also called a [single file component](https://www.swyx.io/react-sfcs-here)), it just happens to follow a couple of conventions that make it work as described above: 1. The name of the file ends in "Cell" 2. The file exports several named components, at the very least one named `QUERY` and another named `Success` 3. The file can optionally export several other components, like `Loading`, `Failure` and `Empty`. You can probably guess what those are for! So, any time React is about to render a cell, the following lifecycle occurs: 1. The `Loading` component is displayed 2. A `useQuery()` hook is fired, using the exported `QUERY` 3. Assuming the data returns successfully, the `Success` component is rendered with one of the props being the data returned from `useQuery()` As an alternative to step 3, if something went wrong then `Failure` is rendered. If the query returned `null` or an empty array, the `Empty` component is rendered. If you don't export either of those then `Success` will be rendered and it would be up to you to show the error or empty state through conditional code. Going back to our testimonals hypothetical, a cell to fetch and display them may look something like: ```js export const QUERY = gql` query GetTestimonials { testimonials { id author quote } } ` export const Loading = () =>
Loading...
export const Failure = ({ error }) => (
An error occured! {error.message}
) export const Success = ({ testimonials }) => { return (
    {testimonials.map((test) => (
  • {test.quote} — {test.author}
  • ))}
) } ``` (In this case we don't export `Empty` so that if there aren't any testimonials, that section of the final page won't render anything, not even indicating to the user that something is missing.) If you ever create additional clients for your server (a mobile app, perhaps) you'll be giving yourself a huge advantage by using GraphQL from the start. Oh, and prerendering also works with cells! At build time, Cedar will start up the GraphQL server and make requests, just as if a user was accessing the pages, rendering the result to plain HTML, ready to be loaded instantly by the browser. ##### Apollo Cache[​](#apollo-cache "Direct link to Apollo Cache") The Apollo Client library also intelligently caches the results of that `QUERY` above, and so if the user browses away and returns to the homepage, the `Success` component is now rendered *immediately* from the cache! Simultaneously, the query is made to the server again to see if any data has changed since the cache was populated. If so, the new data is merged into the cache and the component will re-render to show any new testimonials since the last time it was viewed. So, you get performance benefits of an instant display of cached data, but with the guarantee that you won't only see stale data: it's constantly being kept in sync with the latest from the server. You can also directly manipulate the cache to add or remove entries, or even use it for [state management](https://www.apollographql.com/docs/react/local-state/local-state-management/). If you're familiar with GraphQL then you know that on the backend you define the structure of data that GraphQL queries will return with "resolvers." But GraphQL itself doesn't know anything about talking to databases. How does the raw data in the database make it into those resolvers? That's where our next package comes in. #### The Backend[​](#the-backend "Direct link to The Backend") Now we're into the backend code in the `api` directory. ##### Prisma[​](#prisma "Direct link to Prisma") [Prisma](https://www.prisma.io/) is the package Cedar uses to talk to your database, and provides automated migrations, type-safety and auto-completion in your IDE. Your Cedar app will contain a file called `schema.prisma` that will reflect your current database schema: ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" binaryTargets = "native" } model Testimonial { id Int @id @default(autoincrement()) author String @unique quote String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } ``` Prisma has a couple of command line tools that take changes to this file and turn them into [SQL DDL commands](https://www.sqlshack.com/sql-ddl-getting-started-with-sql-ddl-commands-in-sql-server/) which are executed against your database to update its structure to match. ###### GraphQL[​](#graphql-1 "Direct link to GraphQL") Cedar abstracts the concept of GraphQL resolver into a "service." You will generally start with one service function per GraphQL query/mutation. For example, going back to our testimonials example, you would have a service function named `testimonials()` that returns the data for the GraphQL query named `testimonials`. That function uses Prisma to query the database: ```js import { db } from 'src/lib/db' export const testimonials = () => { return db.testimonial.findMany() } ``` How does GraphQL know to go here for its `testimonials` resolver? Cedar introduces an "SDL" file, which contains the mapping from GraphQL to the world of services: ```js export const schema = gql` type Testimonial { id: Int! author: String! quote: String! createdAt: DateTime! updatedAt: DateTime! } type Query { testimonials: [Testimonial!] @skipAuth } ` ``` Any definitions listed in the `type Query` section are expected to have a service function with the same name: `testimonials` -> `testimonials()` ##### Security[​](#security "Direct link to Security") Cedar is secure-by-default: no GraphQL request will be fulfilled if made by an unauthenticated user. You can choose to allow access to certain query/mutations to the public, but you'll have to enable that manually for each option. Consider a more complete Testimonials SDL file: ```js export const schema = gql` type Testimonial { id: Int! author: String! quote: String! createdAt: DateTime! updatedAt: DateTime! } type CreateTestimonialInput { author: String! quote: String! } type Query { testimonials: [Testimonial!] @skipAuth } type Mutation { createTestimonal($input: CreateTestimonialInput!): Testimonial! @requireAuth deleteTestimonal($id: Int!): Testimonial! @requireAuth } ` ``` The `testimonials` query is marked with the [GraphQL directive](/docs/directives.md) `@skipAuth` meaning that requests here should *not* be limited to authenticated users. However, the critical `createTestimonial` and `deleteTestimonial` mutations are marked `@requireAuth`, and so can only be called by a logged in user. Cedar's backend GraphQL server is powered by [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server) and so you have access to everything that makes Yoga secure and performant: rate and depth limiting, logging, directives, and a ton more. ###### Auth[​](#auth "Direct link to Auth") If a user is logged in, they will be available in any of your services in the `context` object, available everywhere, all the time: ```js import { db } from 'src/lib/db' import { AuthenticationError } from '@cedarjs/graphql-server' export const createTestimonial = ({ data }) => { if (context.currentUser.roles.includes('admin')) { return db.testimonial.create({ data }) } else { throw new AuthenticationError( 'You are not authorized to create testimonials' ) } } ``` So `@requireAuth` and `@skipAuth` provide a gate around entire GraphQL queries for authenticated users, but once inside you can be more fine-grained based on who the user actually is. #### Generators[​](#generators "Direct link to Generators") Let's take a look at an often overlooked tool in many frameworks' kit: the command line tools. Cedar has focused extensively on these, and one of the most powerful are the "generators." These are used to create files, setup integrations, execute scripts, start the dev server, and more. A huge timesaver is generating layouts, pages and cells. There isn't much boilerplate in Cedar's files, but it's still nice to have them built out for, even going so far as creating tests for the bare functionality (more on tests in a minute). They also provide easy access to dev tools like Graphiql (for executing GraphQL functions against your server) and Prisma Studio (providing a full GUI for your database). ![image](https://github.com/redwoodjs/redwood/assets/300/18c928ff-aa34-4f06-941b-69c8035cee61) ![image](https://github.com/redwoodjs/redwood/assets/300/11f7553e-26a5-4a8f-b618-b9464828cafa) Cedar has setup commands for UI libraries like [Tailwind](https://tailwindcss.com/) and [Mantine](https://mantine.dev/), and even provides access to experimental new features, making it easy to enable and disable them on the fly. There's even an interactive console that lets you, for example, execute Prisma queries to fetch data from the database. This comes in handy when you want to double check that your query is fetching the data you think it is, without dropping a bunch of `console.log()` statements in your code and reloading the browser. #### Jest[​](#jest "Direct link to Jest") Being able to develop a full-stack application this easily is great, but how do you verify that it's working as intended? That's where a great test suite comes in. [Jest](https://jestjs.io/) is a test framework that, as they say, focuses on simplicity. We felt that it was a natural fit with Cedar, and so most files you can generate will include the related test file automatically (pre-filled with some tests, even!). Cedar includes several Jest helpers and matchers, allowing you to mock out GraphQL requests, database data, logged in users, and more. * [Scenarios](/docs/testing.md#scenarios) accept a simple JSON object and pre-populate your database with just that data so it's in a known state that you can test against. * [Mock Service Worker](/docs/testing.md#mock-service-worker) allow you to simulate the response from API calls, including GraphQL * `mockCurrentUser()` is a helper that allows you to stub out the user that's logged in on either the `web` or `api` codebase, without having to worry about actually passing them through your auth provider ![image](https://github.com/redwoodjs/redwood/assets/300/614d9867-9765-474f-8b8b-c9217f3f7dcf) You can write Jest tests in both the front- and backend of your app. #### Storybook[​](#storybook "Direct link to Storybook") While Jest can test your code, [Storybook](https://storybook.js.org/) can be used to catalog and test your UI. They call themselves a "frontend workshop for building UI components in isolation" and we couldn't agree more. Build your components separate from your app, even having props be dynamic while viewing their effects. All you have to do is run `yarn redwood storybook`. Cedar adds data mocking for Storybook so that you can display components that would normally be populated with data from GraphQL, but without needing a server running. ![image](https://github.com/redwoodjs/redwood/assets/300/2753a292-01d4-41b9-9975-edc1f8c1c3ac) Storybook is strictly a frontend codebase concern. #### Vite, Babel and Typescript[​](#vite-babel-and-typescript "Direct link to Vite, Babel and Typescript") Notice at no point above did we say "and then we need to write configuration for this package..." Cedar has done all of that for you and will continue to do that with every release of a new version. We're sure you won't miss spending hours or days trying to add and configure a package in your application. You can eject from our default configs, and add custom code if needed, but most apps will never need to do this: everything Just Works. We use vite as our bundler, packaging up the frontend code and automatically code splitting on pages. It also serves the frontend (the `web` directory). The backend (the `api` directory) is compiled by Babel and served with [Fastify](https://fastify.dev/). The entire framework is ([strictly](https://cedarjs.com/docs/typescript/strict-mode)) typed so you can autocomplete all the things in your IDE. #### Deployment[​](#deployment "Direct link to Deployment") Cedar's job doesn't end until your application is deployed to the world! That's why we include deploy commands and config to get your app running on the most popular hosts (whether they are serverless or traditional server infrastructure) including: * [Coherence (GWC/AWS)](https://www.withcoherence.com/) * [Flightcontrol.dev (AWS)](https://www.flightcontrol.dev?ref=redwood) * [Edg.io](https://edg.io) * [Netlify.com](https://www.netlify.com/) * [Render.com](https://render.com) * [Serverless.com](https://serverless.com) * [Vercel.com](https://vercel.com) * anywhere [Docker](https://www.docker.com) is accepted - You can even deploy to your own server via SSH commands (we call that our [Baremetal](/docs/deploy/baremetal.md) deploy)! #### Coming Soon[​](#coming-soon "Direct link to Coming Soon") Cedar is still in active development, and we're working on some [features](https://community.redwoodjs.com/c/experimental-features/25) that are on the cutting edge of the React ecosystem: * [React Server Components](https://community.redwoodjs.com/t/react-server-components-rsc/5081) and a new transparent, non-GraphQL API * [SSR/Streaming](https://community.redwoodjs.com/t/render-modes-ssr-streaming-experimental/4858) * [Realtime and GraphQL Subscriptions](https://community.redwoodjs.com/t/redwoodjs-realtime/5002) * [Cedar Studio](https://community.redwoodjs.com/t/redwood-studio-experimental/4771) for getting runtime insights into your project * [Mailer](https://github.com/redwoodjs/redwood/pull/9058) These are just a few highlights from our current [Bighorn Epoch](https://tom.preston-werner.com/2023/05/30/redwoods-next-epoch-all-in-on-rsc). You can see the full list and follow along via our Roadmap project board at [www.redwoodjs.com/roadmap](https://redwoodjs.com/roadmap). #### Backing[​](#backing "Direct link to Backing") Cedar was created by Tom Preston-Werner, cofounder of GitHub and projects like Semantic Versioning, TOML, Jekyll, and many more. Tom believes that JavaScript applications, specifically full-stack JS applications, are the future of the web, and Cedar has his full support. #### Updates[​](#updates "Direct link to Updates") Cedar is constantly being updated and sticks strictly to semantic versioning requirements. You can be sure that there won't be any sudden, breaking changes without a major version revision. Cedar is famous for its [copious release notes](https://community.redwoodjs.com/t/redwood-3-0-0-is-now-available/3989) and comprehensive upgrade guides, and if code changes need to be made to your app, we make every effort to include a codemod script that will make the changes for you. #### Community[​](#community "Direct link to Community") There's a very active community around Cedar, including a [Discourse forum](https://community.redwoodjs.com/) and [Discord chat](https://cedarjs.com/discord), where even members of the core team can be found answering questions. We're building this framework for users like you, and we need your feedback if we're going to be successful! --- ### Cedar File Structure Let's take a look at the files and directories that were created for us (config files have been excluded for now): info Don't worry about trying to memorize this directory structure right now, it's just a brief overview to get you oriented. Seeing dozens of files before you've even written a single line of code can be daunting, but there's a great organizational structure here, promise. You can also ignore this all for now and we'll touch upon many of these files and directories as we go. * JavaScript * TypeScript ```text ├── api │ ├── db │ │ └── schema.prisma │ └── src │ ├── directives │ │ ├── requireAuth │ │ └── skipAuth │ ├── functions │ │ └── graphql.js │ ├── graphql │ ├── lib │ │ ├── auth.js │ │ ├── db.js │ │ └── logger.js │ └── services │ ├── scripts │ └── seed.js │ └── web ├── public │ ├── favicon.png │ ├── README.md │ └── robots.txt └── src ├── components ├── layouts ├── pages │ ├── FatalErrorPage │ │ └── FatalErrorPage.jsx │ └── NotFoundPage │ └── NotFoundPage.jsx ├── App.jsx ├── entry.client.jsx ├── index.css ├── index.html └── Routes.jsx ``` ```text ├── api │ ├── db │ │ └── schema.prisma │ └── src │ ├── directives │ │ ├── requireAuth │ │ └── skipAuth │ ├── functions │ │ └── graphql.ts │ ├── graphql │ ├── lib │ │ ├── auth.ts │ │ ├── db.ts │ │ └── logger.ts │ └── services │ ├── scripts │ └── seed.ts │ └── web ├── public │ ├── favicon.png │ ├── README.md │ └── robots.txt └── src ├── components ├── layouts ├── pages │ ├── FatalErrorPage │ │ └── FatalErrorPage.tsx │ └── NotFoundPage │ └── NotFoundPage.tsx ├── App.tsx ├── entry.client.tsx ├── index.css ├── index.html └── Routes.tsx ``` At the top level we have three directories, `api`, `scripts` and `web`. Cedar separates the backend (`api`) and frontend (`web`) concerns into their own paths in the codebase. ([Yarn refers to these as "workspaces"](https://yarnpkg.com/features/workspaces). In Cedar, we refer to them as "sides.") When you add packages going forward you'll need to specify which workspace they should go in. For example (**don't run these commands**, we're just looking at the syntax): ```bash yarn workspace web add marked yarn workspace api add better-fs ``` `scripts` is meant to hold any Node scripts you may need to run from the command line that aren't directly related to the api or web sides. The file that's in there, `seed.ts` is used to populate your database with any data that needs to exist for your app to run at all (maybe an admin user or site configuration). ##### The /api Directory[​](#the-api-directory "Direct link to The /api Directory") Within `api` there are four directories: * `db` contains the plumbing for the database: * `schema.prisma` contains the database schema (tables and columns) After we add our first database table, there will also be a SQLite database file named `dev.db` and a directory called `migrations` created for us. `migrations` contains the files that act as snapshots of the database schema changing over time. * `dist` contains the compiled code for the api side and can be ignored when developing. * `src` contains all your backend code. `api/src` contains five more directories: * `directives` will contain GraphQL [schema directives](https://www.graphql-tools.com/docs/schema-directives) for controlling access to queries and transforming values. * `functions` will contain any [lambda functions](https://docs.netlify.com/functions/overview/) your app needs in addition to the `graphql.ts` file auto-generated by Cedar. This file is required to use the GraphQL API. * `graphql` contains your GraphQL schema written in a Schema Definition Language (the files will end in `.sdl.ts`). * `lib` contains a few files:`auth.ts` starts as a placeholder for adding auth functionality and has a couple of bare-bones functions in it to start, `db.ts` instantiates the Prisma database client so we can talk to a database and `logger.ts` which configures, well, logging. You can use this directory for other code related to the API side that doesn't really belong anywhere else. * `services` contains business logic related to your data. When you're querying or mutating data for GraphQL (known as **resolvers**), that code ends up here, but in a format that's reusable in other places in your application. * And finally `types` contains automatically compiled GraphQL types and can be ignored during development That's it for the backend. ##### The /web Directory[​](#the-web-directory "Direct link to The /web Directory") * `public` contains assets not used by React components (they will be copied over unmodified to the final app's root directory): * `favicon.png` is the icon that goes in a browser tab when your page is open (apps start with the CedarJS logo). * `README.md` explains how, and when, to use the `public` folder for static assets. It also covers best practices for importing assets within components via Vite. You can also [read this README.md file on GitHub](https://github.com/cedarjs/cedar/blob/main/packages/create-cedar-app/templates/ts/web/public). * `robots.txt` can be used to control what web indexers are [allowed to do](https://www.robotstxt.org/robotstxt.html). * `src` contains several subdirectories: * `components` contains your traditional React components as well as Cedar *Cells* (more about those soon). * `layouts` contain HTML/components that wrap your content and are shared across *Pages*. * `pages` contain components and are optionally wrapped inside *Layouts* and are the "landing page" for a given URL (a URL like `/articles/hello-world` will map to one page and `/contact-us` will map to another). There are two pages included in a new app: * `NotFoundPage.tsx` will be served when no other route is found (see `Routes.tsx` below). * `FatalErrorPage.tsx` will be rendered when there is an uncaught error that can't be recovered from and would otherwise cause our application to really blow up (normally rendering a blank page). * `App.tsx` the bootstrapping code to get our Cedar app up and running. * `entry.client.tsx` is the standard React starting point for our app. * `index.css` is a good starting place for custom CSS, but there are many options (we like [TailwindCSS](https://tailwindcss.com/) which, believe it or not, may not require you to write any custom CSS for the life of your app!) * `index.html` is what's first sent to a visitor's browser. It fetches `entry.client.tsx`. * `Routes.tsx` the route definitions for our app which map a URL to a *Page*. We'll dip in and out of these directories and files (and create some new ones) as we work through the tutorial. --- ### Our First Page Let's give our users something to look at besides the (awesome) Cedar welcome page (thanks [@alicelovescake](https://github.com/alicelovescake)!). We'll use the `redwood` command line tool to create a page for us: ```bash yarn redwood generate page home / ``` The command above does four things: * Creates `web/src/pages/HomePage/HomePage.tsx`. Cedar takes the name you specified as the first argument after `page` and [PascalCases](https://techterms.com/definition/pascalcase) it, then appends "Page" to construct your new page component. So "home" becomes "HomePage". * Creates a test file to go along with this new page component at `web/src/pages/HomePage/HomePage.test.tsx` with a single, passing test. You *do* write tests for your components, *don't you??* * Creates a Storybook file for this component at `web/src/pages/HomePage/HomePage.stories.tsx`. Storybook is a wonderful tool for efficiently developing and organizing UI components. (If you want to take a peek ahead, we learn about Storybook in [chapter 5 of the tutorial](/docs/tutorial/chapter5/storybook.md)). * Adds a `` in `web/src/Routes.tsx` that maps the path `/` to the new *HomePage* page. Automatic import of pages in the Routes file If you look in Routes you'll notice that we're referencing a component, `HomePage`, that isn't imported anywhere. Cedar automatically imports all pages in the Routes file since we're going to need to reference them all anyway. It saves a potentially huge `import` declaration from cluttering up the routes file. In case you didn't notice, this page is already live (your browser automatically reloaded): ![Default HomePage render](https://user-images.githubusercontent.com/300/148600239-6a147031-74bb-43e8-b4ef-776b4e2a2cc5.png) It's not pretty, but it's a start! Open the page in your editor, change some text and save. Your browser should reload with your new text. ##### Routing[​](#routing "Direct link to Routing") Open up `web/src/Routes.tsx` and take a look at the route that was created: * JavaScript * TypeScript web/src/Routes.jsx ```jsx import { Router, Route } from '@cedarjs/router' const Routes = () => { return ( ) } export default Routes ``` web/src/Routes.tsx ```jsx import { Router, Route } from '@cedarjs/router' const Routes = () => { return ( ) } export default Routes ``` As long as you have a route with path `/`, you'll never see the initial Cedar splash screen again. When no route can be found that matches the requested URL, Cedar will render the `NotFoundPage`. Try changing the route to something like: * JavaScript * TypeScript ```jsx ``` ```jsx ``` The splash screen is available again at , giving you a list of all the available URLs in your app. ![Cedar Splash Screen](https://user-images.githubusercontent.com/17789536/160120107-1157af8e-4cbd-4ec8-b3aa-8adb28ea6eaf.png) Go to `/hello` and you should see the homepage again. Change the route path back to `/` before continuing! ##### Simple Styles[​](#simple-styles "Direct link to Simple Styles") Previous versions of this tutorial had you build everything without any styling, so we could really focus on the code, but let's face it: an unstyled site is pretty ugly. Let's add a really simple stylesheet that will just make things a *little* easier on the eyes as we build out the site. Paste the following into `web/src/index.css`: web/src/index.css ```css body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; } ul { list-style-type: none; margin: 1rem 0; padding: 0; } li { display: inline-block; margin: 0 1rem 0 0; } h1 > a { text-decoration: none; color: black; } button, input, label, textarea { display: block; outline: none; } label { margin-top: 1rem; } .error { color: red; } input.error, textarea.error { border: 1px solid red; } .form-error { color: red; background-color: lavenderblush; padding: 1rem; display: inline-block; } .form-error ul { list-style-type: disc; margin: 1rem; padding: 1rem; } .form-error li { display: list-item; } .flex-between { display: flex; justify-content: space-between; } .flex-between button { display: inline; } ``` These styles will switch to whatever your OS's system font is, put a little margin between things, and just generally clean things up. Feel free to tweak it to your liking (or ignore these styles completely and stick with the browser default) but keep in mind that the following screenshots are made against this base stylesheet so your experience may vary. ![Default homepage with custom styles](https://user-images.githubusercontent.com/300/148600516-f8e048aa-451f-46f0-9749-078d63fe7b07.png) Looking better already! --- ### Installation & Starting Development We'll use yarn ([yarn](https://yarnpkg.com/getting-started/install) is a requirement) to create the basic structure of our app: * JavaScript * TypeScript ```bash yarn create cedar-app ./redwoodblog ``` ```bash yarn create cedar-app --ts ./redwoodblog ``` You'll have a new directory `redwoodblog` containing several directories and files. Change to that directory and we'll start the development server: ```bash cd redwoodblog yarn install yarn redwood dev ``` A browser should automatically open to and you will see the Cedar welcome page: ![Cedar Welcome Page](https://user-images.githubusercontent.com/300/145314717-431cdb7a-1c45-4aca-9bbc-74df4f05cc3b.png) tip Remembering the port number is as easy as counting: 8-9-10! The splash page gives you links to many resources, but don't get distracted: we've got a job to do! ##### First Commit[​](#first-commit "Direct link to First Commit") Now that we have the skeleton of our Cedar app in place, it's a good idea to save the current state of the app as your first commit...just in case. ```bash git init git add . git commit -m 'First commit' ``` [git](https://git-scm.com/) is another of those concepts we assume you know, but you *can* complete the tutorial without it. Well, almost: you won't be able to deploy! At the end we'll be deploying to a provider that requires your codebase to be hosted in either [GitHub](https://github.com) or [GitLab](https://gitlab.com). If you're not worried about deployment for now, you can go ahead and complete the tutorial without using `git` at all. --- ### Layouts One way to solve the duplication of the `
` would be to create a `
` component and include it in both `HomePage` and `AboutPage`. That works, but is there a better solution? Ideally there should only be one reference to the `
` anywhere in our code. When you look at these two pages what do they really care about? They have some content they want to display. They really shouldn't have to care what comes before (like a `
`) or after (like a `