diff --git a/README.md b/README.md index 4a5a9db..8df529b 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ link's build current automatically. - [Architecture](docs/ARCHITECTURE.md) — how the pieces fit, selection, reminders, security - [Roadmap](docs/ROADMAP.md) — shipped phases and what's next - [Backend](backend/README.md) — API endpoints, auth, running locally +- [Email templates](docs/EMAIL_TEMPLATES.md) — branded Supabase emails and installation - [Deployment](mobile/DEPLOYMENT.md) — EAS builds, OTA updates, release runbook ## Contributing diff --git a/backend/README.md b/backend/README.md index 0bcd6bb..fd723d0 100644 --- a/backend/README.md +++ b/backend/README.md @@ -29,6 +29,7 @@ backend/ │ │ └── users.py profile bootstrap (safety net for the DB trigger) │ └── api/v1/ health, topics, daily ├── migrations/ # plain SQL, applied in filename order +├── email-templates/ # account email HTML installed manually in Supabase Auth ├── tests/ # 25 tests: token verification, selection, HTTP ├── Dockerfile # what Railway builds └── .env.example # copy to .env — never commit the filled copy @@ -106,6 +107,11 @@ confusion attacks, both of which are covered by tests. `user_id` is taken from the verified token's `sub` claim and from nowhere else. No endpoint accepts a user id as a parameter. +Supabase Auth sends signup, recovery, and enabled security notifications using +the project's configured sender. See [Email templates](../docs/EMAIL_TEMPLATES.md) +for the three branded HTML files and manual installation steps. An app deployment +does not publish these templates or change SMTP settings. + ## Content generation Gemini writes lessons. It does **not** choose subjects. diff --git a/backend/email-templates/confirm-signup.html b/backend/email-templates/confirm-signup.html new file mode 100644 index 0000000..784094f --- /dev/null +++ b/backend/email-templates/confirm-signup.html @@ -0,0 +1,41 @@ + + + + + + Confirm your email — One Concept + + + +
One last step to finish setting up your account.
+ + +
+ + + + + +
+

One Concept.

+

by Coding Moves

+
+

Confirm your email.

+

Confirm this address to finish setting up your account.

+ + +
+ Confirm email +
+

Then return to the app and sign in.

+
+

If you didn’t sign up, you can ignore this email.

+

Button not working? Copy this link into your browser:

+

+ {{ .ConfirmationURL }} +

+
+ +
+ + diff --git a/backend/email-templates/password-changed.html b/backend/email-templates/password-changed.html new file mode 100644 index 0000000..46897df --- /dev/null +++ b/backend/email-templates/password-changed.html @@ -0,0 +1,34 @@ + + + + + + Your password was changed — One Concept + + + +
A security update for your One Concept account.
+ + +
+ + + + + +
+

One Concept.

+

by Coding Moves

+
+

Pass­word changed.

+

Your One Concept password was changed.

+

If you made this change, no further action is needed.

+
+

Didn’t make this change?

+

Open One Concept and use Forgot password on the sign-in screen to reset your password.

+

Contact support immediately.

+
+ +
+ + diff --git a/backend/email-templates/reset-password.html b/backend/email-templates/reset-password.html new file mode 100644 index 0000000..3367efd --- /dev/null +++ b/backend/email-templates/reset-password.html @@ -0,0 +1,41 @@ + + + + + + Reset your password — One Concept + + + +
Choose a new password for your One Concept account.
+ + +
+ + + + + +
+

One Concept.

+

by Coding Moves

+
+

Reset your pass­word.

+

A password reset was requested for your account. Choose a new password below.

+ + +
+ Reset password +
+

Once it’s saved, return to the app and sign in.

+
+

If you didn’t request this, ignore this email. Your password won’t change.

+

Button not working? Copy this link into your browser:

+

+ {{ .ConfirmationURL }} +

