Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/web/components/layout/header.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default function HeaderComponent() {
if (billingDetails?.has_active_subscription) {
return [
{ name: "Pages", href: ROUTES.PAGES },
{ name: "Zapier", href: ROUTES.ZAPIER },
{ name: "Billing", href: ROUTES.BILLING },
{ name: "Support", href: ROUTES.SUPPORT, external: true },
];
Expand All @@ -41,7 +42,7 @@ export default function HeaderComponent() {

return [
{ name: "Pricing", href: ROUTES.PRICING },
{ name: "Zapier Integration", href: ROUTES.ZAPIER },
{ name: "Automate using Zapier", href: ROUTES.ZAPIER },
{ name: "Knowledge base", href: ROUTES.DOCS, external: true },
{ name: "Support", href: ROUTES.SUPPORT, external: true },
];
Expand Down
17 changes: 17 additions & 0 deletions apps/web/components/marketing/features.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
MailIcon,
StarIcon,
} from "@heroicons/react/solid";
import Head from "next/head";
import Image from "next/image";
import { useMemo } from "react";
import appScreenshot from "../../public/images/hero/app-screenshot.png";
Expand Down Expand Up @@ -76,6 +77,12 @@ export default function Features() {

return (
<div className="bg-gray-900 py-16 sm:py-32">
<Head>
<script
type="module"
src="https://cdn.zapier.com/packages/partner-sdk/v0/zapier-elements/zapier-elements.esm.js"
></script>
</Head>
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-2xl sm:text-center font-semibold">
<h2 className="text-xl leading-8 tracking-tight text-indigo-400">
Expand Down Expand Up @@ -124,6 +131,16 @@ export default function Features() {
))}
</dl>
</div>

<div className="mx-auto mt-16 max-w-7xl px-6 sm:mt-20 md:mt-24 lg:px-8">
<zapier-workflow
client-id="rnKv828fHE7sPhcZdGhwqWbIsJkOfhUEh2RAHQw4"
theme="dark"
intro-copy-display="show"
guess-zap-display="show"
zap-create-from-scratch-display="show"
/>
</div>
</div>
);
}
25 changes: 25 additions & 0 deletions apps/web/inngest/email/send-welcome-email.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import inngestClient from "../../utils/inngest";
import postmarkClient from "../../utils/postmark";

export const sendWelcomeEmail = inngestClient.createFunction(
{ name: "Email: Welcome" },
{ event: "email/user.welcome" },
async ({ event }) => {
const { email, payload } = event.data;

console.log("Job started", {
email,
payload,
});

const result = await postmarkClient.sendEmailWithTemplate({
MessageStream: "outbound",
From: "[email protected]",
To: email,
TemplateAlias: "welcome-user",
TemplateModel: payload,
});

return { body: "Job completed", result };
}
);
5 changes: 5 additions & 0 deletions apps/web/jsx-types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare namespace JSX {
interface IntrinsicElements {
"zapier-workflow": any;
}
}
6 changes: 3 additions & 3 deletions apps/web/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ const withBundleAnalyzer = require("@next/bundle-analyzer")({});

