Skip to content

Commit

Permalink
feat: add makeswift integration
Browse files Browse the repository at this point in the history
  • Loading branch information
fikrikarim authored and migueloller committed Dec 19, 2024
1 parent 1d93439 commit cbc931b
Show file tree
Hide file tree
Showing 15 changed files with 1,071 additions and 32 deletions.
4 changes: 4 additions & 0 deletions core/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Makeswift Site API Key
# In the Makeswift builder, go to Settings > Host and copy the API key for the site.
MAKESWIFT_SITE_API_KEY=

# The hash visible in the subject store's URL when signed in to the store control panel.
# The control panel URL is of the form `https://store-{hash}.mybigcommerce.com`.
BIGCOMMERCE_STORE_HASH=
Expand Down
41 changes: 39 additions & 2 deletions core/app/[locale]/(default)/[...rest]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,42 @@
import { Page as MakeswiftPage } from '@makeswift/runtime/next';
import { getSiteVersion } from '@makeswift/runtime/next/server';
import { notFound } from 'next/navigation';

export default function CatchAllPage() {
notFound();
import { defaultLocale, locales } from '~/i18n/routing';
import { client } from '~/lib/makeswift/client';

export async function generateStaticParams() {
const pages = await client.getPages().toArray();

return pages
.filter((page) => page.path !== '/')
.flatMap((page) =>
locales.map((locale) => ({
rest: page.path.split('/').filter((segment) => segment !== ''),
locale: locale === defaultLocale ? undefined : locale,
})),
);
}

interface Props {
params: Promise<{
locale: string;
rest: string[];
}>;
}

export default async function CatchAllPage({ params }: Props) {
const { rest, locale } = await params;
const path = `/${rest.join('/')}`;

const snapshot = await client.getPageSnapshot(path, {
siteVersion: await getSiteVersion(),
locale: locale === defaultLocale ? undefined : locale,
});

if (snapshot == null) return notFound();

return <MakeswiftPage snapshot={snapshot} />;
}

export const runtime = 'nodejs';
14 changes: 9 additions & 5 deletions core/app/[locale]/(default)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { draftMode } from 'next/headers';
import { setRequestLocale } from 'next-intl/server';
import { PropsWithChildren } from 'react';

import { Footer } from '~/components/footer/footer';
import { Header } from '~/components/header';
import { MakeswiftProvider } from '~/lib/makeswift/provider';

interface Props extends PropsWithChildren {
params: Promise<{ locale: string }>;
Expand All @@ -14,13 +16,15 @@ export default async function DefaultLayout({ params, children }: Props) {
setRequestLocale(locale);

return (
<>
<Header />
<MakeswiftProvider previewMode={(await draftMode()).isEnabled}>
<>
<Header />

<main>{children}</main>
<main>{children}</main>

<Footer />
</>
<Footer />
</>
</MakeswiftProvider>
);
}

Expand Down
4 changes: 4 additions & 0 deletions core/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DraftModeScript } from '@makeswift/runtime/next/server';
import { Analytics } from '@vercel/analytics/react';
import { SpeedInsights } from '@vercel/speed-insights/next';
import { clsx } from 'clsx';
Expand Down Expand Up @@ -113,6 +114,9 @@ export default async function RootLayout({ params, children }: Props) {
className={clsx(inter.variable, dm_serif_text.variable, roboto_mono.variable)}
lang={locale}
>
<head>
<DraftModeScript appOrigin={process.env.MAKESWIFT_APP_ORIGIN} />
</head>
<body>
<Notifications />
<NextIntlClientProvider locale={locale} messages={messages}>
Expand Down
14 changes: 14 additions & 0 deletions core/app/api/makeswift/[...makeswift]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { MakeswiftApiHandler } from '@makeswift/runtime/next/server';
import { strict } from 'assert';

import { runtime } from '~/lib/makeswift/runtime';

strict(process.env.MAKESWIFT_SITE_API_KEY, 'MAKESWIFT_SITE_API_KEY is required');

const handler = MakeswiftApiHandler(process.env.MAKESWIFT_SITE_API_KEY, {
runtime,
apiOrigin: process.env.MAKESWIFT_API_ORIGIN,
appOrigin: process.env.MAKESWIFT_APP_ORIGIN,
});

export { handler as GET, handler as POST };
12 changes: 12 additions & 0 deletions core/app/api/makeswift/draft-mode/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { draftMode } from 'next/headers';
import { NextRequest } from 'next/server';

export const GET = async (request: NextRequest) => {
if (request.headers.get('x-makeswift-api-key') === process.env.MAKESWIFT_SITE_API_KEY) {
const draft = await draftMode();

draft.enable();
}

return new Response(null);
};
11 changes: 11 additions & 0 deletions core/lib/makeswift/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Makeswift } from '@makeswift/runtime/next';
import { strict } from 'assert';

import { runtime } from '~/lib/makeswift/runtime';

strict(process.env.MAKESWIFT_SITE_API_KEY, 'MAKESWIFT_SITE_API_KEY is required');

export const client = new Makeswift(process.env.MAKESWIFT_SITE_API_KEY, {
runtime,
apiOrigin: process.env.MAKESWIFT_API_ORIGIN,
});
Empty file.
20 changes: 20 additions & 0 deletions core/lib/makeswift/provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client';

import { ReactRuntimeProvider, RootStyleRegistry } from '@makeswift/runtime/next';

import { runtime } from '~/lib/makeswift/runtime';
import '~/lib/makeswift/components';

export function MakeswiftProvider({
children,
previewMode,
}: {
children: React.ReactNode;
previewMode: boolean;
}) {
return (
<ReactRuntimeProvider previewMode={previewMode} runtime={runtime}>
<RootStyleRegistry>{children}</RootStyleRegistry>
</ReactRuntimeProvider>
);
}
3 changes: 3 additions & 0 deletions core/lib/makeswift/runtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ReactRuntime } from '@makeswift/runtime/react';

