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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ yarn-error.log*

# env files (can opt-in for committing if needed)
.env*
!**/.env.example

# vercel
.vercel
Expand Down
12 changes: 12 additions & 0 deletions apps/app/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Product application runtime
DATABASE_URL="postgresql://USER:PASSWORD@HOST/DATABASE?sslmode=require"
AUTH_SECRET="replace-with-a-random-secret"

# Auth.js identity providers
AUTH_GITHUB_ID="github-oauth-client-id"
AUTH_GITHUB_SECRET="github-oauth-client-secret"
AUTH_GOOGLE_ID="google-oauth-client-id"
AUTH_GOOGLE_SECRET="google-oauth-client-secret"

# Transactional booking email
RESEND_API_KEY="re_replace_me"
1 change: 1 addition & 0 deletions apps/app/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ yarn-error.log*

# env files (can opt-in for committing if needed)
.env*
!.env.example

# vercel
.vercel
Expand Down
1 change: 0 additions & 1 deletion apps/app/app/[locale]/(dashboard)/availability/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export default async function AvailabilityPage() {
return (
<div className="container max-w-5xl">
<ScheduleForm
userId={user.id}
initialData={{
timeZone: user.timeZone || "UTC", // Corrected fallback
schedule,
Expand Down
2 changes: 1 addition & 1 deletion apps/app/app/[locale]/(dashboard)/bookings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export default async function BookingsPage() {
<div className="flex items-start gap-2 pt-1">
<AlignLeft className="h-4 w-4 text-muted-foreground shrink-0 mt-0.5" />
<p className="text-muted-foreground italic line-clamp-2">
"{booking.guestNotes}"
&ldquo;{booking.guestNotes}&rdquo;
</p>
</div>
)}
Expand Down
78 changes: 60 additions & 18 deletions apps/app/components/auth-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,68 @@ import { signIn, signOut } from "@/auth";

export function SignIn() {
return (
<form
action={async () => {
"use server";
await signIn("github");
}}
>
<button
type="submit"
className="w-full flex items-center justify-center gap-2 px-5 py-3 bg-gray-900 text-white text-sm font-medium rounded-lg hover:bg-gray-800 transition-all shadow-md active:scale-95"
<div className="flex w-full flex-col gap-2 sm:flex-row">
<form
className="w-full"
action={async () => {
"use server";
await signIn("google");
}}
>
<svg
className="w-5 h-5 fill-current"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
<button
type="submit"
className="flex w-full items-center justify-center gap-2 rounded-lg border border-gray-300 bg-white px-5 py-3 text-sm font-medium text-gray-800 shadow-sm transition-all hover:bg-gray-50 active:scale-95 dark:border-gray-600 dark:bg-gray-900 dark:text-white dark:hover:bg-gray-800"
>
<path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z" />
</svg>
Sign in with GitHub
</button>
</form>
<svg
aria-hidden="true"
className="h-5 w-5"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="#4285F4"
d="M21.6 12.23c0-.71-.06-1.4-.18-2.07H12v3.92h5.38a4.6 4.6 0 0 1-2 3.02v2.54h3.24c1.9-1.75 2.98-4.33 2.98-7.4Z"
/>
<path
fill="#34A853"
d="M12 22c2.7 0 4.98-.9 6.63-2.43l-3.24-2.54c-.9.6-2.05.96-3.39.96-2.61 0-4.82-1.77-5.61-4.14H3.04v2.62A10 10 0 0 0 12 22Z"
/>
<path
fill="#FBBC05"
d="M6.39 13.85A6 6 0 0 1 6.07 12c0-.64.11-1.27.32-1.85V7.53H3.04A10 10 0 0 0 2 12c0 1.61.39 3.14 1.04 4.47l3.35-2.62Z"
/>
<path
fill="#EA4335"
d="M12 6.01c1.47 0 2.79.51 3.83 1.5l2.87-2.88A9.64 9.64 0 0 0 12 2a10 10 0 0 0-8.96 5.53l3.35 2.62C7.18 7.78 9.39 6.01 12 6.01Z"
/>
</svg>
Sign in with Google
</button>
</form>

<form
className="w-full"
action={async () => {
"use server";
await signIn("github");
}}
>
<button
type="submit"
className="flex w-full items-center justify-center gap-2 rounded-lg bg-gray-900 px-5 py-3 text-sm font-medium text-white shadow-md transition-all hover:bg-gray-800 active:scale-95 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-100"
>
<svg
aria-hidden="true"
className="h-5 w-5 fill-current"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z" />
</svg>
Sign in with GitHub
</button>
</form>
</div>
);
}

Expand Down
2 changes: 0 additions & 2 deletions apps/app/components/availability/schedule-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ export interface DaySchedule {
}

export interface ScheduleFormProps {
userId?: string;
initialData: {
timeZone: string;
schedule: DaySchedule[];
Expand All @@ -89,7 +88,6 @@ export interface ScheduleFormProps {
}

export function ScheduleForm({
userId: _userId,
initialData,
onSubmit,
}: ScheduleFormProps) {
Expand Down
1 change: 1 addition & 0 deletions apps/app/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const eslintConfig = defineConfig([
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"coverage/**",
"out/**",
"build/**",
"next-env.d.ts",
Expand Down
28 changes: 16 additions & 12 deletions apps/app/hooks/use-mobile.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import * as React from "react"

const MOBILE_BREAKPOINT = 768
const MOBILE_QUERY = `(max-width: ${MOBILE_BREAKPOINT - 1}px)`

export function useIsMobile() {
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
function subscribe(callback: () => void) {
const mediaQuery = window.matchMedia(MOBILE_QUERY)

mediaQuery.addEventListener("change", callback)
return () => mediaQuery.removeEventListener("change", callback)
}

React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
const onChange = () => {
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
}
mql.addEventListener("change", onChange)
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
return () => mql.removeEventListener("change", onChange)
}, [])
function getSnapshot() {
return window.matchMedia(MOBILE_QUERY).matches
}

return !!isMobile
function getServerSnapshot() {
return false
}

export function useIsMobile() {
return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)
}
1 change: 1 addition & 0 deletions apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"dependencies": {
"@base-ui/react": "^1.6.0",
"@hookform/resolvers": "^5.7.1",
"@prisma/client": "^7.9.1",
"@radix-ui/react-label": "^2.1.15",
"@radix-ui/react-slot": "^1.3.3",
"@react-email/components": "^1.0.12",
Expand Down
17 changes: 17 additions & 0 deletions apps/marketing/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";

const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
globalIgnores([
".next/**",
"coverage/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);

export default eslintConfig;
4 changes: 3 additions & 1 deletion apps/marketing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"typescript": "^5"
"eslint": "^9.39.5",
"eslint-config-next": "16.2.12",
"typescript": "^5.9.3"
}
}
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Statements about current behavior should be verifiable in code. Proposed behavio
| [System architecture](./system-architecture.md) | Modular runtime boundaries, request and transaction flows, durable work, integrations, security, and sequences | Proposed runtime design |
| [Deployment architecture](./deployment-architecture.md) | Environments, deployable units, database, releases, secrets, observability, backups, and recovery | Proposed deployment design |
| [Roadmap](./roadmap.md) | Vertical delivery milestones, dependencies, decision gates, and completion evidence | Proposed delivery plan |
| [M0 baseline reconciliation](./baseline-m0.md) | Validation evidence, environment contracts, migration gaps, data-quality queries, and Server Action conventions | Current baseline |
| [Content opportunities](./content-opportunities.md) | Reusable learning and publishing ideas discovered during development | Active backlog |

## Articles
Expand Down
Loading
Loading