@tiniestcloud/create 0.0.0-stage → 0.1.6

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.
Files changed (42) hide show
  1. package/README.md +26 -2
  2. package/index.mjs +117 -0
  3. package/package.json +33 -4
  4. package/sdk.d.ts +290 -0
  5. package/skills/tiny-design/SKILL.md +333 -0
  6. package/skills/tiny-design/app.md +72 -0
  7. package/skills/tiny-design/dashboard.md +54 -0
  8. package/skills/tiny-design/form.md +48 -0
  9. package/skills/tiny-design/presentation.md +127 -0
  10. package/skills/tiny-design/website.md +53 -0
  11. package/templates/app/AGENTS.md +41 -0
  12. package/templates/app/CLAUDE.md +1 -0
  13. package/templates/app/README.md +10 -0
  14. package/templates/app/components.json +25 -0
  15. package/templates/app/gitignore +24 -0
  16. package/templates/app/index.html +27 -0
  17. package/templates/app/package.json +32 -0
  18. package/templates/app/src/App.tsx +39 -0
  19. package/templates/app/src/components/theme-toggle.tsx +57 -0
  20. package/templates/app/src/components/ui/button.tsx +66 -0
  21. package/templates/app/src/components/ui/tooltip.tsx +54 -0
  22. package/templates/app/src/index.css +130 -0
  23. package/templates/app/src/lib/theme.ts +39 -0
  24. package/templates/app/src/lib/tiny.tsx +59 -0
  25. package/templates/app/src/lib/utils.ts +1 -0
  26. package/templates/app/src/main.tsx +20 -0
  27. package/templates/app/src/pages/home.tsx +10 -0
  28. package/templates/app/tsconfig.app.json +29 -0
  29. package/templates/app/tsconfig.json +12 -0
  30. package/templates/app/tsconfig.node.json +24 -0
  31. package/templates/app/vite.config.ts +14 -0
  32. package/templates/site/AGENTS.md +23 -0
  33. package/templates/site/CLAUDE.md +1 -0
  34. package/templates/site/README.md +10 -0
  35. package/templates/site/astro.config.mjs +11 -0
  36. package/templates/site/gitignore +24 -0
  37. package/templates/site/package.json +22 -0
  38. package/templates/site/src/layouts/Layout.astro +30 -0
  39. package/templates/site/src/pages/about.astro +10 -0
  40. package/templates/site/src/pages/index.astro +10 -0
  41. package/templates/site/src/styles/global.css +1 -0
  42. package/templates/site/tsconfig.json +5 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * React helpers over the Tiniest Cloud SDK. `tiny` itself is a global — its types are in
