Merge branch 'feat/refresh' into feat/mobileNavigation

This commit is contained in:
premiare
2023-08-18 19:57:26 +10:00
committed by GitHub
75 changed files with 5137 additions and 165 deletions

View File

@ -0,0 +1,36 @@
---
title: Announcing Pre-Seed and Open Metrics
description: We are exicited to report the closing of our Pre-Seed round. You can find the juicy details on our new /open page. Yes, it was signed using Documenso.
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2023-08-17
tags:
- Funding
- Metrics
- Open Startup
---
Today I'm happy to announce that we closed a \$1.25M Pre-Seed round for Documenso, bringing our total funding to \$1.54M. The round actually closed last month, we just were sneaky about it.
## Two more for the road (to open signing)
We're ecstatic to welcome [OSS Capital](https://twitter.com/osscapital) and especially [Joseph Jacks](https://twitter.com/JosephJacks_) to the inner circle of the open signing revolution. We're also fortunate to be joined by Orrick's very own [John Harrison](https://www.linkedin.com/in/john-harrison-a1213b9/) and his legal experience. For those who are wondering, yes, the round was, of course, signed using Documenso.
## Open Source, Open Metrics
If you follow us, you know we're firmly committed to the open source values of openness and transparency. For us, this includes not only the code side of things but also the business. As we aim to build trust among our investors, customers, and partners, we want to be open about what's going on. We also want to allow everyone to learn from our data and choices, just as we did from so many other COSS (Commercial Open Source) startups. The term "Open Startup" isn't precisely defined (and probably will never be, just like startup). There is however a [great write-up](https://cal.com/blog/open-startup) about the basics by the founder of our favorite open source scheduling tool Cal.com.
The two main takeaways are:
- "Any Startup that shares its metrics as open as technically and operationally possible is an Open Startup."
- "Why should I care? Frankly speaking, Open Startups have a tough time screwing you over."
The more open the culture, the less shady stuff is going on. While this may sound trivial, the implications are profound. A new generation of organizations, operating more ethically and responsibly simply because everything is out in the open.
For us, there are two sides to being an Open Startup:
- The company side: Sharing Financial KPIs like growth, funding, team structure, salary, internal processes, and tools.
- The product side: Sharing insights and data like usage, reach, and GitHub activity.
Both sides aim to contribute to the global knowledge base of how startups work, specifically COSS startups. As we see more and more COSS, best practices and business insights should be broadly available to let the space mature. As we contribute code to the global community, we also contribute our business knowledge to help bring about even more COSS.
Starting today, we're releasing a lot of our data as part of the Open Startup movement. You can find the juicy details on our funding and more here: [documen.so/open](https://documen.so/open)

View File

