xstate-nextjs-workspaces-template
Yarn Workspaces + XState + Next.js = ❤️
What is this?
This template provides a basic yarn
workspaces monorepo for publishing an npm package of XState machines and a Next.js site that allows for easily inspecting the machines. It uses preconstruct
to make local development a breeze.
Develop some machines using the inspector site to help visualize them, publish the machines
package, then publish the Next.js site. BAM! You've got yourself a package of XState machines and a site where users can play with them!
Check out a live version of the inspector site here: https://xstate-nextjs-workspaces-template.vercel.app/
How does it work?
Local development and build
The setup is powered primarily by preconstruct
.
preconstruct
is configured to run the preconstruct dev
script during postinstall
, which allows you to do local development in separate packages that depend on each other without needing to re-build the package each time you make a change.
It also handles building for us (at least for the packages it's configured to build, which is machines
by default), so we don't really have to do much of anything.
Inspector site
The inspector
package is a Next.js site with a fairly barebones setup. It's mostly intended to demonstrate a working pattern for rendering an inspector for each machine while rendering them at separate routes.
There are a few rules:
- You have to render the component that you call
useMachine
in INSIDEMachineContainer
. IfuseMachine
is called beforeMachineContainer
renders and callsinspect
, the inspector won't work. - Don't call
useMachine
in the body of the component that rendersMachineContainer
. That is a violation of #1. Just want to make that clear. - If you want to make changes to machines in the
machines
package and have those changes show up, you'll have to disable Fast Refresh by exporting a non-React export, e.g.export const __preventFastRefresh = true
. There are probably better ways around this that don't involve disabling Fast Refresh, but I haven't figured them out yet. - Make sure to enable the
devTools
option when using the@xstate/react
hooks e.g.useMachine(someMachine, {devTools: true})
.
So basically, if you're following the rules, the page for your machine will look like this:
import {useMachine} from '@xstate/react'
import {someMachine} from 'machines'
import {MachineContainer} from '../../components/MachineContainer'
export default function MachinePage() {
return (
<MachineContainer>
<RenderMachine />
</MachineContainer>
)
}
function RenderMachine() {
useMachine(someMachine, {devTools: true})
return null
}
export const __preventFastRefresh = true
Versioning and publishing
Eventually I'd like to add changesets
to make it easy to version and publish and generate changelogs for the machines
package (and any others you might add), but for now I'm out of time and motivation. PRs welcome though!
TODO
- Add
changesets
- Add
@chakra-ui/react
(Why? Because I'm a Chakra UI maintainer and I'm required by law to demonstrate that kind of bias towards my own stuff) - Make the
inspector
site not look like crap - Add MDX and add cool functionality like what @mattpocock is doing with XState Catalogue
- Figure out a cleaner pattern for handling machine inspector routes. It's a little gross and dirty right now, but it works 🤷
Credits
- @mattpocock for building XState Catalogue, which is the main source of inspiration for this template, and for
xstate#2020
which pointed me to the need to usepatch-package
and also helped me discover theMachineContainer
pattern - @davidkpiano for being one hell of pianist. And for creating XState