React Components (@nowramp/form)
The @nowramp/form package provides ready-to-use React components for crypto on/off-ramp checkout. It handles currency selection, quote comparison, wallet input, and provider checkout — all within your app, no iframe needed.
Installation
npm install @nowramp/form
# or
yarn add @nowramp/form
# or
pnpm add @nowramp/form
@nowramp/form has peer dependencies on react and react-dom (18+). The @nowramp/sdk package is bundled automatically.
Quick Start
import { RampForm } from '@nowramp/form';
function BuyCrypto() {
return (
<RampForm
projectId="your_project_id"
apiUrl="https://api.nowramp.com"
onComplete={(tx) => console.log('Done!', tx.orderId)}
/>
);
}
The main component that renders the complete checkout form with currency selection, quote comparison, wallet input, and provider checkout.
Basic Usage (Partner Dashboard Pattern)
This is the minimal setup used in partner dashboard integrations:
<RampForm
projectId={projectId}
apiUrl={process.env.NEXT_PUBLIC_API_URL}
customerId={externalUserId}
theme={theme}
borderColor={theme === 'dark' ? '#333333' : '#e2e8f0'}
borderRadius="10px"
defaultFiatAmount="250"
/>
Full Branding (Hosted Checkout Pattern)
For hosted checkout flows with complete brand customization:
<RampForm
projectId={config.projectId}
apiUrl="https://api.nowramp.com"
flowType="buy"
customerId={customerId}
theme="dark"
accentColor={branding.accentColor}
bgColor={branding.bgDarkest}
surfaceColor={branding.bgMedium}
inputBgColor={branding.bgLight}
textColor={branding.textPrimary}
textSecondaryColor={branding.textSecondary}
textMutedColor={branding.textMuted}
successColor={branding.accentColor}
borderColor="#222222"
borderRadius="10px"
showFlowToggle={false}
showThemeToggle={false}
defaultFiatCurrency="USD"
defaultFiatAmount="100"
defaultCryptoCurrency="ETH"
defaultNetwork="ethereum"
defaultWalletAddress="0x742d35Cc..."
fieldLocks={{
destinationAddress: { locked: true, value: '0x742d35Cc...' },
destinationCurrency: { locked: true, value: 'ETH' },
}}
onDone={() => router.push('/success')}
onError={(err) => setError(err.message)}
/>
Props Reference
Core Props
| Prop | Type | Default | Description |
|---|
projectId | string | Required | Your NowRamp project ID |
apiUrl | string | https://api.nowramp.com | API base URL |
flowType | 'buy' | 'sell' | 'buy' | Buy crypto or sell crypto |
customerId | string | — | External customer ID |
brandId | string | — | Brand/config slug identifier |
Default Values
| Prop | Type | Default | Description |
|---|
defaultFiatCurrency | string | 'USD' | Initial fiat currency |
defaultCryptoCurrency | string | — | Initial crypto currency |
defaultNetwork | string | — | Initial blockchain network |
defaultFiatAmount | string | — | Initial fiat amount |
defaultCryptoAmount | string | — | Initial crypto amount (for sell) |
defaultWalletAddress | string | — | Pre-filled wallet address |
defaultGateway | string | — | Pre-selected gateway ID |
Theme & Styling
| Prop | Type | Default | Description |
|---|
theme | 'light' | 'dark' | 'light' | Color theme |
skinId | string | — | Skin preset ID |
accentColor | string | — | Primary/accent color (hex) |
bgColor | string | — | Main background color (hex) |
bgImage | string | — | Background image URL |
surfaceColor | string | — | Card/surface background (hex) |
inputBgColor | string | — | Input/pill background (hex) |
textColor | string | — | Primary text color (hex) |
textSecondaryColor | string | — | Secondary/label text (hex) |
textMutedColor | string | — | Muted text color (hex) |
successColor | string | — | Success indicator color (hex) |
borderColor | string | — | Border color (hex) |
borderRadius | string | — | Border radius (CSS value, e.g., '10px') |
UI Controls
| Prop | Type | Default | Description |
|---|
showFlowToggle | boolean | true | Show Buy/Sell toggle tabs |
showSettings | boolean | true | Show settings menu |
showThemeToggle | boolean | true | Show dark/light mode toggle |
showEmail | boolean | false | Show email input field |
requireEmail | boolean | false | Make email required |
autoRedirect | boolean | — | Auto-redirect for redirect-based checkouts |
rateRefreshInterval | number | — | Quote refresh interval (seconds) |
statusPollInterval | number | 5000 | Order status poll interval (ms) |
Display Customization
| Prop | Type | Description |
|---|
explorerUrl | string | Block explorer URL pattern |
doneButtonText | string | Custom done button label |
submitButtonText | string | Custom submit button label |
supportEmail | string | Support email for error screen |
assetBaseUrl | string | CDN base URL for static assets |
Field Locks
| Prop | Type | Description |
|---|
fieldLocks | FieldLocksConfig | Lock specific fields to prevent user modification |
<RampForm
fieldLocks={{
destinationAddress: { locked: true, value: '0x742d35Cc...' },
destinationCurrency: { locked: true, value: 'ETH' },
sourceAmount: { locked: false, min: 50, max: 5000 },
}}
/>
Callbacks
| Prop | Type | Description |
|---|
onComplete | (tx: Transaction) => void | Called when transaction completes |
onError | (err: Error) => void | Called on error |
onDone | () => void | Called when user clicks done button |
RampProvider + useRamp
For full control over the UI, use RampProvider for state management and build your own components.
RampProvider
Wraps your custom UI with configuration, API state, and form management.
import { RampProvider, useRamp } from '@nowramp/form';
function App() {
return (
<RampProvider
projectId="your_project_id"
apiUrl="https://api.nowramp.com"
flowType="buy"
customerId="user_123"
onComplete={(tx) => console.log('Done!', tx)}
>
<CustomCheckoutUI />
</RampProvider>
);
}
useRamp Hook
Access the full ramp context within a RampProvider.
function CustomCheckoutUI() {
const {
// Configuration
config, // OnrampSupported | null
configLoading, // boolean
apiConfig, // { apiUrl, projectId }
// Form state
state, // RampFormState
dispatch, // React.Dispatch<RampAction>
// Quotes
quotes, // QuotesResponse | null
quotesLoading, // boolean
fetchQuotes, // () => void
// Order
order, // CheckoutIntent | null
orderLoading, // boolean
createOrder, // () => Promise<void>
// Transaction status
orderStatus, // Transaction | null
orderStatusLoading,
// Navigation
goToStep, // (step: RampStep) => void
goBack, // () => void
canProceed, // boolean
// Validation
amountError, // string | null
fieldLocks, // FieldLocksConfig | null
} = useRamp();
if (configLoading) return <div>Loading...</div>;
return (
<div>
<p>Selected: {state.fiatAmount} {state.fiatCurrency}</p>
<p>Quotes: {quotes?.quotes.length ?? 0} available</p>
<button onClick={fetchQuotes} disabled={quotesLoading}>
Refresh Quotes
</button>
</div>
);
}
| Field | Type | Description |
|---|
step | RampStep | Current step in the flow |
flowType | 'buy' | 'sell' | Current flow type |
fiatCurrency | string | Selected fiat currency |
fiatAmount | string | Entered fiat amount |
cryptoCurrency | string | Selected crypto currency |
cryptoAmount | string | Crypto amount |
network | string | Selected blockchain network |
paymentMethodId | string | Selected payment method |
walletAddress | string | Entered wallet address |
selectedProvider | string | null | Selected gateway ID |
selectedQuote | Quote | null | Selected quote |
customerId | string | Customer ID |
email | string | Customer email |
errorMessage | string | null | Current error message |
RampStep Values
| Step | Description |
|---|
amount | Currency and amount selection |
quotes | Quote comparison view |
wallet | Wallet address entry |
checkout | Provider checkout (iframe/redirect) |
processing | Waiting for transaction completion |
complete | Success screen |
error | Error screen |
Data Hooks
Standalone hooks for direct API access without the full form UI. Use these to build completely custom checkout experiences.
useRampConfig
Fetches supported gateways, currencies, and payment methods.
import { useRampConfig } from '@nowramp/form';
function CurrencyPicker() {
const { config, loading, error, refetch } = useRampConfig(
{ apiUrl: 'https://api.nowramp.com', projectId: 'your_project_id' },
'buy'
);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<select>
{config?.fiats.map(fiat => (
<option key={fiat.code} value={fiat.code}>
{fiat.symbol} {fiat.name}
</option>
))}
</select>
);
}
Returns:
| Field | Type | Description |
|---|
config | OnrampSupported | null | Supported configuration |
loading | boolean | Loading state |
error | Error | null | Error if failed |
refetch | () => Promise<void> | Manually refetch |
useQuotes
Fetches and ranks quotes from all enabled gateways. Auto-refreshes when params change.
import { useQuotes } from '@nowramp/form';
function QuoteList() {
const { quotes, loading, error } = useQuotes(
{ apiUrl: 'https://api.nowramp.com', projectId: 'your_project_id' },
{
fiatCurrency: 'USD',
fiatAmount: '100',
cryptoCurrency: 'ETH',
network: 'ethereum'
}
);
if (loading) return <div>Fetching quotes...</div>;
return (
<div>
{quotes?.quotes.map(q => (
<div key={q.gatewayId}>
{q.gatewayName}: {q.cryptoAmount} {q.cryptoCurrency}
{q.isBestRate && <span> (Best Rate)</span>}
</div>
))}
</div>
);
}
Pass null as the second argument to skip fetching (useful when form inputs are incomplete).
Returns:
| Field | Type | Description |
|---|
quotes | QuotesResponse | null | Ranked quotes |
loading | boolean | Loading state |
error | Error | null | Error if failed |
refetch | () => Promise<void> | Manually refetch |
useCheckoutIntent
Creates a checkout order with a selected gateway.
import { useCheckoutIntent } from '@nowramp/form';
function CheckoutButton() {
const { order, loading, error, createOrder, reset } = useCheckoutIntent(
{ apiUrl: 'https://api.nowramp.com', projectId: 'your_project_id' }
);
const handleCheckout = async () => {
const intent = await createOrder({
gateway: 'gateway_a',
fiatCurrency: 'USD',
fiatAmount: '100',
cryptoCurrency: 'ETH',
network: 'ethereum',
walletAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f1bD21'
});
if (intent.checkout.method === 'iframe') {
setIframeUrl(intent.checkout.url);
} else {
window.location.href = intent.checkout.url;
}
};
return <button onClick={handleCheckout} disabled={loading}>Checkout</button>;
}
Returns:
| Field | Type | Description |
|---|
order | CheckoutIntent | null | Created checkout intent |
loading | boolean | Loading state |
error | Error | null | Error if failed |
createOrder | (params) => Promise<CheckoutIntent> | Create checkout |
reset | () => void | Reset state |
useTransaction
Polls transaction status until it reaches a terminal state.
import { useTransaction } from '@nowramp/form';
function OrderTracker({ orderId }: { orderId: string }) {
const { status, loading } = useTransaction(
{ apiUrl: 'https://api.nowramp.com' },
orderId,
{ pollInterval: 5000, initialDelay: 15000 }
);
if (!status) return <div>Loading...</div>;
return (
<div>
<p>Status: {status.status}</p>
{status.transactionHash && (
<p>TX: {status.transactionHash}</p>
)}
</div>
);
}
The initialDelay option is useful when embedding a provider checkout iframe — it gives the user time to complete payment before polling starts.
Returns:
| Field | Type | Description |
|---|
status | Transaction | null | Current transaction status |
loading | boolean | Loading state |
error | Error | null | Error if failed |
refetch | () => Promise<void> | Manually refetch |
Theming
Light / Dark Mode
<RampForm projectId="..." theme="dark" />
Custom Colors
Override individual colors for precise brand matching:
<RampForm
projectId="..."
theme="dark"
accentColor="#6366F1"
bgColor="#1a1a2e"
surfaceColor="#16213e"
inputBgColor="#0f3460"
textColor="#e0e0e0"
textSecondaryColor="#a0a0a0"
textMutedColor="#666666"
successColor="#6366F1"
borderColor="#222222"
borderRadius="10px"
/>
Color mapping guide:
| Prop | Applies to |
|---|
accentColor | Buttons, links, active states, progress indicators |
bgColor | Main background of the form |
surfaceColor | Card and panel backgrounds |
inputBgColor | Input fields, pills, dropdowns |
textColor | Primary text, headings |
textSecondaryColor | Labels, secondary text |
textMutedColor | Hints, placeholders, disabled text |
successColor | Success indicators, rate display |
borderColor | Borders on cards, inputs, dividers |
borderRadius | Corner rounding on all elements |
Skin Presets
<RampForm projectId="..." skinId="midnight" />
Skins apply a coordinated set of colors and styles. Available skins are exported from the package as SKINS.
Standalone Mode (IIFE)
For non-React apps (plain HTML, PHP, WordPress, etc.), use the standalone IIFE build.
<script src="https://cdn.example.com/form/latest/nowramp-form.iife.js"></script>
<div id="nowramp"></div>
<script>
NowRampForm.mount('#nowramp', {
projectId: 'your_project_id',
apiUrl: 'https://api.nowramp.com',
assetBaseUrl: 'https://cdn.example.com/form/latest',
theme: 'light',
onComplete: function(tx) {
console.log('Purchase complete:', tx.orderId);
}
});
// To unmount later:
// NowRampForm.unmount('#nowramp');
</script>
| Function | Description |
|---|
NowRampForm.mount(selector, props) | Mount the form into a DOM element |
NowRampForm.unmount(selector) | Unmount a previously mounted form |
The mount function accepts the same props as the RampForm component.
Next.js Integration
// app/buy/page.tsx
'use client';
import { RampForm } from '@nowramp/form';
export default function BuyPage() {
return (
<div className="max-w-md mx-auto py-8">
<RampForm
projectId={process.env.NEXT_PUBLIC_NOWRAMP_PROJECT_ID!}
apiUrl={process.env.NEXT_PUBLIC_NOWRAMP_API_URL}
theme="light"
onComplete={(tx) => {
window.location.href = `/orders/${tx.orderId}`;
}}
/>
</div>
);
}
Always use the 'use client' directive in Next.js App Router since @nowramp/form uses React hooks and browser APIs.
Next Steps