Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
437223e
feat: adding homepage designs
Jul 1, 2025
6f60f17
feat: adding homepage designs
Jul 1, 2025
e90c46e
feat: adding homepage designs
Jul 1, 2025
c400924
feat: adding homepage designs
Jul 1, 2025
9a4d633
feat: adding homepage designs
Jul 1, 2025
b5595db
feat: adding homepage designs
Jul 1, 2025
b9dacef
feat: adding homepage designs
Jul 1, 2025
a66ea01
feat: adding homepage designs
Jul 1, 2025
e54661d
feat: adding homepage designs
Jul 1, 2025
6ba1c36
feat: adding homepage designs
Jul 1, 2025
6d8c1f8
feat: adding homepage designs
Jul 1, 2025
22d29d9
feat: adding homepage designs
Jul 2, 2025
0ee72e5
feat: adding homepage designs
Jul 2, 2025
20202a5
feat: adding homepage designs
Jul 2, 2025
d5f41ba
feat: adding homepage designs
Jul 2, 2025
100cab7
Merge remote-tracking branch 'origin/main' into feat/homepage-v2
Jul 2, 2025
885fd5a
Merge remote-tracking branch 'origin/main' into feat/homepage-v2
Jul 2, 2025
4e53134
feat: added footer image
Jul 2, 2025
c6807c2
feat: added footer image
Jul 2, 2025
3b7179a
feat: added footer image
Jul 3, 2025
4da1801
feat: added footer image
Jul 3, 2025
a525373
feat: added footer image
Jul 3, 2025
796dbbc
feat: added footer image
Jul 3, 2025
4d30f74
feat: added footer image
Jul 3, 2025
6b30db9
feat: added footer image
Jul 3, 2025
df8c15f
feat: added footer image
Jul 3, 2025
4d77097
feat: added footer image
Jul 3, 2025
c015410
feat: added footer image
Jul 3, 2025
6616c1b
feat: added footer image
Jul 7, 2025
d82979a
feat: added mobile styling
Jul 7, 2025
57f312a
feat: added mobile styling
Jul 7, 2025
352d001
Merge remote-tracking branch 'origin/main' into feat/homepage-v3
Jul 7, 2025
e12e22b
feat: updated some frame styling
Jul 7, 2025
bc5fd66
feat: cleaned up home page styling and added empty page callouts
Jul 7, 2025
c1df663
feat: cleaned up home page styling and added empty page callouts
Jul 7, 2025
ad866b2
feat: cleaned up home page styling and added empty page callouts
Jul 8, 2025
f425345
feat: cleaned up product selector icons
Jul 8, 2025
9eac7ae
feat: adding a custom component for the footer
Jul 8, 2025
0c12bef
feat: fixed mobile product swticher
Jul 8, 2025
b04d971
feat: added react status badge
Jul 8, 2025
cb9a3d3
feat: updated product switcher
Jul 8, 2025
92c0608
feat: updated product switcher
Jul 8, 2025
7db2a8c
feat: added empty sdk pages
Jul 8, 2025
462cb0b
feat: merged with main
Jul 9, 2025
47b772d
feat: merged with mainOA
Jul 9, 2025
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
Binary file modified fern/assets/changelogs/.DS_Store
Binary file not shown.
324 changes: 192 additions & 132 deletions fern/assets/styles.css

Large diffs are not rendered by default.

211 changes: 211 additions & 0 deletions fern/components/FernStatus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import React, { useState, useEffect } from 'react';

interface StatusData {
ongoing_incidents?: Array<{
current_worst_impact: string;
}>;
in_progress_maintenances?: Array<any>;
scheduled_maintenances?: Array<{
starts_at: string;
}>;
}

interface StatusState {
dotClass: string;
statusMessage: string;
}

