Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
145 changes: 145 additions & 0 deletions .github/workflows/docs-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: Docs Site CI

# ---------------------------------------------------------------------------
# Triggers
# ---------------------------------------------------------------------------
# Scoped to apps/docs-site so unrelated changes (server, contracts, the
# marketing frontend) don't trigger a docs build/deploy.
on:
push:
branches: [main]
paths:
- "apps/docs-site/**"
- ".github/workflows/docs-ci.yml"
pull_request:
branches: [main]
paths:
- "apps/docs-site/**"
- ".github/workflows/docs-ci.yml"

concurrency:
group: docs-site-ci-${{ github.ref }}
cancel-in-progress: true

# ---------------------------------------------------------------------------
# Jobs
# ---------------------------------------------------------------------------
jobs:

# -------------------------------------------------------------------------
# 1. Build — generate the API/Contract reference pages, type-check, build
# -------------------------------------------------------------------------
build:
name: Docs site (Next.js / Nextra)
runs-on: ubuntu-latest

defaults:
run:
working-directory: apps/docs-site

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Node.js 20
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: apps/docs-site/package-lock.json

- name: Install dependencies
run: npm ci

# Regenerates pages/api-reference/** from openapi/openapi.json and
# pages/contract-reference/** from the Rust doc comments in
# contracts/*/src/lib.rs — keeps generated docs from going stale.
- name: Generate API & Contract reference pages
run: npm run generate

- name: Type-check
run: npx tsc --noEmit

- name: Build (includes Flexsearch index generation)
run: npm run build

- name: Upload docs-site build
uses: actions/upload-artifact@v4
with:
name: docs-site-build
path: apps/docs-site/.next/
retention-days: 7

# -------------------------------------------------------------------------
# 2. Deploy to Vercel — production on main, preview on PRs
# -------------------------------------------------------------------------
# Requires repo secrets: VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID_DOCS_SITE.
# See docs.airflex.io setup instructions in apps/docs-site/pages/deployment.mdx.
deploy:
name: Deploy to Vercel
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push' || github.event_name == 'pull_request'

defaults:
run:
working-directory: apps/docs-site

permissions:
contents: read
pull-requests: write # to comment the preview URL on the PR

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Vercel CLI
run: npm install --global vercel@latest

- name: Pull Vercel environment
run: |
vercel pull --yes \
--environment=${{ github.event_name == 'push' && 'production' || 'preview' }} \
--token=${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_DOCS_SITE }}

- name: Build via Vercel
run: |
if [ "${{ github.event_name }}" = "push" ]; then
vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
else
vercel build --token=${{ secrets.VERCEL_TOKEN }}
fi
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_DOCS_SITE }}

- name: Deploy via Vercel
id: deploy
run: |
if [ "${{ github.event_name }}" = "push" ]; then
URL=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }})
else
URL=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
fi
echo "url=$URL" >> "$GITHUB_OUTPUT"
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_DOCS_SITE }}

# Production deploys are aliased to docs.airflex.io in the Vercel
# project's domain settings (one-time setup — see deployment.mdx),
# so no explicit `vercel alias` step is needed here.
- name: Comment preview URL on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `📚 Docs preview: ${{ steps.deploy.outputs.url }}`,
});
146 changes: 44 additions & 102 deletions .github/workflows/frontend-ci.yml
Original file line number Diff line number Diff line change
@@ -1,145 +1,87 @@
name: Frontend CI (docs-site)
name: Frontend CI

# ---------------------------------------------------------------------------
# Triggers
# ---------------------------------------------------------------------------
# Scoped to apps/docs-site so unrelated changes (server, contracts, the
# marketing frontend) don't trigger a docs build/deploy.
on:
push:
branches: [main]
paths:
- "apps/docs-site/**"
- ".github/workflows/frontend-ci.yml"
pull_request:
branches: [main]
paths:
- "apps/docs-site/**"
- ".github/workflows/frontend-ci.yml"

concurrency:
group: frontend-ci-docs-site-${{ github.ref }}
group: frontend-ci-${{ github.ref }}
cancel-in-progress: true

# ---------------------------------------------------------------------------
# Jobs
# ---------------------------------------------------------------------------
jobs:

# -------------------------------------------------------------------------
# 1. Build — generate the API/Contract reference pages, type-check, build
# -------------------------------------------------------------------------
build:
name: Docs site (Next.js / Nextra)
frontend:
name: Frontend CI
runs-on: ubuntu-latest

defaults:
run:
working-directory: apps/docs-site
working-directory: frontend

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
version: 10.28.0

- name: Set up Node.js 20
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: apps/docs-site/package-lock.json
node-version: 20
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- name: Cache node modules
uses: actions/cache@v4
with:
path: |
node_modules
frontend/node_modules
frontend/.next/cache
key: frontend-ci-${{ runner.os }}-${{ hashFiles('frontend/pnpm-lock.yaml') }}
restore-keys: |
frontend-ci-${{ runner.os }}-

- name: Install dependencies
run: npm ci
working-directory: .
run: pnpm install --frozen-lockfile