3
+ * src/tiny.d.ts — so anything not wrapped here is called directly: `await tiny.db.set(key, value)`.
4
+ */
5
+ import { useEffect, useState } from "react"
6
+
7
+ /** The signed-in person: undefined while loading, null when signed out. */
8
+ export function useMe(): Tiny.User | null | undefined {
9
+ const [me, setMe] = useState<Tiny.User | null | undefined>(undefined)
10
+ useEffect(() => {
11
+ let live = true
12
+ tiny.me().then(
13
+ (user) => live && setMe(user),
14
+ () => live && setMe(null)
15
+ )
16
+ return () => {
17
+ live = false
18
+ }
19
+ }, [])
20
+ return me
21
+ }
22
+
23
+ /**
24
+ * Every entry under a prefix, kept live: re-renders within a second of any change, from any
25
+ * device. `entries` is undefined until the first load.
26
+ *
27
+ * const { entries } = useEntries<Customer>("customer:", { where: { status: "active" } })
28
+ * const { entries: latest } = useEntries<Order>("order:", { order: "-$created_at", limit: 20 })
29
+ */
30
+ export function useEntries<T>(prefix: string, options?: Tiny.Filter & Tiny.Ordered & { limit?: number }) {
31
+ const [entries, setEntries] = useState<Tiny.Entry<T>[] | undefined>(undefined)
32
+ const [error, setError] = useState<Tiny.TinyError | null>(null)
33
+ const where = JSON.stringify(options?.where ?? null)
34
+ const order = options?.order
35
+ const limit = options?.limit
36
+ useEffect(() => {
37
+ setError(null)
38
+ return tiny.db.watch<T>(prefix, setEntries, {
39
+ where: JSON.parse(where) ?? undefined,
40
+ order,
41
+ limit,
42
+ onError: setError,
43
+ })
44
+ }, [prefix, where, order, limit])
45
+ return { entries, error }
46
+ }
47
+
48
+ /** Shown when the page is opened anywhere but Tiniest Cloud, e.g. by `npm run dev`. */
49
+ export function NotOnTiniestCloud() {
50
+ return (
51
+ <main className="mx-auto flex min-h-svh max-w-md flex-col justify-center gap-2 p-6 text-sm">
52
+ <h1 className="text-base font-medium">This app runs on Tiniest Cloud</h1>
53
+ <p className="text-muted-foreground">
54
+ Sign-in, data and AI come from the platform, so they only work once the app is
55
+ deployed. Build it, deploy the dist folder, and open the app&apos;s link.
56
+ </p>
57
+ </main>
58
+ )
59
+ }
@@ -0,0 +1 @@
1
+ export { cn } from "cn"
@@ -0,0 +1,20 @@
1
+ import { StrictMode } from "react"
2
+ import { createRoot } from "react-dom/client"
3
+
4
+ import "./index.css"
5
+ import App from "./App.tsx"
6
+ import { NotOnTiniestCloud } from "@/lib/tiny"
7
+ import { startTheme } from "@/lib/theme"
8
+
9
+ // Light, dark or the device's setting, as the person chose (src/lib/theme.ts); the colours
10
+ // themselves live in index.css.
11
+ startTheme()
12
+
13
+ // `tiny` exists only where Tiniest Cloud serves the app. Anywhere else — `npm run dev` included —
14
+ // say so, rather than let every screen fail on its first call.
15
+ const onPlatform = typeof window.tiny !== "undefined"
16
+ if (onPlatform && "serviceWorker" in navigator) navigator.serviceWorker.register("/sw.js")
17
+
18
+ createRoot(document.getElementById("root")!).render(
19
+ <StrictMode>{onPlatform ? <App /> : <NotOnTiniestCloud />}</StrictMode>
20
+ )
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The first screen. Every screen is a file in src/pages; App.tsx frames them and, once there is
3
+ * more than one, routes to each (React Router). Lay this one out for what it holds: a sidebar for
4
+ * several areas, a grid of cards for things people browse, a table for records, a list with its
5
+ * detail beside it; a narrow centred column only for one focused task. Pieces it shares with
6
+ * other screens go in src/components, its own hooks in src/hooks.
7
+ */
8
+ export default function Home() {
9
+ return <div />
10
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "es2023",
5
+ "lib": ["ES2023", "DOM"],
6
+ "module": "esnext",
7
+ "types": ["vite/client"],
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "verbatimModuleSyntax": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+ "jsx": "react-jsx",
17
+
18
+ /* Linting */
19
+ "strict": true,
20
+ "noUnusedLocals": true,
21
+ "noUnusedParameters": true,
22
+ "erasableSyntaxOnly": true,
23
+ "noFallthroughCasesInSwitch": true,
24
+ "paths": {
25
+ "@/*": ["./src/*"]
26
+ }
27
+ },
28
+ "include": ["src"]
29
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ],
7
+ "compilerOptions": {
8
+ "paths": {
9
+ "@/*": ["./src/*"]
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "es2023",
5
+ "lib": ["ES2023"],
6
+ "module": "esnext",
7
+ "types": ["node"],
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "verbatimModuleSyntax": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+
17
+ /* Linting */
18
+ "noUnusedLocals": true,
19
+ "noUnusedParameters": true,
20
+ "erasableSyntaxOnly": true,
21
+ "noFallthroughCasesInSwitch": true
22
+ },
23
+ "include": ["vite.config.ts"]
24
+ }
@@ -0,0 +1,14 @@
1
+ import path from "path"
2
+ import tailwindcss from "@tailwindcss/vite"
3
+ import react from "@vitejs/plugin-react"
4
+ import { defineConfig } from "vite"
5
+
6
+ // https://vite.dev/config/
7
+ export default defineConfig({
8
+ plugins: [react(), tailwindcss()],
9
+ resolve: {
10
+ alias: {
11
+ "@": path.resolve(import.meta.dirname, "./src"),
12
+ },
13
+ },
14
+ })
@@ -0,0 +1,23 @@
1
+ # This website runs on Tiniest Cloud
2
+
3
+ Astro and Tailwind CSS, built to static pages and deployed to Tiniest Cloud.
4
+
5
+ - Every file in src/pages is a page: src/pages/pricing.astro is served at /pricing/. Link to pages
6
+ with a trailing slash. Keep Astro's static output; there is no server to render on request.
7
+ - Where files go: pages in `src/pages/`, the frame they share in `src/layouts/`, pieces several
8
+ pages use in `src/components/`, styles in `src/styles/`, images and icons in `public/`. A file
9
+ past about 300 lines is doing too much: move its parts into components.
10
+ - `npm run build` writes the site to `dist`; deploy this folder with `dist` built inside (no
11
+ node_modules, no .env files): `dist` is served, and the rest is kept as the source. When
12
+ starting the dev server, use `astro dev --background` (`astro dev stop` to end it).
13
+ - A form that keeps what visitors send (sign-ups, contact requests) uses Tiniest Cloud's storage:
14
+ add `<script is:inline src="/sdk.js"></script>` to the layout's head, and see the Tiniest
15
+ Cloud guide on visitors with no account. Types for it are at /sdk.d.ts on the platform.
16
+ - Logic that must run on the server (checking or pricing what a form sends) is a backend function:
17
+ `public/_functions/<name>.js`, called from the page with `tiny.call("<name>", input)`. See the
18
+ Tiniest Cloud guide, "Server code".
19
+ - Design: before the first page, read the tiny-design skill — `.agents/skills/tiny-design/`
20
+ (the same files are in `.claude/skills/` for Claude Code): SKILL.md, then website.md. Where
21
+ that folder is missing, `tiny_guide` with topic `website` returns the same. If the person has
22
+ a brand or design standards of their own, those come first.
23
+ - Astro's docs: https://docs.astro.build
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -0,0 +1,10 @@
1
+ # Site
2
+
3
+ Built with Astro and Tailwind CSS, and hosted on Tiniest Cloud.
4
+
5
+ npm install
6
+ npm run dev # work on it locally
7
+ npm run build # the site is in dist/
8
+
9
+ Deploy this folder, with `dist` built inside, to Tiniest Cloud: `dist` is served, and the rest is
10
+ kept as the project's source.
@@ -0,0 +1,11 @@
1
+ // @ts-check
2
+ import { defineConfig } from 'astro/config';
3
+
4
+ import tailwindcss from '@tailwindcss/vite';
5
+
6
+ // https://astro.build/config
7
+ export default defineConfig({
8
+ vite: {
9
+ plugins: [tailwindcss()]
10
+ }
11
+ });
@@ -0,0 +1,24 @@
1
+ # build output
2
+ dist/
3
+ # generated types
4
+ .astro/
5
+
6
+ # dependencies
7
+ node_modules/
8
+
9
+ # logs
10
+ npm-debug.log*
11
+ yarn-debug.log*
12
+ yarn-error.log*
13
+ pnpm-debug.log*
14
+
15
+
16
+ # environment variables
17
+ .env
18
+ .env.production
19
+
20
+ # macOS-specific files
21
+ .DS_Store
22
+
23
+ # jetbrains setting folder
24
+ .idea/
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "site",
3
+ "type": "module",
4
+ "version": "0.0.0",
5
+ "private": true,
6
+ "engines": {
7
+ "node": ">=22.12.0"
8
+ },
9
+ "scripts": {
10
+ "dev": "astro dev",
11
+ "build": "astro build",
12
+ "astro": "astro"
13
+ },
14
+ "dependencies": {
15
+ "@tailwindcss/vite": "^4.3.3",
16
+ "astro": "^7.3.5",
17
+ "tailwindcss": "^4.3.3"
18
+ },
19
+ "allowScripts": {
20
+ "esbuild": true
21
+ }
22
+ }
@@ -0,0 +1,30 @@
1
+ ---
2
+ import "../styles/global.css";
3
+
4
+ interface Props {
5
+ title: string;
6
+ description?: string;
7
+ }
8
+
9
+ const { title, description } = Astro.props;
10
+ ---
11
+
12
+ <html lang="en">
13
+ <head>
14
+ <meta charset="utf-8" />
15
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
16
+ <title>{title}</title>
17
+ {description && <meta name="description" content={description} />}
18
+ </head>
19
+ <body class="bg-white text-neutral-900 antialiased">
20
+ <header class="mx-auto flex max-w-6xl items-center justify-between px-6 py-6">
21
+ <a href="/" class="font-medium">Site</a>
22
+ <nav class="flex gap-6 text-sm text-neutral-600">
23
+ <a href="/about/" class="hover:text-neutral-900">About</a>
24
+ </nav>
25
+ </header>
26
+ <main class="mx-auto max-w-6xl px-6 pb-24">
27
+ <slot />
28
+ </main>
29
+ </body>
30
+ </html>
@@ -0,0 +1,10 @@
1
+ ---
2
+ import Layout from "../layouts/Layout.astro";
3
+ ---
4
+
5
+ <Layout title="About · Site">
6
+ <section class="py-16">
7
+ <h1 class="text-3xl font-semibold tracking-tight">About</h1>
8
+ <p class="mt-4 max-w-xl text-neutral-600">This page is src/pages/about.astro, served at /about/.</p>
9
+ </section>
10
+ </Layout>
@@ -0,0 +1,10 @@
1
+ ---
2
+ import Layout from "../layouts/Layout.astro";
3
+ ---
4
+
5
+ <Layout title="Site" description="A website on Tiniest Cloud.">
6
+ <section class="py-16">
7
+ <h1 class="text-4xl font-semibold tracking-tight">Site</h1>
8
+ <p class="mt-4 max-w-xl text-lg text-neutral-600">Every file in src/pages becomes a page.</p>
9
+ </section>
10
+ </Layout>
@@ -0,0 +1 @@
1
+ @import "tailwindcss";
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "astro/tsconfigs/strict",
3
+ "include": [".astro/types.d.ts", "**/*"],
4
+ "exclude": ["dist"]
5
+ }