Skip to content

Commit 9ef28de

Browse files
kgowruKapil GowruKapil GowruKapil GowruKapil Gowru
authored
Feat/homepage v4 (#28)
Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]> Co-authored-by: Kapil Gowru <[email protected]>
1 parent fbdee72 commit 9ef28de

File tree

252 files changed

+1040
-718
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

252 files changed

+1040
-718
lines changed

fern/assets/changelogs/.DS_Store

0 Bytes
Binary file not shown.

fern/assets/styles.css

Lines changed: 192 additions & 132 deletions
Large diffs are not rendered by default.

fern/components/FernStatus.tsx

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
import React, { useState, useEffect } from 'react';
2+
3+
interface StatusData {
4+
ongoing_incidents?: Array<{
5+
current_worst_impact: string;
6+
}>;
7+
in_progress_maintenances?: Array<any>;
8+
scheduled_maintenances?: Array<{
9+
starts_at: string;
10+
}>;
11+
}
12+
13+
interface StatusState {
14+
dotClass: string;
15+
statusMessage: string;
16+
}
17+
18+
export const FernStatusWidget = () => {
19+
const [status, setStatus] = React.useState<StatusState>({
20+
dotClass: 'is-loading',
21+
statusMessage: 'Checking status...'
22+
});
23+
24+
const apiEndpoint = 'https://status.buildwithfern.com/api/v1/summary';
25+
const refreshInterval = 5 * 60 * 1000; // 5 minutes
26+
27+
const updateStatus = (data: StatusData) => {
28+
let dotClass = 'is-green';
29+
let statusMessage = 'All systems operational';
30+
31+
// Check for ongoing incidents
32+
if (data.ongoing_incidents && data.ongoing_incidents.length > 0) {
33+
let worstImpact = 0;
34+
for (const incident of data.ongoing_incidents) {
35+
let impactLevel = 0;
36+
37+
if (incident.current_worst_impact === 'degraded_performance') {
38+
impactLevel = 1;
39+
} else if (incident.current_worst_impact === 'partial_outage') {
40+
impactLevel = 2;
41+
} else if (incident.current_worst_impact === 'full_outage') {
42+
impactLevel = 3;
43+
}
44+
45+
if (impactLevel > worstImpact) {
46+
worstImpact = impactLevel;
47+
}
48+
}
49+
50+
// Set status based on severity
51+
if (worstImpact === 3) {
52+
dotClass = 'is-red';
53+
statusMessage = 'Service outage';
54+
} else if (worstImpact === 2) {
55+
dotClass = 'is-orange';
56+
statusMessage = 'Partial outage';
57+
} else if (worstImpact === 1) {
58+
dotClass = 'is-yellow';
59+
statusMessage = 'Degraded performance';
60+
}
61+
}
62+
63+
// Check for in-progress maintenance
64+
if (data.in_progress_maintenances && data.in_progress_maintenances.length > 0) {
65+
if (dotClass === 'is-green') {
66+
dotClass = 'is-blue';
67+
statusMessage = 'Maintenance in progress';
68+
}
69+
}
70+
71+
// Check for scheduled maintenance
72+
if (data.scheduled_maintenances && data.scheduled_maintenances.length > 0) {
73+
if (dotClass === 'is-green') {
74+
const now = new Date();
75+
let soonMaintenance = false;
76+
77+
for (const maintenance of data.scheduled_maintenances) {
78+
const startsAt = new Date(maintenance.starts_at);
79+
const hoursDiff = (startsAt.getTime() - now.getTime()) / (1000 * 60 * 60);
80+
81+
if (hoursDiff <= 24) {
82+
soonMaintenance = true;
83+
break;
84+
}
85+
}
86+
87+
if (soonMaintenance) {
88+
dotClass = 'is-blue';
89+
statusMessage = 'Scheduled maintenance soon';
90+
}
91+
}
92+
}
93+
94+
setStatus({ dotClass, statusMessage });
95+
};
96+
97+
const fetchStatus = async () => {
98+
try {
99+
const response = await fetch(apiEndpoint);
100+
if (response.ok) {
101+
const data: StatusData = await response.json();
102+
updateStatus(data);
103+
} else {
104+
setStatus({ dotClass: 'is-red', statusMessage: 'Cannot check status' });
105+
}
106+
} catch (error) {
107+
console.error('Error fetching status:', error);
108+
setStatus({ dotClass: 'is-red', statusMessage: 'Cannot check status' });
109+
}
110+
};
111+
112+
React.useEffect(() => {
113+
fetchStatus();
114+
const interval = setInterval(fetchStatus, refreshInterval);
115+
return () => clearInterval(interval);
116+
}, []);
117+
118+
const getBackgroundColor = () => {
119+
switch (status.dotClass) {
120+
case 'is-green': return '#00c853';
121+
case 'is-red': return '#f44336';
122+
case 'is-orange': return '#ff9800';
123+
case 'is-blue': return '#2196f3';
124+
case 'is-yellow': return '#ffc107';
125+
case 'is-loading': return '#cccccc';
126+
default: return '#cccccc';
127+
}
128+
};
129+
130+
return (
131+
<a
132+
href="https://status.buildwithfern.com"
133+
target="_blank"
134+
rel="noopener noreferrer"
135+
style={{ textDecoration: 'none', color: 'inherit' }}
136+
>
137+
<div id="fern-status-widget" className="fern-status-widget">
138+
<div
139+
className={`footer_badge-dot ${status.dotClass}`}
140+
style={{
141+
width: '10px',
142+
height: '10px',
143+
borderRadius: '50%',
144+
marginRight: '8px',
145+
position: 'relative',
146+
display: 'inline-block',
147+
backgroundColor: getBackgroundColor(),
148+
}}
149+
/>
150+
<span id="fern-status-text" className="fern-status-text">{status.statusMessage}</span>
151+
152+
<style jsx>{`
153+
.fern-status-widget {
154+
display: flex;
155+
align-items: center;
156+
gap: 0.5rem;
157+
border-radius: 9999px;
158+
padding: 0.25rem 0.75rem;
159+
align-self: flex-start;
160+
cursor: pointer;
161+
text-decoration: none;
162+
transition: background-color 150ms ease, color 150ms ease;
163+
}
164+
165+
.fern-status-widget svg {
166+
display: none !important;
167+
}
168+
169+
.fern-status-widget:hover {
170+
background-color: var(--grayscale-a4);
171+
}
172+
173+
.fern-status-widget:hover .fern-status-text {
174+
color: var(--grayscale-12);
175+
}
176+
177+
.fern-status-text {
178+
font-size: 0.875rem;
179+
color: var(--grayscale-10);
180+
font-weight: 400;
181+
}
182+
183+
.footer_badge-dot::after {
184+
content: '';
185+
position: absolute;
186+
top: -4px;
187+
left: -4px;
188+
right: -4px;
189+
bottom: -4px;
190+
border-radius: 50%;
191+
background: radial-gradient(circle, transparent 0%, currentColor 70%, currentColor 100%);
192+
opacity: 0.4;
193+
animation: pulse-expand 2s infinite ease-out;
194+
}
195+
196+
.footer_badge-dot.is-green::after { color: #00c853; }
197+
.footer_badge-dot.is-red::after { color: #f44336; }
198+
.footer_badge-dot.is-orange::after { color: #ff9800; }
199+
.footer_badge-dot.is-blue::after { color: #2196f3; }
200+
.footer_badge-dot.is-yellow::after { color: #ffc107; }
201+
.footer_badge-dot.is-loading::after { color: #cccccc; }
202+
203+
@keyframes pulse-expand {
204+
0% { transform: scale(0.6); opacity: 0.5; }
205+
100% { transform: scale(1.5); opacity: 0; }
206+
}
207+
`}</style>
208+
</div>
209+
</a>
210+
);
211+
};

