Files
stats/apps/start/.cursorrules
Carl-Gerhard Lindesvärd 81a7e5d62e feat: dashboard v2, esm, upgrades (#211)
* esm

* wip

* wip

* wip

* wip

* wip

* wip

* subscription notice

* wip

* wip

* wip

* fix envs

* fix: update docker build

* fix

* esm/types

* delete dashboard :D

* add patches to dockerfiles

* update packages + catalogs + ts

* wip

* remove native libs

* ts

* improvements

* fix redirects and fetching session

* try fix favicon

* fixes

* fix

* order and resize reportds within a dashboard

* improvements

* wip

* added userjot to dashboard

* fix

* add op

* wip

* different cache key

* improve date picker

* fix table

* event details loading

* redo onboarding completely

* fix login

* fix

* fix

* extend session, billing and improve bars

* fix

* reduce price on 10M
2025-10-16 12:27:44 +02:00

338 lines
8.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
We use Sentry for watching for errors in our deployed application, as well as for instrumentation of our application.
## Error collection
Error collection is automatic and configured in `src/router.tsx`.
## Instrumentation
We want our server functions instrumented. So if you see a function name like `createServerFn`, you can instrument it with Sentry. You'll need to import `Sentry`:
```tsx
import * as Sentry from '@sentry/tanstackstart-react'
```
And then wrap the implementation of the server function with `Sentry.startSpan`, like so:
```tsx
Sentry.startSpan({ name: 'Requesting all the pokemon' }, async () => {
// Some lengthy operation here
await fetch('https://api.pokemon.com/data/')
})
```
# shadcn instructions
Use the latest version of Shadcn to install new components, like this command to add a button component:
```bash
pnpx shadcn@latest add button
```
# TanStack Router v1 — Routing Concepts (React) Cheat Sheet
> Quick, copypastable reference for filebased routing in TanStack Router v1 (React).
## TL;DR
* **Root route** is always matched; it wraps everything.
* **createFileRoute(path)** defines a route; the path is automanaged by the bundler/CLI.
* **Index routes** use a **trailing slash** (`/posts/`) to target the exact parent path.
* **Dynamic segments** use `$param` (e.g. `/posts/$postId`).
* **Splat (catchall)** route is a lone `$` segment, exposing `params._splat`.
* **Optional segments** use `{-$param}`.
* **Layout routes** are normal routes that render an `<Outlet/>` for children.
* **Pathless layout routes** start with `_` (e.g. `/_settingsShell`), wrap children but dont match URL segments.
* **Nonnested** routes suffix a segment with `_` to un-nest (e.g. `posts_.$postId.edit.tsx`).
* Prefix files/folders with `-` to **exclude** them from routing (colocation).
* Use `(group)` folders to **group** files only (no path impact).
---
## 1) Anatomy of a Route
```tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({
component: PostsComponent,
})
```
* `createFileRoute(path)` → declare a route for this file.
* Path string is autowritten/maintained by the bundler/CLI for type safety.
### Root Route
```tsx
import { createRootRoute } from '@tanstack/react-router'
export const Route = createRootRoute()
```
* No path; always matched; can host loaders, components, search param validation, etc.
**With context**:
```tsx
import { createRootRouteWithContext } from '@tanstack/react-router'
import type { QueryClient } from '@tanstack/react-query'
export interface MyRouterContext { queryClient: QueryClient }
export const Route = createRootRouteWithContext<MyRouterContext>()
```
---
## 2) Basic Routes
```tsx
// routes/about.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/about')({
component: () => <div>About</div>,
})
```
* Exact path match. Renders `component`.
### Index Routes (trailing slash)
```tsx
// routes/posts.index.tsx OR routes/posts/ index file
export const Route = createFileRoute('/posts/')({
component: () => <div>Please select a post!</div>,
})
```
* Matches **exactly** `/posts`. The **trailing `/`** denotes an index.
---
## 3) Dynamic Segments
```tsx
// routes/posts.$postId.tsx
export const Route = createFileRoute('/posts/$postId')({
loader: ({ params }) => fetchPost(params.postId),
component: PostComponent,
})
function PostComponent() {
const { postId } = Route.useParams()
return <div>Post ID: {postId}</div>
}
```
* `$postId` captures `123` for `/posts/123` → `{ postId: '123' }`.
* You can chain: `/posts/$postId/$revisionId` → `{ postId, revisionId }`.
### Splat / CatchAll
```tsx
// routes/files/$.tsx
export const Route = createFileRoute('/files/$')({ component: Files })
```
* Captures the rest of the path into `params._splat` (e.g. `documents/hello-world`).
### Optional Parameters
```tsx
// routes/posts.{-$category}.tsx
export const Route = createFileRoute('/posts/{-$category}')({ component: Posts })
function Posts() {
const { category } = Route.useParams()
return <div>{category ? `Posts in ${category}` : 'All Posts'}</div>
}
```
* Matches `/posts` and `/posts/tech`.
* **Priority note:** routes with optional params are ranked lower than exact matches (e.g. `/posts/featured` beats `/posts/{-$category}`).
---
## 4) Layout & Pathless Layout Routes
### Layout Routes
```tsx
// routes/app.tsx
import { Outlet, createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/app')({ component: AppLayout })
function AppLayout() {
return (
<div>
<h1>App</h1>
<Outlet />
</div>
)
}
```
**Rendering matrix**
* `/app` → `<AppLayout>`
* `/app/dashboard` → `<AppLayout><Dashboard/>`
* `/app/settings` → `<AppLayout><Settings/>`
### Pathless Layout Routes (no URL segment)
```tsx
// routes/_shell.tsx
import { Outlet, createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/_shell')({ component: Shell })
function Shell() {
return (
<div>
<Header/>
<Outlet />
</div>
)
}
```
* File/folder name starts with `_` → doesnt match a URL segment; wraps children.
* **Cannot** include dynamic `$param` in the pathless segment name. Use a real `$param` directory **beside** your `_shell` if needed:
```
routes/
├─ $postId/
├─ _postShell/
```
---
## 5) NonNested Routes ("un-nesting")
Append `_` after a segment name to un-nest a file so it renders its own tree:
```
routes/
├─ posts.tsx
├─ posts.$postId.tsx
├─ posts_.$postId.edit.tsx // un-nested
```
**Resulting renders**
* `/posts` → `<Posts>`
* `/posts/123` → `<Posts><Post id=123>`
* `/posts/123/edit` → `<PostEditor id=123>` (not wrapped by `<Posts>`)
---
## 6) Excluding Files & Colocation
Prefix with `-` to exclude from route generation and safely colocate utilities:
```
routes/
├─ posts.tsx
├─ -posts-table.tsx // ignored
├─ -components/ // ignored
│ ├─ header.tsx // ignored
│ └─ footer.tsx // ignored
```
```tsx
import { PostsTable } from './-posts-table'
```
* Excluded entries are not added to the generated `routeTree.gen.ts`.
---
## 7) Pathless Route Group Directories
Group routes for organization only using `(group)` folders — no effect on paths or nesting:
```
routes/
├─ index.tsx
├─ (app)/
│ ├─ dashboard.tsx
│ ├─ settings.tsx
│ └─ users.tsx
├─ (auth)/
│ ├─ login.tsx
│ └─ register.tsx
```
**URLs render as** `/dashboard`, `/settings`, `/users`, `/login`, `/register`.
---
## 8) Useful APIs & Hooks
* `Route.useParams()` — typed path params for the current file route.
* `Route.useLoaderData()` — typed data returned from the current routes `loader`.
* `<Outlet/>` — placeholder for child routes.
* (See docs for: search param validation, data loading, mutations, type safety, preloading, SSR, etc.)
---
## 9) Common File Naming Patterns (filebased routing)
* `__root.tsx` — root route file.
* `index.tsx` or trailing `/` in `createFileRoute` — index under a segment.
* `$param.tsx` — dynamic segment.
* `$.tsx` — splat (catchall) segment.
* `{-$param}.tsx` — optional segment.
* `_segment.tsx` or `/_segment/route.tsx` — pathless layout route.
* `segment_.tsx` — un-nest that segment from parents.
* `-utils.tsx`, `-components/` — excluded from routing.
* `(group)/` — pathless grouping-only folder.
---
## 10) Quick Reference Examples
```tsx
// Simple loader + params + component
export const Route = createFileRoute('/users/$userId')({
loader: ({ params }) => getUser(params.userId),
component: () => {
const { userId } = Route.useParams()
const user = Route.useLoaderData()
return <UserCard id={userId} data={user} />
},
})
```
```tsx
// Layout
export const Route = createFileRoute('/dashboard')({ component: Layout })
function Layout() {
return <>
<Sidebar />
<Outlet />
</>
}
```
```tsx
// Optional + Splat combo (illustrative)
export const Route = createFileRoute('/docs/{-$section}/$')({ component: Docs })
```
---
## 11) Gotchas & Tips
* Prefer **filebased** routing for less boilerplate and excellent type safety.
* Remember the **trailing slash** for index routes.
* Optional routes are **lower priority** than exact matches.
* Pathless layout routes **cannot** be dynamic.
* Use `-` prefix liberally to colocate nonroute code near routes.
* Use `(group)` folders to tame big route directories.
---
### Further Reading
* Route Trees, Route Matching, FileBased Routing, Outlets, Path/Search Params, Data Loading, SSR, etc.
Happy routing! 🚦