Skip to content

Commit c1a88cd

Browse files
authored
Merge pull request #51 from tinybirdco/onboard
better new state
2 parents 2b39b17 + 5aa1e1b commit c1a88cd

File tree

4 files changed

+81
-92
lines changed

4 files changed

+81
-92
lines changed

apps/web/src/app/[id]/page.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,6 @@ export default function AppPage({ params }: { params: Promise<{ id: string }> })
4545
checkInstallation();
4646
}, [token, id, setToken, router]);
4747

48-
if (!token || !isValidToken) {
49-
return (
50-
<div className="py-6">
51-
<TokenPrompt error={error} />
52-
</div>
53-
);
54-
}
55-
5648
if (!(id in TOOLS)) {
5749
return <div>Tool not found</div>;
5850
}
@@ -74,6 +66,9 @@ export default function AppPage({ params }: { params: Promise<{ id: string }> })
7466
{error && (
7567
<p className="text-sm text-red-500">{error}</p>
7668
)}
69+
{!token || !isValidToken && (
70+
<TokenPrompt />
71+
)}
7772
<Component />
7873
</div>
7974
</div>

apps/web/src/app/page.tsx

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,53 @@
33
import { useQueryState } from 'nuqs';
44
import { Suspense } from 'react';
55
import TokenPrompt from '@/components/token-prompt';
6+
import Link from 'next/link';
7+
import { SquareArrowOutUpRight } from 'lucide-react';
68

79
function HomeContent() {
810
const [token] = useQueryState('token');
911

10-
if (!token) {
11-
return <TokenPrompt />;
12-
}
13-
1412
return (
1513
<div className="py-6">
1614
<div className="space-y-4">
1715
<h1 className="text-2xl font-bold">Welcome to Tinynest</h1>
18-
<p className="text-muted-foreground">
19-
Select an app from the sidebar to get started. Apps are organized by their status:
20-
</p>
21-
<ul className="list-disc list-inside space-y-2 text-muted-foreground">
22-
<li><strong>Configured Apps</strong> - These apps are fully set up and have data. They&apos;re ready to use!</li>
23-
<li><strong>Installed Apps</strong> - Your Tinybird Workspace has the Data Sources installed, but you&apos;re not receiving data.</li>
24-
<li><strong>Available Apps</strong> - Your Tinybird Workspace doesn&apos;t have the Data Sources installed yet.</li>
25-
</ul>
16+
{token && (
17+
<>
18+
<p className="text-muted-foreground">
19+
Select an app from the sidebar to get started. Apps are organized by their status:
20+
</p>
21+
<ul className="list-disc list-inside space-y-2 text-muted-foreground">
22+
<li><strong>Configured Apps</strong> - These apps are fully set up and have data. They&apos;re ready to use!</li>
23+
<li><strong>Installed Apps</strong> - Your Tinybird Workspace has the Data Sources installed, but you&apos;re not receiving data.</li>
24+
<li><strong>Available Apps</strong> - Your Tinybird Workspace doesn&apos;t have the Data Sources installed yet.</li>
25+
</ul>
26+
</>
27+
)}
28+
{!token && (
29+
<div className="prose">
30+
<p>Tinynest lets you see what&apos;s going on in your SaaS stack.</p>
31+
<p>Modern products use a nest of SaaS tools as building blocks, like Tinybird for Analytics, Clerk for Auth, Stripe for Payments, and more.</p>
32+
<p>This lets you focus on building your product and delighting your users.</p>
33+
<p>But it can also make it hard to see the complete picture of how your users are interacting with your product.</p>
34+
<p>Tinynest helps you to bring that data together in one place.</p>
35+
<TokenPrompt />
36+
37+
<h2>New here? Deploy now</h2>
38+
<p>
39+
Deploy a new project to Tinybird to get started
40+
</p>
41+
<Link
42+
href="https://app.tinybird.co/?starter_kit=https://github.com/tinybirdco/tinynest/tinybird"
43+
target="_blank"
44+
className="inline-flex items-center gap-1 rounded-md bg-primary px-3 py-2 text-sm font-semibold text-primary-foreground shadow hover:bg-primary/90"
45+
>
46+
Deploy to Tinybird
47+
<SquareArrowOutUpRight className="h-4 w-4" />
48+
</Link>
49+
</div>
50+
)}
2651
</div>
27-
</div>
52+
</div >
2853
);
2954
}
3055

