@notis_ai/cli 0.2.0 → 0.2.2
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 +122 -158
- package/dist/scaffolds/notes/app/globals.css +3 -0
- package/dist/scaffolds/notes/app/layout.tsx +6 -0
- package/dist/scaffolds/notes/app/page.tsx +1465 -0
- package/dist/scaffolds/notes/components/ui/badge.tsx +28 -0
- package/dist/scaffolds/notes/components/ui/button.tsx +53 -0
- package/dist/scaffolds/notes/components/ui/card.tsx +56 -0
- package/dist/scaffolds/notes/components.json +20 -0
- package/dist/scaffolds/notes/lib/utils.ts +6 -0
- package/dist/scaffolds/notes/notis.config.ts +31 -0
- package/dist/scaffolds/notes/package.json +31 -0
- package/dist/scaffolds/notes/postcss.config.mjs +8 -0
- package/dist/scaffolds/notes/tailwind.config.ts +58 -0
- package/dist/scaffolds/notes/tsconfig.json +22 -0
- package/dist/scaffolds/notes/vite.config.ts +10 -0
- package/dist/scaffolds.json +13 -0
- package/package.json +12 -2
- package/skills/notis-apps/SKILL.md +162 -0
- package/skills/notis-apps/cli.md +208 -0
- package/skills/notis-cli/SKILL.md +258 -0
- package/skills/notis-query/cli.md +40 -0
- package/src/cli.js +1 -1
- package/src/command-specs/apps.js +1029 -59
- package/src/command-specs/helpers.js +6 -41
- package/src/command-specs/index.js +1 -7
- package/src/command-specs/meta.js +7 -6
- package/src/command-specs/tools.js +29 -34
- package/src/runtime/agent-browser.js +192 -0
- package/src/runtime/app-boundary-validator.js +132 -0
- package/src/runtime/app-dev-server.js +605 -0
- package/src/runtime/app-dev-sessions.js +87 -0
- package/src/runtime/app-platform.js +1037 -82
- package/src/runtime/cli-mode.generated.js +4 -0
- package/src/runtime/cli-mode.js +29 -0
- package/src/runtime/output.js +2 -2
- package/src/runtime/ports.js +15 -0
- package/src/runtime/profiles.js +36 -5
- package/src/runtime/transport.js +131 -6
- package/template/.harness/index.html.tmpl +211 -0
- package/template/app/globals.css +3 -0
- package/template/app/layout.tsx +6 -0
- package/template/app/page.tsx +90 -0
- package/template/components/ui/badge.tsx +28 -0
- package/template/components/ui/button.tsx +53 -0
- package/template/components/ui/card.tsx +56 -0
- package/template/components.json +20 -0
- package/template/lib/utils.ts +6 -0
- package/template/metadata/cover.png +0 -0
- package/template/metadata/screenshot-1.png +0 -0
- package/template/metadata/screenshot-2.png +0 -0
- package/template/metadata/screenshot-3.png +0 -0
- package/template/notis.config.ts +37 -0
- package/template/package.json +31 -0
- package/template/packages/sdk/package.json +32 -0
- package/template/packages/sdk/src/components/MultiSelectActionBar.tsx +273 -0
- package/template/packages/sdk/src/components/MultiSelectCheckbox.tsx +91 -0
- package/template/packages/sdk/src/components/MultiSelectDragOverlay.tsx +39 -0
- package/template/packages/sdk/src/config.ts +71 -0
- package/template/packages/sdk/src/hooks/useBackend.ts +41 -0
- package/template/packages/sdk/src/hooks/useDatabase.ts +76 -0
- package/template/packages/sdk/src/hooks/useMultiSelect.ts +503 -0
- package/template/packages/sdk/src/hooks/useNotis.ts +34 -0
- package/template/packages/sdk/src/hooks/useNotisNavigation.ts +49 -0
- package/template/packages/sdk/src/hooks/useTool.ts +64 -0
- package/template/packages/sdk/src/hooks/useTools.ts +56 -0
- package/template/packages/sdk/src/hooks/useTopBarSearch.ts +73 -0
- package/template/packages/sdk/src/hooks/useUpsertDocument.ts +50 -0
- package/template/packages/sdk/src/index.ts +54 -0
- package/template/packages/sdk/src/provider.tsx +43 -0
- package/template/packages/sdk/src/runtime.ts +161 -0
- package/template/packages/sdk/src/styles.css +38 -0
- package/template/packages/sdk/src/ui.ts +15 -0
- package/template/packages/sdk/src/vite.ts +56 -0
- package/template/packages/sdk/tsconfig.json +15 -0
- package/template/postcss.config.mjs +8 -0
- package/template/tailwind.config.ts +58 -0
- package/template/tsconfig.json +22 -0
- package/template/vite.config.ts +10 -0
- package/src/command-specs/auth.js +0 -178
- package/src/command-specs/db.js +0 -163
- package/src/runtime/app-preview-server.js +0 -272
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
3
|
+
|
|
4
|
+
import { cn } from '@/lib/utils';
|
|
5
|
+
|
|
6
|
+
const badgeVariants = cva(
|
|
7
|
+
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: 'border-transparent bg-primary/10 text-primary',
|
|
12
|
+
secondary: 'border-transparent bg-secondary text-secondary-foreground',
|
|
13
|
+
outline: 'text-foreground',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: 'default',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
|
|
23
|
+
|
|
24
|
+
function Badge({ className, variant, ...props }: BadgeProps) {
|
|
25
|
+
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { Badge, badgeVariants };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
import { cn } from '@/lib/utils';
|
|
6
|
+
|
|
7
|
+
const buttonVariants = cva(
|
|
8
|
+
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
13
|
+
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
14
|
+
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
|
|
15
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
16
|
+
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
17
|
+
link: 'text-primary underline-offset-4 hover:underline',
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
default: 'h-10 px-4 py-2',
|
|
21
|
+
sm: 'h-9 rounded-md px-3',
|
|
22
|
+
lg: 'h-11 rounded-md px-8',
|
|
23
|
+
icon: 'h-10 w-10',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
defaultVariants: {
|
|
27
|
+
variant: 'default',
|
|
28
|
+
size: 'default',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
export interface ButtonProps
|
|
34
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
35
|
+
VariantProps<typeof buttonVariants> {
|
|
36
|
+
asChild?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
40
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
41
|
+
const Comp = asChild ? Slot : 'button';
|
|
42
|
+
return (
|
|
43
|
+
<Comp
|
|
44
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
45
|
+
ref={ref}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
Button.displayName = 'Button';
|
|
52
|
+
|
|
53
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
|
+
|
|
5
|
+
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
6
|
+
({ className, ...props }, ref) => (
|
|
7
|
+
<div
|
|
8
|
+
ref={ref}
|
|
9
|
+
className={cn('rounded-2xl border bg-card text-card-foreground shadow-sm', className)}
|
|
10
|
+
{...props}
|
|
11
|
+
/>
|
|
12
|
+
),
|
|
13
|
+
);
|
|
14
|
+
Card.displayName = 'Card';
|
|
15
|
+
|
|
16
|
+
const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
17
|
+
({ className, ...props }, ref) => (
|
|
18
|
+
<div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
|
|
19
|
+
),
|
|
20
|
+
);
|
|
21
|
+
CardHeader.displayName = 'CardHeader';
|
|
22
|
+
|
|
23
|
+
const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
|
|
24
|
+
({ className, ...props }, ref) => (
|
|
25
|
+
<h3
|
|
26
|
+
ref={ref}
|
|
27
|
+
className={cn('text-xl font-semibold leading-none tracking-tight', className)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
),
|
|
31
|
+
);
|
|
32
|
+
CardTitle.displayName = 'CardTitle';
|
|
33
|
+
|
|
34
|
+
const CardDescription = React.forwardRef<
|
|
35
|
+
HTMLParagraphElement,
|
|
36
|
+
React.HTMLAttributes<HTMLParagraphElement>
|
|
37
|
+
>(({ className, ...props }, ref) => (
|
|
38
|
+
<p ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
|
|
39
|
+
));
|
|
40
|
+
CardDescription.displayName = 'CardDescription';
|
|
41
|
+
|
|
42
|
+
const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
43
|
+
({ className, ...props }, ref) => (
|
|
44
|
+
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
|
|
45
|
+
),
|
|
46
|
+
);
|
|
47
|
+
CardContent.displayName = 'CardContent';
|
|
48
|
+
|
|
49
|
+
const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
50
|
+
({ className, ...props }, ref) => (
|
|
51
|
+
<div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} />
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
|
+
CardFooter.displayName = 'CardFooter';
|
|
55
|
+
|
|
56
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "new-york",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "tailwind.config.ts",
|
|
8
|
+
"css": "app/globals.css",
|
|
9
|
+
"baseColor": "zinc",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@/components",
|
|
15
|
+
"utils": "@/lib/utils",
|
|
16
|
+
"ui": "@/components/ui",
|
|
17
|
+
"lib": "@/lib",
|
|
18
|
+
"hooks": "@/hooks"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defineNotisApp } from '@notis/sdk/config';
|
|
2
|
+
|
|
3
|
+
export default defineNotisApp({
|
|
4
|
+
name: 'Notis Notes',
|
|
5
|
+
description: 'Browse notes by documents, table, or calendar with folders in the sidebar.',
|
|
6
|
+
icon: 'lucide:notebook-pen',
|
|
7
|
+
databases: ['note_folders', 'notes'],
|
|
8
|
+
routes: [
|
|
9
|
+
{
|
|
10
|
+
path: '/',
|
|
11
|
+
slug: 'notes',
|
|
12
|
+
name: 'Notes',
|
|
13
|
+
icon: 'lucide:notebook-pen',
|
|
14
|
+
default: true,
|
|
15
|
+
collection: {
|
|
16
|
+
database: 'note_folders',
|
|
17
|
+
titleProperty: 'Name',
|
|
18
|
+
parentProperty: 'Parent',
|
|
19
|
+
sidebar: {
|
|
20
|
+
mode: 'tree',
|
|
21
|
+
allowCreate: true,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
tools: [
|
|
27
|
+
'notis_query_database',
|
|
28
|
+
'notis_get_document',
|
|
29
|
+
'notis_upsert_document',
|
|
30
|
+
],
|
|
31
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "notis-notes-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@notis/sdk": "file:../../packages/sdk",
|
|
12
|
+
"@radix-ui/react-slot": "^1.1.0",
|
|
13
|
+
"class-variance-authority": "^0.7.0",
|
|
14
|
+
"clsx": "^2.1.1",
|
|
15
|
+
"lucide-react": "^0.474.0",
|
|
16
|
+
"react": "^19.0.0",
|
|
17
|
+
"react-dom": "^19.0.0",
|
|
18
|
+
"tailwind-merge": "^2.6.0",
|
|
19
|
+
"tailwindcss-animate": "^1.0.7"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^22.0.0",
|
|
23
|
+
"@types/react": "^19.0.0",
|
|
24
|
+
"@types/react-dom": "^19.0.0",
|
|
25
|
+
"@vitejs/plugin-react": "^4.0.0",
|
|
26
|
+
"postcss": "^8.0.0",
|
|
27
|
+
"tailwindcss": "^3.4.0",
|
|
28
|
+
"typescript": "^5.0.0",
|
|
29
|
+
"vite": "^6.0.0"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Config } from 'tailwindcss';
|
|
2
|
+
import tailwindAnimate from 'tailwindcss-animate';
|
|
3
|
+
|
|
4
|
+
const config: Config = {
|
|
5
|
+
darkMode: ['class'],
|
|
6
|
+
content: [
|
|
7
|
+
'./app/**/*.{ts,tsx}',
|
|
8
|
+
'./components/**/*.{ts,tsx}',
|
|
9
|
+
'./lib/**/*.{ts,tsx}',
|
|
10
|
+
],
|
|
11
|
+
theme: {
|
|
12
|
+
extend: {
|
|
13
|
+
colors: {
|
|
14
|
+
border: 'hsl(var(--border))',
|
|
15
|
+
input: 'hsl(var(--input))',
|
|
16
|
+
ring: 'hsl(var(--ring))',
|
|
17
|
+
background: 'hsl(var(--background))',
|
|
18
|
+
foreground: 'hsl(var(--foreground))',
|
|
19
|
+
primary: {
|
|
20
|
+
DEFAULT: 'hsl(var(--primary))',
|
|
21
|
+
foreground: 'hsl(var(--primary-foreground))',
|
|
22
|
+
},
|
|
23
|
+
secondary: {
|
|
24
|
+
DEFAULT: 'hsl(var(--secondary))',
|
|
25
|
+
foreground: 'hsl(var(--secondary-foreground))',
|
|
26
|
+
},
|
|
27
|
+
destructive: {
|
|
28
|
+
DEFAULT: 'hsl(var(--destructive))',
|
|
29
|
+
foreground: 'hsl(var(--destructive-foreground))',
|
|
30
|
+
},
|
|
31
|
+
muted: {
|
|
32
|
+
DEFAULT: 'hsl(var(--muted))',
|
|
33
|
+
foreground: 'hsl(var(--muted-foreground))',
|
|
34
|
+
},
|
|
35
|
+
accent: {
|
|
36
|
+
DEFAULT: 'hsl(var(--accent))',
|
|
37
|
+
foreground: 'hsl(var(--accent-foreground))',
|
|
38
|
+
},
|
|
39
|
+
popover: {
|
|
40
|
+
DEFAULT: 'hsl(var(--popover))',
|
|
41
|
+
foreground: 'hsl(var(--popover-foreground))',
|
|
42
|
+
},
|
|
43
|
+
card: {
|
|
44
|
+
DEFAULT: 'hsl(var(--card))',
|
|
45
|
+
foreground: 'hsl(var(--card-foreground))',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
borderRadius: {
|
|
49
|
+
lg: 'var(--radius)',
|
|
50
|
+
md: 'calc(var(--radius) - 2px)',
|
|
51
|
+
sm: 'calc(var(--radius) - 4px)',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
plugins: [tailwindAnimate],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default config;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2017",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"types": ["vite/client"],
|
|
16
|
+
"paths": {
|
|
17
|
+
"@/*": ["./*"]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
21
|
+
"exclude": ["node_modules"]
|
|
22
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { notisViteConfig } from '@notis/sdk/vite';
|
|
2
|
+
import react from '@vitejs/plugin-react';
|
|
3
|
+
import appConfig from './notis.config';
|
|
4
|
+
|
|
5
|
+
const config = notisViteConfig(appConfig);
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
...config,
|
|
9
|
+
plugins: [react(), ...(config.plugins || [])],
|
|
10
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"source": "apps/*/notis.config.ts",
|
|
3
|
+
"scaffolds": [
|
|
4
|
+
{
|
|
5
|
+
"slug": "notes",
|
|
6
|
+
"name": "Notis Notes",
|
|
7
|
+
"description": "Browse notes by documents, table, or calendar with folders in the sidebar.",
|
|
8
|
+
"icon": "lucide:notebook-pen",
|
|
9
|
+
"categories": [],
|
|
10
|
+
"tagline": "Browse notes by documents, table, or calendar with folders in the sidebar."
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notis_ai/cli",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Agent-first Notis CLI for apps
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Agent-first Notis CLI for apps and generic tool execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"notis": "bin/notis.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin/",
|
|
11
|
+
"dist/",
|
|
11
12
|
"src/",
|
|
13
|
+
"skills/",
|
|
14
|
+
"template/",
|
|
12
15
|
"README.md"
|
|
13
16
|
],
|
|
14
17
|
"scripts": {
|
|
18
|
+
"build": "node ./scripts/build-scaffolds.js",
|
|
15
19
|
"docs:generate": "node ./scripts/generate-docs.js",
|
|
16
20
|
"docs:check": "node ./scripts/generate-docs.js --check",
|
|
21
|
+
"prepack": "npm run build",
|
|
22
|
+
"release:prepare": "npm run build && node ./scripts/prepare-publish.js --apply",
|
|
23
|
+
"cli:set-mode": "node ./scripts/set-cli-mode.js",
|
|
17
24
|
"test": "node --test"
|
|
18
25
|
},
|
|
19
26
|
"engines": {
|
|
@@ -29,5 +36,8 @@
|
|
|
29
36
|
"ai",
|
|
30
37
|
"agent-skills"
|
|
31
38
|
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
32
42
|
"license": "MIT"
|
|
33
43
|
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: notis-apps
|
|
3
|
+
description: Design and package Notis apps. Use when users want an app that groups databases, routes, documents, automations, and skills into one installable Notis product.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Notis Apps Skill
|
|
7
|
+
|
|
8
|
+
Use this skill when the user wants to create, edit, debug, or package a Notis app. Notis apps are Vite + React projects that deploy into the Notis Portal as installed apps for the current user or team.
|
|
9
|
+
|
|
10
|
+
Run the Notis CLI through NPX, for example `npx --package @notis_ai/cli@latest -- notis apps list`. Notis Desktop keeps the CLI auth profile current. This `notis-apps` skill is delivered through normal Notis skill sync for the signed-in user, alongside other curated skills.
|
|
11
|
+
|
|
12
|
+
## Platform Model
|
|
13
|
+
|
|
14
|
+
A Notis app is:
|
|
15
|
+
|
|
16
|
+
- a Vite + React project
|
|
17
|
+
- built with `@notis/sdk`
|
|
18
|
+
- configured through `notis.config.ts`
|
|
19
|
+
- packaged as an ES module bundle with `app.js`, `app.css`, and `manifest.json`
|
|
20
|
+
- rendered by the Notis Portal as a React component, not an iframe
|
|
21
|
+
- connected to Notis data and tools through the Portal-provided runtime and SDK hooks
|
|
22
|
+
|
|
23
|
+
Use the Notis CLI for the app lifecycle:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx --package @notis_ai/cli@latest -- notis apps init
|
|
27
|
+
npx --package @notis_ai/cli@latest -- notis apps dev
|
|
28
|
+
npx --package @notis_ai/cli@latest -- notis apps build
|
|
29
|
+
npx --package @notis_ai/cli@latest -- notis apps verify
|
|
30
|
+
npx --package @notis_ai/cli@latest -- notis apps create
|
|
31
|
+
npx --package @notis_ai/cli@latest -- notis apps link
|
|
32
|
+
npx --package @notis_ai/cli@latest -- notis apps pull
|
|
33
|
+
npx --package @notis_ai/cli@latest -- notis apps deploy
|
|
34
|
+
npx --package @notis_ai/cli@latest -- notis apps doctor
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Use this command form everywhere:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx --package @notis_ai/cli@latest -- notis apps ...
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Hard Rules
|
|
44
|
+
|
|
45
|
+
- Use React + Vite only. Do not use Next.js or a custom server for app projects.
|
|
46
|
+
- Build standard pages in `app/`. Do not write raw `views/<slug>/index.js` files.
|
|
47
|
+
- Keep navigation in `notis.config.ts` `routes`; each route needs a stable `slug`.
|
|
48
|
+
- Reference existing databases by slug in `notis.config.ts`; do not assume deploy creates databases automatically.
|
|
49
|
+
- Declare runtime tool access in `notis.config.ts` `tools`.
|
|
50
|
+
- Use `@notis/sdk` hooks instead of direct runtime access.
|
|
51
|
+
- Do not rely on `window.__NOTIS_RUNTIME__` or portal-owned DOM hooks.
|
|
52
|
+
- `npx --package @notis_ai/cli@latest -- notis apps deploy` updates an installed app. It does not publish to the public App Store.
|
|
53
|
+
- Public or team App Store publishing is a Portal review flow.
|
|
54
|
+
- Use Phosphor icon names with the `phosphor:` prefix. Do not use emoji icons.
|
|
55
|
+
- Prefer scaffolded shadcn components and portal theme tokens over custom visual systems.
|
|
56
|
+
|
|
57
|
+
## App Workflow
|
|
58
|
+
|
|
59
|
+
1. Discover existing apps if needed:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx --package @notis_ai/cli@latest -- notis apps list
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
2. Start from a scaffold or pull an existing app:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx --package @notis_ai/cli@latest -- notis apps scaffolds list
|
|
69
|
+
npx --package @notis_ai/cli@latest -- notis apps init "My App"
|
|
70
|
+
npx --package @notis_ai/cli@latest -- notis apps pull <app-id> ./my-app
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
3. Install dependencies and develop:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm install
|
|
77
|
+
npx --package @notis_ai/cli@latest -- notis apps dev
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
4. Build and verify:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx --package @notis_ai/cli@latest -- notis apps build
|
|
84
|
+
npx --package @notis_ai/cli@latest -- notis apps verify
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
5. Create or link the remote app, then deploy:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npx --package @notis_ai/cli@latest -- notis apps create "My App" .
|
|
91
|
+
npx --package @notis_ai/cli@latest -- notis apps deploy
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
or:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npx --package @notis_ai/cli@latest -- notis apps link <app-id>
|
|
98
|
+
npx --package @notis_ai/cli@latest -- notis apps deploy
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## App Structure
|
|
102
|
+
|
|
103
|
+
Expected project shape:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
notis.config.ts
|
|
107
|
+
vite.config.ts
|
|
108
|
+
app/
|
|
109
|
+
components/
|
|
110
|
+
metadata/
|
|
111
|
+
.notis/output/
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`notis.config.ts` owns:
|
|
115
|
+
|
|
116
|
+
- app metadata: name, title, description, icon, categories, tagline
|
|
117
|
+
- database slug references
|
|
118
|
+
- route definitions
|
|
119
|
+
- tool access
|
|
120
|
+
|
|
121
|
+
Example:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { defineNotisApp } from '@notis/sdk/config';
|
|
125
|
+
|
|
126
|
+
export default defineNotisApp({
|
|
127
|
+
name: 'my-app',
|
|
128
|
+
title: 'My App',
|
|
129
|
+
description: 'A focused Notis app.',
|
|
130
|
+
icon: 'phosphor:squares-four',
|
|
131
|
+
databases: ['tasks'],
|
|
132
|
+
routes: [
|
|
133
|
+
{
|
|
134
|
+
path: '/',
|
|
135
|
+
slug: 'tasks',
|
|
136
|
+
name: 'Tasks',
|
|
137
|
+
icon: 'phosphor:check-square',
|
|
138
|
+
default: true,
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
tools: ['notis-default-query', 'notis-default-upsert_tasks'],
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Runtime Usage
|
|
146
|
+
|
|
147
|
+
Use SDK hooks for data and tool access:
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import { useTool } from '@notis/sdk';
|
|
151
|
+
|
|
152
|
+
const query = useTool('notis-default-query');
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Do not fetch Notis backend endpoints directly from app code unless the SDK explicitly requires it. The Portal provides authentication, runtime context, and route rendering.
|
|
156
|
+
|
|
157
|
+
## Troubleshooting
|
|
158
|
+
|
|
159
|
+
- If deploy fails with backend connectivity errors, run `npx --package @notis_ai/cli@latest -- notis apps doctor` and check the configured API base.
|
|
160
|
+
- If editing an existing app, use `npx --package @notis_ai/cli@latest -- notis apps pull <app-id>` when source snapshots are available.
|
|
161
|
+
- If the Portal shows a stale bundle, hard refresh the Portal or deploy a new version.
|
|
162
|
+
- If an app route fails to load, run `npx --package @notis_ai/cli@latest -- notis apps verify` and inspect `.notis/output/manifest.json`.
|