fern/docs.yml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,28 @@ products:
77
- display-name: Home
88
path: ./products/home/home.yml
99
# icon: fa-regular fa-home
10-
image: ./images/product-switcher/home.svg
10+
image: ./images/product-switcher/product-switcher-home-light.png
1111
slug: home
12-
subtitle: Products that delight your developers
12+
subtitle: Products that elevate your developer experience
1313

1414
- display-name: SDKs
1515
path: ./products/sdks/sdks.yml
1616
icon: fa-brands fa-codepen
17-
image: ./images/product-switcher/sdks.png
17+
image: ./images/product-switcher/product-switcher-sdks-light.png
1818
slug: sdks
1919
subtitle: Generate client libraries in multiple languages
2020

2121
- display-name: Docs
2222
path: ./products/docs/docs.yml
2323
icon: fa-regular fa-browser
24-
image: ./images/product-switcher/docs.png
24+
image: ./images/product-switcher/product-switcher-docs-light.png
2525
slug: docs
2626
subtitle: Generate beautiful, interactive documentation websites
2727

2828
- display-name: Ask Fern
2929
path: ./products/ask-fern/ask-fern.yml
3030
icon: fa-regular fa-magnifying-glass
31-
image: ./images/product-switcher/ask-fern.png
31+
image: ./images/product-switcher/product-switcher-askfern-light.png
3232
slug: ask-fern
3333
subtitle: Let users find answers in your documentation instantly
3434

@@ -119,3 +119,7 @@ layout:
119119
header-height: 75px
120120
searchbar-placement: header
121121
tabs-placement: header
122+
123+
experimental:
124+
mdx-components:
125+
- ./components

fern/images/.DS_Store

2 KB
Binary file not shown.
8.19 KB
Loading
8.19 KB
Loading
6.79 KB
Loading
9.73 KB
Loading
8.15 KB
Loading

0 commit comments

Comments
 (0)