尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Recovery is difficult to manage without structure. Pulse provides patients transitioning from hospital or clinical care with daily check-in rituals, progress visibility, and community support.
Patients leaving hospital or clinical care face a critical gap: the loss of daily medical oversight and structured routine. Between appointments, motivation declines, progress becomes invisible, and recovery drifts without reinforcement. The result is disengagement and setbacks.查看完整 README ↗Recovery is difficult to manage without structure. Pulse provides patients transitioning from hospital or clinical care with daily check-in rituals, progress visibility, and community support.
Patients leaving hospital or clinical care face a critical gap: the loss of daily medical oversight and structured routine. Between appointments, motivation declines, progress becomes invisible, and recovery drifts without reinforcement. The result is disengagement and setbacks.
Pulse addresses this by creating a structured daily check-in ritual, making recovery progress visible through charts, and providing community connection with others in similar circumstances.
Structure: Recovery benefits from daily routine. A single check-in per day creates the behavioral anchor needed for consistency.
Visibility: Progress is often hard to feel day by day. Charts and trends make recovery visible over time, revealing patterns individual days cannot show.
Early Detection: Pattern analysis can identify when engagement or mood is declining, helping catch setbacks early.
Community: Connection with others going through recovery reduces isolation during a vulnerable time.
Daily Check-Ins Users log mood (1-10), pain level (1-10), activities, and notes in a single daily ritual. The system enforces one check-in per calendar day; subsequent submissions update the existing entry.
Progress Visualization Mood and pain charts display trends over time, making recovery visible and tangible.
Community Forum
A space for patients to share experiences, ask questions, and connect with others in recovery. Includes posts, replies, voting, and tag-based filtering. Opening a post detail page records a view with a fire-and-forget POST /forum/posts/:postId/view (useRecordPostView, once per mount per post, errors ignored); the server counts one view per profile per post per rolling 24 h and skips the author. It is a dedicated call because the detail page often seeds from the list cache and makes no GET /forum/posts/:id. The post list and the replies list load with keyset paging: the first request sends neither cursor nor page, and each next request sends cursor set to the id of the last item loaded; an empty page ends the list (in cursor mode a full page can be the last one). The popular filter stays on page numbers, because the server rejects cursor with hot and popular; GET /forum/posts/saved takes no cursor. If the server answers 404 Cursor not found (the cursor item was deleted while scrolling) the list restarts from the first page instead of showing an error (useResetOnLostCursor).
Launch emails link to /?utm_source=launch&utm_campaign=<slug>&lm=<token>. On landing, on any page, LaunchOpenTracker (useRecordLaunchOpen) sends POST /launch-funnel/open with { token } once per visit (flag in sessionStorage); a token that does not match [A-Za-z0-9_-]{16,128} is not sent, and failures are ignored. The server sets the launch_token httpOnly cookie and records the registration itself on signup, so the client never sends lm at signup.
User Profiles Profiles capture bio, location, timezone, and emerging personalization through health interests and activity preferences. These support improved recommendations and community connection.
Insights
Lightweight, supportive insights generated from check-in patterns help detect trends and maintain motivation. Insights are explicitly labeled as AI-assisted suggestions, not medical advice. They are kept short (about two sentences; the daily observation title is 5 words or fewer in Hebrew), so layouts should not assume long text. Check-in notes are included in the AI prompt by default; users can turn this off with "Use my notes for insights" in Settings, under App Preferences. Insights are generated by the server after the check-in is saved: the submit returns immediately with insightsStatus: 'pending', and the client polls GET /check-in?limit=1 every 3 s (up to 60 s, then stops silently) until the status is 'ready', then shows the insight toasts (useCheckInInsightsPolling, mounted in CheckInContext).
Support
/support is the help center: an FAQ and a contact form (topic + message, plus an email field for logged-out visitors) that posts to POST /support/contact, which emails [email protected]. /contact-support redirects to the form (/support#contact). Search, quick-help cards and browse-by-topic cards are built but hidden behind the supportSearch, supportQuickHelp and supportTopics flags in src/config/features.ts until the help articles, chat and care-team features exist.
Legal Pages
/privacy and /terms (English and Hebrew) with a table of contents and a localized last-updated date. Each page has a "Download PDF" button that links to a pre-generated PDF in public/legal/ ({privacy,terms}-{en-US,he-IL}.pdf). The privacy policy discloses the essential cookies, on-device storage and service providers; Pulse sets no tracking cookies, so there is no cookie-consent popup.
Installable App (PWA)
Pulse can be installed to the home screen and opens standalone. src/app/manifest.ts serves the web app manifest (name, theme color, 192/512/maskable icons); the favicon and WebP apple-touch icon live in public/, and docs/design/pwa/ holds the SVG sources they are rendered from. public/sw.js is a deliberately minimal service worker that caches nothing, so no signed-in page is ever stored; it registers in production only. Signed-in phone users see an install dialog (InstallPromptDialog): an Install button on Android/Chrome (the beforeinstallprompt event, captured in src/lib/installPromptStore.ts) and Add to Home Screen steps on iOS. It is hidden once installed, and dismissing it snoozes it for 14 days via one localStorage key, disclosed on the Privacy page. No server changes are involved.
| Layer | Technology |
|---|---|
| Frontend | Next.js 16, React 19, TypeScript, TanStack Query |
| Styling | TailwindCSS 4, shadcn/ui |
| Routing | Next.js App Router (file-based) |
| Forms | react-hook-form, Zod |
| HTTP | Axios with CSRF interceptors |
| State | TanStack Query, Next.js Context |
| Deployment | AWS EC2+Docker (production, auto-deploy CI/CD), Vercel (preview/staging) |
Note: This is a frontend-only repository. The backend API runs separately.
http://localhost:4001 (optional for development)# Clone and install
git clone https://github.com/BarcDevs/Pulse--client.git
cd Pulse--client
npm install
# Create environment file
cp .env.example .env.local
# Start dev server
npm run dev
# Backend API endpoint
NEXT_PUBLIC_API_URL=http://localhost:4001
# Error tracking (optional)
NEXT_PUBLIC_SENTRY_DSN=your-sentry-dsn
npm run dev # Start Next.js dev server (localhost:3000)
npm run build # Production build
npm run start # Run production server
npm run lint # Check ESLint violations
npm run lint:fix # Auto-fix formatting and linting
npm run typecheck # TypeScript type checking
npm run legal:pdf # Regenerate public/legal/*.pdf from the running dev server (localhost:5173)
The legal PDFs are generated, not built on the fly. After changing legal copy in messages/*.json (or the page layout), start npm run dev, run npm run legal:pdf, and commit the updated PDFs.
See docs/structure.md for complete structure.
Key directories:
See Technical PRD for:
Code follows CORE_RULES.md conventions:
Pulse supports two authentication methods:
Email & Password
Google OAuth
Both methods use the same session system:
accessToken cookie (auto-sent on requests)_csrf cookie (read and sent as x-csrf-token header for mutations)The server is language-agnostic and always returns English message text (diagnostics only —
logs/dev display). Every error response also carries a stable code plus optional params,
meant for the client to drive its own translation table:
{
"message": "Post not found! please check your inputs and try again!",
"error": [
{
"statusType": "Not Found",
"statusCode": 404,
"code": "NOT_FOUND",
"params": { "resource": "Post" },
"error": "Post not found! please check your inputs and try again!"
}
]
}
Codes are fixed per server error-factory method (not per resource) — e.g. NOT_FOUND covers
every resource type via params.resource, so new server-side resources never require a new
client translation entry. Full code list and shapes: server README.md → Error Responses
(../pulse--server/README.md#error-responses).
To build the client translation table: map each code in src/constants/errorCodes.ts
(server repo) to a localized string per supported language, interpolating any params values
into the message. Never localize by parsing the English message string — it's not stable and
not meant for that.
Production runs on AWS EC2+Docker at https://pulserehab.app, on a separate instance from the server (blast-radius isolation). The client is the sole public front door — next.config.mjs proxies /api/:path* to the server over a private VPC connection, so browsers only ever talk to one origin (no CORS).
Ingress — Cloudflare reaches the box only through a Cloudflare Tunnel (cloudflared container, outbound-only, started by ec2-redeploy.sh with the token from Secrets Manager pulse/client/CLOUDFLARE_TUNNEL_TOKEN). The app binds to 127.0.0.1:80 and the security group has no public HTTP/HTTPS ingress, so the origin can't be hit directly.
CI/CD — every push to main that passes CI (.github/workflows/ci.yml) triggers .github/workflows/deploy.yml:
runner Docker target, tag with the commit SHA, push to ECR (pulse-client-app).scripts/deploy/ec2-redeploy.sh on the EC2 box via AWS SSM (no SSH/git access needed on the box).GET /), then swapped onto port 80. Failed health check rolls back to the previous container automatically./ and /api/status) before the workflow reports success.Can also be triggered manually: gh workflow run deploy.yml --ref main.
Also mirrored to Vercel at https://pulse-rehab.vercel.app (automatic builds from main) for preview/staging convenience — not the production origin.
Every push to development auto-deploys a staging build, isolated from production.
| Property | Value |
|---|---|
| URL | staging.pulserehab.app |
| Branch | development |
| Host | Vercel (production runs on AWS — staging stays on Vercel) |
| Vercel Authentication | Disabled (publicly reachable) |
Branch-scoped env vars — NEXT_PUBLIC_SERVER_URL is overridden for preview + development branch only (vercel env ls preview), pointing at the staging server. All other preview branches fall back to the default value.
Backend URL variable — the /api rewrite in next.config.mjs reads SERVER_URL first and falls back to NEXT_PUBLIC_SERVER_URL (kept so the Vercel preview override above keeps working). The EC2 Docker build passes only the non-public SERVER_URL, so the private backend address is never inlined into the browser bundle. Don't reintroduce a NEXT_PUBLIC_ copy or read it from src/config.
Gotcha: NEXT_PUBLIC_* vars are inlined into the JS bundle at build time. Adding/changing one does not affect already-deployed builds — trigger a rebuild:
vercel redeploy <deployment-url> --target preview