Skip to content

Commit

Permalink
feat: add newsletter cta to cheat sheet
Browse files Browse the repository at this point in the history
  • Loading branch information
joelhooks committed Sep 20, 2024
1 parent 1428706 commit 2c7b94b
Show file tree
Hide file tree
Showing 8 changed files with 358 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .node-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.17.1
20.12.0
3 changes: 3 additions & 0 deletions apps/epic-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"scripts": {
"dev": "next dev -p 3024",
"dev:sanity": "sanity dev",
"dev:party": "pnpx partykit dev",
"dev:stripe": "echo 'Run epic-web `pnpm dev` to handle stripe webhooks for kcd-products' && exit 1",
"build": "next build",
"postbuild": "NODE_ENV=production next-sitemap",
Expand Down Expand Up @@ -113,6 +114,8 @@
"nodemailer": "^6.7.2",
"nodemailer-postmark-transport": "^5.2.1",
"openai": "^4.12.1",
"partysocket": "1.0.2",
"partykit": "0.0.110",
"pluralize": "^8.0.0",
"postmark": "^3.1.1",
"prism-react-renderer": "^2.3.1",
Expand Down
70 changes: 70 additions & 0 deletions apps/epic-react/party/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import type * as Party from 'partykit/server'

const CORS = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Allow-Headers':
'Origin, X-Requested-With, Content-Type, Accept',
}

export default class Server implements Party.Server {
constructor(readonly party: Party.Room) {}

async onConnect(conn: Party.Connection, ctx: Party.ConnectionContext) {
// A websocket just connected!
console.log(
`Connected:
id: ${conn.id}
room: ${this.party.id}
url: ${new URL(ctx.request.url).pathname}`,
)
}

messages: string[] = []

async onStart() {
this.messages = (await this.party.storage.get<string[]>('messages')) ?? []
}

async onRequest(req: Party.Request) {
if (req.method === 'GET') {
// For SSR, return the current presence of all connections
// const users = [...this.party.getConnections()].reduce(
// (acc, user) => ({...acc, [user.id]: this.getUser(user)}),
// {},
// )
return Response.json({users: []}, {status: 200, headers: CORS})
}

// respond to cors preflight requests
if (req.method === 'OPTIONS') {
return Response.json({ok: true}, {status: 200, headers: CORS})
}

if (req.method === 'POST') {
const messageBody: {requestId: string; body: string; name: string} =
await req.json()

this.party.broadcast(JSON.stringify(messageBody))

return new Response(
`Party ${this.party.id} has received ${this.messages.length} messages`,
)
}

return new Response('Method Not Allowed', {status: 405})
}

onMessage(message: string, sender: Party.Connection) {
// let's log the message
console.log(`connection ${sender.id} sent message: ${message}`)
// as well as broadcast it to all the other connections in the room...
this.party.broadcast(
`${sender.id}: ${message}`,
// ...except for the connection it came from
[sender.id],
)
}
}

Server satisfies Party.Worker
6 changes: 6 additions & 0 deletions apps/epic-react/partykit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "epic-react",
"main": "party/index.ts",
"compatibilityDate": "2023-10-20",
"team": "skillrecordings"
}
4 changes: 4 additions & 0 deletions apps/epic-react/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export default function RootLayout({children}: {children: React.ReactNode}) {
>
{children}
</ThemeProvider>
<script
async
src="https://cursor-party.skillrecordings.partykit.dev/cursors.js"
></script>
</body>
</html>
)
Expand Down
3 changes: 3 additions & 0 deletions apps/epic-react/src/components/primary-newsletter-cta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type PrimaryNewsletterCtaProps = {
actionLabel?: string
id?: string
className?: string
formId?: string
trackProps?: {
event?: string
params?: Record<string, string>
Expand All @@ -33,6 +34,7 @@ export const PrimaryNewsletterCta: React.FC<
actionLabel = common['primary-newsletter-button-cta-label'],
trackProps = {event: 'subscribed', params: {}},
onSuccess,
formId,
}) => {
const router = useRouter()
const handleOnSuccess = (subscriber: Subscriber | undefined) => {
Expand All @@ -57,6 +59,7 @@ export const PrimaryNewsletterCta: React.FC<
</div>
)}
<SubscribeToConvertkitForm
formId={formId}
onSuccess={onSuccess ? onSuccess : handleOnSuccess}
actionLabel={actionLabel}
/>
Expand Down
67 changes: 67 additions & 0 deletions apps/epic-react/src/pages/react-19-cheatsheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Button} from '@skillrecordings/ui'
import Share from '@/components/share'
import {HeartIcon} from '@heroicons/react/solid'
import {track} from '@/utils/analytics'
import {PrimaryNewsletterCta} from '@/components/primary-newsletter-cta'

const CheatSheetPage = () => {
return (
Expand Down Expand Up @@ -83,6 +84,72 @@ const CheatSheetPage = () => {
</div>
</Share>
</div>

<main
id="newsletter"
className="mx-auto flex w-full max-w-screen-md flex-col items-center justify-center py-10 dark:bg-[radial-gradient(50%_50%_at_50%_50%,_#1C2434_0%,_hsl(var(--background))_100%)] sm:py-20"
>
<PrimaryNewsletterCta
className="[&>[data-sr-convertkit-subscribe-form]]:flex-col [&_[data-nospam]]:hidden"
actionLabel="Stay Up to Date"
formId="7122145"
>
<div className="flex flex-col px-5">
<h1 className="text-balance text-center text-2xl font-semibold sm:text-4xl">
Get more React 19 resources
</h1>
<h2 className="mb-10 mt-5 max-w-2xl items-center justify-center px-5 text-center text-blue-600 dark:text-blue-200 sm:text-lg">
Sign up and we will send you emails when we have new React 19
tips, tools, and techniques like this cheat sheet by
<span className="relative inline-flex translate-y-1.5 items-center sm:translate-y-2.5">
<Image
src={require('../../public/kent-c-dodds.png')}
alt=""
priority
aria-hidden="true"
width={40}
height={40}
className="ml-3 mr-1.5 size-6 rounded-full bg-gray-300 dark:bg-gray-800 sm:size-8"
/>{' '}
Kent C. Dodds
</span>
</h2>
</div>
</PrimaryNewsletterCta>
<p
data-nospam=""
className="inline-flex items-center gap-2 pt-0 text-center text-xs text-gray-600 dark:text-gray-400"
>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
aria-hidden="true"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.5 9C14.5 13.5 8 15.5 8 15.5C8 15.5 1.5 13.5 1.5 9V2.5L8 0.5L14.5 2.5V9Z"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
></path>
<path
d="M6.5 7.5V6C6.5 5.172 7.172 4.5 8 4.5C8.828 4.5 9.5 5.172 9.5 6V7.5"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
></path>
<path
d="M10.5 7.5H5.5V10.5H10.5V7.5Z"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
></path>
</svg>
I respect your privacy. Unsubscribe at any time.
</p>
</main>
</main>
</Layout>
)
Expand Down
Loading

0 comments on commit 2c7b94b

Please sign in to comment.