export const FernStatusWidget = () => {
const [status, setStatus] = React.useState<StatusState>({
dotClass: 'is-loading',
statusMessage: 'Checking status...'
});

const apiEndpoint = 'https://status.buildwithfern.com/api/v1/summary';
const refreshInterval = 5 * 60 * 1000; // 5 minutes

const updateStatus = (data: StatusData) => {
let dotClass = 'is-green';
let statusMessage = 'All systems operational';

// Check for ongoing incidents
if (data.ongoing_incidents && data.ongoing_incidents.length > 0) {
let worstImpact = 0;
for (const incident of data.ongoing_incidents) {
let impactLevel = 0;

if (incident.current_worst_impact === 'degraded_performance') {
impactLevel = 1;
} else if (incident.current_worst_impact === 'partial_outage') {
impactLevel = 2;
} else if (incident.current_worst_impact === 'full_outage') {
impactLevel = 3;
}

if (impactLevel > worstImpact) {
worstImpact = impactLevel;
}
}

// Set status based on severity
if (worstImpact === 3) {
dotClass = 'is-red';
statusMessage = 'Service outage';
} else if (worstImpact === 2) {
dotClass = 'is-orange';
statusMessage = 'Partial outage';
} else if (worstImpact === 1) {
dotClass = 'is-yellow';
statusMessage = 'Degraded performance';
}
}

// Check for in-progress maintenance
if (data.in_progress_maintenances && data.in_progress_maintenances.length > 0) {
if (dotClass === 'is-green') {
dotClass = 'is-blue';
statusMessage = 'Maintenance in progress';
}
}

// Check for scheduled maintenance
if (data.scheduled_maintenances && data.scheduled_maintenances.length > 0) {
if (dotClass === 'is-green') {
const now = new Date();
let soonMaintenance = false;

for (const maintenance of data.scheduled_maintenances) {
const startsAt = new Date(maintenance.starts_at);
const hoursDiff = (startsAt.getTime() - now.getTime()) / (1000 * 60 * 60);

if (hoursDiff <= 24) {
soonMaintenance = true;
break;
}
}

if (soonMaintenance) {
dotClass = 'is-blue';
statusMessage = 'Scheduled maintenance soon';
}
}
}

setStatus({ dotClass, statusMessage });
};

const fetchStatus = async () => {
try {
const response = await fetch(apiEndpoint);
if (response.ok) {
const data: StatusData = await response.json();
updateStatus(data);
} else {
setStatus({ dotClass: 'is-red', statusMessage: 'Cannot check status' });
}
} catch (error) {
console.error('Error fetching status:', error);
setStatus({ dotClass: 'is-red', statusMessage: 'Cannot check status' });
}
};

React.useEffect(() => {
fetchStatus();
const interval = setInterval(fetchStatus, refreshInterval);
return () => clearInterval(interval);
}, []);

const getBackgroundColor = () => {
switch (status.dotClass) {
case 'is-green': return '#00c853';
case 'is-red': return '#f44336';
case 'is-orange': return '#ff9800';
case 'is-blue': return '#2196f3';
case 'is-yellow': return '#ffc107';
case 'is-loading': return '#cccccc';
default: return '#cccccc';
}
};

return (
<a
href="https://status.buildwithfern.com"
target="_blank"
rel="noopener noreferrer"
style={{ textDecoration: 'none', color: 'inherit' }}
>
<div id="fern-status-widget" className="fern-status-widget">
<div
className={`footer_badge-dot ${status.dotClass}`}
style={{
width: '10px',
height: '10px',
borderRadius: '50%',
marginRight: '8px',
position: 'relative',
display: 'inline-block',
backgroundColor: getBackgroundColor(),
}}
/>
<span id="fern-status-text" className="fern-status-text">{status.statusMessage}</span>

<style jsx>{`
.fern-status-widget {
display: flex;
align-items: center;
gap: 0.5rem;
border-radius: 9999px;
padding: 0.25rem 0.75rem;
align-self: flex-start;
cursor: pointer;
text-decoration: none;
transition: background-color 150ms ease, color 150ms ease;
}

.fern-status-widget svg {
display: none !important;
}

.fern-status-widget:hover {
background-color: var(--grayscale-a4);
}

.fern-status-widget:hover .fern-status-text {
color: var(--grayscale-12);
}

.fern-status-text {
font-size: 0.875rem;
color: var(--grayscale-10);
font-weight: 400;
}

.footer_badge-dot::after {
content: '';
position: absolute;
top: -4px;
left: -4px;
right: -4px;
bottom: -4px;
border-radius: 50%;
background: radial-gradient(circle, transparent 0%, currentColor 70%, currentColor 100%);
opacity: 0.4;
animation: pulse-expand 2s infinite ease-out;
}

.footer_badge-dot.is-green::after { color: #00c853; }
.footer_badge-dot.is-red::after { color: #f44336; }
.footer_badge-dot.is-orange::after { color: #ff9800; }
.footer_badge-dot.is-blue::after { color: #2196f3; }
.footer_badge-dot.is-yellow::after { color: #ffc107; }
.footer_badge-dot.is-loading::after { color: #cccccc; }

@keyframes pulse-expand {
0% { transform: scale(0.6); opacity: 0.5; }
100% { transform: scale(1.5); opacity: 0; }
}
`}</style>
</div>
</a>
);
};
14 changes: 9 additions & 5 deletions fern/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,28 @@ products:
- display-name: Home
path: ./products/home/home.yml
# icon: fa-regular fa-home
image: ./images/product-switcher/home.svg
image: ./images/product-switcher/product-switcher-home-light.png
slug: home
subtitle: Products that delight your developers
subtitle: Products that elevate your developer experience

