Developer documentation
PulseIQ documentation
Everything you need to install, run, deploy and extend PulseIQ — a production-grade website health platform with a real audit engine, AI consultant insights and premium reporting.
Overview
PulseIQ audits any public website: it fetches the real HTML, parses SEO meta, headings, images, links, security headers and page structure, runs 20+ checks across six categories, and produces a weighted 0–100 score. A consultant layer ( src/lib/audit/insights.ts ) turns those raw findings into business observations, prioritized fixes, time estimates and a Before-vs-After simulator. Reports are exportable as branded PDF, CSV and JSON.
The stack is Next.js 16 (App Router) + React 19 + Tailwind CSS v4 + TypeScript. All data currently lives in the browser (localStorage) behind a clean store API, so swapping in a real backend is a drop-in change.
Quick Start
Get the app running locally in under two minutes:
# 1. Install dependencies
npm install
# 2. Start the development server
npm run dev
# 3. Open the app and run your first audit
open http://localhost:3000
# → sign up (demo auth), paste a URL, view your live reportNo database, API keys or environment variables are required — the app runs entirely self-contained. When you're ready to make it yours, see the Branding guide (one file controls the whole brand) and the Production checklist.
Installation
Requirements: Node.js 20.9+ and npm (or pnpm / yarn).
# 1. Install dependencies
npm install
# 2. (Optional) create your local env file
cp .env.example .env.local
# 3. Start the development server
npm run dev
# → http://localhost:3000The app runs entirely locally. No database, API keys or external services are required for the default experience.
Environment variables
PulseIQ ships with sensible defaults and runs with zero required variables. All variables are optional and future-proof the deployment:
# Optional — defaults shown; OAuth vars enable social sign-in
NEXT_PUBLIC_APP_URL=http://localhost:3000 # Canonical base URL (sharing, OG tags)
AUTH_SECRET=long-random-string # Signs session cookies (required in prod)
GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET=
GITHUB_CLIENT_ID= GITHUB_CLIENT_SECRET=
MICROSOFT_CLIENT_ID= MICROSOFT_CLIENT_SECRET=
AUDIT_TIMEOUT_MS=15000 # Per-request fetch timeout for the audit engine
AUDIT_MAX_BYTES=5242880 # Max page size the scanner will download (5 MB)
AUDIT_USER_AGENT=PulseIQBot/1.0 # User agent used when fetching pagesThe audit engine already hardcodes safe production defaults for timeouts and size limits, so these are pure tuning knobs.
Build & commands
npm run dev # Start the dev server (Turbopack HMR)
npm run build # Production build — all routes + type safety
npm run start # Serve the production build
npm run lint # ESLint across the whole project
npm run typecheck # tsc --noEmit (zero-config type checking)The production build is verified green before every release — it compiles all routes including the audit API, dashboard, public share views and docs.
Project structure
src/
├── app/
│ ├── layout.tsx # Root layout, metadata, theme + auth providers
│ ├── page.tsx # Marketing landing page
│ ├── api/audit/route.ts # POST /api/audit — the real audit endpoint
│ ├── (auth)/ # Login, register, forgot/reset password
│ ├── dashboard/ # Dashboard shell + all app pages
│ │ ├── audit/ # New audit flow (form → scan → LiveReport)
│ │ ├── history/ # Saved audits, search/filter/sort
│ │ ├── reports/ # Report index + saved-report viewer
│ │ ├── compare/ # Competitor comparison (real audits)
│ │ ├── actions/ # Action Center (fix tracking)
│ │ ├── fixes/ settings/ billing/ monitoring/ help/
│ └── share/[id]/ # Public read-only report route
├── components/
│ ├── audit/ # LiveReport, AI Insights, Fix Generator,
│ │ # Content Studio, Improvement Plan,
│ │ # Before/After, Export Center, PDF report
│ ├── dashboard/ # Sidebar, header
│ ├── landing/ # Marketing sections
│ ├── ui/ # Button, Card, charts, grade badge, etc.
├── lib/
│ ├── audit/ # THE AUDIT ENGINE (see Architecture)
│ │ ├── fetcher.ts url.ts ssrf.ts sitemap.ts broken-links.ts
│ │ ├── parser/ # meta, headings, images, links, page-info,
│ │ │ # security, structured-data
│ │ ├── checks/ # seo, accessibility, technical, performance,
│ │ │ # security, best-practices
│ │ ├── score.ts # Configurable weighted scoring engine
│ │ ├── insights.ts # AI consultant engine (all derived from real data)
│ │ ├── fix-generator.ts content-generator.ts grade.ts types.ts
│ ├── audit-store.ts # localStorage persistence for audits
│ ├── action-store.ts # Action Center progress persistence
│ ├── exporters.ts # CSV + JSON export
│ └── validators.ts utils.ts sample-data.ts
│ ├── auth/ # REAL authentication
│ │ ├── types.ts # AuthUser, session payload, provider profiles
│ │ ├── session.ts # HMAC-signed httpOnly session cookie
│ │ ├── providers.ts # OAuth endpoint + scope config per provider
│ │ ├── oauth.ts # PKCE authorize / code exchange / profile fetch
│ │ └── redirect.ts # safe post-login redirect validation
│ ├── auth-provider.tsx # client useAuth() hook (reads /api/auth/session)Architecture overview
The audit engine is deliberately layered so new modules can be added without touching existing code:
URL → fetcher (validate → SSRF-guard → fetch → size/timeout limits)
→ parser/* (cheerio, extracts every signal into plain types)
→ checks/* (each module returns AuditCheck[] with severity/impact/effort/
whyItMatters/fix/docs)
→ score.ts (weighted categories → 0–100 + status)
→ AuditResult (pure data, no presentation)
→ insights.ts (consultant layer: business impact, priority timeline,
improvement potential, time/difficulty estimates)
→ UI (LiveReport tabs, Export Center, PDF, dashboard, compare)- Parsers and checks only read — they never mutate shared state. Every check is a pure function of the parsed page.
- The scoring engine is data-driven: category weights, severity deductions and impact multipliers are exported constants you can rebalance.
- The consultant layer derives every number from real findings via documented formulas — nothing is fabricated.
- Persistence is behind two small stores (audits, actions). Swapping localStorage for Postgres/Supabase touches only those files.
Configuration
The scoring engine lives in src/lib/audit/score.ts — category weights, severity penalties and the status thresholds are exported constants:
export const DEFAULT_CATEGORIES = [
{ key: "seo", label: "SEO", weight: 0.25 },
{ key: "performance", label: "Performance", weight: 0.20 },
{ key: "security", label: "Security", weight: 0.20 },
{ key: "accessibility", label: "Accessibility", weight: 0.15 },
{ key: "technical", label: "Technical", weight: 0.10 },
{ key: "best-practices", label: "Best Practices", weight: 0.10 },
];To rebalance: change a weight (they must sum to 1) and the overall score recomputes everywhere — the dashboard, reports, share views and PDF export all read the same result.
Branding guide
PulseIQis designed to be reskinned by a buyer in minutes. Every visible brand surface — product name, wordmark, tagline, description, company name, support & contact emails, website, social links, SEO metadata, Open Graph, Twitter cards, feature flags, subscription plans, audit defaults, localStorage keys and the scanner's user agent — is centralized in one file:
export const brand = {
name: "PulseIQ",
wordmark: { prefix: "Pulse", suffix: "IQ", suffixClassName: "text-gradient" },
tagline: "Know Your Website. Grow Your Business.",
description: "...",
websiteUrl: "https://pulseiq.ai",
appUrl: "https://app.pulseiq.ai",
iconPath: "/favicon-32x32.png", // primary browser favicon
icons: { favicon16, favicon32, favicon48, appleTouch, icon192, icon512 },
};
export const company = {
legalName: "PulseIQ",
supportEmail: "support@pulseiq.ai",
contactEmail: "hello@pulseiq.ai",
website: "https://pulseiq.ai",
socials: [ { label: "X (Twitter)", href: "..." }, ... ],
};
export const metadata = { ... }; // SEO / Open Graph / Twitter
export const features = { ... }; // demoMode, contentStudio, ...
export const plans = [ ... ]; // subscription tiers
export const identifiers = { ... }; // storage keys + bot user agentTo rebrand, edit this one file plus two assets:
- Edit src/config/site.ts — names, tagline, emails, URLs, socials, metadata, plans and flags.
- Replace the favicon PNGs in public/ (favicon-16x16.png, favicon-32x32.png, apple-touch-icon.png, …) — the icons used in the browser tab, mobile home screens and exports.
- Tune the brand colors in src/app/globals.css (the brand-500 → brand-600 Tailwind tokens) if you want a different accent.
- Everything else — dashboard, landing, auth, PDF reports, exports, share pages, docs — reads from config and updates automatically.
Customization guide
Common customizations and where to make them:
- Subscription plans & pricing — edit the plans array in src/config/site.ts; the landing pricing section, billing page and upgrade cards all render from it.
- Demo mode — set features.demoMode to false to hide all sample data and show honest empty states instead.
- Free-plan audit allowance — auditDefaults.freeMonthlyAudits controls the counter shown on the audit page.
- Default scan device & depth — auditDefaults.device and auditDefaults.depth set the scanner defaults.
- Storage & bot identity — identifiers.storagePrefix namespaces localStorage; identifiers.botUserAgent identifies the scanner to sites.
- Feature flags — features.contentStudio and features.competitorCompare toggle whole sections of the product.
- Support links — links.docs / links.help / links.pricing drive the help center and footer navigation.
The architecture keeps every extension point small and isolated, so a buyer can ship custom features without fighting the framework.
Troubleshooting
- “Audit failed with code dns” — the domain has no resolvable addresses; check the spelling or try the www subdomain.
- “Audit failed with code blocked” — some sites (or their CDNs) block automated scanners. The engine reports this gracefully instead of crashing.
- Scores differ between runs — sites change constantly. Cache headers, A/B tests and dynamic content all affect the measured page.
- Shared report links only work on this device — reports are stored per-browser until a backend store is connected (see Extension points).
- Slow audits — the engine intentionally caps page size and timeout so one heavy site can never stall the server.
Production checklist
Before launching to real users, walk this list — each item is a one-line change or a config value:
- Set features.demoMode = false in src/config/site.ts so users see honest empty states instead of sample data.
- Update brand.websiteUrl / brand.appUrl to your real domains and set NEXT_PUBLIC_APP_URL in your hosting env.
- Replace the placeholder social links and contact/support emails in the company block of src/config/site.ts.
- Provide real Terms and Privacy pages and point links.terms / links.privacy at them.
- Replace the favicon PNGs in public/ with your brand mark and confirm the browser tab renders it (the config iconPath points at favicon-32x32.png).
- Confirm identifiers.botUserAgent and identifiers.storagePrefix are unique to your deployment.
- Enable HTTPS on the hosting domain and verify the audit API responds with a sane timeout under load.
- Run npm run build && npm run lint to confirm the production build is green before each deploy.
The audit API already applies SSRF guards, size limits, timeouts and friendly error codes, so no additional hardening is required for the default deployment.
Deployment
PulseIQ is a standard Next.js app — deploy it anywhere Node.js runs.
# Framework preset: Next.js
# Build command: npm run build
# Output directory: .next
# No environment variables are required.npm ci
npm run build
npm run start # serves on process.env.PORT or 3000- The audit API uses server-side fetch with its own timeouts — no serverless function size tuning is needed for the default flow.
- For high-traffic deployments, wrap the API in a queue or worker; the route is already stateless.
- Custom domains, SSL and caching follow standard Next.js hosting guidance.
Future extension points
PulseIQ is architected so the next features drop in without rewrites:
- Backend persistence — replace getSavedAudits/saveAudit (src/lib/audit-store.ts) with an API; the reports, history, share and compare pages need zero changes.
- Real authentication — OAuth (Google, GitHub, Microsoft) and email sessions are already server-side; swap the session store for a database-backed user store to enable password verification and account recovery.
- New audit modules — add a parser + a checks/* module and register it; the scoring engine, report UI and PDF automatically pick it up.
- Public share with auth — the /share/[id] route and share URL scheme are already live; private links/expiry need only a permission check on the store.
- Scheduled monitoring — the API is stateless, so a cron or queue calling POST /api/audit and diffing scores is a straight add.
- PDF rendering server-side — the branded PdfReport component is pure React; it can be rendered to HTML for html-pdf/puppeteer without redesign.
Frequently asked questions
Do I need a database or API keys to run this?
No. PulseIQ runs fully self-contained: audits are real (server-side fetch + parser), reports are stored in the browser behind a clean store API, and authentication uses real OAuth (Google, GitHub, Microsoft) with an HMAC-signed httpOnly session cookie. A backend can be added later without rewrites.
How long does an audit take?
Most pages complete in 10–40 seconds depending on size and redirects. The engine caps page size and per-request timeout so one heavy site can never stall the server.
Are the scores and AI recommendations real?
Yes. Every score is computed by the weighted scoring engine from the parsed page, and every insight, fix and estimate in the consultant layer is derived from those real findings via documented formulas — nothing is fabricated.
Can I resell or white-label this product?
Yes — that is the point of the branding guide. Edit src/config/site.ts, swap the favicon PNGs in public/, adjust the accent colors in globals.css, and the whole product (dashboard, landing, auth, PDFs, exports, share pages) re-brands itself.
Where can I get help?
Reach the maintainers at support@pulseiq.ai (support) or hello@pulseiq.ai (general).
What happens when demo mode is off?
Sample data disappears everywhere. Empty states (dashboard, reports, monitoring, fixes) become honest prompts to run your first real audit.
© 2026 PulseIQ. All rights reserved. · Know Your Website. Grow Your Business.
Return to the product