Manual setup
Manually integrate Makeswift with your Next.js app.
AnchorBefore you start
The fastest way to get started with Makeswift on a new Next.js project is to follow our getting started guide. If you have an existing Next.js application or want to set things up yourself, continue with the rest of this guide.
AnchorCreate a project
First, we need a Next.js project. If you don't already have one, the easiest way to get one set up
is with Create Next App. Feel free to
change the name from makeswift-app
to something else.
npx create-next-app makeswift-app
cd makeswift-app
AnchorInstall Makeswift dependencies
Then, let's install the @makeswift/runtime
package. This package contains all of the necessary
code to integrate Makeswift into your Next.js app.
npm install @makeswift/runtime
or
yarn add @makeswift/runtime
AnchorAdd the Makeswift Next.js plugin
Add the Makeswift Next.js plugin to next.config.js
. This is necessary to configure next/image
with Makeswift domains, support Makeswift's integration with Next.js Preview Mode, and support
code-splitting via next/dynamic
for builtin components.
// next.config.js
const withMakeswift = require('@makeswift/runtime/next/plugin')()
const nextConfig = {
/* Your Next.js config... */
}
module.exports = withMakeswift(nextConfig)
AnchorAdd the Makeswift API handler
We'll then add the Makeswift API handler. If you're familiar with
NextAuth.js, this works in a similar way. Create the file
pages/api/makeswift/[...makeswift].js
. It's important that the file has that exact name, excluding
the extension, which can be ts
if you're using TypeScript.
import { MakeswiftApiHandler } from '@makeswift/runtime/next'
export default MakeswiftApiHandler('<makeswift_site_api_key>')
This API route will add support for Preview Mode, On-demand Revalidation, and other features that make Makeswift work seamlessly with your Next.js app.
You need to provide your Makeswift site API key as the first argument to the API handler function. You can get your API key from your Makeswift site settings. We recommend using environment variables for your site API key.
AnchorSet up custom Document
Next we'll add a custom Document
. The
custom document will properly handle styles during server-side rendering and use Next.js'
Preview Mode when opening your pages in
the Makeswift builder.
Create the _document.js
page and export Document
from @makeswift/runtime/next
.
// pages/_document.js
export { Document as default } from '@makeswift/runtime/next'
If you already have a _document.js
, you can update it to extend the Document
from @makeswift/runtime/next
.
AnchorAdd a route for Makeswift pages
Let's create a new
optional catch-all route
named [[...path]].js
. In this route we'll fetch and render your Makeswift pages.
We'll use the Makeswift API to fetch page data in getStaticProps
and getStaticPaths
. The
Makeswift Page
component will take care of rendering your pages.
// pages/[[...path]].js
import { Makeswift, Page as MakeswiftPage } from '@makeswift/runtime/next'
export async function getStaticPaths() {
const makeswift = new Makeswift('<makeswift_site_api_key>')
const pages = await makeswift.getPages()
return {
paths: pages.map((page) => ({
params: { path: page.path.split('/').filter((segment) => segment !== '') },
})),
fallback: 'blocking',
}
}
export async function getStaticProps(ctx) {
const makeswift = new Makeswift('<makeswift_site_api_key>')
const path = '/' + (ctx.params?.path ?? []).join('/')
const snapshot = await makeswift.getPageSnapshot(path, { preview: ctx.preview })
if (snapshot == null) return { notFound: true }
return { props: { snapshot } }
}
export default function Page({ snapshot }) {
return <MakeswiftPage snapshot={snapshot} />
}
There's a lot going on here, so let's unpack it.
First, we import the Makeswift
API client and Page
React component to use in our Next.js page.
We alias Page
to MakeswiftPage
to avoid naming conflicts.
import { Makeswift, Page as MakeswiftPage } from '@makeswift/runtime/next'
Then, we define our getStaticPaths
function. You can read more about getStaticPaths
in the
Next.js documentation.
export async function getStaticPaths() {
const makeswift = new Makeswift('<makeswift_site_api_key>')
const pages = await makeswift.getPages()
return {
paths: pages.map((page) => ({
params: { path: page.path.split('/').filter((segment) => segment !== '') },
})),
fallback: 'blocking',
}
}
There's a couple of important things to note here:
-
You need to provide your Makeswift site API key to the
Makeswift
constructor. This is the same API key you used when configuring the Makeswift API handler. -
We use
fallback: 'blocking'
. This is important so that your Next.js app doesn't need to be re-deployed whenever a new Makeswift page is created.
We then fetch our page's data with getStaticProps
.
export async function getStaticProps(ctx) {
const makeswift = new Makeswift('<makeswift_site_api_key>')
const path = '/' + (ctx.params?.path ?? []).join('/')
const snapshot = await makeswift.getPageSnapshot(path, { preview: ctx.preview })
if (snapshot == null) return { notFound: true }
return { props: { snapshot } }
}
Things to note here:
-
You'll need to provide your Makeswift site API key again. Just like we did for
getStaticPaths
and the Makeswift API handler. -
The
path
param is defined by the filename. If the file was named[[...slug]].js
instead of[[...path]].js
then the param would be namedslug
. Because this is an optional catch-all route, there will be no params when visiting the index (i.e.,/
) path so we have to default it to an empty array.
With this setup, your pages will be rendered using
Incremental Static Regeneration.
We don't need to add a revalidate
field to the returned value of getStaticProps
because
Makeswift pages are automatically revalidated using
On-demand Revalidation
by levaraging the Makeswift API handler.
AnchorRegister components with Makeswift
We'll register components in a centralized file that we'll import in our Makeswift catch-all route.
You can place this file wherever you want and give it any name you want. For this guide, we'll do
lib/makeswift/register-components.js
.
// lib/makeswift/register-components.js
import { ReactRuntime } from '@makeswift/runtime/react'
import { Style } from '@makeswift/runtime/controls'
function HelloWorld(props) {
return <p {...props}>Hello, world!</p>
}
ReactRuntime.registerComponent(HelloWorld, {
type: 'hello-world',
label: 'Hello, world!',
props: {
className: Style(),
},
})
Don't forget to import this file in your Makeswift page route.
// pages/[[...path]].js
+ import '../lib/makeswift/register-components'
+
import { Makeswift, Page as MakeswiftPage } from '@makeswift/runtime/next'
You can learn more about registering components here.
AnchorStart your local dev server
Run the local development script. This will start the Next.js app at http://localhost:3000
.
npm run dev
or
yarn dev
If port 3000
is already in use, Next.js will try port 3001
, then 3002
, and so forth until an
unused port is found. Take note of this port for the next step.
AnchorAdd your app's URL to Makeswift
Finally, you'll just need to add your app's URL to your Makeswift site settings. If you haven't
changed anything in the example and it's running on port 3000
, the value should be
http://localhost:3000
.
When you're ready to deploy, you'll probably set up a separate site and use your deployment URL
instead of localhost
. You can keep this site for local development.
AnchorStart building!
That's it! You should be able to create a page in Makeswift and start dropping in registered components.
You will find your registered components in the toolbar of the Makeswift builder. Drag and drop your components into your page and start building!
You can learn more about registering components here.