@ -1,13 +1,13 @@
---
title: Switching to Discord
description: Join us on documen.so/discord to share ideas, support, and memes.
description: The Documenso community is growing and we feel the need to have a more community and developer-friendly environment. We're switching to Discord.
authorName: 'Flo Merian'
authorImage: '/blog/blog-author-flo.jpeg'
authorRole: 'Go-to-market'
date: 2023-08-02
tags:
- Announcement
- Community
- Community
---
Were switching to Discord.
@ -20,15 +20,15 @@ As the community grows (reached 2K stars on GitHub and 100 community members on
The Documenso team is growing, too. [Lucas joined Timur](https://twitter.com/ElTimuro/status/1648608988391514112), then [Ephraim](https://twitter.com/documenso/status/1662418374243041280) and [David](https://github.com/dguyen) recently joined the journey. We want to stay in touch with the community as much as possible and avoid context-switching to focus on work, support, and fun.
Were an open-source project and focus on building a great developer experience. So, when we thought of a Slack replacement, community- and developer-friendly, Discord was an obvious choice — not to mention that it would help us keep up with [OSS friends](https://documen.so/oss), too.
Were an open-source project and focus on building a great developer experience. So, when we thought of a Slack replacement, community and developer-friendly, Discord was an obvious choice — not to mention that it would help us keep up with [OSS friends](https://documen.so/oss), too.
So, were switching all conversations, team- and community-wide, to Discord.
So, were switching all conversations, team and community-wide, to Discord.
In this post, we wont debate *why* were switching — Slack vs. Discord is a long-lasting debate with pros and cons, and fans on both sides. There are great [stories](https://blog.meilisearch.com/from-slack-to-discord-our-migration/) and [threads](https://twitter.com/McPizza0/status/1655519558600470528) on the topic. We just dont want to write yet another story here.
Instead, well focus on *how* we plan to make the switch.
## ## Who is this story for?
## Who is this story for?
First, we wrote this post for the team so were ready for the switch. Then we post it online because we value transparency and thought it might help the community.
@ -47,15 +47,15 @@ The detailed plan goes like this:
- 2023-08-02 `t+8`: We announce to the community the upcoming changes in the different channels — GitHub, Twitter, and Slack.
- **GitHub**
- [ ] Create new Pull Request
- [ ] Add story to the blog
- [ ] Update link to the community
- Create new Pull Request
- Add story to the blog
- Update link to the community
```
https://documen.so/discord
```
- [ ] Start a new Discussion
- Start a new Discussion
```markdown
Happy Wednesday!
@ -73,9 +73,9 @@ The detailed plan goes like this:
```
- **Twitter**
- [ ] Tweet the announcement
- [ ] Pin Tweet
- [ ] Update link in bio
- [Tweet the announcement](https://twitter.com/documenso/status/1686719482096766977)
- Pin Tweet
- Update link in bio
```
The Open Source DocuSign Alternative.
@ -87,7 +87,7 @@ The detailed plan goes like this:
```
- **Slack**
- [ ] Post message in `#general`
- Post message in `#general`
```markdown
Happy Wednesday!
@ -104,18 +104,18 @@ The detailed plan goes like this:
Flo
```
- [ ] Pin post
- [ ] Set topic and description
- Pin post
- Set topic and description
```
We're switching to Discord. Join the fun: https://documen.so/discord
```
- [ ] Archive channels: `#code-review` `#how-to` `#meet-and-greet` `#random-memes` `#self-hosting` `#support`
- Archive channels: `#code-review` `#how-to` `#meet-and-greet` `#random-memes` `#self-hosting` `#support`
- 2023-08-09 `t+15`: 7 days later, we send a reminder on Slack.
- **Slack**
- [ ] Schedule reminder in `#general` (Flo)
- Schedule reminder in `#general`
```
Friendly reminder: we're switching to Discord and will soon disconnect this Slack workspace.
@ -125,8 +125,8 @@ The detailed plan goes like this:
- 2023-08-16 `t+22`: 15 days later, were making the final edits to the Slack workspace.
- **Slack**
- [ ] [Edit posting permissions](https://app.slack.com/slackhelp/en-US/360004635551) in `#general`
- [ ] Disconnect Slack
- [Edit posting permissions](https://app.slack.com/slackhelp/en-US/360004635551) in `#general`
- Disconnect Slack
## Final thoughts

View File

@ -28,6 +28,7 @@
"react-dom": "18.2.0",
"react-hook-form": "^7.43.9",
"react-icons": "^4.8.0",
"recharts": "^2.7.2",
"typescript": "5.1.6",
"zod": "^3.21.4"
},

View File

@ -0,0 +1,87 @@
'use client';
import { HTMLAttributes, useEffect, useState } from 'react';
import { Cell, Legend, Pie, PieChart, Tooltip } from 'recharts';
import { cn } from '@documenso/ui/lib/utils';
import { CAP_TABLE } from './data';
const COLORS = ['#7fd843', '#a2e771', '#c6f2a4'];
const RADIAN = Math.PI / 180;
export type LabelRenderProps = {
cx: number;
cy: number;
midAngle: number;
innerRadius: number;
outerRadius: number;
percent: number;
};
const renderCustomizedLabel = ({
cx,
cy,
midAngle,
innerRadius,
outerRadius,
percent,
}: LabelRenderProps) => {
const radius = innerRadius + (outerRadius - innerRadius) * 0.25;
const x = cx + radius * Math.cos(-midAngle * RADIAN);
const y = cy + radius * Math.sin(-midAngle * RADIAN);
return (
<text x={x} y={y} fill="white" textAnchor={x > cx ? 'start' : 'end'} dominantBaseline="central">
{`${(percent * 100).toFixed(1)}%`}
</text>
);
};
export type CapTableProps = HTMLAttributes<HTMLDivElement>;
export const CapTable = ({ className, ...props }: CapTableProps) => {
const [isSSR, setIsSSR] = useState(true);
useEffect(() => {
setIsSSR(false);
}, []);
return (
<div className={cn('flex flex-col', className)} {...props}>
<h3 className="px-4 text-lg font-semibold">Cap Table</h3>
<div className="border-border mt-2.5 flex flex-1 items-center justify-center rounded-2xl border shadow-sm hover:shadow">
{!isSSR && (
<PieChart width={400} height={400}>
<Pie
data={CAP_TABLE}
cx="50%"
cy="50%"
labelLine={false}
label={renderCustomizedLabel}
outerRadius={160}
innerRadius={80}
fill="#8884d8"
dataKey="percentage"
>
{CAP_TABLE.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Legend
formatter={(value) => {
return <span className="text-sm text-black">{value}</span>;
}}
/>
<Tooltip
formatter={(percent: number, name, props) => {
return [`${percent}%`, name || props['name'] || props['payload']['name']];
}}
/>
</PieChart>
)}
</div>
</div>
);
};

View File

@ -0,0 +1,124 @@
export const TEAM_MEMBERS = [
{
name: 'Timur Ercan',
role: 'Co-Founder, CEO',
salary: 95_000,
location: 'Germany',
engagement: 'Full-Time',
joinDate: 'November 14th, 2022',
},
{
name: 'Lucas Smith',
role: 'Co-Founder, CTO',
salary: 95_000,
location: 'Australia',
engagement: 'Full-Time',
joinDate: 'April 19th, 2023',
},
{
name: 'Ephraim Atta-Duncan',
role: 'Software Engineer - Intern',
salary: 15_000,
location: 'Ghana',
engagement: 'Part-Time',
joinDate: 'June 6th, 2023',
},
{
name: 'Florent Merian',
role: 'Marketer - III',
salary: 'Project-Based',
location: 'France',
engagement: 'Full-Time',
joinDate: 'July 10th, 2023',
},
{
name: 'Thilo Konzok',
role: 'Designer',
salary: 'Project-Based',
location: 'Germany',
engagement: 'Full-Time',
joinDate: 'April 26th, 2023',
},
{
name: 'David Nguyen',
role: 'Software Engineer - III',
salary: 100_000,
location: 'Australia',
engagement: 'Full-Time',
joinDate: 'July 26th, 2023',
},
];
export const FUNDING_RAISED = [
{
date: '2023-04',
amount: 0,
},
{
date: '2023-05',
amount: 300_000,
},
{
date: '2023-07',
amount: 1_550_000,
},
];
export const SALARY_BANDS = [
{
title: 'Software Engineer - Intern',
seniority: 'Intern',
salary: 30_000,
},
{
title: 'Software Engineer - I',
seniority: 'Junior',
salary: 60_000,
},
{
title: 'Software Engineer - II',
seniority: 'Mid',
salary: 80_000,
},
{
title: 'Software Engineer - III',
seniority: 'Senior',
salary: 100_000,
},
{
title: 'Software Engineer - IV',
seniority: 'Principal',
salary: 120_000,
},
{
title: 'Designer - III',
seniority: 'Senior',
salary: 100_000,
},
{
title: 'Designer - IV',
seniority: 'Principal',
salary: 120_000,
},
{
title: 'Marketer - I',
seniority: 'Junior',
salary: 50_000,
},
{
title: 'Marketer - II',
seniority: 'Mid',
salary: 65_000,
},
{
title: 'Marketer - III',
seniority: 'Senior',
salary: 80_000,
},
];
export const CAP_TABLE = [
{ name: 'Founders', percentage: 75.5 },
{ name: 'Investors', percentage: 14.5 },
{ name: 'Team Pool', percentage: 10 },
];

View File

@ -0,0 +1,57 @@
'use client';
import { HTMLAttributes } from 'react';
import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
import { formatMonth } from '@documenso/lib/client-only/format-month';
import { cn } from '@documenso/ui/lib/utils';
import { FUNDING_RAISED } from '~/app/(marketing)/open/data';
export type FundingRaisedProps = HTMLAttributes<HTMLDivElement>;
export const FundingRaised = ({ className, ...props }: FundingRaisedProps) => {
const formattedData = FUNDING_RAISED.map((item) => ({
amount: Number(item.amount),
date: formatMonth(item.date),
}));
return (
<div className={cn('flex flex-col', className)} {...props}>
<h3 className="px-4 text-lg font-semibold">Total Funding Raised</h3>
<div className="border-border mt-2.5 flex flex-1 flex-col items-center justify-center rounded-2xl border p-4 shadow-sm hover:shadow">
<ResponsiveContainer width="100%" height={400}>
<BarChart data={formattedData} margin={{ top: 40, right: 40, bottom: 20, left: 40 }}>
<XAxis dataKey="date" />
<YAxis
tickFormatter={(value) =>
Number(value).toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
maximumFractionDigits: 0,
})
}
/>
<Tooltip
itemStyle={{
color: 'hsl(var(--primary-foreground))',
}}
formatter={(value) => [
Number(value).toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
maximumFractionDigits: 0,
}),
'Amount Raised',
]}
cursor={{ fill: 'hsl(var(--primary) / 10%)' }}
/>
<Bar dataKey="amount" fill="hsl(var(--primary))" label="Amount Raised" />
</BarChart>
</ResponsiveContainer>
</div>
</div>
);
};

View File

@ -0,0 +1,59 @@
'use client';
import { HTMLAttributes } from 'react';
import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
import { formatMonth } from '@documenso/lib/client-only/format-month';
import { cn } from '@documenso/ui/lib/utils';
import { StargazersType } from './page';
export type MetricsDataKey = 'stars' | 'forks' | 'mergedPRs' | 'openIssues';
export type GithubMetricProps = HTMLAttributes<HTMLDivElement> & {
data: StargazersType;
metricKey: MetricsDataKey;
title: string;
label: string;
chartHeight?: number;
};
export const GithubMetric = ({
className,
data,
metricKey,
title,
label,
chartHeight = 400,
...props
}: GithubMetricProps) => {
const formattedData = Object.keys(data)
.map((key) => ({
month: formatMonth(key),
[metricKey]: data[key][metricKey],
}))
.reverse();
return (
<div className={cn('flex flex-col', className)} {...props}>
<h3 className="px-4 text-lg font-semibold">{title}</h3>
<div className="border-border mt-2.5 flex flex-1 items-center justify-center rounded-2xl border pr-2 shadow-sm hover:shadow">
<ResponsiveContainer width="100%" height={chartHeight}>
<BarChart data={formattedData} margin={{ top: 30, right: 20 }}>
<XAxis dataKey="month" />
<YAxis />
<Tooltip
itemStyle={{
color: 'hsl(var(--primary-foreground))',
}}
formatter={(value) => [Number(value), label]}
cursor={{ fill: 'hsl(var(--primary) / 10%)' }}
/>
<Bar dataKey={metricKey} fill="hsl(var(--primary))" label={label} />
</BarChart>
</ResponsiveContainer>
</div>
</div>
);
};

View File

@ -0,0 +1,18 @@
import { HTMLAttributes } from 'react';
import { cn } from '@documenso/ui/lib/utils';
export type MetricCardProps = HTMLAttributes<HTMLDivElement> & {
title: string;
value: string;
};
export const MetricCard = ({ className, title, value, ...props }: MetricCardProps) => {
return (
<div className={cn('rounded-md border p-4 shadow-sm hover:shadow', className)} {...props}>
<h4 className="text-muted-foreground text-sm font-medium">{title}</h4>
<p className="mb-2 mt-6 text-4xl font-bold">{value}</p>
</div>
);
};

View File

@ -0,0 +1,157 @@
import { z } from 'zod';
import { MetricCard } from '~/app/(marketing)/open/metric-card';
import { SalaryBands } from '~/app/(marketing)/open/salary-bands';
import { CapTable } from './cap-table';
import { FundingRaised } from './funding-raised';
import { GithubMetric } from './gh-metrics';
import { TeamMembers } from './team-members';
export const revalidate = 86400;
const ZGithubStatsResponse = z.object({
stargazers_count: z.number(),
forks_count: z.number(),
open_issues: z.number(),
});
const ZMergedPullRequestsResponse = z.object({
total_count: z.number(),
});
const ZStargazersLiveResponse = z.record(
z.object({
stars: z.number(),
forks: z.number(),
mergedPRs: z.number(),
openIssues: z.number(),
}),
);
export type StargazersType = z.infer<typeof ZStargazersLiveResponse>;
// const ZOpenPullRequestsResponse = ZMergedPullRequestsResponse;
export default async function OpenPage() {
const {
forks_count: forksCount,
open_issues: openIssues,
stargazers_count: stargazersCount,
} = await fetch('https://api.github.com/repos/documenso/documenso', {
headers: {
accept: 'application/vnd.github.v3+json',
},
})
.then((res) => res.json())
.then((res) => ZGithubStatsResponse.parse(res));
const { total_count: mergedPullRequests } = await fetch(
'https://api.github.com/search/issues?q=repo:documenso/documenso/+is:pr+merged:>=2010-01-01&page=0&per_page=1',
{
headers: {
accept: 'application/vnd.github.v3+json',
},
},
)
.then((res) => res.json())
.then((res) => ZMergedPullRequestsResponse.parse(res));
const STARGAZERS_DATA = await fetch('https://stargrazer-live.onrender.com/api/stats', {
headers: {
accept: 'application/json',
},
})
.then((res) => res.json())
.then((res) => ZStargazersLiveResponse.parse(res));
return (
<div className="mx-auto mt-12 max-w-screen-lg">
<div className="flex flex-col items-center justify-center">
<h1 className="text-3xl font-bold lg:text-5xl">Open Startup</h1>
<p className="text-muted-foreground mt-4 max-w-[60ch] text-center text-lg leading-normal">
All our metrics, finances, and learnings are public. We believe in transparency and want
to share our journey with you. You can read more about why here:{' '}
<a className="font-bold" href="https://documenso.com/blog/pre-seed" target="_blank">
Announcing Open Metrics
</a>
</p>
</div>
<div className="mt-12 grid grid-cols-12 gap-8">
<div className="col-span-12 grid grid-cols-4 gap-4">
<MetricCard
className="col-span-2 lg:col-span-1"
title="Stargazers"
value={stargazersCount.toLocaleString('en-US')}
/>
<MetricCard
className="col-span-2 lg:col-span-1"
title="Forks"
value={forksCount.toLocaleString('en-US')}
/>
<MetricCard
className="col-span-2 lg:col-span-1"
title="Open Issues"
value={openIssues.toLocaleString('en-US')}
/>
<MetricCard
className="col-span-2 lg:col-span-1"
title="Merged PR's"
value={mergedPullRequests.toLocaleString('en-US')}
/>
</div>
<TeamMembers className="col-span-12" />
<SalaryBands className="col-span-12 lg:col-span-6" />
<FundingRaised className="col-span-12 lg:col-span-6" />
<CapTable className="col-span-12 lg:col-span-6" />
<GithubMetric
data={STARGAZERS_DATA}
metricKey="stars"
title="Github: Total Stars"
label="Stars"
className="col-span-12 lg:col-span-6"
/>
<GithubMetric
data={STARGAZERS_DATA}
metricKey="mergedPRs"
title="Github: Total Merged PRs"
label="Merged PRs"
chartHeight={300}
className="col-span-12 lg:col-span-4"
/>
<GithubMetric
data={STARGAZERS_DATA}
metricKey="forks"
title="Github: Total Forks"
label="Forks"
chartHeight={300}
className="col-span-12 lg:col-span-4"
/>
<GithubMetric
data={STARGAZERS_DATA}
metricKey="openIssues"
title="Github: Total Open Issues"
label="Open Issues"
chartHeight={300}
className="col-span-12 lg:col-span-4"
/>
<div className="col-span-12 mt-12 flex flex-col items-center justify-center">
<h2 className="text-2xl font-bold">Where's the rest?</h2>
<p className="text-muted-foreground mt-4 max-w-[55ch] text-center text-lg leading-normal">
We're still working on getting all our metrics together. We'll update this page as soon
as we have more to share.
</p>
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,50 @@
import { HTMLAttributes } from 'react';
import { cn } from '@documenso/ui/lib/utils';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@documenso/ui/primitives/table';
import { SALARY_BANDS } from '~/app/(marketing)/open/data';
export type SalaryBandsProps = HTMLAttributes<HTMLDivElement>;
export const SalaryBands = ({ className, ...props }: SalaryBandsProps) => {
return (
<div className={cn('flex flex-col', className)} {...props}>
<h3 className="px-4 text-lg font-semibold">Global Salary Bands</h3>
<div className="border-border mt-2.5 flex-1 rounded-2xl border shadow-sm hover:shadow">
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-[200px]">Title</TableHead>
<TableHead>Seniority</TableHead>
<TableHead className="w-[100px] text-right">Salary</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{SALARY_BANDS.map((band, index) => (
<TableRow key={index}>
<TableCell className="font-medium">{band.title}</TableCell>
<TableCell>{band.seniority}</TableCell>
<TableCell className="text-right">
{band.salary.toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
maximumFractionDigits: 0,
})}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
);
};

View File

@ -0,0 +1,57 @@
import { HTMLAttributes } from 'react';
import { cn } from '@documenso/ui/lib/utils';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@documenso/ui/primitives/table';
import { TEAM_MEMBERS } from './data';
export type TeamMembersProps = HTMLAttributes<HTMLDivElement>;
export const TeamMembers = ({ className, ...props }: TeamMembersProps) => {
return (
<div className={cn('flex flex-col', className)} {...props}>
<h2 className="px-4 text-2xl font-semibold">Team</h2>
<div className="border-border mt-2.5 flex-1 rounded-2xl border shadow-sm hover:shadow">
<Table>
<TableHeader>
<TableRow>
<TableHead className="">Name</TableHead>
<TableHead>Role</TableHead>
<TableHead>Salary</TableHead>
<TableHead>Engagement</TableHead>
<TableHead>Location</TableHead>
<TableHead className="w-[100px] text-right">Join Date</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{TEAM_MEMBERS.map((member) => (
<TableRow key={member.name}>
<TableCell className="font-medium">{member.name}</TableCell>
<TableCell>{member.role}</TableCell>
<TableCell>
{member.salary.toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
maximumFractionDigits: 0,
})}
</TableCell>
<TableCell>{member.engagement}</TableCell>
<TableCell>{member.location}</TableCell>
<TableCell className="text-right">{member.joinDate}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
);
};

View File

@ -9,6 +9,8 @@ import { Hero } from '~/components/(marketing)/hero';
import { OpenBuildTemplateBento } from '~/components/(marketing)/open-build-template-bento';
import { ShareConnectPaidWidgetBento } from '~/components/(marketing)/share-connect-paid-widget-bento';
export const revalidate = 600;
const fontCaveat = Caveat({
weight: ['500'],
subsets: ['latin'],
@ -17,15 +19,24 @@ const fontCaveat = Caveat({
});
export default async function IndexPage() {
const starCount = await fetch('https://api.github.com/repos/documenso/documenso', {
headers: {
accept: 'application/vnd.github.v3+json',
},
})
.then((res) => res.json())
.then((res) => (typeof res.stargazers_count === 'number' ? res.stargazers_count : undefined))
.catch(() => undefined);
return (
<div className={cn('mt-12', fontCaveat.variable)}>
<Hero />
<Hero starCount={starCount} />
<FasterSmarterBeautifulBento className="my-48" />
<ShareConnectPaidWidgetBento className="my-48" />
<OpenBuildTemplateBento className="my-48" />
<Callout />
<Callout starCount={starCount} />
</div>
);
}

View File

@ -7,7 +7,12 @@ import { usePlausible } from 'next-plausible';
import { Button } from '@documenso/ui/primitives/button';
export const Callout = () => {
export type CalloutProps = {
starCount?: number;
[key: string]: unknown;
};
export const Callout = ({ starCount }: CalloutProps) => {
const event = usePlausible();
const onSignUpClick = () => {
@ -36,7 +41,7 @@ export const Callout = () => {
onClick={onSignUpClick}
>
Get the Community Plan
<span className="bg-primary -mr-2 ml-2.5 rounded-full px-2 py-1.5 text-xs">
<span className="bg-primary -mr-2.5 ml-2.5 rounded-full px-2 py-1.5 text-xs">
$30/mo. forever!
</span>
</Button>
@ -49,6 +54,11 @@ export const Callout = () => {
<Button variant="outline" className="rounded-full bg-transparent backdrop-blur-sm">
<Github className="mr-2 h-5 w-5" />
Star on Github
{starCount && starCount > 0 && (
<span className="bg-primary -mr-2.5 ml-2.5 rounded-full px-2 py-1.5 text-xs">
{starCount.toLocaleString('en-US')}
</span>
)}
</Button>
</Link>
</div>

View File

@ -46,10 +46,6 @@ export const Footer = ({ className, ...props }: FooterProps) => {
</div>
<div className="flex flex-wrap items-center gap-x-4 gap-y-2.5">
<Link href="/blog" className="flex-shrink-0 text-sm text-[#8D8D8D] hover:text-[#6D6D6D]">
Blog
</Link>
<Link
href="/pricing"
className="flex-shrink-0 text-sm text-[#8D8D8D] hover:text-[#6D6D6D]"
@ -57,6 +53,14 @@ export const Footer = ({ className, ...props }: FooterProps) => {
Pricing
</Link>
<Link href="/blog" className="flex-shrink-0 text-sm text-[#8D8D8D] hover:text-[#6D6D6D]">
Blog
</Link>
<Link href="/open" className="flex-shrink-0 text-sm text-[#8D8D8D] hover:text-[#6D6D6D]">
Open
</Link>
<Link
href="https://status.documenso.com"
target="_blank"

View File

@ -26,12 +26,16 @@ export const Header = ({ className, ...props }: HeaderProps) => {
</Link>
<div className="hidden items-center gap-x-6 md:flex">
<Link href="/pricing" className="text-sm font-semibold text-[#8D8D8D] hover:text-[#6D6D6D]">
Pricing
</Link>
<Link href="/blog" className="text-sm font-semibold text-[#8D8D8D] hover:text-[#6D6D6D]">
Blog
</Link>
<Link href="/pricing" className="text-sm font-semibold text-[#8D8D8D] hover:text-[#6D6D6D]">
Pricing
<Link href="/open" className="text-sm font-semibold text-[#8D8D8D] hover:text-[#6D6D6D]">
Open
</Link>
<Link