+
+ +
+ + diff --git a/docs/CODEBASE_MAP.md b/docs/CODEBASE_MAP.md index 84e0c03..6063f16 100644 --- a/docs/CODEBASE_MAP.md +++ b/docs/CODEBASE_MAP.md @@ -18,6 +18,7 @@ learned history, streaks, likes, saved concepts, and push reminders. | Operations | `.github/workflows/`, `backend/railway.json`, `backend/Dockerfile`, `mobile/eas.json`, `mobile/app.config.js`. | | Documentation | Root `README.md`, `RELEASING.md`, `CONTRIBUTING.md`, `docs/ARCHITECTURE.md`, `docs/ROADMAP.md`, and the backend/mobile guides. | | Agent guidance | Root `AGENTS.md`; `mobile/AGENTS.md` adds Expo documentation requirements and `mobile/CLAUDE.md` references it. | +| Authentication email | `backend/email-templates/` contains branded signup, recovery, and password-changed HTML; `docs/EMAIL_TEMPLATES.md` covers manual Supabase installation and activation checks. Templates use the configured sender and are not installed by app deployment. | ## Mobile navigation and presentation diff --git a/docs/EMAIL_TEMPLATES.md b/docs/EMAIL_TEMPLATES.md new file mode 100644 index 0000000..4e429d9 --- /dev/null +++ b/docs/EMAIL_TEMPLATES.md @@ -0,0 +1,68 @@ +# One Concept email templates + +These three templates customize emails sent by Supabase Auth. They work with +the project's configured sender; installing the HTML does not require Resend, +a purchased domain, or an app update. Provider setup remains separate in +[draft PR #187](https://github.com/Coding-Moves/one-concept/pull/187). + +**Merging or releasing the app does not install these files in Supabase.** +Paste the templates into the dashboard to change future emails. The repository +stores their reviewed source; it does not synchronize production settings. + +## Install + +1. Open the correct Supabase project, then **Authentication → Emails → Templates**. +2. Open each template listed below and set its subject exactly as shown. +3. Replace the body with the entire raw HTML file, starting with ``. + Copy the file's source, not its rendered browser preview, and save. +4. Under **Security → Password changed**, also enable the notification and save. + +| Supabase template | Subject | HTML source | +| --- | --- | --- | +| Confirm sign up | `Confirm your email — One Concept` | [confirm-signup.html](../backend/email-templates/confirm-signup.html) | +| Reset password | `Reset your password — One Concept` | [reset-password.html](../backend/email-templates/reset-password.html) | +| Password changed (Security) | `Your password was changed — One Concept` | [password-changed.html](../backend/email-templates/password-changed.html) | + +Keep every `{{ .ConfirmationURL }}` placeholder in signup and recovery. Supabase +fills in the appropriate verification URL; the button and copyable fallback +must both pass through that verification. Password changed reports a completed +change and intentionally has no token or reset-link placeholder. It directs +unrecognized changes to Forgot password in the app and the existing support email. + +Preserve the project's existing working redirect configuration. Signup uses the +configured Site URL for `/confirmed`; recovery requests `/reset-password` on the +app's API base URL. The corresponding HTTPS destinations must be allowed in +Supabase's URL Configuration. Do not replace verification links with those +landing-page URLs. See [Supabase email templates](https://supabase.com/docs/guides/auth/auth-email-templates). + +## Sending and activation + +Template customization and sending capacity are separate. Supabase's default +sender is for testing: it currently sends only to project-team addresses and +allows two emails per hour. Other recipients require custom SMTP, which can be +the owner's existing Gmail setup once configured and tested. These templates +do not remove sender limits or establish delivery. See +[Supabase SMTP documentation](https://supabase.com/docs/guides/auth/auth-smtp) +(checked 2026-09-12). + +Before announcing the new emails to users, test with accounts and inboxes you +control under the configured sender's limits: + +- Confirm signup, follow the email's button, and successfully sign in to the app. +- Request Forgot password, set a new password through the recovery email, and + sign in with it. Verify the separate Password changed notification arrives. +- Check the design in a real inbox on phone and desktop, the full fallback links, + and the Coding Moves organization and support destinations. Use a second inbox + provider and a non-team recipient when custom SMTP is available. + +Record the results before treating production activation as complete. Local +browser previews verify layout, not Gmail/Outlook rendering or live delivery. +No production settings or messages are changed by the template PR itself. + +## Design + +The dark masthead uses the owner's selected One Concept text branding and links +Coding Moves once to its GitHub organization. The app's current image assets are +Expo starter icons, so the emails do not use them as a logo. Inline styles, +presentation tables, system fonts, and text links need no external assets. +Subjects are separate dashboard fields; the HTML comments do not configure them. diff --git a/docs/WORK_LOG.md b/docs/WORK_LOG.md index 00ba6d9..7eaae3e 100644 --- a/docs/WORK_LOG.md +++ b/docs/WORK_LOG.md @@ -7,6 +7,17 @@ claims as completed work. ## Current status +- Published the three branded Supabase templates in non-draft + [PR #188](https://github.com/Coding-Moves/one-concept/pull/188) into `develop`, + from `a6e81f1` on `codex/branded-auth-email-templates`. GitHub reports the PR + mergeable with no conflicts; no CI checks are configured for this PR. +- Resend delivery preparation remains in [draft PR #187](https://github.com/Coding-Moves/one-concept/pull/187). + Its duplicate template files are removed in a follow-up commit. Original + histories are intact. Template installation is independent of a domain purchase + or app release and still requires pasting HTML into Supabase. +- No SMTP settings, live templates, notifications, or production release were + changed. Real inbox rendering and delivery remain unverified. + - Implemented and validated [#151](https://github.com/Coding-Moves/one-concept/issues/151), shared daily Gemini generation budget, on `codex/151-shared-generation-budget` from refreshed `origin/develop` (`65eb21d`). Published @@ -21,6 +32,38 @@ claims as completed work. - PR #185 (#150) is merged. Preserve the owner's identity and the preference for more focused commits in this and future PRs. +## Separate branded email templates — 2026-09-12 + +- Owner requested the three templates in a separate non-draft PR, allowing + branding to merge while domain/provider setup stays deferred. Rechecked + Supabase documentation: customizing templates does not remove the built-in + sender's team-only/two-emails-per-hour restrictions. Existing configured + Gmail SMTP can be used separately once authenticated and tested. +- Preserved nine original template commits from #187, in order, covering signup, + recovery, copy/spacing improvements, the dark text masthead, the Coding Moves + organization link, and the password-changed notification. Sources are byte for + byte identical to the previously validated versions. The owner selected text + branding; no custom app logo was available. +- Added `docs/EMAIL_TEMPLATES.md` with exact subjects, manual installation, + confirmation placeholders, the security toggle, existing redirect contract, + and activation checks. The guide does not require domain purchase or Resend. +- **Validation:** the unchanged HTML previously passed 60 Chromium scenarios: + 48 for signup/recovery and 12 for password changed, across four widths and + normal/doubled/stripped styles, plus normal/long verification URLs. Those checks + covered links, fallback URLs, styled overflow, spacing, action sizes, and no + external resources; mobile/desktop/enlarged previews were inspected. For this + split, verified byte equality with `b0695ca`, inspected app redirect/support + source, checked local Markdown paths/anchors, and ran `git diff --check`. + Browser scenarios were not repeated for identical HTML. Backend/mobile and + live-email tests were not run for this HTML/documentation-only change. +- Commits: `245b7f6` records scope; `d88f432` through `50d065d` preserve the nine + template changes; `4ccba83` adds installation/navigation docs; this handoff is + `docs: record independent email template PR and validation`. +- **Handoff:** merge #188 independently of #187. Then install/test templates in + Supabase before announcing the changed emails. Merging/releasing the app does + not synchronize templates or enable security notifications. Delivery issues + #152/#171 stay open for the remaining operational work; no release PR opened. + ## Shared generation budget (#151) — 2026-09-12 - Confirmed both gaps before implementation against the same generation source