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%); +}