nuqiwealth-widgets
v1.1.0
Published
Embeddable React / Next.js widgets for live stock market data — powered by Nuqi Wealth
Maintainers
Readme
nuqiwealth-widgets
Embeddable React / Next.js widgets for live stock market data, powered by Nuqi Wealth.
npm install nuqiwealth-widgetsCredentials required. The package installs freely but every widget renders a neutral locked state without a valid
apiKeyandclientId. Purchase a plan at nuqiwealth.com or contact [email protected] to get yours.
Widgets
| Component | Description | Feature key |
|-----------|-------------|-------------|
| StockList | Filterable, sortable, paginated stock table | stock-list |
| StockDetail | Full-screen overlay — chart, financials, analyst ratings & news | stock-detail |
| BasketList | Card grid of curated investment baskets with mini charts and CAGR | curated-baskets |
| BasketDetail | Full-screen overlay — basket performance chart, composition & description | cep-detail |
- React 18 & 19 · Next.js 13 / 14 / 15 (App Router & Pages Router)
- Dual build — ESM + CJS +
.d.tstypes - Pre-compiled CSS — no Tailwind setup needed in your project
- 8 built-in themes including
darkandlight - Container-responsive — widgets reflow on their own width, not the viewport
- Per-client feature lock — same package, different widgets unlocked per partner
Quick start
React (Vite)
// src/main.tsx
import 'nuqiwealth-widgets/styles.css'// src/App.tsx
import { useState } from 'react'
import { NuqiWidgets, StockList, StockDetail } from 'nuqiwealth-widgets'
export default function App() {
const [stockKey, setStockKey] = useState<string | null>(null)
return (
<NuqiWidgets
apiKey={import.meta.env.VITE_NUQI_API_KEY}
clientId={import.meta.env.VITE_NUQI_CLIENT_ID}
baseUrl={import.meta.env.VITE_NUQI_BASE_URL}
theme="dark"
>
<StockList onStockClick={setStockKey} />
{stockKey && (
<StockDetail stockKey={stockKey} onClose={() => setStockKey(null)} />
)}
</NuqiWidgets>
)
}Next.js App Router
// app/providers.tsx
'use client'
import { NuqiWidgets } from 'nuqiwealth-widgets'
import 'nuqiwealth-widgets/styles.css'
export function Providers({ children }: { children: React.ReactNode }) {
return (
<NuqiWidgets
apiKey={process.env.NEXT_PUBLIC_NUQI_API_KEY!}
clientId={process.env.NEXT_PUBLIC_NUQI_CLIENT_ID!}
baseUrl={process.env.NEXT_PUBLIC_NUQI_BASE_URL!}
theme="dark"
>
{children}
</NuqiWidgets>
)
}// app/layout.tsx
import { Providers } from './providers'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}Next.js Pages Router
// pages/_app.tsx
import type { AppProps } from 'next/app'
import { NuqiWidgets } from 'nuqiwealth-widgets'
import 'nuqiwealth-widgets/styles.css'
export default function App({ Component, pageProps }: AppProps) {
return (
<NuqiWidgets
apiKey={process.env.NEXT_PUBLIC_NUQI_API_KEY!}
clientId={process.env.NEXT_PUBLIC_NUQI_CLIENT_ID!}
baseUrl={process.env.NEXT_PUBLIC_NUQI_BASE_URL!}
theme="dark"
>
<Component {...pageProps} />
</NuqiWidgets>
)
}Environment variables
# .env (Vite)
VITE_NUQI_API_KEY=your_api_key_here
VITE_NUQI_CLIENT_ID=your_client_id_here
VITE_NUQI_BASE_URL=https://api.nuqiwealth.com
# .env.local (Next.js)
NEXT_PUBLIC_NUQI_API_KEY=your_api_key_here
NEXT_PUBLIC_NUQI_CLIENT_ID=your_client_id_here
NEXT_PUBLIC_NUQI_BASE_URL=https://api.nuqiwealth.comNever commit these to source control.
API reference
<NuqiWidgets> — provider
Wrap your app (or the section that renders widgets) once. All widgets must be descendants.
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| apiKey | string | ✓ | Publishable widget key issued by Nuqi Wealth |
| clientId | string | ✓ | Client identifier issued by Nuqi Wealth |
| baseUrl | string | ✓ | API base URL provided with your credentials |
| theme | PresetThemeName \| ThemeConfig | | Preset name or custom theme object. Default: "dark" |
| userToken | string | | End-user JWT for per-user feature gating |
| refreshInterval | number | | Polling interval in ms. Default: 30000 |
| onError | (err: NuqiError) => void | | Error callback |
<StockList>
Filterable, sortable, paginated table of stocks. Container-responsive — switches layouts automatically at different widths.
import { StockList } from 'nuqiwealth-widgets'
<StockList
onStockClick={(key) => setStockKey(key)}
exchange="NASDAQ"
sector="Technology"
limit={20}
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| onStockClick | (key: string) => void | | Called when a row is clicked |
| exchange | string | | Filter by exchange |
| country | string | | Filter by country |
| sector | string | | Filter by sector |
| search | string | | Pre-fill the search input |
| defaultSort | string | | Default sort column key |
| sortableColumns | string[] | | Override which columns are sortable |
| limit | number | | Max rows per page |
| height | number \| string | | Widget height |
| width | number \| string | | Widget width. Omit to fill parent |
| theme | PresetThemeName \| ThemeConfig | | Per-widget theme override |
| className | string | | |
| style | React.CSSProperties | | |
<StockDetail>
Full-screen overlay showing a single stock's chart, financials, analyst ratings, and news. Renders into a portal so it sits above your page layout.
import { StockDetail } from 'nuqiwealth-widgets'
{stockKey && (
<StockDetail
stockKey={stockKey}
onClose={() => setStockKey(null)}
/>
)}| Prop | Type | Required | Description |
|------|------|----------|-------------|
| stockKey | string | ✓ | Stock identifier (returned by StockList.onStockClick) |
| onClose | () => void | ✓ | Called when the overlay is dismissed |
| width | number \| string | | Panel max-width. Default: 680px |
| height | number \| string | | Panel max-height. Default: 90vh |
| theme | PresetThemeName \| ThemeConfig | | Per-widget theme override |
| className | string | | |
| style | React.CSSProperties | | |
| overlayClassName | string | | |
| overlayStyle | React.CSSProperties | | |
<BasketList>
Responsive card grid of curated investment baskets, each showing a mini performance chart, CAGR, and risk level.
import { BasketList } from 'nuqiwealth-widgets'
import type { BasketItem } from 'nuqiwealth-widgets'
<BasketList
onBasketClick={(basket: BasketItem) => setBasket(basket)}
risk="growth"
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| onBasketClick | (basket: BasketItem) => void | | Called when a card is clicked |
| risk | 'all' \| 'conservative' \| 'balanced' \| 'growth' \| 'aggressive' | 'all' | Filter by risk level |
| limit | number | | Max baskets to display |
| height | number \| string | | Scrollable card area height |
| width | number \| string | | Widget width. Omit to fill parent |
| theme | PresetThemeName \| ThemeConfig | | Per-widget theme override |
| className | string | | |
| style | React.CSSProperties | | |
<BasketDetail>
Full-screen overlay showing a basket's performance chart, stock composition table, and description.
import { BasketDetail } from 'nuqiwealth-widgets'
{basket && (
<BasketDetail
basketId={basket.id}
onClose={() => setBasket(null)}
/>
)}| Prop | Type | Required | Description |
|------|------|----------|-------------|
| basketId | string | ✓ | Basket identifier (from BasketItem.id) |
| onClose | () => void | ✓ | Called when the overlay is dismissed |
| width | number \| string | | Panel max-width. Default: 760px |
| height | number \| string | | Panel max-height. Default: 90vh |
| theme | PresetThemeName \| ThemeConfig | | Per-widget theme override |
| className | string | | |
| style | React.CSSProperties | | |
| overlayClassName | string | | |
| overlayStyle | React.CSSProperties | | |
Themes
Eight built-in presets:
| Preset | Accent | Mode |
|--------|--------|------|
| dark | Teal | Dark — default |
| light | Teal | Light |
| midnight | Blue | Dark |
| forest | Emerald | Dark |
| sunset | Amber | Dark |
| violet | Purple | Dark |
| arctic | Cyan | Light |
| dawn | Amber-brown | Light |
// Preset string
<NuqiWidgets theme="midnight" ...>
// Spread a preset and override specific tokens
import { MidnightTheme } from 'nuqiwealth-widgets'
<NuqiWidgets theme={{ ...MidnightTheme, accent: '#6366f1' }} ...>
// Per-widget override (overrides the provider theme for that widget only)
<StockList theme="arctic" />Without credentials
If apiKey or clientId is missing or invalid:
NuqiWidgetsmarks itself ready immediately — no infinite spinner- Each widget renders a neutral locked placeholder instead of fetching data
- No errors are thrown; no network requests are made
- Your app layout is never broken
You can build your UI with widgets in place before credentials are issued.
Security
- Keys are browser-safe by design.
apiKeyandclientIdare publishable widget keys scoped to read-only market data for your registered domain. They are not admin credentials. - No secrets are bundled. This package contains no hardcoded keys, no backend credentials, and no internal infrastructure details.
- Per-user gating. Pass an end-user JWT as
userTokento apply per-user feature restrictions. A per-user lock can only restrict — it cannot grant access the client plan does not already include. - Requests abort on unmount. All polling is cancelled when a widget unmounts — no stale requests or memory leaks.
Getting credentials
Purchase a plan at nuqiwealth.com to receive your apiKey, clientId, baseUrl, and the list of feature keys included in your plan. For enterprise enquiries contact [email protected].
License
Proprietary — see LICENSE. A valid purchased API key is required to use this software. Redistribution and reverse engineering are prohibited.
