CopilotKit / CopilotKit/outpost
templates/ never reaches the production image, so every email send fails with emailSent: false
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7
- Forks
- 3
- Avg merge
- 7d 16h
- Merged PRs (30d)
- 15
Description
Every email template is absent from the production web image, so every send fails and returns emailSent: false. This is on main today; no PR introduces it and no open issue covers it.
Raised by @NathanTarbert on #248 as "worth confirming against a built image". I confirmed it against the tree.
The chain
templates/is seven.mdfiles at the repo root —digest,escalation,invite,sla-breach,ticket-created,ticket-resolved,welcome..dockerignore:7is*.md, and:8re-includes only!README.md. The templates never enter the build context, so the pruner'sCOPY . .cannot pick them up.- No Dockerfile in the repo copies
templates/—grep -rn "templates" --include="Dockerfile*" .returns nothing.apps/web/Dockerfile's runner stage copies.next/standalone,.next/static,public, the Prisma artifacts andstart.sh. findTemplatesDir()(packages/outpost/shared/src/templates/loader.ts:50-68) walks four candidate paths, finds none, and falls back tojoin(process.cwd(), 'templates').loadFromFilesystem(:70-82) —readFileSyncthrows, thecatchreturnsnull.sendEmail(packages/outpost/shared/src/email/sender.ts:166-168) returns{ success: false, error: 'Template "invite" not found', method: 'console' }.apps/web/src/app/api/team/invite/route.ts:92-95turns that into aconsole.warnandNextResponse.json({ ...responseData, emailSent: false }).
Impact
sendEmail has exactly two live call sites, both invites (api/team/invite/route.ts:72, api/team/invite/resend/route.ts:52). So in production, inviting a teammate creates the member row and sends nothing — the invitee has to be sent the inviteUrl by hand. The remaining six templates are unreachable for the same reason if anything starts using them.
It fails as a returned value rather than a throw, and the only signal is one console.warn plus a JSON field. Whether the UI surfaces emailSent: false is worth checking as part of this.
Why it has stayed hidden
The 35 template tests run from apps/web, where join(cwd, '..', '..', 'templates') resolves against the real repo root. They pass for a reason that does not exist inside the image.
Fix
Either un-ignore the directory and copy it into the runner stage:
# .dockerignore
*.md
!README.md
!templates/*.md
# apps/web/Dockerfile, runner stage
COPY --from=installer --chown=outpost:outpost /app/templates ./templates
…or stop loading them from disk at runtime — import them as modules so bundling carries them, which also removes findTemplatesDir()'s four-candidate CWD walk.
Whichever way, this wants a test that fails when the templates are not resolvable, rather than one that passes because it runs from a checkout.
Not verified
I read the Dockerfiles and .dockerignore, not a built image. Next's standalone output tracing will not pick up a runtime-computed readFileSync path, so I do not think it saves this — but docker build on apps/web then ls templates in the runner settles it in a minute, and I would rather be corrected than have this taken on my reading.
Related
- #248 lists this as open item 2 against the template-preview work.
- #226 (stored XSS in the template preview) and #215 (Postmark DNS) both assume this path works.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with .dockerignore, apps/web/Dockerfile, and packages/outpost/shared/src/templates/loader.ts, then build the apps/web image and inspect the runner's templates directory. Trace the invite flow through sender.ts and the two invite routes. Done means the production image resolves all seven templates and the invite response no longer reports emailSent: false because a template is missing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, nextjs, typescript
- Domain
- backend, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100