Skip to content

feat(deploy): add production-ready Dockerfile, docker-compose, and un… - #1158

Merged
itzzavdhesh merged 13 commits into
itzzavdhesh:mainfrom
Myparadox-creator:feat/docker-deployment
Aug 11, 2026
Merged

feat(deploy): add production-ready Dockerfile, docker-compose, and un…#1158
itzzavdhesh merged 13 commits into
itzzavdhesh:mainfrom
Myparadox-creator:feat/docker-deployment

Conversation

@Myparadox-creator

@Myparadox-creator Myparadox-creator commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

🚀 Program

ELUSOC

📝 Description

This PR introduces a production-ready Docker setup for VoiceForge, streamlining containerized deployment with multi-stage builds, non-root security compliance, automated healthchecks, and unified static asset serving.

Key Changes:

  • Multi-Stage Dockerfile: Built on node:20-alpine with separate builder (compiles React client) and unprivileged runner (USER node) stages.
  • Production Static Serving: Updated server/index.js to serve compiled React SPA assets from client/dist when in production mode (NODE_ENV=production) with SPA route fallback.
  • Docker Compose Setup: Added docker-compose.yml for single-command stack orchestration (docker compose up -d --build).
  • Optimization (.dockerignore): Excluded node_modules, test artifacts, logs, and unnecessary binaries to minimize container context footprint (~150MB).
  • UI & Subtitle Fixes: Fixed component import extensions, state hook dependencies, and subtitle ref handling across App.jsx, Onboarding.jsx, Call.jsx, VoiceRecorder.jsx, and SpeechHistory.jsx.

🔗 Related Issue

Closes #1109

🔄 Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 🔍 SEO improvement
  • 🎨 Style / UI improvement
  • ♿ Accessibility improvement
  • 📝 Documentation
  • ⚙️ CI / configuration
  • 🧹 Refactor / cleanup

🧪 How to Test

  1. Build the production Docker image:
    docker build -t voiceforge:latest .
  2. Run the container:
    docker run -d --name voiceforge-app -p 3001:3001 voiceforge:latest
  3. Verify container health & API status:
    curl http://localhost:3001/api/health (Returns {"ok":true,"service":"voiceforge-api"})
    curl http://localhost:3001/api/voice/status
  4. Verify unified client UI:
    Open http://localhost:3001 in Chrome or Edge browser.
  5. Verify non-root container security:
    docker exec voiceforge-app id (Outputs uid=1000(node))
  6. Verify Docker Compose:
    docker compose up -d --build

📸 Screenshots (if applicable)

Screenshot 1: Successful Docker Build

Screenshot 2026-07-25 183155

Screenshot 2: Active Container & Healthcheck

Screenshot 2026-07-25 183443

Screenshot 3: API Endpoint Verification

Screenshot 2026-07-25 182810

Screenshot 4: VoiceForge UI in Browser

Screenshot 2026-07-25 183730

Screenshot 5: Build matrics

Screenshot 2026-07-25 182842

✅ Checklist

  • I am contributing under ELUSOC
  • My code follows the project's existing style
  • I have tested my changes in a browser
  • I have linked the related issue above
  • My PR title follows Conventional Commits format (e.g. feat: add voice preview)

Summary by CodeRabbit

  • New Features
    • Added subtitle overlays with persisted preferences and active-text display.
    • Added speech-history tagging, tag filtering, quick-reply actions, and improved analytics.
    • Enabled production SPA hosting with health checks and client-side route support.
  • Bug Fixes
    • Improved audio extraction safety and recording validation.
    • Added a user-friendly error fallback with reload support.
    • Hardened subtitle, tag, backup, and recording input handling.
  • Documentation
    • Added MIT license information.
  • Chores
    • Added container build configuration with restricted port exposure.

@vercel

vercel Bot commented Jul 26, 2026

Copy link
Copy Markdown

@Myparadox-creator is attempting to deploy a commit to the itzzavdhesh's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds production Docker deployment and SPA serving. It updates speech-history tagging and analytics, recording extraction, subtitle state, startup error handling, imports, and the text-to-speech control.

Changes

VoiceForge production and frontend runtime

