diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index e10b962..5abb25b 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -12,7 +12,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- project: [docs-starter, graphql, grpc, i18n, multi-source/homepage, multi-source/seeds, multi-source/seeds-sunflower, multi-source/seeds-tomato, multi-source/greenhouses, multi-source/nursery, versioning]
+ project: [docs-starter, graphql, grpc, i18n, multi-source/homepage, multi-source/seeds, multi-source/seeds-sunflower, multi-source/seeds-tomato, multi-source/greenhouses, multi-source/nursery, sse, versioning]
steps:
- name: Checkout repository
uses: actions/checkout@v4
diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml
index 170bd75..eae4b03 100644
--- a/.github/workflows/preview-docs.yml
+++ b/.github/workflows/preview-docs.yml
@@ -31,7 +31,7 @@ jobs:
FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
- PROJECTS="docs-starter graphql grpc i18n multi-source/homepage multi-source/seeds multi-source/seeds-sunflower multi-source/seeds-tomato multi-source/greenhouses multi-source/nursery versioning"
+ PROJECTS="docs-starter graphql grpc i18n multi-source/homepage multi-source/seeds multi-source/seeds-sunflower multi-source/seeds-tomato multi-source/greenhouses multi-source/nursery sse versioning"
CHANGED_FILES=$(git diff --name-only origin/main...HEAD)
: > comment.md
diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml
index 0880c5d..b18b9f6 100644
--- a/.github/workflows/publish-docs.yml
+++ b/.github/workflows/publish-docs.yml
@@ -12,7 +12,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- project: [docs-starter, graphql, grpc, i18n, multi-source/homepage, multi-source/seeds, multi-source/seeds-sunflower, multi-source/seeds-tomato, multi-source/greenhouses, multi-source/nursery, versioning]
+ project: [docs-starter, graphql, grpc, i18n, multi-source/homepage, multi-source/seeds, multi-source/seeds-sunflower, multi-source/seeds-tomato, multi-source/greenhouses, multi-source/nursery, sse, versioning]
steps:
- name: Checkout repository
uses: actions/checkout@v4
diff --git a/README.md b/README.md
index c874970..0b6e495 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@ Example Fern docs projects. Each top-level folder is a self-contained example wi
| [`grpc`](./grpc) | gRPC API Reference from `.proto` files | [grpc.docs.buildwithfern.com](https://grpc.docs.buildwithfern.com) |
| [`i18n`](./i18n) | Multi-language docs with English + Japanese translations | [i18n.docs.buildwithfern.com](https://i18n.docs.buildwithfern.com) |
| [`multi-source`](./multi-source) | Multi-source docs — six independent projects publishing to one domain with global theme, nested sub-paths, and shared branding | [multi-source.docs.buildwithfern.com](https://multi-source.docs.buildwithfern.com) |
+| [`sse`](./sse) | SSE streaming API Reference with `x-fern-streaming` | [sse.docs.buildwithfern.com](https://sse.docs.buildwithfern.com) |
| [`versioning`](./docs-versioned) | Versioned site with a version dropdown and a shared page | [versioning.docs.buildwithfern.com](https://versioning.docs.buildwithfern.com) |
## Use an example
diff --git a/sse/fern/docs.yml b/sse/fern/docs.yml
new file mode 100644
index 0000000..4705c06
--- /dev/null
+++ b/sse/fern/docs.yml
@@ -0,0 +1,69 @@
+# yaml-language-server: $schema=https://schema.buildwithfern.dev/docs-yml.json
+
+instances:
+ - url: sse.docs.buildwithfern.com
+
+title: SSE Docs Example
+
+layout:
+ searchbar-placement: header
+ page-width: full
+ tabs-placement: header
+
+tabs:
+ home:
+ display-name: Docs
+ icon: home
+ API Reference:
+ display-name: API Reference
+ icon: puzzle
+
+navigation:
+ - tab: home
+ layout:
+ - section: Get started
+ contents:
+ - page: Welcome
+ path: docs/pages/welcome.mdx
+ icon: fa-duotone fa-house
+ - tab: API Reference
+ layout:
+ - section: Overview
+ contents:
+ - page: API reference
+ path: docs/pages/api-reference-overview.mdx
+ icon: fa-duotone fa-book
+ - api: Plant Store Streaming API
+ flattened: true
+
+navbar-links:
+ - type: minimal
+ text: Fork this repo
+ url: https://github.com/fern-api/docs-examples
+ - type: filled
+ text: Dashboard
+ url: https://dashboard.buildwithfern.com
+ - type: github
+ value: https://github.com/fern-api/fern
+
+colors:
+ accent-primary:
+ dark: "#70E155"
+ light: "#008700"
+ background:
+ dark: "#111113"
+ light: "#FFFFFF"
+
+theme:
+ page-actions: toolbar
+ footer-nav: minimal
+
+logo:
+ dark: docs/assets/logo-dark.svg
+ light: docs/assets/logo.svg
+ height: 20
+ href: https://buildwithfern.com
+
+favicon: docs/assets/favicon.svg
+
+css: styles.css
diff --git a/sse/fern/docs/assets/favicon.svg b/sse/fern/docs/assets/favicon.svg
new file mode 100644
index 0000000..568bb7e
--- /dev/null
+++ b/sse/fern/docs/assets/favicon.svg
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/sse/fern/docs/assets/fern-logo-primary.svg b/sse/fern/docs/assets/fern-logo-primary.svg
new file mode 100644
index 0000000..a21927d
--- /dev/null
+++ b/sse/fern/docs/assets/fern-logo-primary.svg
@@ -0,0 +1,4 @@
+
diff --git a/sse/fern/docs/assets/fern-logo-white.svg b/sse/fern/docs/assets/fern-logo-white.svg
new file mode 100644
index 0000000..9dd77b1
--- /dev/null
+++ b/sse/fern/docs/assets/fern-logo-white.svg
@@ -0,0 +1,4 @@
+
diff --git a/sse/fern/docs/assets/logo-dark.svg b/sse/fern/docs/assets/logo-dark.svg
new file mode 100644
index 0000000..144e0e3
--- /dev/null
+++ b/sse/fern/docs/assets/logo-dark.svg
@@ -0,0 +1,9 @@
+
diff --git a/sse/fern/docs/assets/logo-light.svg b/sse/fern/docs/assets/logo-light.svg
new file mode 100644
index 0000000..7cf2ee2
--- /dev/null
+++ b/sse/fern/docs/assets/logo-light.svg
@@ -0,0 +1,14 @@
+
diff --git a/sse/fern/docs/assets/logo.svg b/sse/fern/docs/assets/logo.svg
new file mode 100644
index 0000000..2d280fe
--- /dev/null
+++ b/sse/fern/docs/assets/logo.svg
@@ -0,0 +1,11 @@
+
diff --git a/sse/fern/docs/pages/api-reference-overview.mdx b/sse/fern/docs/pages/api-reference-overview.mdx
new file mode 100644
index 0000000..f890dd4
--- /dev/null
+++ b/sse/fern/docs/pages/api-reference-overview.mdx
@@ -0,0 +1,25 @@
+---
+title: API reference
+subtitle: Interactive documentation generated from an OpenAPI spec with SSE streaming
+slug: api-reference
+---
+
+Fern generates interactive API Reference documentation from your OpenAPI spec, including endpoints that use server-sent events (SSE). This example uses a sample Plant Store Streaming API to demonstrate the feature.
+
+The generated reference includes standard REST endpoints alongside SSE streaming endpoints, with the `x-fern-streaming` extension controlling how streaming is represented.
+
+## Plant Store Streaming API
+
+Browse the API endpoints in the sidebar, or jump to a section:
+
+
+
+ CRUD operations for managing plants
+
+
+ Place and retrieve plant orders
+
+
+ Real-time SSE streaming endpoints
+
+
diff --git a/sse/fern/docs/pages/welcome.mdx b/sse/fern/docs/pages/welcome.mdx
new file mode 100644
index 0000000..c05f124
--- /dev/null
+++ b/sse/fern/docs/pages/welcome.mdx
@@ -0,0 +1,26 @@
+---
+title: SSE docs example
+subtitle: Generate API Reference documentation with server-sent events streaming
+slug: welcome
+---
+
+This example shows how [Fern](https://buildwithfern.com) generates interactive API Reference documentation for APIs that use server-sent events (SSE). It uses a sample Plant Store Streaming API with real-time sensor monitoring, order tracking, and a chat assistant with a `stream` parameter.
+
+Navigate to the [API Reference](/api-reference) tab to see the generated documentation.
+
+## What's included
+
+
+
+
+
+
+
+
+
+
+
+
+## Learn more
+
+For configuration details, see the [SSE streaming documentation](https://buildwithfern.com/learn/api-definition/openapi/endpoints/sse).
diff --git a/sse/fern/fern.config.json b/sse/fern/fern.config.json
new file mode 100644
index 0000000..9f41ff5
--- /dev/null
+++ b/sse/fern/fern.config.json
@@ -0,0 +1,4 @@
+{
+ "organization": "fern-docs-examples",
+ "version": "5.35.0"
+}
diff --git a/sse/fern/generators.yml b/sse/fern/generators.yml
new file mode 100644
index 0000000..ee07da7
--- /dev/null
+++ b/sse/fern/generators.yml
@@ -0,0 +1,4 @@
+# yaml-language-server: $schema=https://schema.buildwithfern.dev/generators-yml.json
+api:
+ specs:
+ - openapi: openapi.yaml
diff --git a/sse/fern/openapi.yaml b/sse/fern/openapi.yaml
new file mode 100644
index 0000000..a862d86
--- /dev/null
+++ b/sse/fern/openapi.yaml
@@ -0,0 +1,431 @@
+openapi: 3.1.0
+servers:
+ - url: https://api.plantstore.dev/v1
+ description: Demo server
+info:
+ title: Plant Store Streaming API
+ version: 1.0.0
+ description: |
+ A sample Plant Store API that uses server-sent events (SSE) to stream
+ real-time updates for plant care monitoring, order tracking, and
+ inventory changes.
+paths:
+ /plants/{plantId}:
+ get:
+ tags:
+ - plant
+ summary: Get a plant by ID
+ operationId: getPlant
+ parameters:
+ - name: plantId
+ in: path
+ required: true
+ description: Unique identifier for the plant.
+ schema:
+ type: string
+ responses:
+ "200":
+ description: The requested plant.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Plant"
+ examples:
+ fern:
+ summary: A fern plant
+ value:
+ id: "plt_001"
+ name: "Boston Fern"
+ species: "Nephrolepis exaltata"
+ status: "healthy"
+ moisture: 72
+ light: 45
+ temperature: 21.5
+ "404":
+ description: Plant not found.
+ /plants:
+ get:
+ tags:
+ - plant
+ summary: List all plants
+ operationId: listPlants
+ parameters:
+ - name: status
+ in: query
+ required: false
+ description: Filter by plant health status.
+ schema:
+ type: string
+ enum: [healthy, warning, critical]
+ - name: limit
+ in: query
+ required: false
+ description: Maximum number of results to return.
+ schema:
+ type: integer
+ default: 20
+ responses:
+ "200":
+ description: A list of plants.
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ plants:
+ type: array
+ items:
+ $ref: "#/components/schemas/Plant"
+ total:
+ type: integer
+ description: Total number of plants matching the filter.
+ post:
+ tags:
+ - plant
+ summary: Add a new plant
+ operationId: createPlant
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/CreatePlantRequest"
+ examples:
+ fern:
+ summary: Add a fern
+ value:
+ name: "Maidenhair Fern"
+ species: "Adiantum raddianum"
+ responses:
+ "201":
+ description: Plant created.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Plant"
+ /plants/{plantId}/monitor:
+ post:
+ tags:
+ - streaming
+ summary: Stream plant sensor readings
+ description: |
+ Opens a server-sent events stream that delivers real-time sensor
+ readings for a plant. Events include moisture, light, and
+ temperature data as they are recorded by the sensor.
+ operationId: monitorPlant
+ x-fern-streaming:
+ format: sse
+ parameters:
+ - name: plantId
+ in: path
+ required: true
+ description: Unique identifier for the plant to monitor.
+ schema:
+ type: string
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/MonitorRequest"
+ responses:
+ "200":
+ description: A stream of sensor reading events.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/SensorReading"
+ /orders/{orderId}/track:
+ post:
+ tags:
+ - streaming
+ summary: Track order status updates
+ description: |
+ Opens a server-sent events stream that delivers real-time status
+ updates for an order. The stream emits an event each time the
+ order transitions to a new status and sends a `[DONE]` message
+ when the order reaches a terminal state.
+ operationId: trackOrder
+ x-fern-streaming:
+ format: sse
+ terminator: "[DONE]"
+ parameters:
+ - name: orderId
+ in: path
+ required: true
+ description: Unique identifier for the order to track.
+ schema:
+ type: string
+ responses:
+ "200":
+ description: A stream of order status events.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/OrderStatusEvent"
+ "404":
+ description: Order not found.
+ /plants/chat:
+ post:
+ tags:
+ - streaming
+ summary: Chat with the plant care assistant
+ description: |
+ Sends a question to the plant care assistant. When `stream` is
+ `true`, the response is delivered as server-sent events. When
+ `stream` is `false` or omitted, the full response is returned
+ as a single JSON object.
+ operationId: chatWithAssistant
+ x-fern-streaming:
+ format: sse
+ terminator: "[DONE]"
+ stream-condition: $request.stream
+ response:
+ $ref: "#/components/schemas/ChatResponse"
+ response-stream:
+ $ref: "#/components/schemas/ChatChunk"
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ChatRequest"
+ responses:
+ "200":
+ description: The assistant's response (streamed or complete).
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ChatResponse"
+ /orders:
+ post:
+ tags:
+ - order
+ summary: Place a new order
+ operationId: placeOrder
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/PlaceOrderRequest"
+ examples:
+ singlePlant:
+ summary: Order a single plant
+ value:
+ items:
+ - plantId: "plt_001"
+ quantity: 2
+ responses:
+ "201":
+ description: Order placed.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Order"
+ /orders/{orderId}:
+ get:
+ tags:
+ - order
+ summary: Get an order by ID
+ operationId: getOrder
+ parameters:
+ - name: orderId
+ in: path
+ required: true
+ description: Unique identifier for the order.
+ schema:
+ type: string
+ responses:
+ "200":
+ description: The requested order.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Order"
+ "404":
+ description: Order not found.
+components:
+ schemas:
+ Plant:
+ type: object
+ properties:
+ id:
+ type: string
+ description: Unique identifier for the plant.
+ name:
+ type: string
+ description: Common name of the plant.
+ species:
+ type: string
+ description: Botanical (Latin) name.
+ status:
+ type: string
+ enum: [healthy, warning, critical]
+ description: Current health status.
+ moisture:
+ type: number
+ description: Latest soil moisture percentage.
+ light:
+ type: number
+ description: Latest light level in lux.
+ temperature:
+ type: number
+ description: Latest temperature in degrees Celsius.
+ required:
+ - id
+ - name
+ - species
+ - status
+ CreatePlantRequest:
+ type: object
+ properties:
+ name:
+ type: string
+ description: Common name of the plant.
+ species:
+ type: string
+ description: Botanical (Latin) name.
+ required:
+ - name
+ - species
+ MonitorRequest:
+ type: object
+ properties:
+ intervalSeconds:
+ type: integer
+ description: How often to emit sensor readings, in seconds.
+ default: 5
+ metrics:
+ type: array
+ items:
+ type: string
+ enum: [moisture, light, temperature]
+ description: Which sensor metrics to include. Defaults to all.
+ SensorReading:
+ type: object
+ properties:
+ plantId:
+ type: string
+ description: ID of the plant.
+ timestamp:
+ type: string
+ format: date-time
+ description: When the reading was taken.
+ moisture:
+ type: number
+ description: Soil moisture percentage.
+ light:
+ type: number
+ description: Light level in lux.
+ temperature:
+ type: number
+ description: Temperature in degrees Celsius.
+ required:
+ - plantId
+ - timestamp
+ Order:
+ type: object
+ properties:
+ id:
+ type: string
+ description: Unique identifier for the order.
+ items:
+ type: array
+ items:
+ $ref: "#/components/schemas/OrderItem"
+ description: Items in the order.
+ status:
+ type: string
+ enum: [pending, confirmed, shipped, delivered, cancelled]
+ description: Current order status.
+ placedAt:
+ type: string
+ format: date-time
+ description: When the order was placed.
+ required:
+ - id
+ - items
+ - status
+ OrderItem:
+ type: object
+ properties:
+ plantId:
+ type: string
+ description: ID of the plant being ordered.
+ quantity:
+ type: integer
+ description: Number of units.
+ required:
+ - plantId
+ - quantity
+ PlaceOrderRequest:
+ type: object
+ properties:
+ items:
+ type: array
+ items:
+ $ref: "#/components/schemas/OrderItem"
+ description: Items to include in the order.
+ required:
+ - items
+ OrderStatusEvent:
+ type: object
+ properties:
+ orderId:
+ type: string
+ description: ID of the order.
+ previousStatus:
+ type: string
+ enum: [pending, confirmed, shipped, delivered, cancelled]
+ description: Previous order status.
+ newStatus:
+ type: string
+ enum: [pending, confirmed, shipped, delivered, cancelled]
+ description: New order status.
+ updatedAt:
+ type: string
+ format: date-time
+ description: When the status changed.
+ required:
+ - orderId
+ - newStatus
+ - updatedAt
+ ChatRequest:
+ type: object
+ properties:
+ message:
+ type: string
+ description: The user's question about plant care.
+ stream:
+ type: boolean
+ description: Whether to stream the response as SSE events.
+ default: false
+ required:
+ - message
+ ChatResponse:
+ type: object
+ properties:
+ message:
+ type: string
+ description: The assistant's full response.
+ tokens:
+ type: integer
+ description: Number of tokens used.
+ required:
+ - message
+ ChatChunk:
+ type: object
+ properties:
+ delta:
+ type: string
+ description: A fragment of the assistant's response.
+ required:
+ - delta
+tags:
+ - name: plant
+ description: Manage plants in the store.
+ - name: order
+ description: Place and retrieve orders.
+ - name: streaming
+ description: Real-time streaming endpoints using server-sent events.
diff --git a/sse/fern/styles.css b/sse/fern/styles.css
new file mode 100644
index 0000000..154c7a8
--- /dev/null
+++ b/sse/fern/styles.css
@@ -0,0 +1,10 @@
+/* Custom styles for Fern Docs Starter */
+
+/* Subtle linear gradient background */
+.fern-background-image {
+ background-image: linear-gradient(180deg, rgba(0, 135, 0, 0.03) 0%, transparent 50%);
+}
+
+:root.dark .fern-background-image {
+ background-image: linear-gradient(180deg, rgba(112, 225, 85, 0.03) 0%, transparent 50%);
+}