create-varity-app 2.0.0-beta.2 → 2.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/create.js +3 -3
- package/dist/index.js +0 -0
- package/package.json +7 -7
- package/template/.env.example +3 -2
- package/template/.turbo/turbo-build.log +8 -8
- package/template/package.json +3 -3
- package/template/src/app/dashboard/layout.tsx +26 -22
- package/template/src/app/dashboard/settings/page.tsx +11 -11
- package/template/src/app/login/page.tsx +25 -21
- package/template/src/components/providers.tsx +1 -1
- package/template/src/lib/hooks.ts +7 -7
package/dist/create.js
CHANGED
|
@@ -9,9 +9,9 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
const VARITY_PACKAGE_VERSION = "^2.0.0-beta.2";
|
|
11
11
|
const WORKSPACE_DEPS = {
|
|
12
|
-
"@varity-labs/sdk":
|
|
13
|
-
"@varity-labs/types":
|
|
14
|
-
"@varity-labs/ui-kit":
|
|
12
|
+
"@varity-labs/sdk": "^2.0.0-beta.2",
|
|
13
|
+
"@varity-labs/types": "^2.0.0-beta.2",
|
|
14
|
+
"@varity-labs/ui-kit": "^2.0.0-beta.5",
|
|
15
15
|
};
|
|
16
16
|
const EXCLUDED_FILES = new Set([
|
|
17
17
|
".env.local",
|
package/dist/index.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-varity-app",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.4",
|
|
4
4
|
"description": "Create production-ready apps with auth, database, and payments built in",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,6 +38,11 @@
|
|
|
38
38
|
"LICENSE"
|
|
39
39
|
],
|
|
40
40
|
"type": "module",
|
|
41
|
+
"scripts": {
|
|
42
|
+
"prebuild": "node scripts/copy-template.mjs",
|
|
43
|
+
"build": "tsc",
|
|
44
|
+
"clean": "rm -rf dist template"
|
|
45
|
+
},
|
|
41
46
|
"dependencies": {
|
|
42
47
|
"chalk": "^5.3.0",
|
|
43
48
|
"commander": "^12.1.0",
|
|
@@ -52,10 +57,5 @@
|
|
|
52
57
|
"@types/prompts": "^2.4.9",
|
|
53
58
|
"@types/validate-npm-package-name": "^4.0.2",
|
|
54
59
|
"typescript": "^5.5.0"
|
|
55
|
-
},
|
|
56
|
-
"scripts": {
|
|
57
|
-
"prebuild": "node scripts/copy-template.mjs",
|
|
58
|
-
"build": "tsc",
|
|
59
|
-
"clean": "rm -rf dist template"
|
|
60
60
|
}
|
|
61
|
-
}
|
|
61
|
+
}
|
package/template/.env.example
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
# For production: `varitykit app deploy` injects all credentials automatically.
|
|
7
7
|
# You never need to manually set these values.
|
|
8
8
|
|
|
9
|
-
# Auth
|
|
10
|
-
|
|
9
|
+
# Auth configuration (managed by Varity)
|
|
10
|
+
# Leave blank for dev mode, auto-configured on deploy
|
|
11
|
+
NEXT_PUBLIC_VARITY_AUTH_ID=
|
|
11
12
|
|
|
12
13
|
# Database (optional — dev database used automatically when blank)
|
|
13
14
|
NEXT_PUBLIC_VARITY_APP_TOKEN=
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
Creating an optimized production build ...
|
|
15
15
|
⚠ Mismatching @next/swc version, detected: 15.5.7 while Next.js is on 15.5.11. Please ensure these match
|
|
16
|
-
✓ Compiled successfully in
|
|
16
|
+
✓ Compiled successfully in 36.9s
|
|
17
17
|
Linting and checking validity of types ...
|
|
18
18
|
Collecting page data ...
|
|
19
19
|
Generating static pages (0/11) ...
|
|
@@ -31,17 +31,17 @@ Deploy with `varitykit app deploy` to get your own private database.
|
|
|
31
31
|
Route (app) Size First Load JS
|
|
32
32
|
┌ ○ / 5.69 kB 125 kB
|
|
33
33
|
├ ○ /_not-found 132 B 116 kB
|
|
34
|
-
├ ○ /dashboard 3.75 kB 1.
|
|
35
|
-
├ ○ /dashboard/projects 4.95 kB 1.
|
|
36
|
-
├ ○ /dashboard/settings 5.88 kB 1.
|
|
37
|
-
├ ○ /dashboard/tasks 3.17 kB 1.
|
|
38
|
-
├ ○ /dashboard/team 3.06 kB 1.
|
|
34
|
+
├ ○ /dashboard 3.75 kB 1.37 MB
|
|
35
|
+
├ ○ /dashboard/projects 4.95 kB 1.37 MB
|
|
36
|
+
├ ○ /dashboard/settings 5.88 kB 1.37 MB
|
|
37
|
+
├ ○ /dashboard/tasks 3.17 kB 1.37 MB
|
|
38
|
+
├ ○ /dashboard/team 3.06 kB 1.37 MB
|
|
39
39
|
├ ○ /icon.svg 0 B 0 B
|
|
40
|
-
└ ○ /login 1.
|
|
40
|
+
└ ○ /login 1.32 kB 1.37 MB
|
|
41
41
|
+ First Load JS shared by all 116 kB
|
|
42
42
|
├ chunks/79135-4ac590d187e38d6f.js 45.3 kB
|
|
43
43
|
├ chunks/f0439f7a-76e885cef8778491.js 54.3 kB
|
|
44
|
-
├ chunks/webpack-
|
|
44
|
+
├ chunks/webpack-8c7850c3c7158c7b.js 16.1 kB
|
|
45
45
|
└ other shared chunks (total) 241 B
|
|
46
46
|
|
|
47
47
|
|
package/template/package.json
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"deploy": "varitykit app deploy"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@varity-labs/sdk": "
|
|
21
|
-
"@varity-labs/types": "
|
|
22
|
-
"@varity-labs/ui-kit": "
|
|
20
|
+
"@varity-labs/sdk": "^2.0.0-beta.2",
|
|
21
|
+
"@varity-labs/types": "^2.0.0-beta.2",
|
|
22
|
+
"@varity-labs/ui-kit": "^2.0.0-beta.5",
|
|
23
23
|
"lucide-react": "^0.400.0",
|
|
24
24
|
"next": "^15.0.0",
|
|
25
25
|
"react": "^18.3.0",
|
|
@@ -7,18 +7,20 @@ import { useProjects, useTasks, useTeam } from '@/lib/hooks';
|
|
|
7
7
|
import { CommandPalette } from '@varity-labs/ui-kit';
|
|
8
8
|
import { Menu, X } from 'lucide-react';
|
|
9
9
|
|
|
10
|
-
// Conditionally import
|
|
10
|
+
// Conditionally import UI-Kit components
|
|
11
11
|
let DashboardLayout: any = null;
|
|
12
|
-
let
|
|
13
|
-
let
|
|
14
|
-
let
|
|
12
|
+
let ProtectedRoute: any = null;
|
|
13
|
+
let AuthStackComponent: any = null;
|
|
14
|
+
let ZeroDevProviderComponent: any = null;
|
|
15
|
+
let useAuthHook: any = null;
|
|
15
16
|
|
|
16
17
|
try {
|
|
17
18
|
const uiKit = require('@varity-labs/ui-kit');
|
|
18
19
|
DashboardLayout = uiKit.DashboardLayout;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
ProtectedRoute = uiKit.PrivyProtectedRoute;
|
|
21
|
+
AuthStackComponent = uiKit.PrivyStack;
|
|
22
|
+
ZeroDevProviderComponent = uiKit.ZeroDevProvider;
|
|
23
|
+
useAuthHook = uiKit.useAuth;
|
|
22
24
|
} catch {}
|
|
23
25
|
|
|
24
26
|
function RedirectToLogin() {
|
|
@@ -111,8 +113,8 @@ function MobileNav({
|
|
|
111
113
|
|
|
112
114
|
function DashboardShell({ children }: { children: React.ReactNode }) {
|
|
113
115
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() success, stable across renders
|
|
114
|
-
const
|
|
115
|
-
const { user, logout } =
|
|
116
|
+
const auth = useAuthHook ? useAuthHook() : { user: null, logout: async () => {} };
|
|
117
|
+
const { user, logout } = auth;
|
|
116
118
|
const pathname = usePathname();
|
|
117
119
|
const router = useRouter();
|
|
118
120
|
const isMobile = useIsMobile();
|
|
@@ -152,7 +154,7 @@ function DashboardShell({ children }: { children: React.ReactNode }) {
|
|
|
152
154
|
const userName = user?.email?.address?.split('@')[0] || 'User';
|
|
153
155
|
const userEmail = user?.email?.address || '';
|
|
154
156
|
|
|
155
|
-
const
|
|
157
|
+
const handleSignOut = async () => {
|
|
156
158
|
await logout();
|
|
157
159
|
router.push('/');
|
|
158
160
|
};
|
|
@@ -194,7 +196,7 @@ function DashboardShell({ children }: { children: React.ReactNode }) {
|
|
|
194
196
|
</nav>
|
|
195
197
|
<div className="mt-8 px-3 border-t border-gray-200 pt-4">
|
|
196
198
|
<button
|
|
197
|
-
onClick={
|
|
199
|
+
onClick={handleSignOut}
|
|
198
200
|
className="flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium text-red-600 hover:bg-red-50 transition-colors"
|
|
199
201
|
>
|
|
200
202
|
Sign Out
|
|
@@ -210,7 +212,7 @@ function DashboardShell({ children }: { children: React.ReactNode }) {
|
|
|
210
212
|
onClose={() => setMobileMenuOpen(false)}
|
|
211
213
|
navItems={navWithActive}
|
|
212
214
|
userEmail={userEmail}
|
|
213
|
-
onLogout={
|
|
215
|
+
onLogout={handleSignOut}
|
|
214
216
|
onNavigate={(path) => router.push(path)}
|
|
215
217
|
/>
|
|
216
218
|
)}
|
|
@@ -241,7 +243,7 @@ function DashboardShell({ children }: { children: React.ReactNode }) {
|
|
|
241
243
|
onClose={() => setMobileMenuOpen(false)}
|
|
242
244
|
navItems={navWithActive}
|
|
243
245
|
userEmail={userEmail}
|
|
244
|
-
onLogout={
|
|
246
|
+
onLogout={handleSignOut}
|
|
245
247
|
onNavigate={(path) => router.push(path)}
|
|
246
248
|
/>
|
|
247
249
|
)}
|
|
@@ -257,7 +259,7 @@ function DashboardShell({ children }: { children: React.ReactNode }) {
|
|
|
257
259
|
name: userName,
|
|
258
260
|
address: userEmail,
|
|
259
261
|
}}
|
|
260
|
-
onLogout={
|
|
262
|
+
onLogout={handleSignOut}
|
|
261
263
|
onNavigateToProfile={() => router.push('/dashboard/settings')}
|
|
262
264
|
onNavigateToSettings={() => router.push('/dashboard/settings')}
|
|
263
265
|
onSearchClick={() => setCommandPaletteOpen(true)}
|
|
@@ -277,21 +279,23 @@ export default function DashboardRootLayout({
|
|
|
277
279
|
}: {
|
|
278
280
|
children: React.ReactNode;
|
|
279
281
|
}) {
|
|
280
|
-
//
|
|
281
|
-
if (!
|
|
282
|
+
// Auth provider (managed by Varity) with gas sponsorship
|
|
283
|
+
if (!ProtectedRoute || !AuthStackComponent || !ZeroDevProviderComponent) {
|
|
282
284
|
// Fallback if ui-kit package isn't installed
|
|
283
285
|
return <DashboardShell>{children}</DashboardShell>;
|
|
284
286
|
}
|
|
285
287
|
|
|
286
288
|
return (
|
|
287
|
-
<
|
|
288
|
-
appId={process.env.
|
|
289
|
+
<AuthStackComponent
|
|
290
|
+
appId={process.env.NEXT_PUBLIC_VARITY_AUTH_ID}
|
|
289
291
|
loginMethods={['email', 'google']}
|
|
290
292
|
appearance={{ theme: 'light', accentColor: '#2563EB', logo: '/logo.svg' }}
|
|
291
293
|
>
|
|
292
|
-
<
|
|
293
|
-
<
|
|
294
|
-
|
|
295
|
-
|
|
294
|
+
<ZeroDevProviderComponent>
|
|
295
|
+
<ProtectedRoute fallback={<RedirectToLogin />}>
|
|
296
|
+
<DashboardShell>{children}</DashboardShell>
|
|
297
|
+
</ProtectedRoute>
|
|
298
|
+
</ZeroDevProviderComponent>
|
|
299
|
+
</AuthStackComponent>
|
|
296
300
|
);
|
|
297
301
|
}
|
|
@@ -37,15 +37,15 @@ import {
|
|
|
37
37
|
Key,
|
|
38
38
|
} from 'lucide-react';
|
|
39
39
|
|
|
40
|
-
const
|
|
40
|
+
const authAppId = process.env.NEXT_PUBLIC_VARITY_AUTH_ID;
|
|
41
41
|
|
|
42
|
-
let
|
|
43
|
-
let
|
|
42
|
+
let UserProfileComponent: any = null;
|
|
43
|
+
let useAuthHook: any = null;
|
|
44
44
|
|
|
45
45
|
try {
|
|
46
46
|
const uiKit = require('@varity-labs/ui-kit');
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
UserProfileComponent = uiKit.PrivyUserProfile;
|
|
48
|
+
useAuthHook = uiKit.useAuth;
|
|
49
49
|
} catch {}
|
|
50
50
|
|
|
51
51
|
const TABS = [
|
|
@@ -79,7 +79,7 @@ export default function SettingsPage() {
|
|
|
79
79
|
const { settings, loading, update: updateSettings } = useUserSettings();
|
|
80
80
|
const toast = useToast();
|
|
81
81
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() + env var, stable across renders
|
|
82
|
-
const
|
|
82
|
+
const auth = authAppId && useAuthHook ? useAuthHook() : { logout: async () => {} };
|
|
83
83
|
|
|
84
84
|
const [activeTab, setActiveTab] = useState<TabId>('general');
|
|
85
85
|
|
|
@@ -556,14 +556,14 @@ export default function SettingsPage() {
|
|
|
556
556
|
)}
|
|
557
557
|
</div>
|
|
558
558
|
|
|
559
|
-
{/*
|
|
560
|
-
{
|
|
559
|
+
{/* Advanced Account Settings */}
|
|
560
|
+
{authAppId && UserProfileComponent && (
|
|
561
561
|
<div className="rounded-xl border border-gray-200 bg-white p-6 shadow-sm">
|
|
562
562
|
<h2 className="mb-4 text-lg font-semibold text-gray-900 flex items-center gap-2">
|
|
563
563
|
<Key className="h-5 w-5" />
|
|
564
|
-
Account Settings
|
|
564
|
+
Advanced Account Settings
|
|
565
565
|
</h2>
|
|
566
|
-
<
|
|
566
|
+
<UserProfileComponent showLogoutButton={false} />
|
|
567
567
|
</div>
|
|
568
568
|
)}
|
|
569
569
|
|
|
@@ -577,7 +577,7 @@ export default function SettingsPage() {
|
|
|
577
577
|
These actions are permanent and cannot be undone.
|
|
578
578
|
</p>
|
|
579
579
|
<div className="flex flex-wrap gap-3">
|
|
580
|
-
<Button variant="danger" onClick={() =>
|
|
580
|
+
<Button variant="danger" onClick={() => auth.logout()}>
|
|
581
581
|
<LogOut className="h-4 w-4" />
|
|
582
582
|
Sign Out
|
|
583
583
|
</Button>
|
|
@@ -6,29 +6,31 @@ import Link from 'next/link';
|
|
|
6
6
|
import { CheckCircle } from 'lucide-react';
|
|
7
7
|
import { APP_NAME } from '@/lib/constants';
|
|
8
8
|
|
|
9
|
-
let
|
|
10
|
-
let
|
|
9
|
+
let AuthStackComponent: any = null;
|
|
10
|
+
let ZeroDevProviderComponent: any = null;
|
|
11
|
+
let useAuthHook: (() => { authenticated: boolean; ready: boolean; login: () => void }) | null = null;
|
|
11
12
|
|
|
12
13
|
try {
|
|
13
14
|
const uiKit = require('@varity-labs/ui-kit');
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
AuthStackComponent = uiKit.PrivyStack;
|
|
16
|
+
ZeroDevProviderComponent = uiKit.ZeroDevProvider;
|
|
17
|
+
useAuthHook = uiKit.useAuth;
|
|
16
18
|
} catch {}
|
|
17
19
|
|
|
18
20
|
function LoginContent() {
|
|
19
21
|
const router = useRouter();
|
|
20
22
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() success, stable across renders
|
|
21
|
-
const
|
|
23
|
+
const auth = useAuthHook ? useAuthHook() : null;
|
|
22
24
|
|
|
23
25
|
useEffect(() => {
|
|
24
|
-
if (
|
|
26
|
+
if (auth?.authenticated) {
|
|
25
27
|
router.push('/dashboard');
|
|
26
28
|
}
|
|
27
|
-
}, [
|
|
29
|
+
}, [auth?.authenticated, router]);
|
|
28
30
|
|
|
29
|
-
const
|
|
30
|
-
if (
|
|
31
|
-
|
|
31
|
+
const handleSignIn = () => {
|
|
32
|
+
if (auth?.login) {
|
|
33
|
+
auth.login();
|
|
32
34
|
}
|
|
33
35
|
};
|
|
34
36
|
|
|
@@ -49,15 +51,15 @@ function LoginContent() {
|
|
|
49
51
|
</div>
|
|
50
52
|
|
|
51
53
|
<div className="rounded-xl border border-gray-200 bg-white p-8 shadow-sm">
|
|
52
|
-
{
|
|
54
|
+
{auth ? (
|
|
53
55
|
<button
|
|
54
|
-
onClick={
|
|
55
|
-
disabled={!
|
|
56
|
+
onClick={handleSignIn}
|
|
57
|
+
disabled={!auth.ready || auth.authenticated}
|
|
56
58
|
className="w-full px-6 py-3 bg-primary-600 hover:bg-primary-700 disabled:bg-gray-300 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors shadow-sm"
|
|
57
59
|
>
|
|
58
|
-
{!
|
|
60
|
+
{!auth.ready
|
|
59
61
|
? 'Loading...'
|
|
60
|
-
:
|
|
62
|
+
: auth.authenticated
|
|
61
63
|
? 'Already Signed In'
|
|
62
64
|
: 'Sign In with Email or Social'}
|
|
63
65
|
</button>
|
|
@@ -79,16 +81,18 @@ function LoginContent() {
|
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
export default function LoginPage() {
|
|
82
|
-
//
|
|
83
|
-
if (
|
|
84
|
+
// Auth provider (managed by Varity) with gas sponsorship
|
|
85
|
+
if (AuthStackComponent && ZeroDevProviderComponent) {
|
|
84
86
|
return (
|
|
85
|
-
<
|
|
86
|
-
appId={process.env.
|
|
87
|
+
<AuthStackComponent
|
|
88
|
+
appId={process.env.NEXT_PUBLIC_VARITY_AUTH_ID}
|
|
87
89
|
loginMethods={['email', 'google']}
|
|
88
90
|
appearance={{ theme: 'light', accentColor: '#2563EB', logo: '/logo.svg' }}
|
|
89
91
|
>
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
+
<ZeroDevProviderComponent>
|
|
93
|
+
<LoginContent />
|
|
94
|
+
</ZeroDevProviderComponent>
|
|
95
|
+
</AuthStackComponent>
|
|
92
96
|
);
|
|
93
97
|
}
|
|
94
98
|
|
|
@@ -5,7 +5,7 @@ import { ToastProvider } from '@varity-labs/ui-kit';
|
|
|
5
5
|
|
|
6
6
|
export function Providers({ children }: { children: ReactNode }) {
|
|
7
7
|
// Only ToastProvider at the global level.
|
|
8
|
-
//
|
|
8
|
+
// Auth provider is added in dashboard/layout.tsx and login/page.tsx —
|
|
9
9
|
// the landing page loads instantly without any auth dependency.
|
|
10
10
|
return <ToastProvider>{children}</ToastProvider>;
|
|
11
11
|
}
|
|
@@ -4,18 +4,18 @@ import { useState, useEffect, useCallback } from 'react';
|
|
|
4
4
|
import { projects, tasks, teamMembers, userSettings } from './database';
|
|
5
5
|
import type { Project, Task, TeamMember, UserSettings } from '../types';
|
|
6
6
|
|
|
7
|
-
let
|
|
7
|
+
let useAuthHook: any = null;
|
|
8
8
|
try {
|
|
9
9
|
const uiKit = require('@varity-labs/ui-kit');
|
|
10
|
-
|
|
10
|
+
useAuthHook = uiKit.useAuth;
|
|
11
11
|
} catch {}
|
|
12
12
|
|
|
13
13
|
export function useCurrentUser() {
|
|
14
14
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() success, stable across renders
|
|
15
|
-
const
|
|
15
|
+
const auth = useAuthHook ? useAuthHook() : { user: null, authenticated: false, logout: async () => {} };
|
|
16
16
|
|
|
17
|
-
// Extract email from any
|
|
18
|
-
const user =
|
|
17
|
+
// Extract email from any auth method (email, Google, GitHub, etc.)
|
|
18
|
+
const user = auth.user;
|
|
19
19
|
const email =
|
|
20
20
|
user?.email?.address ||
|
|
21
21
|
user?.google?.email ||
|
|
@@ -30,8 +30,8 @@ export function useCurrentUser() {
|
|
|
30
30
|
id: user?.id || 'dev-user-id',
|
|
31
31
|
email,
|
|
32
32
|
name,
|
|
33
|
-
authenticated:
|
|
34
|
-
logout:
|
|
33
|
+
authenticated: auth.authenticated,
|
|
34
|
+
logout: auth.logout,
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
|