const ContentSecurityPolicy = `
script-src 'self' 'unsafe-eval' 'unsafe-inline' *;
style-src 'self' data: 'unsafe-inline' maxcdn.bootstrapcdn.com cdn.jsdelivr.net;
style-src 'self' data: 'unsafe-inline' maxcdn.bootstrapcdn.com cdn.jsdelivr.net cdn.zapier.com fonts.googleapis.com;
img-src 'self' * data: blob:;
font-src 'self' data: maxcdn.bootstrapcdn.com cdn.jsdelivr.net;
connect-src 'self' wss: *.supabase.co *.changes.page manageprompt.com;
font-src 'self' data: maxcdn.bootstrapcdn.com cdn.jsdelivr.net fonts.gstatic.com;
connect-src 'self' wss: *.supabase.co *.changes.page manageprompt.com zapier.com *.zapier.com www.google.com;
worker-src 'self' blob:;
report-to default
`;
Expand Down
4 changes: 4 additions & 0 deletions apps/web/pages/_document.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export default class MyDocument extends Document {
media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image"
/>
<link
rel="stylesheet"
href="https://cdn.zapier.com/packages/partner-sdk/v0/zapier-elements/zapier-elements.css"
/>
</Head>
<body>
<Main />
Expand Down
2 changes: 2 additions & 0 deletions apps/web/pages/api/inngest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { serve } from "inngest/next";
import { handleSubscriptionChange } from "../../inngest/billing/handle-subscription";
import { reportUsageForStripeInvoice } from "../../inngest/billing/report-pages-usage-invoice";
import { sendConfirmEmailNotification } from "../../inngest/email/send-confirm-email-notification";
import { sendWelcomeEmail } from "../../inngest/email/send-welcome-email";
import { deleteImagesJob } from "../../inngest/jobs/delete-images";
import { sendPostNotification } from "./../../inngest/email/send-post-notification";

Expand All @@ -13,6 +14,7 @@ export default serve("changes-page", [
// Emails
sendConfirmEmailNotification,
sendPostNotification,
sendWelcomeEmail,
// Background Jobs
deleteImagesJob,
]);
57 changes: 57 additions & 0 deletions apps/web/pages/api/users/webhook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { NextApiRequest, NextApiResponse } from "next";
import inngestClient from "../../../utils/inngest";

const databaseWebhook = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === "POST") {
try {
if (req?.headers["x-webhook-key"] !== process.env.SUPABASE_WEBHOOK_KEY) {
return res
.status(400)
.json({ error: { statusCode: 500, message: "Invalid webhook key" } });
}

const { type, record, old_record } = req.body;
const user: {
id: string;
email?: string;
raw_user_meta_data?: {
name?: string;
full_name?: string;
};
} = record || old_record;

const { id, email } = user;
console.log("Trigger databaseWebhook [Users]: Record:", type, id);

if (type === "INSERT") {
await inngestClient.send({
name: "email/user.welcome",
data: {
email,
payload: {
first_name:
user.raw_user_meta_data?.full_name ??
user.raw_user_meta_data?.name ??
"there",
},
},
user: {
id,
},
});
}

return res.status(200).json({ ok: true });
} catch (err) {
console.log("Trigger databaseWebhook [Users]: Error:", err);
res
.status(500)
.json({ error: { statusCode: 500, message: err.message } });
}
} else {
res.setHeader("Allow", "POST,PUT");
res.status(405).end("Method Not Allowed");
}
};

export default databaseWebhook;
145 changes: 29 additions & 116 deletions apps/web/pages/integrations/zapier.tsx
Original file line number Diff line number Diff line change
@@ -1,128 +1,41 @@
import { InboxIcon, SparklesIcon } from "@heroicons/react/outline";
import Image from "next/image";
import { GetServerSidePropsContext } from "next";
import Head from "next/head";
import FooterComponent from "../../components/layout/footer.component";
import HeaderComponent from "../../components/layout/header.component";
import Page from "../../components/layout/page.component";
import zapierGitHub from "../../public/images/zapier/github.png";
import zapierTweet from "../../public/images/zapier/tweet.png";
import { getSupabaseServerClient } from "../../utils/supabase/supabase-admin";