export const runtime = new ReactRuntime();
9 changes: 8 additions & 1 deletion core/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@ import { composeMiddlewares } from './middlewares/compose-middlewares';
import { withAuth } from './middlewares/with-auth';
import { withChannelId } from './middlewares/with-channel-id';
import { withIntl } from './middlewares/with-intl';
import { withMakeswift } from './middlewares/with-makeswift';
import { withRoutes } from './middlewares/with-routes';

export const middleware = composeMiddlewares(withAuth, withIntl, withChannelId, withRoutes);
export const middleware = composeMiddlewares(
withAuth,
withMakeswift,
withIntl,
withChannelId,
withRoutes,
);

export const config = {
matcher: [
Expand Down
39 changes: 39 additions & 0 deletions core/middlewares/with-makeswift.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { NextRequest } from 'next/server';
import { parse as parseSetCookie } from 'set-cookie-parser';

import { MiddlewareFactory } from './compose-middlewares';

export const withMakeswift: MiddlewareFactory = (middleware) => {
return async (request, event) => {
const apiKey = request.nextUrl.searchParams.get('x-makeswift-draft-mode');

if (apiKey === process.env.MAKESWIFT_SITE_API_KEY) {
const response = await fetch(new URL('/api/makeswift/draft-mode', request.nextUrl.origin), {
headers: {
'x-makeswift-api-key': apiKey,
},
});

const cookies = parseSetCookie(response.headers.get('set-cookie') || '');
const prerenderBypassValue = cookies.find((c) => c.name === '__prerender_bypass')?.value;

if (!prerenderBypassValue) {
return middleware(request, event);
}

// https://github.com/vercel/next.js/issues/52967#issuecomment-1644675602
// if we don't pass request twice, headers are stripped
const proxiedRequest = new NextRequest(request, request);

proxiedRequest.cookies.set('__prerender_bypass', prerenderBypassValue);
proxiedRequest.cookies.set(
'x-makeswift-draft-data',
JSON.stringify({ makeswift: true, siteVersion: 'Working' }),
);

return middleware(proxiedRequest, event);
}

return middleware(request, event);
};
};
5 changes: 5 additions & 0 deletions core/next.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import createWithMakeswift from '@makeswift/runtime/next/plugin';
import bundleAnalyzer from '@next/bundle-analyzer';
import type { NextConfig } from 'next';
import createNextIntlPlugin from 'next-intl/plugin';
Expand All @@ -7,6 +8,7 @@ import { client } from './client';
import { graphql } from './client/graphql';
import { cspHeader } from './lib/content-security-policy';

const withMakeswift = createWithMakeswift({ previewMode: false });
const withNextIntl = createNextIntlPlugin();

const LocaleQuery = graphql(`
Expand Down Expand Up @@ -61,6 +63,9 @@ export default async (): Promise<NextConfig> => {
// Apply withNextIntl to the config
nextConfig = withNextIntl(nextConfig);

// Apply withMakeswift to the config
nextConfig = withMakeswift(nextConfig);

if (process.env.ANALYZE === 'true') {
const withBundleAnalyzer = bundleAnalyzer();

Expand Down
3 changes: 3 additions & 0 deletions core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@conform-to/react": "^1.2.2",
"@conform-to/zod": "^1.2.2",
"@icons-pack/react-simple-icons": "^10.2.0",
"@makeswift/runtime": "0.0.0-snapshot-20241213071732",
"@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-alert-dialog": "^1.1.2",
"@radix-ui/react-checkbox": "^1.1.2",
Expand Down Expand Up @@ -63,6 +64,7 @@
"react-hot-toast": "^2.4.1",
"schema-dts": "^1.1.2",
"server-only": "^0.0.1",
"set-cookie-parser": "^2.6.0",
"sharp": "^0.33.5",
"sonner": "^1.7.1",
"tailwind-merge": "^2.5.5",
Expand All @@ -85,6 +87,7 @@
"@types/react-dom": "^19.0.1",
"@types/react-google-recaptcha": "^2.1.9",
"@types/react-headroom": "^3.2.3",
"@types/set-cookie-parser": "^2.4.10",
"@types/uuid": "^10.0.0",
"autoprefixer": "^10.4.20",
"dotenv": "^16.4.7",
Expand Down
Loading

0 comments on commit cbc931b

Please sign in to comment.