diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 35b3e9a..a36f5a3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -87,6 +87,7 @@ jobs:
run: pnpm build
env:
NEXT_PUBLIC_CONVEX_URL: https://terrific-llama-923.convex.cloud
+ NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ vars.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
- name: Upload build artifacts
uses: actions/upload-artifact@v4
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 9538516..86e7b11 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -55,6 +55,7 @@ jobs:
run: pnpm build
env:
NEXT_PUBLIC_CONVEX_URL: https://terrific-llama-923.convex.cloud
+ NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ vars.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index bef35d9..90f243c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -79,6 +79,7 @@ jobs:
run: pnpm build
env:
NEXT_PUBLIC_CONVEX_URL: https://terrific-llama-923.convex.cloud
+ NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ vars.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
release:
name: Create GitHub Release
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ffd0f07..2103f17 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,94 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
---
+## [0.3.0] - 2026-06-30
+
+### Overview
+
+This release integrates **Clerk** as the authentication provider for `apps/web`,
+wired directly into the Convex real-time backend via `ConvexProviderWithClerk`.
+Authentication is enforced at both the UI layer (Next.js 16 proxy middleware) and
+the backend layer (Convex mutation identity checks).
+
+---
+
+### Added
+
+#### Clerk authentication — `apps/web`
+
+- **`@clerk/nextjs ^7.5.9`** added to `apps/web` dependencies
+- **`app/layout.tsx`** — `ClerkProvider` wraps the entire application, providing
+ Clerk session context to all pages and components
+- **`proxy.ts`** (Next.js 16 middleware filename) — `clerkMiddleware()` protects all
+ routes by default; public routes `/sign-in(.*)` and `/sign-up(.*)` are exempt
+- **`app/(auth)/layout.tsx`** — centered layout for all auth pages
+- **`app/(auth)/sign-in/[[...sign-in]]/page.tsx`** — Clerk hosted `` component
+ with catch-all routing for multi-step sign-in flows
+- **`app/(auth)/sign-up/[[...sign-up]]/page.tsx`** — Clerk hosted `` component
+ with catch-all routing for multi-step sign-up flows
+- **`app/page.tsx`** — `` / `` guards from Convex;
+ authenticated view shows `` and the Add user mutation button;
+ unauthenticated view shows ``
+
+#### Convex + Clerk session bridging
+
+- **`components/theme-provider.tsx`** — replaced bare `ConvexProvider` with
+ `ConvexProviderWithClerk` (from `convex/react-clerk`), passing `useAuth` from
+ `@clerk/nextjs` so Convex automatically includes the active Clerk JWT in all
+ function calls. Removed dead `ThemeHotkey`, `isTypingTarget`, `NextThemesProvider`,
+ and `useTheme` code that was leftover from the previous provider setup.
+
+#### Convex backend auth hardening — `packages/backend`
+
+- **`convex/auth.config.ts`** — Clerk JWT provider configuration; reads
+ `CLERK_JWT_ISSUER_DOMAIN` from the Convex Dashboard environment. Uses
+ `/// ` because this file runs in Node.js (Convex CLI),
+ not the V8 function isolate runtime.
+- **`convex/users.ts`** — `add` mutation now calls `ctx.auth.getUserIdentity()` and
+ throws `"Not Authenticated"` for unauthenticated callers, preventing anonymous
+ writes to the users table.
+- **`package.json`** — added `@types/node ^20.19.41` dev dependency
+
+---
+
+### Fixed
+
+- **`packages/backend/tsconfig.json`** — removed deprecated `baseUrl` compiler option.
+ In TypeScript 5+, `paths` does not require `baseUrl` to be set; the option was
+ flagged as deprecated in TS 5.0 and will stop functioning in TS 7.0.
+
+---
+
+### Changed
+
+- **`apps/widget/components/theme-provider.tsx`** — removed dead `ThemeHotkey`,
+ `isTypingTarget`, `NextThemesProvider`, and `useTheme` code, matching the cleanup
+ done in `apps/web`.
+
+#### CI/tooling
+
+- `ci.yml`, `release.yml`, `codeql.yml` — `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` added
+ to the build step environment, reading from the `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY`
+ GitHub repository variable. This prevents `ClerkProvider` from throwing during
+ `next build` in CI environments where `.env.local` is absent.
+
+---
+
+### Technical Decisions
+
+- **`ConvexProviderWithClerk` over manual token injection** — Convex's official Clerk
+ integration handles token refresh, expiry, and re-auth automatically. Manual token
+ passing would require re-implementing this logic.
+- **Middleware-level route protection** — protecting routes at the `proxy.ts` layer
+ means unauthenticated users are redirected before any page code runs, not just
+ hidden by client-side conditionals.
+- **`ctx.auth.getUserIdentity()` in mutations** — server-side auth checks are the last
+ line of defence; even if middleware is bypassed, mutations reject unauthenticated calls.
+- **`proxy.ts` (not `middleware.ts`)** — Next.js 16 renamed the middleware file from
+ `middleware.ts` to `proxy.ts`. The code API is identical; only the filename changed.
+
+---
+
## [0.2.0] - 2026-06-29
### Overview
@@ -249,7 +337,8 @@ Initial release of **Echo** — an enterprise-grade full-stack monorepo platform
---
-[Unreleased]: https://github.com/RISHII7/echo/compare/v0.2.0...HEAD
+[Unreleased]: https://github.com/RISHII7/echo/compare/v0.3.0...HEAD
+[0.3.0]: https://github.com/RISHII7/echo/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/RISHII7/echo/compare/v0.1.1...v0.2.0
[0.1.1]: https://github.com/RISHII7/echo/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/RISHII7/echo/releases/tag/v0.1.0
diff --git a/README.md b/README.md
index 13d3642..00f7308 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,7 @@
[](https://turbo.build)
[](https://tailwindcss.com)
[](https://convex.dev)
+[](https://clerk.com)
[](CONTRIBUTING.md)
[Report Bug](https://github.com/RISHII7/echo/issues/new?template=bug_report.yml) · [Request Feature](https://github.com/RISHII7/echo/issues/new?template=feature_request.yml) · [Documentation](https://github.com/RISHII7/echo/wiki)
@@ -57,7 +58,8 @@ Echo is a production-ready, full-stack monorepo platform engineered for enterpri
## Features
- **Monorepo Architecture** — Turborepo with remote caching, task pipelines, and workspace dependency graph
-- **Real-Time Backend** — Convex reactive database with live queries and server mutations
+- **Authentication** — Clerk with hosted sign-in/sign-up UI, session management, and middleware-level route protection
+- **Real-Time Backend** — Convex reactive database with live queries and server mutations, bridged to Clerk sessions
- **Type Safety** — End-to-end TypeScript with strict mode and generated API types across all packages
- **Design System** — Shared UI component library built on shadcn/ui and Radix primitives
- **Performance** — Next.js Turbopack, React Server Components, and Tailwind CSS v4
@@ -96,6 +98,7 @@ The monorepo uses a **workspace dependency graph** where apps consume packages,
| UI Library | React 19 |
| Styling | Tailwind CSS 4 |
| Components | shadcn/ui + Radix UI |
+| Auth | Clerk |
| Backend | Convex (real-time DB) |
| Icons | Lucide React |
| Monorepo | Turborepo 2 |
@@ -133,20 +136,30 @@ pnpm dev
### Environment Variables
-Create `apps/web/.env.local` and `apps/widget/.env.local` with the following:
+Create `apps/web/.env.local`:
-| Variable | Description | Required |
-| ------------------------ | --------------------------------- | -------- |
-| `NEXT_PUBLIC_CONVEX_URL` | Convex deployment URL | Yes |
-| `NEXT_PUBLIC_APP_URL` | Public URL of the web application | No |
+| Variable | Description | Required |
+| ----------------------------------- | ------------------------------------- | -------- |
+| `NEXT_PUBLIC_CONVEX_URL` | Convex deployment URL | Yes |
+| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk publishable key (`pk_test_...`) | Yes |
+| `CLERK_SECRET_KEY` | Clerk secret key (`sk_test_...`) | Yes |
-To get your `NEXT_PUBLIC_CONVEX_URL`, run `pnpm --filter backend dev` and copy the deployment URL from the Convex dashboard, or from `packages/backend/.env.local` after the first `convex dev` run.
+Create `packages/backend/.env.local` (auto-generated by `convex dev`):
+
+| Variable | Description | Required |
+| ------------------------- | ------------------------------------ | -------- |
+| `CONVEX_DEPLOYMENT` | Convex deployment identifier | Yes |
+| `CLERK_JWT_ISSUER_DOMAIN` | Clerk JWT issuer URL for Convex auth | Yes |
```bash
# apps/web/.env.local
NEXT_PUBLIC_CONVEX_URL=https://.convex.cloud
+NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
+CLERK_SECRET_KEY=sk_test_...
```
+Get your Clerk keys from the [Clerk Dashboard](https://dashboard.clerk.com) → **API Keys**.
+
---
## Development
diff --git a/apps/web/app/(auth)/layout.tsx b/apps/web/app/(auth)/layout.tsx
new file mode 100644
index 0000000..5e74a56
--- /dev/null
+++ b/apps/web/app/(auth)/layout.tsx
@@ -0,0 +1,9 @@
+const Layout = ({ children }: { children: React.ReactNode }) => {
+ return (
+
+ {children}
+
+ )
+}
+
+export default Layout
diff --git a/apps/web/app/(auth)/sign-in/[[...sign-in]]/page.tsx b/apps/web/app/(auth)/sign-in/[[...sign-in]]/page.tsx
new file mode 100644
index 0000000..4602981
--- /dev/null
+++ b/apps/web/app/(auth)/sign-in/[[...sign-in]]/page.tsx
@@ -0,0 +1,7 @@
+import { SignIn } from "@clerk/nextjs"
+
+const Page = () => {
+ return
+}
+
+export default Page
diff --git a/apps/web/app/(auth)/sign-up/[[...sign-up]]/page.tsx b/apps/web/app/(auth)/sign-up/[[...sign-up]]/page.tsx
new file mode 100644
index 0000000..2c0d33c
--- /dev/null
+++ b/apps/web/app/(auth)/sign-up/[[...sign-up]]/page.tsx
@@ -0,0 +1,7 @@
+import { SignUp } from "@clerk/nextjs"
+
+const Page = () => {
+ return
+}
+
+export default Page
diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
index 9863fc1..f414c59 100644
--- a/apps/web/app/layout.tsx
+++ b/apps/web/app/layout.tsx
@@ -1,9 +1,12 @@
+import { ClerkProvider } from "@clerk/nextjs"
import { Geist, Geist_Mono } from "next/font/google"
-import "@workspace/ui/globals.css"
-import { ThemeProvider } from "@/components/theme-provider"
import { cn } from "@workspace/ui/lib/utils"
+import { ThemeProvider } from "@/components/theme-provider"
+
+import "@workspace/ui/globals.css"
+
const geist = Geist({ subsets: ["latin"], variable: "--font-sans" })
const fontMono = Geist_Mono({
@@ -28,7 +31,9 @@ export default function RootLayout({
)}
>
- {children}
+
+ {children}
+