Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ BETTER_AUTH_URL=http://localhost:3000
# Set to "true" to disable new user signups (existing users can still sign in)
# DISABLE_SIGNUPS=true

# Email (Resend)
RESEND_API_KEY=re_xxxxx
# Email (SMTP)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-smtp-username
SMTP_PASS=your-smtp-password
EMAIL_FROM="Manage <noreply@yourdomain.com>"

# S3-compatible storage (MinIO for self-hosted)
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
- **Authentication**: Better-auth
- **Styling**: Tailwind CSS + Shadcn
- **Real-time**: TurboWire for WebSockets
- **Email**: React Email + Resend
- **Email**: React Email + SMTP (nodemailer)
- **File Storage**: S3-compatible storage
- **Monitoring**: Sentry
- **Linting**: Biome
Expand Down
31 changes: 0 additions & 31 deletions app/(api)/api/webhook/email/inbound/route.ts

This file was deleted.

55 changes: 24 additions & 31 deletions app/(dashboard)/[tenant]/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Building2, ChartBar, User2, Users } from "lucide-react";
import PageSection from "@/components/core/section";
import PageTitle from "@/components/layout/page-title";
import { ProfileSettings } from "@/components/settings/profile-settings";
import { TeamSettings } from "@/components/settings/team-settings";
import { WorkspaceSettings } from "@/components/settings/workspace-settings";
import { bytesToMegabytes } from "@/lib/blobStore";
import { caller } from "@/trpc/server";
import { ChartBar, User2, Users } from "lucide-react";

export default async function Settings() {
const [user, storage, timezone, projectsData] = await Promise.all([
caller.user.getCurrentUser(),
const [storage, timezone, projectsData] = await Promise.all([
caller.settings.getStorageUsage(),
caller.settings.getTimezone(),
caller.user.getProjects({ statuses: ["active", "archived"] }),
Expand All @@ -19,6 +20,14 @@ export default async function Settings() {
<>
<PageTitle title="Settings" />

<PageSection
title="Workspace"
titleIcon={<Building2 className="w-5 h-5" />}
bottomMargin
>
<WorkspaceSettings />
</PageSection>

<PageSection
title="Team"
titleIcon={<Users className="w-5 h-5" />}
Expand Down Expand Up @@ -60,38 +69,22 @@ export default async function Settings() {
</div>
</PageSection>

{user ? (
<PageSection
title="Profile"
titleIcon={<User2 className="w-5 h-5" />}
bottomMargin
>
<div className="p-4 sm:flex items-center">
<p className="font-semibold text-gray-900 dark:text-gray-200 sm:w-64 sm:flex-none sm:pr-6">
Name
</p>
<p>
{user.firstName} {user.lastName}
</p>
</div>
<PageSection
title="Profile"
titleIcon={<User2 className="w-5 h-5" />}
bottomMargin
>
<ProfileSettings />

<div className="p-4 sm:flex items-center">
{timezone ? (
<div className="p-4 sm:flex">
<p className="font-semibold text-gray-900 dark:text-gray-200 sm:w-64 sm:flex-none sm:pr-6">
Email address
Timezone
</p>
<p>{user.email}</p>
<div className="text-gray-900 dark:text-gray-200">{timezone}</div>
</div>

{timezone ? (
<div className="p-4 sm:flex">
<p className="font-semibold text-gray-900 dark:text-gray-200 sm:w-64 sm:flex-none sm:pr-6">
Timezone
</p>
<div className="text-gray-900 dark:text-gray-200">{timezone}</div>
</div>
) : null}
</PageSection>
) : null}
) : null}
</PageSection>
</>
);
}
28 changes: 22 additions & 6 deletions app/start/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { eq } from "drizzle-orm";
import { headers } from "next/headers";
import { ClientRedirect } from "@/components/core/client-redirect";
import { organization } from "@/drizzle/auth-schema";
import { auth } from "@/lib/auth";
import { database } from "@/lib/utils/useDatabase";

export const fetchCache = "force-no-store";
export const dynamic = "force-dynamic";
Expand All @@ -10,11 +13,24 @@ export default async function Start() {
headers: await headers(),
});

const activeOrg = session?.session?.activeOrganizationId;
if (!session?.user) {
return <ClientRedirect path="/sign-in" />;
}

return (
<ClientRedirect
path={session?.user ? `/${activeOrg ?? "me"}/today` : "/sign-in"}
/>
);
const activeOrgId = session.session.activeOrganizationId;

let slug = "me";
if (activeOrgId) {
const db = database();
const org = await db
.select({ slug: organization.slug })
.from(organization)
.where(eq(organization.id, activeOrgId))
.limit(1);
if (org[0]) {
slug = org[0].slug;
}
}

return <ClientRedirect path={`/${slug}/today`} />;
}
Loading