Layer / File(s) Summary
Production image assembly
.dockerignore, Dockerfile
Docker builds compile the client, prune development dependencies, exclude local artifacts, and run the server as the unprivileged node user.
SPA serving and container wiring
server/index.js, docker-compose.yml
Express serves the compiled SPA for browser navigation requests. Compose binds port 3001 to localhost and retains health-check configuration.
Speech history tagging and analytics
client/src/hooks/useSpeechHistory.js, client/src/components/SpeechHistory.jsx, client/src/components/VoiceForge.jsx
History entries use UUID fallback generation. Tag actions update history immutably. SpeechHistory validates, filters, and aggregates tagged data.
Persisted subtitle rendering
client/src/pages/Call.jsx, client/src/components/VideoPreview.jsx
Call loads subtitle preferences and tracks active speech text. VideoPreview receives and synchronizes the subtitle state.
Recording extraction and onboarding validation
client/src/components/VoiceRecorder.jsx, client/src/pages/Onboarding.jsx
Extraction payloads are normalized safely. Recording is blocked during extraction. Onboarding stores normalized recording metadata and duration.
Startup resilience and frontend cleanup
client/src/main.jsx, client/src/App.jsx, client/src/components/VoiceForge.jsx, client/src/components/TextToSpeech.jsx, README.md
The app gains a reloadable error fallback. Selected imports use explicit extensions. The Clear control is removed. The README declares the MIT license.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

  • itzzavdhesh/VoiceForge#752: Relates to the Dockerfile and Docker Compose containerization changes.
  • itzzavdhesh/VoiceForge#1122: Relates to adding a production Dockerfile and exposing the application port.

Possibly related PRs

Suggested labels: type:refactor, needs revision

