Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#
# `.env.local` is git-ignored, so your local values never get committed.

# Public site origin used for canonical, Open Graph, sitemap, and share URLs.
NEXT_PUBLIC_SITE_URL=https://flowstar.app

# ─── Stellar contract ─────────────────────────────────────────────────────────

# Deployed streaming contract addresses on Stellar.
Expand Down
3 changes: 2 additions & 1 deletion __tests__/components/streams/qr-share-dialog.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { fireEvent, render, screen } from '@testing-library/react'
import { QrShareDialog } from '@/components/streams/qr-share-dialog'
import { SITE_URL } from '@/lib/site'
import type { StreamData } from '@/types/stream'

const { mockToastSuccess, mockWriteText } = vi.hoisted(() => ({
Expand All @@ -23,7 +24,7 @@ vi.mock('qrcode.react', () => ({
),
}))

const STREAM_URL = 'https://flowstar.app/stream/stream-123'
const STREAM_URL = `${SITE_URL}/stream/stream-123`

function makeStream(overrides?: Partial<StreamData>): StreamData {
return {
Expand Down
5 changes: 3 additions & 2 deletions app/app/stream/[id]/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { fetchStream } from "@/lib/contract";
import { NETWORK } from "@/lib/stellar";
import { shortenAddress } from "@/lib/stream-utils";
import { captureError } from "@/lib/sentry";
import { SITE_URL } from "@/lib/site";

export async function generateMetadata({
params,
Expand All @@ -20,7 +21,7 @@ export async function generateMetadata({
};
}

const ogImageUrl = new URL("/api/og", "https://flowstar.app");
const ogImageUrl = new URL("/api/og", SITE_URL);
ogImageUrl.searchParams.append(
"amount",
(
Expand All @@ -45,7 +46,7 @@ export async function generateMetadata({
return {
title: `Stream #${stream.id}`,
description,
metadataBase: new URL("https://flowstar.app"),
metadataBase: new URL(SITE_URL),
openGraph: {
type: "website",
siteName: "FlowStar",
Expand Down
3 changes: 2 additions & 1 deletion app/app/stream/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from 'lucide-react'
import { toast } from 'sonner'
import { ConnectWalletButton } from '@/components/layout/connect-wallet-button'
import { SITE_URL } from '@/lib/site'
import { StreamStatusBadge } from '@/components/streams/stream-status-badge'
import { ProgressBar } from '@/components/ui/progress-bar'
import { TokenAmount } from '@/components/ui/token-amount'
Expand Down Expand Up @@ -795,7 +796,7 @@ function ShareButtons({
const streamUrl =
typeof window !== 'undefined'
? window.location.href
: `https://flowstar.app/app/stream/${streamId}`
: `${SITE_URL}/app/stream/${streamId}`
const shareText = copy.shareButtons.shareText(streamId)

function copyLink() {
Expand Down
5 changes: 3 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { WalletProvider } from '@/components/providers/wallet-provider'
import { Toaster } from '@/components/ui/sonner'
import { ServiceWorkerRegister } from '@/components/pwa/service-worker-register'
import { InstallPrompt } from '@/components/pwa/install-prompt'
import { SITE_URL } from '@/lib/site'
import './globals.css'

// JSON-LD structured data
Expand All @@ -15,7 +16,7 @@ const jsonLd = {
'@type': 'WebApplication',
name: 'FlowStar',
description: 'Stream tokens by the second with cliffs and cancellations on Stellar Soroban',
url: 'https://flowstar.app',
url: SITE_URL,
applicationCategory: 'FinanceApplication',
operatingSystem: 'Web',
offers: {
Expand Down Expand Up @@ -43,7 +44,7 @@ export const metadata: Metadata = {
description:
'Stream tokens by the second with cliffs and cancellations on Stellar Soroban. Create vesting schedules, payroll, and grants that unlock continuously — withdraw anytime, cancel anytime.',
keywords: ['stellar', 'soroban', 'token streaming', 'DeFi', 'payment streams', 'vesting', 'payroll', 'grants'],
metadataBase: new URL('https://flowstar.app'),
metadataBase: new URL(SITE_URL),
alternates: {
canonical: '/',
},
Expand Down
3 changes: 2 additions & 1 deletion app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { MetadataRoute } from 'next'
import { SITE_URL } from '@/lib/site'

export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = 'https://flowstar.app'
const baseUrl = SITE_URL

return [
{
Expand Down
3 changes: 2 additions & 1 deletion components/streams/qr-share-dialog.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'
import { useState } from 'react'
import { Toaster } from 'sonner'
import { QrShareDialog } from './qr-share-dialog'
import { SITE_URL } from '@/lib/site'
import { Button } from '@/components/ui/button'
import type { StreamData } from '@/types/stream'

Expand Down Expand Up @@ -56,7 +57,7 @@ export const OpenWithSampleStream: Story = {
args: {
open: true,
onOpenChange: () => {},
streamUrl: 'https://flowstar.app/app/streams/42',
streamUrl: `${SITE_URL}/app/streams/42`,
stream: sampleStream,
status: 'streaming',
},
Expand Down
3 changes: 2 additions & 1 deletion components/streams/stream-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
} from '@/components/ui/dropdown-menu'
import { getFederationNameForAddress } from '@/lib/address-book'
import { streamCardCopy as copy } from '@/lib/copy/streams'
import { SITE_URL } from '@/lib/site'
import type { StreamData } from '@/types/stream'

// Pick update interval based on a quick pre-check of stream state.
Expand Down Expand Up @@ -146,7 +147,7 @@ function StreamCardInner({
const url =
typeof window !== 'undefined'
? `${window.location.origin}/app/stream/${stream.id}`
: `https://flowstar.app/app/stream/${stream.id}`
: `${SITE_URL}/app/stream/${stream.id}`
navigator.clipboard.writeText(url)
setCopiedLink(true)
setTimeout(() => setCopiedLink(false), 1500)
Expand Down
7 changes: 7 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,11 @@ export default [
},
},
},
{
files: ['scripts/**/*.mjs'],
rules: {
'no-console': 'off',
'security/detect-non-literal-fs-filename': 'off',
},
},
]
1 change: 1 addition & 0 deletions lib/site.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://flowstar.app'
2 changes: 2 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ async function withBundleAnalyzer(config) {
const { default: analyzer } = await import('@next/bundle-analyzer')
return analyzer({ enabled: true })(config)
} catch {
// This warning explains why optional bundle analysis was skipped.
// eslint-disable-next-line no-console
console.warn('[FlowStar] @next/bundle-analyzer not installed — skipping analysis')
return config
}
Expand Down
Binary file removed public/placeholder-logo.png
Binary file not shown.
1 change: 0 additions & 1 deletion public/placeholder-logo.svg

This file was deleted.

Binary file removed public/placeholder-user.jpg
Binary file not shown.
Binary file removed public/placeholder.jpg
Binary file not shown.
1 change: 0 additions & 1 deletion public/placeholder.svg

This file was deleted.

Loading