@flocon-ai/react 0.0.0-stage → 0.0.1

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/README.md CHANGED
@@ -1,3 +1,141 @@
1
- # Temporary Holding Version
1
+ # @flocon-ai/react
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Show your [Flocon AI](https://flocon-ai.com) pages in a **server-rendered** React website.
4
+ You create the pages from your AI tool (Claude, Cursor…). This lib renders them.
5
+
6
+ > ⚠️ **Browser-only React apps are not supported** (Vite SPA, Create React App).
7
+ > Most AI bots do not run JavaScript. They would see an empty page.
8
+ > Use a framework that renders on the server: React Router v7 (framework mode), TanStack Start…
9
+ > On Next.js, use [`@flocon-ai/next`](https://www.npmjs.com/package/@flocon-ai/next).
10
+
11
+ - Needs React 18+.
12
+ - Call the client **on the server only** (route loader, server function). The token must never reach the browser.
13
+ - Pages are read on each request, so a new page shows up on the next visit. Drafts are never returned.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm i @flocon-ai/react
19
+ ```
20
+
21
+ ## Token
22
+
23
+ Copy your **website token** from [flocon-ai.com/app/tokens](https://flocon-ai.com/app/tokens).
24
+
25
+ ```bash
26
+ # .env
27
+ FLOCON_TOKEN=your_read_token
28
+ ```
29
+
30
+ Never commit it. Never send it to the browser.
31
+
32
+ Token not in `FLOCON_TOKEN`? Every helper that calls the API takes an optional `token`:
33
+
34
+ ```ts
35
+ await getPage({ path, token: myToken })
36
+ await floconSitemap({ url, token: myToken })
37
+ ```
38
+
39
+ ## Page route (React Router v7, framework mode)
40
+
41
+ ```tsx
42
+ // app/routes/flocon.tsx (route: "*")
43
+ import { FloconPage, getFloconMetadata, getPage } from "@flocon-ai/react"
44
+ import type { Route } from "./+types/flocon"
45
+
46
+ // Your URL rule. One locale: keep as is.
47
+ // Several locales: put the locale in the URL (e.g. `https://example.com/${locale}${path}`),
48
+ // or every hreflang link points to the same URL.
49
+ const url = ({ locale, path }: { locale: string; path: string }) => `https://example.com${path}`
50
+
51
+ export async function loader({ params }: Route.LoaderArgs) {
52
+ const page = await getPage({ path: "/" + params["*"] })
53
+ if (!page) throw new Response("Not found", { status: 404 })
54
+ return page
55
+ }
56
+
57
+ export function meta({ data }: Route.MetaArgs) {
58
+ // No data on a 404.
59
+ if (!data) return [{ title: "Not found" }]
60
+ const m = getFloconMetadata({ page: data, url })
61
+ return [
62
+ { title: m.title },
63
+ { name: "description", content: m.description },
64
+ // Free plan only: `m.generator` is "Flocon AI".
65
+ ...(m.generator ? [{ name: "generator", content: m.generator }] : []),
66
+ { property: "og:type", content: m.openGraph.type },
67
+ { property: "og:title", content: m.openGraph.title },
68
+ { property: "og:description", content: m.openGraph.description },
69
+ { property: "og:url", content: m.openGraph.url },
70
+ { property: "og:locale", content: m.openGraph.locale },
71
+ { name: "twitter:card", content: m.twitter.card },
72
+ { name: "twitter:title", content: m.twitter.title },
73
+ { name: "twitter:description", content: m.twitter.description },
74
+ // Canonical + hreflang go here: `links()` gets no loader data.
75
+ { tagName: "link", rel: "canonical", href: m.canonical },
76
+ ...Object.entries(m.languages).map(([hrefLang, href]) => ({ tagName: "link", rel: "alternate", hrefLang, href }))
77
+ ]
78
+ }
79
+
80
+ export default function Page({ loaderData }: Route.ComponentProps) {
81
+ return <FloconPage page={loaderData} url={url} />
82
+ }
83
+ ```
84
+
85
+ - `getPage({ path, locale? })` returns the page, or `null` when it does not exist (return a 404).
86
+ - `locale` is optional. No `locale` = the default locale of your website.
87
+ - `<FloconPage page={page} />` does no fetching. It renders the blocks, the JSON-LD script and (Free plan) the "❄ Made with Flocon AI · flocon-ai.com" badge (link to flocon-ai.com).
88
+ - `url({ locale, path })` is **your** URL rule. The lib adds no prefix of its own.
89
+ - `getFloconMetadata({ page, url })` returns plain data: `title`, `description`, `keywords`, `canonical`, `languages` (hreflang, with `x-default`), `openGraph`, `twitter`. Put it in the `<head>` the way your framework does. It sets no OG image. On the Free plan, it also returns `generator: "Flocon AI"` (for `<meta name="generator">`).
90
+
91
+ ## Sitemap and llms.txt
92
+
93
+ ```ts
94
+ // app/routes/sitemap[.]xml.ts
95
+ import { floconSitemap } from "@flocon-ai/react"
96
+
97
+ export async function loader() {
98
+ const xml = await floconSitemap({ url: ({ locale, path }) => `https://example.com${path}` })
99
+ return new Response(xml, { headers: { "content-type": "application/xml; charset=utf-8" } })
100
+ }
101
+ ```
102
+
103
+ ```ts
104
+ // app/routes/llms[.]txt.ts
105
+ import { floconLlmsTxt } from "@flocon-ai/react"
106
+
107
+ export async function loader() {
108
+ const text = await floconLlmsTxt({ url: ({ locale, path }) => `https://example.com${path}` })
109
+ return new Response(text, { headers: { "content-type": "text/plain; charset=utf-8" } })
110
+ }
111
+ ```
112
+
113
+ Both list **published** pages only. `floconSitemap` returns XML with hreflang links.
114
+ On the Free plan, `llms.txt` ends with a "Made with [Flocon AI](https://flocon-ai.com)" line.
115
+ `getAllPages()` gives you the same list if you need it.
116
+
117
+ ## Theming
118
+
119
+ The CSS is added by `<FloconPage />`. Nothing to import.
120
+
121
+ - **Your website uses shadcn?** The page uses your colors, radius, font and dark mode. Nothing to do.
122
+ - **No shadcn?** The page uses the Flocon colors. It turns dark only if your website has a dark mode: `color-scheme: dark` (or `light dark` with a dark browser) on your page, or a `.dark` class (Tailwind).
123
+ - Old shadcn (Tailwind v3, colors like `222 47% 11%`) is not supported yet: set the `--flocon-*` variables yourself.
124
+ - Override any `--flocon-*` variable on `.flocon-page`: `--flocon-primary`, `--flocon-background`, `--flocon-foreground`, `--flocon-card`, `--flocon-muted`, `--flocon-muted-foreground`, `--flocon-border`, `--flocon-radius`, `--flocon-font`.
125
+ - All the CSS is in `@layer flocon`: your unlayered CSS on the class names wins.
126
+
127
+ ## Exports
128
+
129
+ | Export | What |
130
+ | --- | --- |
131
+ | `getPage` | One published page (or `null`) |
132
+ | `FloconPage` | Renders one page from its data |
133
+ | `getFloconMetadata` | Title, description, canonical, hreflang, `og:*`, `twitter:*` as plain data |
134
+ | `getAllPages` | All published pages (light) |
135
+ | `floconSitemap`, `floconLlmsTxt` | Sitemap XML and `llms.txt` text |
136
+ | `createFloconClient` | Typed Packages API client (server only) |
137
+ | types | `PageEntry`, `UrlOption`, `TokenOption`, `FloconPageData`, `paths`, `components` |
138
+
139
+ ## Docs
140
+
141
+ [flocon-ai.com/docs](https://flocon-ai.com/docs)