Skip to content

Commit 9647210

Browse files
committed
feat: tinylytics kudo + pageview + sidebar fix
1 parent d9f45b8 commit 9647210

5 files changed

Lines changed: 122 additions & 14 deletions

File tree

AGENT.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Repository Guidelines
2+
3+
## Project Structure & Module Organization
4+
5+
- Source: `src/` with:
6+
- `pages/` (Astro routes and API endpoints: `.astro`, `*.ts` like `image.png.ts`).
7+
- `components/` (client/server React `.tsx` and `.astro`).
8+
- `layouts/`, `styles/`, `domains/` (domain logic), `routes/` (route helpers), and `content/` (MDX content).
9+
- Public assets: `public/` (served at `/`, e.g., `/background.png`). Build output: `dist/`.
10+
- Content collections: configured in `src/content.config.ts` using Astro Content. Collections include `creators`, `games`, `assets`, `resources`, and `docs`, with content under `src/content/<collection>/`.
11+
12+
## Build & Development
13+
14+
- `bun install`: install dependencies.
15+
- `bun run dev`: start local dev server (defaults to `http://localhost:4321`).
16+
- `bun run build`: production build to `dist/` (runs `astro build`).
17+
- `bun run preview`: serve the built site locally.
18+
- `bun run check`: Astro/TS diagnostics (type and config checks).
19+
- Deployment: Netlify adapter is configured in `astro.config.mjs`; scripts `alpha`/`prod` use the Netlify CLI.
20+
21+
## Style & Syntax
22+
23+
- Prettier + Tailwind plugin enforce formatting. Use PascalCase for components, camelCase for functions, UPPER_SNAKE for constants; filenames generally kebab-case. Dynamic route params use descriptive camelCase (e.g., `[creatorSlug]`).
24+
- Prefer `function` declarations/expressions for non-passed functions (route handlers, utilities). Use arrow functions when passing (React event handlers, callbacks). Prefer `type` over `interface`.
25+
- For non-render functions, accept a single `params` object (no destructuring); favor readable, multi-line steps over deep chains.
26+
- Curly braces: always include `{}` for control statements (`if/else`, `for`, `while`, `do`, `switch`, and non-trivial arrow bodies). Avoid single-line or inline `if` without braces.
27+
28+
## Components & UI
29+
30+
- Single `props` param: components accept a single `props` parameter. Do not destructure in the signature.
31+
- Inline prop types: annotate the parameter inline; avoid exporting standalone `*Props` types.
32+
- Defaults rule: create local defaults from `props`, e.g., `const size = props.size ?? "2"`.
33+
- Spreading rule: if spreading HTML attributes, destructure inside the body to obtain `...rest`; otherwise avoid destructuring `props`.
34+
- Order: function declaration and defaults → React state hooks → derived consts → effects (name `useEffect` callbacks) → event handlers (`function handleClick() {}`) → return JSX → sub-render helpers at bottom.
35+
- React hooks import: import hooks directly (`import { useState, useEffect } from "react"`), do not call them off the React namespace (avoid `React.useEffect`, `React.useState`).
36+
- Styling: prefer Tailwind utilities; use `cn(...)`/`twMerge(...)` for class merging when needed.
37+
- Sub-render helpers: when extracting tiny render fragments inside a component, use plain functions scoped to that component and name them `renderThing(params)`. These are not React components and should not use hooks; they return JSX and are called like `renderThing({ ... })`.
38+
- Components vs helpers: anything used as `<Thing />` is a real React component and must accept a single `props` parameter (not `params`). Reserve `params` objects for non-React functions and sub-render helpers.
39+
- Render helpers placement: do not declare render helpers inline inside JSX. Define them as `function` declarations after the component’s return block. Call them inside JSX like `renderThing({ ... })`.
40+
41+
## Testing & PRs
42+
43+
- Run `bun run check` to check for errors/warnings.
44+
- Commits: conventional prefixes (`feat:`, `fix:`, `chore:`). PRs: summary, linked issues, screenshots for UI, and notes on env/migrations.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"alpha": "netlify build && netlify deploy",
1414
"prod": "netlify build && netlify deploy --prod",
1515
"content": "bun ./scripts/content.ts",
16+
"codex": "bun install -g @openai/codex@latest && codex",
1617
"knip": "knip"
1718
},
1819
"dependencies": {
Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,65 @@
11
---
2-
32
---
43

5-
<script src="https://tinylytics.app/embed/-VTUbs6KP1RTrgeepgoh.js" defer></script>
4+
<div class="fixed bottom-4 inset-x-0 z-40 w-full flex justify-center pointer-events-none">
5+
<div
6+
aria-label="Page analytics and like"
7+
class="pointer-events-auto inline-flex items-center gap-2 rounded-full border border-black/10 dark:border-white/10 bg-white/80 dark:bg-neutral-900/80 backdrop-blur px-3.5 py-2 shadow-lg"
8+
>
9+
<span
10+
class="views-chip inline-flex items-center rounded-full border border-black/10 dark:border-white/10 bg-black/5 dark:bg-white/10 px-3 py-1.5 text-xs leading-none text-neutral-800 dark:text-neutral-200"
11+
>
12+
<span class="tinylytics_hits tabular-nums">–</span>
13+
</span>
14+
<button
15+
class="tinylytics_kudos tabular-nums cursor-pointer relative inline-flex items-center rounded-full bg-gradient-to-r from-rose-500 to-orange-500 px-3 py-1.5 text-white text-xs leading-none font-medium shadow hover:shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-500 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-neutral-900"
16+
type="button"
17+
aria-label="Like this page"
18+
>
19+
-
20+
</button>
21+
</div>
22+
23+
</div>
24+
625

26+
<style is:global>
27+
/* CSS-only icons for Tinylytics widgets */
28+
.tinylytics_kudos {
29+
line-height: 1;
30+
}
31+
.tinylytics_kudos::before {
32+
content: "";
33+
display: inline-block;
34+
width: 1em;
35+
height: 1em;
36+
background: currentColor;
37+
-webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 21s-6.716-4.632-9.428-7.344A5.25 5.25 0 0 1 10.5 6.75l1.5 1.5 1.5-1.5A5.25 5.25 0 0 1 21.428 13.656C18.716 16.368 12 21 12 21Z'/></svg>");
38+
-webkit-mask-repeat: no-repeat;
39+
-webkit-mask-size: contain;
40+
-webkit-mask-position: center;
41+
mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 21s-6.716-4.632-9.428-7.344A5.25 5.25 0 0 1 10.5 6.75l1.5 1.5 1.5-1.5A5.25 5.25 0 0 1 21.428 13.656C18.716 16.368 12 21 12 21Z'/></svg>");
42+
mask-repeat: no-repeat;
43+
mask-size: contain;
44+
mask-position: center;
45+
vertical-align: text-bottom;
46+
margin-right: 0.35em;
47+
}
48+
.views-chip::before {
49+
content: "";
50+
display: inline-block;
51+
width: 1em;
52+
height: 1em;
53+
background: currentColor;
54+
-webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='currentColor' d='M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z' /><circle cx='12' cy='12' r='3' fill='currentColor' /></svg>");
55+
-webkit-mask-repeat: no-repeat;
56+
-webkit-mask-size: contain;
57+
-webkit-mask-position: center;
58+
mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='currentColor' d='M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z' /><circle cx='12' cy='12' r='3' fill='currentColor' /></svg>");
59+
mask-repeat: no-repeat;
60+
mask-size: contain;
61+
mask-position: center;
62+
vertical-align: text-bottom;
63+
margin-right: 0.35em;
64+
}
65+
</style>

src/layouts/Layout.astro

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
22
import "@radix-ui/themes/styles.css";
3-
import { ClientRouter, fade } from "astro:transitions";
43
54
import { Debug } from "astro:components";
65
import { Graphic } from "../components/client/Graphic/Graphic";
@@ -73,7 +72,7 @@ const ogImageUrl = AppUrl.ogImage({
7372
---
7473

7574
<!doctype html>
76-
<html lang="en" transition:animate={fade({ duration: ".150s" })}>
75+
<html lang="en" >
7776
<head>
7877
<meta charset="UTF-8" />
7978
<meta name="viewport" content="width=device-width" />
@@ -147,8 +146,13 @@ const ogImageUrl = AppUrl.ogImage({
147146
}
148147
</script>
149148

150-
<!-- Animation -->
151-
<ClientRouter />
149+
150+
151+
<!-- Tinylytics embed with custom hits/kudos UI enabled -->
152+
<script
153+
src="https://tinylytics.app/embed/-VTUbs6KP1RTrgeepgoh.js?hits&kudos=custom"
154+
defer
155+
></script>
152156
</head>
153157
<UI.Theme {...themeProps} className="">
154158
<body>

src/routes/ResourceRoute/ResourceRoute.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,18 @@ export function ResourceRoute(props: {
128128
<Toaster />
129129
<CampaignContext.Provider value={campaignManager}>
130130
<div>
131-
<div className="flex flex-row gap-9">
132-
<div className="hidden w-[300px] flex-shrink-0 flex-grow basis-[300px] lg:flex">
133-
<div
134-
className="sticky top-6"
135-
style={{ maxHeight: "calc(100vh - 32px)" }}
136-
>
137-
<div className="relative h-full overflow-y-scroll pb-[10rem]">
131+
<div className="lg:grid lg:grid-cols-[300px_minmax(0,1fr)] lg:gap-9">
132+
<div className="hidden lg:block min-w-0">
133+
<div className="sticky top-6">
134+
<div
135+
className="relative overflow-y-auto overflow-x-hidden pb-[10rem]"
136+
style={{ maxHeight: "calc(100vh - 32px)" }}
137+
>
138138
{renderSidebar({ withImage: true })}
139139
</div>
140140
</div>
141141
</div>
142-
<div className="flex flex-col">
142+
<div className="flex flex-col min-w-0">
143143
<div className="block w-full">
144144
<div className="flex flex-col">
145145
<div className="mb-6">{renderPatreonBanner()}</div>

0 commit comments

Comments
 (0)