Skip to content

Commit 2cff5a5

Browse files
Merge pull request #32 from AsyncStatus/cursor/AS-101-create-pull-request-for-marketing-culture-issue-a15d
Make marketing page more coherent, less bs
2 parents 9b704d7 + 88e4413 commit 2cff5a5

10 files changed

Lines changed: 262 additions & 240 deletions

File tree

apps/marketing-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"dependencies": {
1515
"@asyncstatus/api": "workspace:*",
1616
"@asyncstatus/dayjs": "workspace:*",
17-
"@asyncstatus/ui": "workspace:*",
1817
"@asyncstatus/typed-handlers": "workspace:*",
18+
"@asyncstatus/ui": "workspace:*",
1919
"@opennextjs/cloudflare": "1.6.5",
2020
"framer-motion": "12.23.7",
2121
"next": "15.4.6",

apps/marketing-app/src/app/(app)/page.tsx

Lines changed: 79 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,20 @@
11
import { AsyncStatusLogo } from "@asyncstatus/ui/components/async-status-logo";
22
import { Button } from "@asyncstatus/ui/components/button";
33
import Link from "next/link";
4-
import { BetaMessage } from "../components/beta-message";
5-
import { ConnectCard } from "../components/connect-card";
4+
65
import { CtaSection } from "../components/cta-section";
7-
import { FeaturesList } from "../components/features-list";
86
import { Footer } from "../components/footer";
9-
import { GenerateCard } from "../components/generate-card";
7+
import { IntegrationsList } from "../components/integrations-list";
108
import { MobileMenu } from "../components/mobile-menu";
119
import { Pricing } from "../components/pricing";
12-
import { ReviewCard } from "../components/review-card";
1310
import SavingsCalculator from "../components/savings-calculator";
1411
import { TargetAudience } from "../components/target-audience";
15-
import { TrackCard } from "../components/track-card";
16-
import { UseItYourWay } from "../components/use-it-your-way";
17-
import { peopleSummary } from "./people-summary";
18-
import { PersonSelect } from "./person-select";
19-
20-
export default async function Page(props: {
21-
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
22-
}) {
23-
const searchParams = await props.searchParams;
24-
const person =
25-
typeof searchParams.person === "string"
26-
? (searchParams.person ?? "frontend-developer")
27-
: "frontend-developer";
12+
import { BrandCTA, ValueDescriptions } from "../components/brand-copy";
13+
14+
15+
16+
17+
export default async function Page() {
2818

2919
return (
3020
<>
@@ -56,12 +46,10 @@ export default async function Page(props: {
5646
<Link href="#how-it-works" className="hover:text-foreground">
5747
How it works
5848
</Link>
59-
<Link href="#features" className="hover:text-foreground">
60-
Features
61-
</Link>
6249
<Link href="#team" className="hover:text-foreground">
6350
Use cases
6451
</Link>
52+
6553
<Link href="#pricing" className="hover:text-foreground">
6654
Pricing
6755
</Link>
@@ -120,57 +108,25 @@ export default async function Page(props: {
120108
that value their time.
121109
</h3> */}
122110

123-
<div className="flex justify-center pt-16 pb-12 max-sm:pt-16 max-sm:pb-12">
124-
<a
125-
href="https://www.producthunt.com/products/async-status-updates-for-remote-startups?embed=true&utm_source=badge-featured&utm_medium=badge&utm_source=badge-asyncstatus"
126-
target="_blank"
127-
rel="noopener"
128-
>
129-
{/** biome-ignore lint/performance/noImgElement: it's a product hunt badge */}
130-
<img
131-
src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=999509&theme=neutral&t=1754045157676"
132-
alt="AsyncStatus - Don&#0039;t&#0032;join&#0032;another&#0032;9&#0058;30am&#0032;standup&#0032;meeting&#0032;ever&#0032;again&#0046; | Product Hunt"
133-
style={{ width: "187.5px", height: "40.5px" }}
134-
width="187.5"
135-
height="40.5"
136-
/>
137-
</a>
138-
</div>
111+
<IntegrationsList />
139112

140113
<h2 className="text-fit mr-[2.5vw] text-center font-bold max-sm:hidden">
141114
<span>
142-
<span>Standup meetings suck</span>
115+
<span>Automate status updates</span>
143116
</span>
144-
<span aria-hidden="true">Standup meetings suck</span>
117+
<span aria-hidden="true">Automate status updates</span>
145118
</h2>
146-
<h2 className="hidden text-center text-5xl font-bold max-sm:block">
147-
Standup meetings suck
119+
<h2 className="hidden text-center text-5xl font-bold max-sm:block max-sm:mt-6">
120+
Automate status updates
148121
</h2>
149122

150123
<h3 className="text-muted-foreground mt-6 text-center text-2xl leading-normal text-balance max-md:text-lg max-sm:text-base">
151-
Your team already pushed code, closed tickets, replied in threads, fixed small things no
152-
one asked them to. We turn it into an update. Or you can write it yourself. Either way, no
153-
one has to talk about it at 9:30 a.m.
124+
Generate status updates by monitoring your team's activity in code, Slack, and others. Or write them yourself.
154125
</h3>
155126

156-
<div className="mt-14 flex flex-col items-center justify-center max-sm:mt-6">
157-
<Button size="lg" asChild>
158-
<Link
159-
href={`${process.env.NEXT_PUBLIC_APP_URL}/sign-up`}
160-
className="hover:text-foreground"
161-
>
162-
<span>Turn activity into updates</span>
163-
</Link>
164-
</Button>
165127

166-
<p className="text-muted-foreground text-xs mt-2">
167-
No credit card required. Cancel anytime.
168-
</p>
169-
</div>
170-
171-
{/* aspect-[2.4/1] */}
172128
<video
173-
className="mt-36 w-full rounded-lg max-sm:mt-16 aspect-[2.4/1]"
129+
className="mt-8 w-full rounded-lg max-sm:mt-6 aspect-[2.4/1]"
174130
autoPlay
175131
loop
176132
muted
@@ -181,7 +137,7 @@ export default async function Page(props: {
181137
Your browser does not support the video tag.
182138
</video>
183139

184-
<div className="flex justify-center mt-12 gap-4 max-sm:flex-col">
140+
<div className="flex justify-center mt-8 gap-4 max-sm:flex-col">
185141
<Button variant="secondary" asChild>
186142
<Link href="https://youtu.be/y_Hl0rVJHKs" target="_blank">
187143
<span>Watch intro video</span>
@@ -194,119 +150,89 @@ export default async function Page(props: {
194150
</Button>
195151
</div>
196152

197-
{/* <img
198-
src="/hero-light.webp"
199-
alt="AsyncStatus app screenshot"
200-
className="border-border mt-36 w-full rounded-lg border max-sm:mt-16"
201-
/> */}
202-
203-
<div className="mt-36 flex flex-col items-center">
204-
<div className="relative w-full max-w-6xl">
205-
<div className="flex items-center justify-between">
206-
<div className="bg-background border-border rounded-lg border px-4 py-2 max-sm:w-full">
207-
<div className="inline-flex items-center gap-0.5 max-sm:gap-1.5">
208-
<span className="text-lg">Standup for</span>
209-
<PersonSelect defaultValue="frontend-developer" value={person} />
210-
</div>
153+
<div className="mt-14 flex flex-col items-center justify-center">
154+
<Button size="lg" asChild>
155+
<Link
156+
href={`${process.env.NEXT_PUBLIC_APP_URL}/sign-up`}
157+
className="hover:text-foreground"
158+
>
159+
<BrandCTA variant="Secondary" />
160+
</Link>
161+
</Button>
162+
163+
<p className="text-muted-foreground text-xs mt-2">
164+
No credit card required. Cancel anytime.
165+
</p>
166+
</div>
167+
168+
{/* How it works section */}
169+
<section id="how-it-works" className="mt-36 max-sm:mt-24">
170+
<div className="mb-16 text-center max-sm:mb-12">
171+
<h3 className="text-center text-6xl font-bold max-sm:text-4xl">
172+
How it works?
173+
</h3>
174+
</div>
175+
176+
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-sm:gap-6">
177+
<div className="flex flex-col items-center text-center">
178+
<div className="bg-primary text-primary-foreground flex h-12 w-12 items-center justify-center rounded-full font-bold text-lg mb-4 max-sm:h-10 max-sm:w-10 max-sm:text-base max-sm:mb-3">
179+
1
180+
</div>
181+
<div>
182+
<h5 className="text-xl font-semibold mb-3 max-sm:text-lg max-sm:mb-2">
183+
Connect to your workflow
184+
</h5>
185+
<p className="text-muted-foreground text-lg leading-relaxed max-sm:text-base">
186+
Connect to your work (GitHub, Slack) which takes less than 5 minutes
187+
</p>
211188
</div>
212189
</div>
213190

214-
<div className="mt-4 flex flex-col gap-12">
191+
<div className="flex flex-col items-center text-center">
192+
<div className="bg-primary text-primary-foreground flex h-12 w-12 items-center justify-center rounded-full font-bold text-lg mb-4 max-sm:h-10 max-sm:w-10 max-sm:text-base max-sm:mb-3">
193+
2
194+
</div>
215195
<div>
216-
<h4 className="text-muted-foreground mb-3 text-sm font-medium">In the meeting</h4>
217-
<div className="border-border/40 bg-muted/30 rounded-lg border p-4">
218-
<p className="text-muted-foreground/90 text-lg text-balance">
219-
{(() => {
220-
const fullText = peopleSummary[person].standupText;
221-
const words = fullText.split(/\s+/);
222-
if (words.length <= 100) {
223-
return fullText;
224-
} else {
225-
return (
226-
<>
227-
{words.slice(0, 100).join(" ")}
228-
<span className="text-foreground">
229-
{" "}
230-
and {words.length - 100} more words.
231-
</span>
232-
</>
233-
);
234-
}
235-
})()}
236-
</p>
237-
<div className="text-muted-foreground mt-3 flex items-center gap-3 text-sm">
238-
<span>{peopleSummary[person].meetingDetails.time}</span>
239-
<span>·</span>
240-
<span>
241-
{peopleSummary[person].meetingDetails.peopleListening} people listening
242-
</span>
243-
<span>·</span>
244-
<span>{peopleSummary[person].meetingDetails.peopleTyping} people typing</span>
245-
</div>
246-
</div>
196+
<h5 className="text-xl font-semibold mb-3 max-sm:text-lg max-sm:mb-2">
197+
We generate updates automatically
198+
</h5>
199+
<p className="text-muted-foreground text-lg leading-relaxed max-sm:text-base">
200+
We listen for updates from your tools and generate status updates from your team's activity.
201+
</p>
247202
</div>
203+
</div>
248204

205+
<div className="flex flex-col items-center text-center">
206+
<div className="bg-primary text-primary-foreground flex h-12 w-12 items-center justify-center rounded-full font-bold text-lg mb-4 max-sm:h-10 max-sm:w-10 max-sm:text-base max-sm:mb-3">
207+
3
208+
</div>
249209
<div>
250-
<h4 className="text-muted-foreground mb-3 text-sm font-medium">
251-
What actually happened
252-
</h4>
253-
<div className="flex flex-col gap-2">
254-
{peopleSummary[person].summary.map((summary, index) => (
255-
<div key={summary} className="flex items-start gap-4">
256-
<span className="text-primary mt-1 text-sm font-medium">0{index + 1}</span>
257-
<div className="flex-1">
258-
<p className="text-lg">{summary}</p>
259-
</div>
260-
</div>
261-
))}
262-
</div>
210+
<h5 className="text-xl font-semibold mb-3 max-sm:text-lg max-sm:mb-2">
211+
You are always up to date
212+
</h5>
213+
<p className="text-muted-foreground text-lg leading-relaxed max-sm:text-base">
214+
Receive updates from your team. Don't worry about obsolete info in ticketing systems.
215+
</p>
263216
</div>
264217
</div>
265218
</div>
266-
</div>
267-
268-
<h3 className="mt-36 text-center text-6xl font-bold max-sm:text-5xl" id="how-it-works">
269-
How it works
270-
</h3>
271-
<div className="mt-24 grid grid-cols-1 gap-8 max-sm:gap-12 sm:grid-cols-2 md:gap-12">
272-
<ConnectCard />
273-
<TrackCard />
274-
<GenerateCard />
275-
<ReviewCard />
276-
</div>
277-
278-
<UseItYourWay />
219+
</section>
279220

280221
<section id="team">
281222
<TargetAudience />
282223
</section>
283224

284-
<section id="features">
285-
<FeaturesList />
286-
</section>
287225

288-
<section id="early-stage">
289-
<BetaMessage />
290-
<div className="flex justify-center mt-12">
291-
<Button size="lg" asChild>
292-
<Link
293-
href={`${process.env.NEXT_PUBLIC_APP_URL}/sign-up`}
294-
className="hover:text-foreground"
295-
>
296-
<span>Turn activity into updates</span>
297-
</Link>
298-
</Button>
299-
</div>
300-
</section>
226+
227+
301228

302229
<section id="calculator" className="mt-36">
303230
<div className="mb-12 text-center">
304231
<h3 className="text-center text-6xl font-bold max-sm:text-5xl">
305232
Calculate your savings
306233
</h3>
307234
<h3 className="text-muted-foreground mt-6 text-xl text-pretty">
308-
See how much time and money your team can save by replacing synchronous standups with
309-
AsyncStatus.
235+
See how much time and money your team saves by dropping standups for async updates.
310236
</h3>
311237
</div>
312238
<SavingsCalculator />
@@ -337,6 +263,8 @@ export default async function Page(props: {
337263
</p>
338264
</section>
339265

266+
267+
340268
<section id="pricing">
341269
<Pricing />
342270
</section>

0 commit comments

Comments
 (0)