# Regenerates pages/api-reference/** from openapi/openapi.json and
# pages/contract-reference/** from the Rust doc comments in
# contracts/*/src/lib.rs — keeps generated docs from going stale.
- name: Generate API & Contract reference pages
run: npm run generate
- name: Lint
run: pnpm lint

- name: Type-check
run: npx tsc --noEmit
run: pnpm tsc --noEmit

- name: Build (includes Flexsearch index generation)
run: npm run build
- name: Test
run: pnpm test:coverage

- name: Upload docs-site build
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
with:
name: docs-site-build
path: apps/docs-site/.next/
name: frontend-coverage
path: frontend/coverage/
if-no-files-found: ignore
retention-days: 7

# -------------------------------------------------------------------------
# 2. Deploy to Vercel — production on main, preview on PRs
# -------------------------------------------------------------------------
# Requires repo secrets: VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID_DOCS_SITE.
# See docs.airflex.io setup instructions in apps/docs-site/pages/deployment.mdx.
deploy:
name: Deploy to Vercel
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push' || github.event_name == 'pull_request'

defaults:
run:
working-directory: apps/docs-site

permissions:
contents: read
pull-requests: write # to comment the preview URL on the PR

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Vercel CLI
run: npm install --global vercel@latest

- name: Pull Vercel environment
run: |
vercel pull --yes \
--environment=${{ github.event_name == 'push' && 'production' || 'preview' }} \
--token=${{ secrets.VERCEL_TOKEN }}
- name: Build
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_DOCS_SITE }}
NEXT_PUBLIC_API_URL: http://localhost:3001
run: pnpm build

- name: Build via Vercel
run: |
if [ "${{ github.event_name }}" = "push" ]; then
vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
else
vercel build --token=${{ secrets.VERCEL_TOKEN }}
fi
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_DOCS_SITE }}

- name: Deploy via Vercel
id: deploy
run: |
if [ "${{ github.event_name }}" = "push" ]; then
URL=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }})
else
URL=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
fi
echo "url=$URL" >> "$GITHUB_OUTPUT"
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_DOCS_SITE }}

# Production deploys are aliased to docs.airflex.io in the Vercel
# project's domain settings (one-time setup — see deployment.mdx),
# so no explicit `vercel alias` step is needed here.
- name: Comment preview URL on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
- name: Upload frontend build
uses: actions/upload-artifact@v4
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `📚 Docs preview: ${{ steps.deploy.outputs.url }}`,
});
name: frontend-build
path: frontend/.next/
retention-days: 7
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ vite.config.ts.timestamp-*
# Kiro IDE
.kiro/

# Turbo
.turbo

# Pull request description docs (local only, not for version control)
pr-*.md
PULL_REQUEST.md
2 changes: 1 addition & 1 deletion apps/docs-site/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const nextConfig = {
ignoreDuringBuilds: true,
},
// The docs site is deployed standalone at docs.airflex.io (see
// .github/workflows/frontend-ci.yml), so it does not need to share a
// .github/workflows/docs-ci.yml), so it does not need to share a
// basePath with the marketing/app frontend in ../../frontend.
};

Expand Down
2 changes: 1 addition & 1 deletion apps/docs-site/pages/deployment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ and tagged releases (`v*.*.*`) are packaged via
## This documentation site

`apps/docs-site` deploys to Vercel at **docs.airflex.io** via
[`.github/workflows/frontend-ci.yml`](https://github.com/arflexx/Airflex/blob/main/.github/workflows/frontend-ci.yml),
[`.github/workflows/docs-ci.yml`](https://github.com/arflexx/Airflex/blob/main/.github/workflows/docs-ci.yml),
which builds and deploys on every push to `main` that touches
`apps/docs-site/**` (and posts a preview deployment on pull requests).

Expand Down
3 changes: 3 additions & 0 deletions frontend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
2 changes: 1 addition & 1 deletion frontend/app/auth/signup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default function SignupPage() {
Create your account
</h1>
<p className="mt-2 text-sm text-gray-500 dark:text-gray-400">
Enter your phone number and we'll send a 6-digit OTP to verify it.
Enter your phone number and we&apos;ll send a 6-digit OTP to verify it.
</p>
</div>

Expand Down
14 changes: 9 additions & 5 deletions frontend/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ interface TradesResponse {

async function getActiveListings(): Promise<TradesResponse> {
const apiUrl = process.env["NEXT_PUBLIC_API_URL"] ?? "http://localhost:3001";
const res = await fetch(`${apiUrl}/api/v1/trades?page=1&limit=20`, {
next: { revalidate: 30 },
});
if (!res.ok) {
try {
const res = await fetch(`${apiUrl}/api/v1/trades?page=1&limit=20`, {
next: { revalidate: 30 },
});
if (!res.ok) {
return { data: [], pagination: { page: 1, limit: 20, total: 0, totalPages: 0 } };
}
return res.json() as Promise<TradesResponse>;
} catch {
return { data: [], pagination: { page: 1, limit: 20, total: 0, totalPages: 0 } };
}
return res.json() as Promise<TradesResponse>;
}

function formatAssetType(raw: string): string {
Expand Down
Loading