A Next.js stock dashboard. The charts, heatmap, news and quotes are embedded TradingView widgets; the app's own code adds ticker search through the Finnhub API, a page per symbol, and two Inngest jobs that e-mail a welcome note and a daily news summary written by Gemini.
Status: experimental, version 0.1.0, not production-ready. It started from the JavaScript Mastery "Signalist" tutorial app. There is no sign-in and the watchlist is not saved, so it is a read-only dashboard today.
- Open
/for the market overview, stock heatmap, top stories and market quotes. - Press ⌘K (Ctrl-K) or click Search in the header, type a company or ticker, and pick a result.
- Read
/stocks/<SYMBOL>: price header, candlestick and baseline charts, technical analysis, company profile and financials. The "Add to Watchlist" button toggles, but nothing is stored.
- Search.
lib/actions/finnhub.actions.tscalls Finnhub/searchfor queries and/stock/profile2for the popular-symbol list shown before you type. The list is fetched in the header on the server. - Market widgets.
components/TradingViewWidget.tsxinjects TradingView's embed scripts in the browser. Prices, charts and ratings come from TradingView, not from this app. - E-mail jobs.
/api/inngestserves two functions fromlib/inngest/functions.ts:sign-up-emailon theapp/user.createdevent, anddaily-news-summaryon cron0 12 * * *(UTC) or theapp/send.daily.newsevent. The daily job reads users and watchlists from MongoDB, fetches Finnhub news per symbol, asks Gemini for a summary and sends it with nodemailer over Gmail. These jobs have not been run end to end; they need MongoDB, Inngest, Gemini and Gmail credentials.
Not in this repository
- Sign-in, sign-up and sessions. The auth pages and the Better Auth route handler are missing; only the helpers
lib/better-auth/auth.tsandlib/actions/auth.actions.tsremain. No page passes a user to the header, so the user menu (UserDropdown) never appears. - Watchlist storage. The button only changes local component state.
- Alerts.
Real screenshot of /stocks/AAPL from a production build with no API keys. Everything below the header except the
yellow watchlist button is an embedded third-party TradingView widget; the prices, charts, ratings and financials
come from TradingView, not from this app.
Requires Node.js 22 or newer. Tested with Node 24 and npm 11; CI uses Node 22 and 24.
git clone https://github.com/hellpuffyt/puffer-tracker.git && cd puffer-tracker
npm ci
cp .env.example .env.local # then set FINNHUB_API_KEY
npm run devOpen http://localhost:3000. Without FINNHUB_API_KEY the app still runs; the TradingView widgets work, the search
list is empty and the server logs Error in stock search: Error: FINNHUB API key is not configured.
For a production server, run npm run build && npm start.
See .env.example. FINNHUB_API_KEY is the only variable the pages need; the rest are for the
e-mail jobs and the auth helpers. The dashboard is prerendered at build time, so set FINNHUB_API_KEY before
npm run build if you want the popular-stock list in a production build.
/api/inngest answers 401 {"message":"Unauthorized"} unless INNGEST_SIGNING_KEY is set (production) or
INNGEST_DEV=1 is set (local, with the Inngest dev server); with
INNGEST_DEV=1 it returns the Inngest introspection JSON listing the 2 functions.
app/ routes (App Router): /, /stocks/[symbol], /api/inngest
components/ UI components (shadcn/ui primitives in components/ui)
lib/ Finnhub actions, Inngest jobs, mailer, auth helpers, widget configs
database/ MongoDB connection and watchlist model
tests/ Vitest unit tests
npm run lint
npm run typecheck
npm test # vitest; no network, Finnhub calls are mocked
npm run build
npm run test:db # optional: connects to MONGODB_URI from .env (not .env.local), prints OK or ERRORnpm run lint currently reports 0 errors and 6 warnings. CI (.github/workflows/ci.yml) runs lint, typecheck, test
and build on Node 22 and 24 with no secrets.
docs/PRODUCTION_READINESS.md records which commands were run and what was not checked.
- No authentication, no saved watchlist, no alerts.
- The e-mail jobs and live Finnhub calls have not been exercised (no credentials were available).
- On screens narrower than 640 px the header navigation, including Search, is hidden (
hidden sm:block) and no mobile menu replaces it, so search is not reachable on phones. - AI-generated summaries are inserted into the e-mail HTML without escaping; see docs/PRODUCTION_READINESS.md.
Report vulnerabilities through a private GitHub advisory,
as described in SECURITY.md. Keep keys in .env.local; .env* files other than .env.example are
git-ignored.
See CONTRIBUTING.md.
None. This app started from the JavaScript Mastery "Signalist" tutorial
(adrianhajdin/signalist_stock-tracker-app),
and that repository publishes no license: there is no LICENSE file, no license field in its
package.json, and no reuse terms in its README (checked 2026-10-26). Without a license from the
original author I can't grant rights to the code derived from it, so this repository has no license
either and all rights stay with the respective authors. Read the code for learning; don't reuse it.