export default function Example() {
export async function getServerSideProps(ctx: GetServerSidePropsContext) {
const { user } = await getSupabaseServerClient(ctx);

return {
props: { email: user?.email },
};
}

export default function Zapier({ email }: { email?: string }) {
return (
<div className="h-full bg-gray-100 dark:bg-gray-800">
<HeaderComponent />
<Head>
<script
type="module"
src="https://cdn.zapier.com/packages/partner-sdk/v0/zapier-elements/zapier-elements.esm.js"
></script>
</Head>

<Page title="Zapier Integration" fullWidth>
<div className="relative pt-16 pb-32 overflow-hidden">
<Page title="Automate using Zapier">
<div className="relative pb-32 overflow-hidden">
<div className="relative">
<div className="lg:mx-auto lg:max-w-7xl text-center">
<div className="px-4 max-w-xl mx-auto sm:px-6 lg:py-4 pb-8 lg:pb-16 lg:max-w-none lg:mx-0 lg:px-0">
<h2 className="text-3xl font-extrabold tracking-tight text-gray-900 dark:text-gray-50">
Connect with Zapier and{" "}
<span className="text-indigo-600 dark:text-indigo-500">
automate your workflow
</span>
, here are some examples:
</h2>
</div>
</div>

<div className="lg:mx-auto lg:max-w-7xl lg:px-8 lg:grid lg:grid-cols-2 lg:grid-flow-col-dense lg:gap-24">
<div className="px-4 max-w-xl mx-auto sm:px-6 lg:py-16 lg:max-w-none lg:mx-0 lg:px-0">
<div>
<div className="hidden lg:block">
<span className="h-12 w-12 rounded-md flex items-center justify-center bg-indigo-600">
<InboxIcon
className="h-6 w-6 text-white"
aria-hidden="true"
/>
</span>
</div>
<div className="mt-6">
<h2 className="text-3xl font-extrabold tracking-tight text-gray-900 dark:text-gray-50">
Tweet when you create a post
</h2>
<p className="mt-4 text-lg text-gray-500 dark:text-gray-400">
Share your new posts on Twitter so that customers are in
the loop with latest changes in your product.
</p>
<div className="mt-6">
<a
href="https://zapier.com/developer/public-invite/156052/c952eac2cc1df107ce2c1ff82feddc19/"
target="_blank"
rel="noopener noreferrer"
className="inline-flex px-4 py-2 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700"
>
Get started
</a>
</div>
</div>
</div>
</div>
<div className="mt-12 sm:mt-16 lg:mt-0">
<div className="pl-4 -mr-48 sm:pl-6 md:-mr-16 lg:px-0 lg:m-0 lg:relative lg:h-full">
<Image
className="w-full rounded-xl shadow-xl ring-1 ring-black ring-opacity-5 lg:absolute lg:left-0 lg:h-full lg:w-auto lg:max-w-none"
src={zapierTweet.src}
alt="Post to Tweet"
width={667}
height={374}
/>
</div>
</div>
</div>
</div>
<div className="mt-24">
<div className="lg:mx-auto lg:max-w-7xl lg:px-8 lg:grid lg:grid-cols-2 lg:grid-flow-col-dense lg:gap-24">
<div className="px-4 max-w-xl mx-auto sm:px-6 lg:py-32 lg:max-w-none lg:mx-0 lg:px-0 lg:col-start-2">
<div className="hidden lg:block">
<span className="h-12 w-12 rounded-md flex items-center justify-center bg-indigo-600">
<SparklesIcon
className="h-6 w-6 text-white"
aria-hidden="true"
/>
</span>
</div>
<div className="mt-6">
<h2 className="text-3xl font-extrabold tracking-tight text-gray-900 dark:text-gray-50">
Sync GitHub releases
</h2>
<p className="mt-4 text-lg text-gray-500 dark:text-gray-400">
Automatically create a new post in your changes page every
time you publish a new release in GitHub.
</p>
<div className="mt-6">
<a
href="https://zapier.com/developer/public-invite/156052/c952eac2cc1df107ce2c1ff82feddc19/"
target="_blank"
rel="noopener noreferrer"
className="inline-flex px-4 py-2 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700"
>
Get started
</a>
</div>
</div>
</div>
<div className="mt-12 sm:mt-16 lg:mt-0 lg:col-start-1">
<div className="pr-4 -ml-48 sm:pr-6 md:-ml-16 lg:px-0 lg:m-0 lg:relative lg:h-full">
<Image
className="w-full rounded-xl shadow-xl ring-1 ring-black ring-opacity-5 lg:absolute lg:right-0 lg:h-full lg:w-auto lg:max-w-none"
src={zapierGitHub.src}
alt="Copy releases from GitHub"
width={892}
height={502}
/>
</div>
</div>
</div>
</div>

<div className="lg:mx-auto lg:max-w-7xl text-center mt-24">
<div className="px-4 max-w-xl mx-auto sm:px-6 py-8 lg:py-16 lg:max-w-none lg:mx-0 lg:px-0">
<p className="text-xl text-gray-900 dark:text-gray-50">
Zapier lets you connect changes.page with thousands of the most
popular apps, so you can automate your work and have more time
for what matters most—no code required.
</p>
<div className="lg:mx-auto lg:max-w-7xl text-center mx-4 md:mx-0">
<zapier-workflow
sign-up-email={email}
client-id="rnKv828fHE7sPhcZdGhwqWbIsJkOfhUEh2RAHQw4"
theme="auto"
intro-copy-display="show"
guess-zap-display="show"
zap-create-from-scratch-display="show"
/>
</div>
</div>
</div>
Expand Down
10 changes: 7 additions & 3 deletions apps/web/utils/useDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ export const getUserById = async (user_id: string): Promise<IUser> => {

return {
...user,
has_active_subscription: user.pro_gifted ? true : ["trialing", "active"].includes(
(user?.stripe_subscription as unknown as Stripe.Subscription)?.status
),
has_active_subscription:
user.pro_gifted === true
? true
: ["trialing", "active"].includes(
(user?.stripe_subscription as unknown as Stripe.Subscription)
?.status
),
} as unknown as IUser;
};

Expand Down
Loading