feat: Phase 4-5 — demo mode, polish, deploy, and bug fixes

Add demo mode with mock data provider, Docker deployment, Playwright
tests, PostHog analytics, error boundaries, and SEO metadata. Fix
residences API response unwrapping, kanban drag-and-drop with optimistic
updates, trailing slash proxy redirects, and column name mismatches with
Go API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-03-03 11:37:41 -06:00
parent 5a50d77515
commit 7884ebbfd4
133 changed files with 3904 additions and 300 deletions
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/contractors/[id]/edit/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/contractors/[id]/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/contractors/new/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/contractors/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/documents/[id]/edit/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/documents/[id]/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/documents/new/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/documents/page";
+32
View File
@@ -0,0 +1,32 @@
"use client";
import { Sidebar } from '@/components/layout/sidebar';
import { TopBar } from '@/components/layout/top-bar';
import { MobileNav } from '@/components/layout/mobile-nav';
import { DemoBanner } from '@/components/demo/demo-banner';
import { DataProviderProvider } from '@/lib/demo/data-provider-context';
import { demoProvider } from '@/lib/demo/demo-provider';
export default function DemoAppLayout({ children }: { children: React.ReactNode }) {
return (
<DataProviderProvider value={demoProvider}>
<div className="min-h-screen bg-background">
<DemoBanner />
{/* Sidebar - hidden on mobile */}
<Sidebar />
{/* Main content area */}
<div className="md:ml-16 lg:ml-64 flex flex-col min-h-screen">
<TopBar />
<main className="flex-1 p-4 lg:p-6 pb-20 md:pb-6">
{children}
</main>
</div>
{/* Mobile bottom nav */}
<MobileNav />
</div>
</DataProviderProvider>
);
}
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/residences/[id]/edit/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/residences/[id]/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/residences/[id]/share/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/residences/join/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/residences/new/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/residences/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/settings/layout";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/settings/notifications/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/settings/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/settings/profile/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/settings/subscription/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/tasks/[id]/complete/page";
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/tasks/[id]/edit/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/tasks/[id]/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/tasks/new/page";
+2
View File
@@ -0,0 +1,2 @@
"use client";
export { default } from "@/app/app/tasks/page";
+21
View File
@@ -0,0 +1,21 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Try Casera — Free Demo",
description:
"Try Casera without an account. Manage tasks, contractors, and documents in a live demo.",
openGraph: {
title: "Try Casera — Free Demo",
description:
"Try Casera without an account. Manage tasks, contractors, and documents in a live demo.",
type: "website",
},
};
export default function DemoLayout({
children,
}: {
children: React.ReactNode;
}) {
return children;
}
+41
View File
@@ -0,0 +1,41 @@
"use client";
import Link from "next/link";
import { Button } from "@/components/ui/button";
export default function DemoLandingPage() {
return (
<div className="flex min-h-screen flex-col items-center justify-center bg-background px-4">
<div className="mx-auto max-w-md text-center">
{/* Logo */}
<h1 className="mb-8 text-2xl font-bold tracking-tight text-primary">
Casera
</h1>
{/* Hero */}
<h2 className="text-3xl font-bold tracking-tight">
Try Casera &mdash; No Account Needed
</h2>
<p className="mt-3 text-muted-foreground">
Manage your home maintenance, track tasks, organize contractors, and
store documents.
</p>
{/* Actions */}
<div className="mt-8 flex flex-col gap-3">
<Button size="lg" asChild>
<Link href="/demo/app">Start Demo</Link>
</Button>
</div>
{/* Login link */}
<p className="mt-6 text-sm text-muted-foreground">
Already have an account?{" "}
<Link href="/login" className="text-primary hover:underline">
Log In
</Link>
</p>
</div>
</div>
);
}