add fonts and some basic routes

This commit is contained in:
2026-02-21 11:37:19 +01:00
parent 2933465ba9
commit f2ee7d773f
11 changed files with 168 additions and 26 deletions

5
apps/web/CLAUDE.md Normal file
View File

@@ -0,0 +1,5 @@
# ZENDEGI WEB APP
Zendegi is a web app for creating and exploring timelines. They could be personal or professional.
The timelines are shown horizontally and are interactive.

View File

@@ -11,6 +11,8 @@
}, },
"dependencies": { "dependencies": {
"@base-ui/react": "^1.0.0", "@base-ui/react": "^1.0.0",
"@fontsource-variable/inter": "^5.2.8",
"@fontsource/instrument-serif": "^5.2.8",
"@tailwindcss/vite": "^4.1.8", "@tailwindcss/vite": "^4.1.8",
"@tanstack/react-form": "^1.23.5", "@tanstack/react-form": "^1.23.5",
"@tanstack/react-query": "^5.80.6", "@tanstack/react-query": "^5.80.6",

BIN
apps/web/public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -6,6 +6,7 @@ export default function Header() {
const links = [ const links = [
{ to: "/", label: "Home" }, { to: "/", label: "Home" },
{ to: "/dashboard", label: "Dashboard" }, { to: "/dashboard", label: "Dashboard" },
{ to: "/timelines", label: "Timelines" },
] as const; ] as const;
return ( return (

View File

@@ -1,6 +1,9 @@
@import "tailwindcss"; @import "tailwindcss";
@import "tw-animate-css"; @import "tw-animate-css";
@import "@fontsource-variable/inter";
@import "@fontsource/instrument-serif";
@custom-variant dark (&:is(.dark *)); @custom-variant dark (&:is(.dark *));
:root { :root {
@@ -74,6 +77,7 @@
@theme inline { @theme inline {
--font-sans: "Inter Variable", sans-serif; --font-sans: "Inter Variable", sans-serif;
--font-mono: "Instrument Serif", monospace;
--color-sidebar-ring: var(--sidebar-ring); --color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border); --color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);

View File

@@ -9,12 +9,25 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root' import { Route as rootRouteImport } from './routes/__root'
import { Route as TimelinesRouteImport } from './routes/timelines'
import { Route as TimelineRouteImport } from './routes/timeline'
import { Route as LoginRouteImport } from './routes/login' import { Route as LoginRouteImport } from './routes/login'
import { Route as DemoRouteImport } from './routes/demo' import { Route as DemoRouteImport } from './routes/demo'
import { Route as DashboardRouteImport } from './routes/dashboard' import { Route as DashboardRouteImport } from './routes/dashboard'
import { Route as IndexRouteImport } from './routes/index' import { Route as IndexRouteImport } from './routes/index'
import { Route as TimelineTimelineIdRouteImport } from './routes/timeline.$timelineId'
import { Route as ApiAuthSplatRouteImport } from './routes/api/auth/$' import { Route as ApiAuthSplatRouteImport } from './routes/api/auth/$'
const TimelinesRoute = TimelinesRouteImport.update({
id: '/timelines',
path: '/timelines',
getParentRoute: () => rootRouteImport,
} as any)
const TimelineRoute = TimelineRouteImport.update({
id: '/timeline',
path: '/timeline',
getParentRoute: () => rootRouteImport,
} as any)
const LoginRoute = LoginRouteImport.update({ const LoginRoute = LoginRouteImport.update({
id: '/login', id: '/login',
path: '/login', path: '/login',
@@ -35,6 +48,11 @@ const IndexRoute = IndexRouteImport.update({
path: '/', path: '/',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any) } as any)
const TimelineTimelineIdRoute = TimelineTimelineIdRouteImport.update({
id: '/$timelineId',
path: '/$timelineId',
getParentRoute: () => TimelineRoute,
} as any)
const ApiAuthSplatRoute = ApiAuthSplatRouteImport.update({ const ApiAuthSplatRoute = ApiAuthSplatRouteImport.update({
id: '/api/auth/$', id: '/api/auth/$',
path: '/api/auth/$', path: '/api/auth/$',
@@ -46,6 +64,9 @@ export interface FileRoutesByFullPath {
'/dashboard': typeof DashboardRoute '/dashboard': typeof DashboardRoute
'/demo': typeof DemoRoute '/demo': typeof DemoRoute
'/login': typeof LoginRoute '/login': typeof LoginRoute
'/timeline': typeof TimelineRouteWithChildren
'/timelines': typeof TimelinesRoute
'/timeline/$timelineId': typeof TimelineTimelineIdRoute
'/api/auth/$': typeof ApiAuthSplatRoute '/api/auth/$': typeof ApiAuthSplatRoute
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
@@ -53,6 +74,9 @@ export interface FileRoutesByTo {
'/dashboard': typeof DashboardRoute '/dashboard': typeof DashboardRoute
'/demo': typeof DemoRoute '/demo': typeof DemoRoute
'/login': typeof LoginRoute '/login': typeof LoginRoute
'/timeline': typeof TimelineRouteWithChildren
'/timelines': typeof TimelinesRoute
'/timeline/$timelineId': typeof TimelineTimelineIdRoute
'/api/auth/$': typeof ApiAuthSplatRoute '/api/auth/$': typeof ApiAuthSplatRoute
} }
export interface FileRoutesById { export interface FileRoutesById {
@@ -61,14 +85,42 @@ export interface FileRoutesById {
'/dashboard': typeof DashboardRoute '/dashboard': typeof DashboardRoute
'/demo': typeof DemoRoute '/demo': typeof DemoRoute
'/login': typeof LoginRoute '/login': typeof LoginRoute
'/timeline': typeof TimelineRouteWithChildren
'/timelines': typeof TimelinesRoute
'/timeline/$timelineId': typeof TimelineTimelineIdRoute
'/api/auth/$': typeof ApiAuthSplatRoute '/api/auth/$': typeof ApiAuthSplatRoute
} }
export interface FileRouteTypes { export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' | '/dashboard' | '/demo' | '/login' | '/api/auth/$' fullPaths:
| '/'
| '/dashboard'
| '/demo'
| '/login'
| '/timeline'
| '/timelines'
| '/timeline/$timelineId'
| '/api/auth/$'
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo
to: '/' | '/dashboard' | '/demo' | '/login' | '/api/auth/$' to:
id: '__root__' | '/' | '/dashboard' | '/demo' | '/login' | '/api/auth/$' | '/'
| '/dashboard'
| '/demo'
| '/login'
| '/timeline'
| '/timelines'
| '/timeline/$timelineId'
| '/api/auth/$'
id:
| '__root__'
| '/'
| '/dashboard'
| '/demo'
| '/login'
| '/timeline'
| '/timelines'
| '/timeline/$timelineId'
| '/api/auth/$'
fileRoutesById: FileRoutesById fileRoutesById: FileRoutesById
} }
export interface RootRouteChildren { export interface RootRouteChildren {
@@ -76,11 +128,27 @@ export interface RootRouteChildren {
DashboardRoute: typeof DashboardRoute DashboardRoute: typeof DashboardRoute
DemoRoute: typeof DemoRoute DemoRoute: typeof DemoRoute
LoginRoute: typeof LoginRoute LoginRoute: typeof LoginRoute
TimelineRoute: typeof TimelineRouteWithChildren
TimelinesRoute: typeof TimelinesRoute
ApiAuthSplatRoute: typeof ApiAuthSplatRoute ApiAuthSplatRoute: typeof ApiAuthSplatRoute
} }
declare module '@tanstack/react-router' { declare module '@tanstack/react-router' {
interface FileRoutesByPath { interface FileRoutesByPath {
'/timelines': {
id: '/timelines'
path: '/timelines'
fullPath: '/timelines'
preLoaderRoute: typeof TimelinesRouteImport
parentRoute: typeof rootRouteImport
}
'/timeline': {
id: '/timeline'
path: '/timeline'
fullPath: '/timeline'
preLoaderRoute: typeof TimelineRouteImport
parentRoute: typeof rootRouteImport
}
'/login': { '/login': {
id: '/login' id: '/login'
path: '/login' path: '/login'
@@ -109,6 +177,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport parentRoute: typeof rootRouteImport
} }
'/timeline/$timelineId': {
id: '/timeline/$timelineId'
path: '/$timelineId'
fullPath: '/timeline/$timelineId'
preLoaderRoute: typeof TimelineTimelineIdRouteImport
parentRoute: typeof TimelineRoute
}
'/api/auth/$': { '/api/auth/$': {
id: '/api/auth/$' id: '/api/auth/$'
path: '/api/auth/$' path: '/api/auth/$'
@@ -119,11 +194,25 @@ declare module '@tanstack/react-router' {
} }
} }
interface TimelineRouteChildren {
TimelineTimelineIdRoute: typeof TimelineTimelineIdRoute
}
const TimelineRouteChildren: TimelineRouteChildren = {
TimelineTimelineIdRoute: TimelineTimelineIdRoute,
}
const TimelineRouteWithChildren = TimelineRoute._addFileChildren(
TimelineRouteChildren,
)
const rootRouteChildren: RootRouteChildren = { const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute, IndexRoute: IndexRoute,
DashboardRoute: DashboardRoute, DashboardRoute: DashboardRoute,
DemoRoute: DemoRoute, DemoRoute: DemoRoute,
LoginRoute: LoginRoute, LoginRoute: LoginRoute,
TimelineRoute: TimelineRouteWithChildren,
TimelinesRoute: TimelinesRoute,
ApiAuthSplatRoute: ApiAuthSplatRoute, ApiAuthSplatRoute: ApiAuthSplatRoute,
} }
export const routeTree = rootRouteImport export const routeTree = rootRouteImport

View File

@@ -4,31 +4,24 @@ export const Route = createFileRoute("/")({
component: HomeComponent, component: HomeComponent,
}); });
const TITLE_TEXT = `
██████╗ ███████╗████████╗████████╗███████╗██████╗
██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗
██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝
██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗
██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║
╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
████████╗ ███████╗████████╗ █████╗ ██████╗██╗ ██╗
╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝
██║ ███████╗ ██║ ███████║██║ █████╔╝
██║ ╚════██║ ██║ ██╔══██║██║ ██╔═██╗
██║ ███████║ ██║ ██║ ██║╚██████╗██║ ██╗
╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
`;
function HomeComponent() { function HomeComponent() {
return ( return (
<div className="container mx-auto max-w-3xl px-4 py-2"> <section className="container mx-auto max-w-3xl px-4 py-2">
<pre className="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre> <div className="space-y-7">
<div className="grid gap-6"> <div className="w-80">
<section className="rounded-lg border p-4"> <img alt="Zendegi" src="public/logo.png" />
<h2 className="mb-2 font-medium">API Status</h2> </div>
</section> <div className="space-y-3">
<h1 className="text-4xl sm:text-7xl font-serif font-bold">
Everything you need to visualize your story
</h1>
<p>
With our web app, bring to life stunning timelines of your
milestones, stories, and plans. Unleash creativity, boost
productivity, and transform how you experience your world.
</p>
</div>
</div> </div>
</div> </section>
); );
} }

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/timeline/$timelineId")({
component: RouteComponent,
});
function RouteComponent() {
return <div>Timeline detail</div>;
}

View File

@@ -0,0 +1,14 @@
import { Outlet, createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/timeline")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
Shell of timeline
<Outlet />
</div>
);
}

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/timelines")({
component: RouteComponent,
});
function RouteComponent() {
return <div>List of timelines</div>;
}

16
pnpm-lock.yaml generated
View File

@@ -60,6 +60,12 @@ importers:
'@base-ui/react': '@base-ui/react':
specifier: ^1.0.0 specifier: ^1.0.0
version: 1.1.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) version: 1.1.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@fontsource-variable/inter':
specifier: ^5.2.8
version: 5.2.8
'@fontsource/instrument-serif':
specifier: ^5.2.8
version: 5.2.8
'@tailwindcss/vite': '@tailwindcss/vite':
specifier: ^4.1.8 specifier: ^4.1.8
version: 4.1.18(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) version: 4.1.18(vite@7.3.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))
@@ -1050,6 +1056,12 @@ packages:
'@floating-ui/utils@0.2.10': '@floating-ui/utils@0.2.10':
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
'@fontsource-variable/inter@5.2.8':
resolution: {integrity: sha512-kOfP2D+ykbcX/P3IFnokOhVRNoTozo5/JxhAIVYLpea/UBmCQ/YWPBfWIDuBImXX/15KH+eKh4xpEUyS2sQQGQ==}
'@fontsource/instrument-serif@5.2.8':
resolution: {integrity: sha512-s+bkz+syj2rO00Rmq9g0P+PwuLig33DR1xDR8pTWmovH1pUjwnncrFk++q9mmOex8fUQ7oW80gPpPDaw7V1MMw==}
'@hono/node-server@1.19.9': '@hono/node-server@1.19.9':
resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==} resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==}
engines: {node: '>=18.14.1'} engines: {node: '>=18.14.1'}
@@ -5178,6 +5190,10 @@ snapshots:
'@floating-ui/utils@0.2.10': {} '@floating-ui/utils@0.2.10': {}
'@fontsource-variable/inter@5.2.8': {}
'@fontsource/instrument-serif@5.2.8': {}
'@hono/node-server@1.19.9(hono@4.11.9)': '@hono/node-server@1.19.9(hono@4.11.9)':
dependencies: dependencies:
hono: 4.11.9 hono: 4.11.9