Suggested reviewers: joyprakashk, rushi-k12

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant Express
  participant ClientDist
  Browser->>Express: GET browser route with text/html Accept
  Express->>ClientDist: Serve client/dist/index.html
  ClientDist-->>Browser: Return SPA entry document
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Several UI, subtitle, history, error-boundary, and licensing changes are unrelated to the Docker deployment objective in [#1109]. Move unrelated UI and licensing changes to separate pull requests or link issues that explicitly require them.
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary deployment change by naming the production Dockerfile and Compose setup.
Linked Issues check ✅ Passed The PR adds a multi-stage production Dockerfile, removes development dependencies from the runtime image, and supports successful execution for [#1109].
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown

✍️ DCO Sign-off Needed

Hey @Myparadox-creator! 👋 One or more commits in this PR are missing a Signed-off-by: line.

Warning

  • ef49e47 Merge branch 'main' into feat/docker-deployment
  • 800050b Merge branch 'main' into feat/docker-deployment

How to fix:

For the latest commit:

git commit --amend --signoff
git push --force-with-lease

For multiple commits, replace N with the number to update:

git rebase --signoff HEAD~N
git push --force-with-lease

This comment will update automatically after you push.


🤖 VoiceForge Automation · Updates automatically on edits

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown

🎉 PR Ready for Mentor Review

Hey @Myparadox-creator! 👋 Your PR passed all checks and is now in the ELUSOC review queue.

Note

🔗 Closing: #1109 · 📐 427 lines across 13 file(s) · 📬 Already requested or no eligible reviewer found

@joyprakashk @rushi-k12, this PR is ready for your review — please confirm scope, check behavior and tests, then approve or request changes.

Important

This is not an approval. Please wait for mentor feedback before expecting a merge. If changes are requested, push them to this same branch and keep the PR focused on the linked issue.


🤖 VoiceForge Automation · Updates automatically on edits

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 14 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="client/src/components/SpeechHistory.jsx">

<violation number="1" location="client/src/components/SpeechHistory.jsx:19">
P1: Tag management and quick-reply promotion in the history panel are non-functional because the new callbacks (`onAddTag`, `onRemoveTag`, `onAddToQuickReplies`) are passed to `MessageCard` but never wired from the parent `VoiceForge` component. Adding a tag in the history panel silently discards the input, and clicking the "Promote to Quick Reply" button does nothing even though `VoiceForge` already defines `handleAddToQuickReplies`. Wire all three callbacks from `VoiceForge` to `<SpeechHistory>` so these UI features work correctly.</violation>
</file>

<file name="client/src/pages/Call.jsx">

<violation number="1" location="client/src/pages/Call.jsx:27">
P1: Subtitle overlay settings are stored and rendered in the UI, but the state values are never passed to `<VideoPreview>`, which is the component responsible for drawing the subtitle overlay on canvas. The subtitle configuration UI has no observable effect, and `VideoPreview.jsx` additionally references undeclared refs (`subtitlesEnabledRef`, `subtitleFontSizeRef`, `subtitleBgOpacityRef`, `activeTextRef`) that would throw `ReferenceError` during the animation draw loop.

Pass `subtitlesEnabled`, `subtitleFontSize`, and `subtitleBgOpacity` as props to `<VideoPreview>`, and refactor `VideoPreview` to accept and use them (either via received props or declared refs). `activeTextRef` also needs to be provided from the parent to supply the subtitle text content.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread client/src/pages/Onboarding.jsx Outdated
Comment thread client/src/pages/Call.jsx
Comment thread docker-compose.yml Outdated
Comment thread Dockerfile Outdated
Comment thread client/src/components/SpeechHistory.jsx
Comment thread client/src/components/VoiceRecorder.jsx Outdated
Comment thread client/src/main.jsx Outdated
Comment thread Dockerfile Outdated
Comment thread Dockerfile Outdated
Comment thread server/index.js Outdated
…ified asset serving

Signed-off-by: Aditya R. Satapathy <adityaranjanwxd@gmail.com>
…dingReady callback

Signed-off-by: Aditya R. Satapathy <adityaranjanwxd@gmail.com>
… and client

Signed-off-by: Aditya R. Satapathy <adityaranjanwxd@gmail.com>
…d verify tag callbacks

Signed-off-by: Aditya R. Satapathy <adityaranjanwxd@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@client/src/components/SpeechHistory.jsx`:
- Around line 26-39: Update the SpeechHistory state flow around selectedTag and
allUniqueTags so history changes cannot leave selectedTag set to a tag no longer
present. Reset invalid selections to “All Tags” (or make filtering treat them
equivalently), while preserving valid tag selections and the existing
allUniqueTags derivation.
- Around line 41-56: The analyticsData memo currently uses deduplicated history,
undercounting repeated speech events. Update SpeechHistory to accept the event
history, use analyticsHistory or sessionTranscript as the memo’s input for
totalSentences, totalWords, and top counts, and update the dependency
accordingly while preserving the existing analytics shape.
- Around line 31-39: Normalize imported message tags in importBackup (or the
shared validation path) to an array of non-empty strings, removing invalid
values before storing messages. Also guard the allUniqueTags derivation and
downstream tag-search consumers so malformed tags cannot reach .some() or
.toLowerCase(), while preserving valid tags.

In `@client/src/components/VoiceRecorder.jsx`:
- Around line 189-203: In the file-extraction flow after await
extractAudioFromFile, return immediately when isMountedRef.current is false
before creating the object URL, updating refs/state, or calling
onRecordingReady. Also guard the catch and finally state updates so unmounted
extraction results do not call setRecorderError or setIsExtracting.

In `@client/src/main.jsx`:
- Around line 25-30: The error boundary render output currently exposes raw
stack or error text. Update the error display around this.state.error to show
stack/toString diagnostics only in the development build, and render a generic
user-safe message in production.

In `@client/src/pages/Call.jsx`:
- Around line 510-512: Update the Call component’s handleSpeak flow to store the
spoken text in state, then pass that state as activeText to VideoPreview
alongside the existing subtitle props. Ensure the stored value updates whenever
handleSpeak receives new text so subtitle rendering uses the current spoken
text.

In `@client/src/pages/Onboarding.jsx`:
- Around line 206-227: Update handleRecordingReady to detect when the normalized
blob is missing, including the onRecordingReady(null) case, then call
setRecording(null) and return before constructing the recording state object.
Preserve the existing validation and setRecording({ blob, duration, isValid })
behavior for valid recording payloads.

In `@docker-compose.yml`:
- Around line 8-9: Update the service ports mapping in the Docker Compose
configuration to bind host port 3001 explicitly to 127.0.0.1, preserving
container port 3001 and the intended localhost-only deployment.

In `@server/index.js`:
- Around line 57-66: Update the SPA fallback middleware around app.use so it
only serves index.html for GET document requests whose Accept header includes
text/html; continue passing /api requests and all other methods or non-HTML
resource requests to next() so they can resolve as 404s.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dccba455-a32f-48e7-9d40-66994b3e823e

📥 Commits

Reviewing files that changed from the base of the PR and between e915118 and 7ca8ec8.

📒 Files selected for processing (14)
  • .dockerignore
  • Dockerfile
  • client/src/App.jsx
  • client/src/components/SpeechHistory.jsx
  • client/src/components/VideoPreview.jsx
  • client/src/components/VoiceForge.jsx
  • client/src/components/VoiceRecorder.jsx
  • client/src/hooks/useSpeechHistory.js
  • client/src/main.jsx
  • client/src/pages/Analytics.jsx
  • client/src/pages/Call.jsx
  • client/src/pages/Onboarding.jsx
  • docker-compose.yml
  • server/index.js

Comment thread client/src/components/SpeechHistory.jsx
Comment thread client/src/components/SpeechHistory.jsx
Comment thread client/src/components/SpeechHistory.jsx Outdated
Comment on lines +41 to +56
const analyticsData = useMemo(() => {
const totalSentences = history.length;
const totalWords = history.reduce((acc, msg) => acc + (msg.text ? msg.text.split(/\s+/).length : 0), 0);
const counts = {};
history.forEach((msg) => {
if (msg.text) {
const key = msg.text.trim();
counts[key] = (counts[key] || 0) + 1;
}
});
const top = Object.entries(counts)
.sort((a, b) => b[1] - a[1])
.slice(0, 3)
.map(([text, count]) => ({ text, count }));
return { totalSentences, totalWords, top };
}, [history]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Base analytics on non-deduplicated speech events.

history preserves only one entry per unique message text, while analyticsHistory and sessionTranscript record every utterance. Computing counts from history means repeated phrases can never have a count above one and usage totals are undercounted. Pass the event history into SpeechHistory and use it for this memo.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/SpeechHistory.jsx` around lines 41 - 56, The
analyticsData memo currently uses deduplicated history, undercounting repeated
speech events. Update SpeechHistory to accept the event history, use
analyticsHistory or sessionTranscript as the memo’s input for totalSentences,
totalWords, and top counts, and update the dependency accordingly while
preserving the existing analytics shape.

Comment thread client/src/components/VoiceRecorder.jsx Outdated
Comment thread client/src/main.jsx
Comment thread client/src/pages/Call.jsx
Comment thread client/src/pages/Onboarding.jsx
Comment thread docker-compose.yml Outdated
Comment thread server/index.js
Signed-off-by: Aditya R. Satapathy <adityaranjanwxd@gmail.com>
Signed-off-by: Aditya R. Satapathy <adityaranjanwxd@gmail.com>
@github-actions github-actions Bot added bug Something isn't working enhancement New feature or request and removed large PR needs-template needs-template labels Jul 26, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Aug 11, 2026
13 tasks
@itzzavdhesh
itzzavdhesh merged commit 7a1387b into itzzavdhesh:main Aug 11, 2026
5 of 8 checks passed
@github-actions

Copy link
Copy Markdown

🎊 PR Merged Successfully

Hey @Myparadox-creator! 👋 Congratulations and thank you for your contribution to VoiceForge!

Note

🔗 Linked issue(s): #1109 · ✅ Marked as merged and complete

Maintainers may still handle final cleanup, release notes, or follow-up tracking after the merge.


🤖 VoiceForge Automation · Updates automatically on edits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

assignee-match bug Something isn't working client completed dco-missing documentation Improvements or additions to documentation ELUSOC ELUSOC enhancement New feature or request gssoc:approved gssoc:approved gssoc26 gssoc26 Hard hard level:intermediate level:intermediate linked-issue-ok mentor:Anushreebasics GSSoC: Mentor-@Anushreebasics mentor:itsdakshjain GSSoC: Mentor-@itsdakshjain mentor:Nitya-003 Applied by mentor automation mentor:sabeenaviklar GSSoC: Mentor-@sabeenaviklar merged pr-merged pr-validated quality:clean quality:clean ready for review server size/l SSoC26 SSOC template-ok type:accessibility type type:bug type:bug type:feature type:feature type:performance type:performance type:refactor type:refactor VETERAN VETERAN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Create Dockerfile for production deployment

2 participants