A monorepo built for rapid full stack web development using KeystoneJS and tRPC. This repository contains a CMS, UI component library and end-to-end tests. The packages are organized by their functionalities and can be developed and tested independently.
cms: KeystoneJS CMSapp: Screens with data fetching with UI componentsui: UI library with twin.macro and stitchese2e: End-to-end tests using Playwright
The monorepo also includes client applications
astro-app: Astro web applicationnext-app: Next.js web application
Install all packages and dependencies using:
git clone https://github.com/lachlanhawthorne/keystone-t3.git
pnpmYou can run all apps and packages simultaneously from the root directory or individually using:
pnpm devpnpm cms:dev
pnpm ui:dev
pnpm astro-app:dev
pnpm next-app:dev
pnpm remix-app:dev
pnpm qwick-app:dev
pnpm vite-app:devYou can quickly generate new components with Storybook stories and tests using:
pnpm ui:newFor more information on generating styled components, follow the guidelines outlined in the twin.macro documentation.
The ui package is configured to use Storybook for component development. You can run Storybook using:
pnpm storybook:devThe e2e package contains an adapter create a tRPC server and client using KeystoneJS. This allows you to use KeystoneJS as a data source for your tRPC API.
To link a new KeystoneJS project to the tRPC server, add the following to your KeystoneJS schema.ts file:
import { KeystoneContext } from '@keystone-next/types';
import { createKeystoneAdapter } from '@keystone-next-trpc-twin.macro/e2e';
export const keystone = new Keystone({
adapter: createKeystoneAdapter({
context: KeystoneContext,
schemaName: 'public',
}),
});To link a new Next.js project to the tRPC client, add the following to your Next.js pages/api/trpc/[trpc].ts file:
import { createNextApiHandler } from '@keystone-next-trpc-twin.macro/e2e';
export default createNextApiHandler();To create a new tRPC route, add a new file to the e2e/routes directory. The file should export a function that returns a tRPC route. For example:
import { createRouter } from '@trpc/server';
import { createContext } from '@keystone-next-trpc-twin.macro/e2e';
export const createRoutes = () =>
createRouter()
.query('hello', {
resolve() {
return 'Hello World!';
},
})
.mutation('createUser', {
input: z.object({
name: z.string(),
}),
resolve({ input }) {
return createContext().db.user.create({
data: {
name: input.name,
},
});
},
});To use a tRPC route, import the useQuery or useMutation hook from @trpc/react and pass the route name as the first argument. For example:
import { useQuery, useMutation } from '@trpc/react';
const { data } = useQuery('hello');
const [createUser] = useMutation('createUser');To add access control to a tRPC route, add a middleware function to the route. For example:
import { createRouter } from '@trpc/server';
import { createContext } from '@keystone-next-trpc-twin.macro/e2e';
export const createRoutes = () =>
createRouter()
.query('hello', {
resolve() {
return 'Hello World!';
},
})
.mutation('updateUser', {
input: z.object({
id: z.string(),
name: z.string(),
}),
resolve({ input }) {
return createContext().db.user.update({
where: {
id: input.id,
},
data: {
name: input.name,
},
});
},
}
.middleware(async ({ ctx, next }) => {
if (!ctx.session?.data?.userId) {
throw new Error('Not authenticated');
}
return next();
});You tests for all apps and packages simultaneously or individually using:
pnpm testpnpm cms:test
pnpm web:test
pnpm ui:test
pnpm e2e:testTo build a production version of the cms or web application, navigate to the respective directory and run pnpm build. This will build the application and output the files to the build directory. You can build all apps and packages using:
pnpm buildRefer to the KeystoneJS documentation and the NextJS documentation for further deployment instructions.
This repository is configured to use GitHub CI for continuous integration. Any changes pushed to the master branch will trigger a build and test run.
Any changes to the UI package will trigger