- display-name: SDKs
path: ./products/sdks/sdks.yml
icon: fa-brands fa-codepen
image: ./images/product-switcher/sdks.png
image: ./images/product-switcher/product-switcher-sdks-light.png
slug: sdks
subtitle: Generate client libraries in multiple languages

- display-name: Docs
path: ./products/docs/docs.yml
icon: fa-regular fa-browser
image: ./images/product-switcher/docs.png
image: ./images/product-switcher/product-switcher-docs-light.png
slug: docs
subtitle: Generate beautiful, interactive documentation websites

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

Expand Down Expand Up @@ -119,3 +119,7 @@ layout:
header-height: 75px
searchbar-placement: header
tabs-placement: header

experimental:
mdx-components:
- ./components
Binary file modified fern/images/.DS_Store
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
title: Customer Showcase
---

# Customer Showcase
Examples and case studies of customers using AsyncAPI definitions successfully.

See how other customers are using OpenAPI definitions to power their APIs and documentation.
<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
title: Get to OpenAPI
---

# Get to OpenAPI
How to transition from AsyncAPI to OpenAPI or integrate both specifications.

Learn how to create or obtain your OpenAPI definition. Explore different approaches including handwriting, generating from code, and more.
<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ title: FastAPI

# Generate OpenAPI from FastAPI

Instructions for generating an OpenAPI definition from a FastAPI project.
Instructions for generating an OpenAPI definition from a FastAPI project.

<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ title: NestJS

# Generate OpenAPI from NestJS

Instructions for generating an OpenAPI definition from a NestJS project.
Instructions for generating an OpenAPI definition from a NestJS project.

<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
---
title: Request a new framework
title: Request New Framework
---

# Request a New Framework

Don't see your framework? Let us know which framework you'd like to see supported for OpenAPI generation.
Don't see your framework? Let us know which framework you'd like to see supported for OpenAPI generation.

<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ title: Swaggo

# Generate OpenAPI from Swaggo

Instructions for generating an OpenAPI definition from a Swaggo (Go) project.
Instructions for generating an OpenAPI definition from a Swaggo (Go) project.

<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
---
title: Handwrite it
title: Handwrite It
---

# Handwrite Your OpenAPI Definition

Step-by-step guide to manually writing your OpenAPI definition from scratch.
Step-by-step guide to manually writing your OpenAPI definition from scratch.

<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Overlay customizations
title: Overlay Customizations
---

# Overlay Customizations
Learn how to customize your OpenAPI overlays to fit your unique requirements.

Learn how to customize your OpenAPI overlays to fit your unique requirements.
<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
4 changes: 2 additions & 2 deletions fern/products/asyncapi-def/pages/getting-started/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
title: Overview
---

# Overview
This is the overview page for Getting Started with your OpenAPI definition. Here you will find a high-level introduction and guidance on how to begin.

This is the overview page for Getting Started with your OpenAPI definition. Here you will find a high-level introduction and guidance on how to begin.
<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
title: Philosophy
---

# Philosophy
The philosophy and principles behind AsyncAPI definitions and how they enhance API development.

Understand the philosophy behind designing and maintaining your OpenAPI definitions. Learn best practices and guiding principles.
<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
6 changes: 3 additions & 3 deletions fern/products/asyncapi-def/pages/schemas/allof.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: AllOf
title: All Of
---

# AllOf
How to use the `allOf` keyword to compose schemas in OpenAPI.

How to use the `allOf` keyword to compose schemas in OpenAPI.
<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
6 changes: 3 additions & 3 deletions fern/products/asyncapi-def/pages/schemas/anyof.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: AnyOf
title: Any Of
---

# AnyOf
How to use the `anyOf` keyword to allow multiple possible schemas in OpenAPI.

How to use the `anyOf` keyword to allow multiple possible schemas in OpenAPI.
<Warning>This page is a WIP, please refer to our previous [documentation](https://buildwithfern.com/learn).</Warning>
Loading