apps/web/src/components/sidebar.tsx

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function AppCard({
1919
}: {
2020
app: AppGridItem;
2121
state: ToolState;
22-
token?: string;
22+
token?: string | null;
2323
isActive: boolean;
2424
}) {
2525
const stateColors = {
@@ -35,7 +35,6 @@ function AppCard({
3535
>
3636
<Card className={`p-3 hover:bg-accent mb-2 ${stateColors[state]} ${isActive ? 'bg-accent' : ''}`}>
3737
<div className="flex items-center gap-3">
38-
{/* <div className="text-xl">{app.icon}</div> */}
3938
{app.icon_url && <Image src={app.icon_url} width={16} height={16} alt={app.name} />}
4039
<div>
4140
<div className="flex items-center gap-2">
@@ -72,14 +71,13 @@ function SidebarContent({ activeAppId }: { activeAppId?: string }) {
7271
const [token, setToken] = useQueryState('token');
7372
const [toolStates, setToolStates] = useState<Record<string, ToolState>>({});
7473
const [isLoading, setIsLoading] = useState(false);
75-
const [error, setError] = useState<string>();
74+
// const [error,setError] = useState<string>();
7675

7776
useEffect(() => {
7877
async function fetchToolStates() {
7978
if (!token) return;
80-
8179
setIsLoading(true);
82-
setError(undefined);
80+
// setError(undefined);
8381
try {
8482
const allStates = await checkToolState(token);
8583
const states = Object.values(TOOLS).map((app) => {
@@ -88,22 +86,19 @@ function SidebarContent({ activeAppId }: { activeAppId?: string }) {
8886
setToolStates(Object.fromEntries(states));
8987
} catch (error) {
9088
if (error instanceof InvalidTokenError) {
91-
setError('Invalid token');
89+
// setError('Invalid token');
9290
setToken(null);
9391
} else {
9492
console.error('Failed to fetch tool states:', error);
95-
setError('Failed to fetch tool states');
93+
// setError('Failed to fetch tool states');
9694
}
9795
} finally {
9896
setIsLoading(false);
9997
}
10098
}
101-
102-
fetchToolStates();
99+
if (token) fetchToolStates();
103100
}, [token, setToken]);
104101

105-
if (!token || error) return null;
106-
107102
return (
108103
<div className="w-64 border-r h-screen">
109104
<div className="p-4 border-b">
@@ -183,26 +178,30 @@ function SidebarContent({ activeAppId }: { activeAppId?: string }) {
183178
)}
184179

185180
{/* Available Apps */}
186-
<div className="space-y-2">
187-
<SectionHeader
188-
title="Available Apps"
189-
tooltip="Your Tinybird Workspace doesn't have the Data Sources installed yet. Click an app to learn how to install it."
190-
/>
181+
{Object.values(TOOLS).some(app => toolStates[app.id] === 'available') && (
191182
<div className="space-y-2">
192-
{Object.values(TOOLS)
193-
.filter(app => !toolStates[app.id] || toolStates[app.id] === 'available')
194-
.map(app => (
195-
<AppCard
196-
key={app.id}
197-
app={app}
198-
state={toolStates[app.id] || 'available'}
199-
token={token}
200-
isActive={app.id === activeAppId}
201-
/>
202-
))}
183+
<SectionHeader
184+
title="Available Apps"
185+
tooltip="Your Tinybird Workspace doesn't have the Data Sources installed yet. Click an app to learn how to install it."
186+
/>
187+
<div className="space-y-2">
188+
{Object.values(TOOLS)
189+
.filter(app => !toolStates[app.id] || toolStates[app.id] === 'available')
190+
.map(app => (
191+
<AppCard
192+
key={app.id}
193+
app={app}
194+
state={toolStates[app.id] || 'available'}
195+
token={token}
196+
isActive={app.id === activeAppId}
197+
/>
198+
))}
199+
</div>
203200
</div>
204-
</div>
201+
)}
202+
205203
</div>
204+
206205
)}
207206
</ScrollArea>
208207
</div>
Lines changed: 13 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
"use client"
22

3-
import { SquareArrowOutUpRight } from 'lucide-react'
43
import { useQueryState } from 'nuqs'
54
import { useState } from 'react'
65
import { Button } from './ui/button'
76
import { Input } from './ui/input'
8-
import Link from 'next/link'
97

10-
export default function TokenPrompt({ error }: { error?: string }) {
8+
export default function TokenPrompt() {
119
const [token, setToken] = useQueryState('token')
1210
const [inputToken, setInputToken] = useState('')
1311

@@ -19,46 +17,18 @@ export default function TokenPrompt({ error }: { error?: string }) {
1917
if (token) return null
2018

2119
return (
22-
<div className="fixed inset-0 bg-background/80 backdrop-blur-sm z-50">
23-
<div className="fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg sm:rounded-lg">
24-
<div className="space-y-8">
25-
<div className="space-y-2">
26-
<h2 className="text-lg font-semibold tracking-tight">Already deployed?</h2>
27-
<p className="text-sm text-muted-foreground">
28-
Enter your Tinybird admin token to continue
29-
</p>
30-
<div className="flex w-full max-w-sm flex-col gap-2">
31-
<div className="flex items-center space-x-2">
32-
<Input
33-
placeholder="Enter your token"
34-
value={inputToken}
35-
onChange={(e) => setInputToken(e.target.value)}
36-
onKeyDown={(e) => e.key === 'Enter' && handleSave()}
37-
/>
38-
<Button onClick={handleSave}>Save</Button>
39-
</div>
40-
{error && (
41-
<p className="text-sm text-red-500">{error}</p>
42-
)}
43-
</div>
44-
</div>
45-
46-
<div className="space-y-2">
47-
<h2 className="text-lg font-semibold tracking-tight">New here?</h2>
48-
<p className="text-sm text-muted-foreground">
49-
Deploy a new project to Tinybird to get started
50-
</p>
51-
<Link
52-
href="https://app.tinybird.co/?starter_kit=https://github.com/tinybirdco/tinynest/tinybird"
53-
target="_blank"
54-
className="inline-flex items-center gap-1 rounded-md bg-primary px-3 py-2 text-sm font-semibold text-primary-foreground shadow hover:bg-primary/90"
55-
>
56-
Deploy to Tinybird
57-
<SquareArrowOutUpRight className="h-4 w-4" />
58-
</Link>
59-
</div>
60-
</div>
20+
<>
21+
<h2>Already deployed? Enter your token</h2>
22+
<div className="flex w-full max-w-sm items-center space-x-2">
23+
<Input
24+
type="password"
25+
placeholder="Enter your 'read' token from Tinybird"
26+
value={inputToken}
27+
onChange={(e) => setInputToken(e.target.value)}
28+
onKeyDown={(e) => e.key === 'Enter' && handleSave()} />
29+
<Button type="submit" onClick={handleSave}>Save</Button>
6130
</div>
62-
</div>
31+
</>
32+
6333
)
6434
}

0 commit comments

Comments
 (0)