# Preview changes
> Learn how to preview documentation changes with Fern using local development servers and shareable preview links before publishing.
Fern offers two ways to preview documentation changes:
* **[Local development](#local-development)**: Fast iteration with hot reload, best for active development
* **[Preview links](#preview-links)**: Shareable URLs for reviews and collaboration
Install the following:
* Node.js version 18 or higher
* [The Fern CLI](/learn/cli-api-reference/cli-reference/overview#install-fern-cli)
## Local development
[Run a local preview server](/learn/cli-api-reference/cli-reference/commands#fern-docs-dev) to view documentation changes instantly with hot reload. Offline access is available after the first online run.
```bash
# Start preview server (from directory containing fern folder)
fern docs dev
# Or use a custom port
fern docs dev --port 3002
```
Your documentation will be available at `http://localhost:3000` (default) or the port you specified. If you attempt to run Fern on a port that's already in use, it will use the next available port.
Some features are disabled in local development:
* Search
* SEO (favicon, auto-generated meta tags, etc.)
* Authentication
## Preview links
Generate shareable preview URLs to review and collaborate on documentation changes before publishing. Each preview link includes a unique UUID and isn't indexed by search engines. Links don't expire.
```bash
fern generate --docs --preview
```
```bash Example output
[docs]: Found 0 errors and 1 warnings. Run fern check --warnings to print out the warnings.
[docs]: Published docs to https://fern-preview-c973a36e-337b-44f5-ab83-aab.docs.buildwithfern.com/learn
┌─
│ ✓ docs.example.com
└─
```
### Automate with GitHub Actions
Generate preview links automatically for every pull request by adding a GitHub Actions workflow. [Add your `FERN_TOKEN` to the repository secrets](/learn/cli-api-reference/cli-reference/commands#fern-token) before using these workflows.
```yaml
name: Preview Docs
on:
pull_request
jobs:
run:
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Fern
run: npm install -g fern-api
- name: Generate preview URL
env:
FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
run: |
OUTPUT=$(fern generate --docs --preview 2>&1) || true
echo "$OUTPUT"
URL=$(echo "$OUTPUT" | grep -oP 'Published docs to \K.*(?= \()')
echo "🌿 Preview your docs: $URL" > preview_url.txt
- name: Comment URL in PR
uses: thollander/actions-comment-pull-request@v2.4.3
with:
filePath: preview_url.txt
```
If your repository accepts contributions from forks, use `pull_request_target` instead of `pull_request` to allow the workflow to access your `FERN_TOKEN` secret:
```yaml
name: Preview Docs
on:
pull_request_target:
branches:
- main
jobs:
run:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Fern
run: npm install -g fern-api
- name: Checkout PR
run: |
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr-${{ github.event.pull_request.number }}
git checkout pr-${{ github.event.pull_request.number }}
- name: Generate preview URL
env:
FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
run: |
OUTPUT=$(fern generate --docs --preview 2>&1) || true
echo "$OUTPUT"
URL=$(echo "$OUTPUT" | grep -oP 'Published docs to \K.*(?= \()')
echo "🌿 Preview your docs: $URL" > preview_url.txt
- name: Comment URL in PR
uses: thollander/actions-comment-pull-request@v2.4.3
with:
filePath: preview_url.txt
```