@inbeat/standards 0.7.0

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 (47) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/agents/app-section.md +22 -0
  3. package/agents/standard.md +114 -0
  4. package/package.json +46 -0
  5. package/skills/ib-feature/SKILL.md +40 -0
  6. package/skills/ib-toolkit/SKILL.md +125 -0
  7. package/skills/ib-ui/SKILL.md +155 -0
  8. package/src/cli.ts +85 -0
  9. package/src/create-args.ts +10 -0
  10. package/src/create.ts +240 -0
  11. package/src/foundation.ts +42 -0
  12. package/src/mcp-servers.ts +8 -0
  13. package/src/mcp.ts +383 -0
  14. package/src/sync.ts +117 -0
  15. package/src/template.ts +34 -0
  16. package/template/.agents/skills/ib-feature/SKILL.md +40 -0
  17. package/template/.agents/skills/ib-toolkit/SKILL.md +125 -0
  18. package/template/.agents/skills/ib-ui/SKILL.md +155 -0
  19. package/template/.dependency-cruiser.cjs +1 -0
  20. package/template/.env.example +12 -0
  21. package/template/.github/workflows/ci.yml +14 -0
  22. package/template/AGENTS.md +139 -0
  23. package/template/_gitignore +10 -0
  24. package/template/biome.json +6 -0
  25. package/template/next.config.ts +32 -0
  26. package/template/package.json +62 -0
  27. package/template/postcss.config.mjs +7 -0
  28. package/template/sentry.edge.config.ts +11 -0
  29. package/template/sentry.server.config.ts +12 -0
  30. package/template/src/app/api/health/route.test.ts +12 -0
  31. package/template/src/app/api/health/route.ts +7 -0
  32. package/template/src/app/error.tsx +24 -0
  33. package/template/src/app/global-error.tsx +20 -0
  34. package/template/src/app/globals.css +4 -0
  35. package/template/src/app/icon.svg +1 -0
  36. package/template/src/app/layout.tsx +24 -0
  37. package/template/src/app/loading.tsx +9 -0
  38. package/template/src/app/not-found.tsx +14 -0
  39. package/template/src/app/page.tsx +7 -0
  40. package/template/src/app/robots.ts +6 -0
  41. package/template/src/instrumentation-client.ts +14 -0
  42. package/template/src/instrumentation.ts +13 -0
  43. package/template/src/shared/config/env.ts +19 -0
  44. package/template/src/shared/config/routes.ts +3 -0
  45. package/template/src/test/server-only.ts +1 -0
  46. package/template/tsconfig.json +10 -0
  47. package/template/vitest.config.ts +14 -0
@@ -0,0 +1,20 @@
1
+ "use client";
2
+
3
+ import * as Sentry from "@sentry/nextjs";
4
+ import NextError from "next/error";
5
+ import { useEffect } from "react";
6
+
7
+ export default function GlobalError({ error }: { error: Error & { digest?: string } }) {
8
+ useEffect(() => {
9
+ Sentry.captureException(error);
10
+ }, [error]);
11
+
12
+ return (
13
+ <html lang="en">
14
+ <body>
15
+ {/* App Router exposes no status code here; 0 renders Next's generic message. */}
16
+ <NextError statusCode={0} />
17
+ </body>
18
+ </html>
19
+ );
20
+ }
@@ -0,0 +1,4 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @import "shadcn/tailwind.css";
4
+ @import "@inbeat/ui/theme.css";
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><title>App icon</title><rect width="32" height="32" rx="8" fill="#111"/><circle cx="16" cy="16" r="6" fill="#fff"/></svg>
@@ -0,0 +1,24 @@
1
+ import { fontVariables } from "@inbeat/next/fonts";
2
+ import { Toaster } from "@inbeat/ui/components/sonner";
3
+ import { TooltipProvider } from "@inbeat/ui/components/tooltip";
4
+ import type { Metadata } from "next";
5
+ import type { ReactNode } from "react";
6
+ import "./globals.css";
7
+
8
+ export const metadata: Metadata = {
9
+ title: "inBeat app",
10
+ description: "Built on the inBeat toolkit",
11
+ };
12
+
13
+ export default function RootLayout({ children }: Readonly<{ children: ReactNode }>) {
14
+ return (
15
+ <html lang="en" className={fontVariables}>
16
+ <body className="min-h-screen font-sans antialiased">
17
+ <TooltipProvider>
18
+ <Toaster position="top-center" />
19
+ {children}
20
+ </TooltipProvider>
21
+ </body>
22
+ </html>
23
+ );
24
+ }
@@ -0,0 +1,9 @@
1
+ import { Spinner } from "@inbeat/ui/components/spinner";
2
+
3
+ export default function Loading() {
4
+ return (
5
+ <main className="flex min-h-screen items-center justify-center">
6
+ <Spinner />
7
+ </main>
8
+ );
9
+ }
@@ -0,0 +1,14 @@
1
+ import { Button } from "@inbeat/ui/components/button";
2
+ import Link from "next/link";
3
+ import { ROUTES } from "@/shared/config/routes";
4
+
5
+ export default function NotFound() {
6
+ return (
7
+ <main className="flex min-h-screen flex-col items-center justify-center gap-4 px-6 text-center">
8
+ <h1 className="text-2xl font-medium">Page not found</h1>
9
+ <Button variant="outline" asChild>
10
+ <Link href={ROUTES.home}>Back home</Link>
11
+ </Button>
12
+ </main>
13
+ );
14
+ }
@@ -0,0 +1,7 @@
1
+ export default function HomePage() {
2
+ return (
3
+ <main className="grid min-h-screen place-items-center">
4
+ <p className="text-muted-foreground">inBeat app</p>
5
+ </main>
6
+ );
7
+ }
@@ -0,0 +1,6 @@
1
+ import type { MetadataRoute } from "next";
2
+
3
+ export default function robots(): MetadataRoute.Robots {
4
+ // Internal tools by default; public sites must opt in to indexing.
5
+ return { rules: { userAgent: "*", disallow: "/" } };
6
+ }
@@ -0,0 +1,14 @@
1
+ import { sentryClientOptions } from "@inbeat/next/sentry-client";
2
+ import * as Sentry from "@sentry/nextjs";
3
+ import { env } from "@/shared/config/env";
4
+
5
+ Sentry.init(
6
+ sentryClientOptions({
7
+ dsn: env.NEXT_PUBLIC_SENTRY_DSN,
8
+ // Dev and E2E fixture failures would otherwise trip the new-issue alert.
9
+ enabled: process.env.NODE_ENV === "production",
10
+ environment: env.NEXT_PUBLIC_VERCEL_ENV,
11
+ }),
12
+ );
13
+
14
+ export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
@@ -0,0 +1,13 @@
1
+ import * as Sentry from "@sentry/nextjs";
2
+
3
+ export async function register() {
4
+ if (process.env.NEXT_RUNTIME === "nodejs") {
5
+ await import("../sentry.server.config");
6
+ }
7
+
8
+ if (process.env.NEXT_RUNTIME === "edge") {
9
+ await import("../sentry.edge.config");
10
+ }
11
+ }
12
+
13
+ export const onRequestError = Sentry.captureRequestError;
@@ -0,0 +1,19 @@
1
+ import { appUrlEnv, sentryClientEnv } from "@inbeat/core/env";
2
+ import { createEnv } from "@t3-oss/env-nextjs";
3
+ import { z } from "zod";
4
+
5
+ export const env = createEnv({
6
+ server: {
7
+ ...appUrlEnv,
8
+ },
9
+ client: {
10
+ ...sentryClientEnv,
11
+ NEXT_PUBLIC_VERCEL_ENV: z.enum(["production", "preview", "development"]).optional(),
12
+ },
13
+ experimental__runtimeEnv: {
14
+ NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
15
+ NEXT_PUBLIC_VERCEL_ENV: process.env.NEXT_PUBLIC_VERCEL_ENV,
16
+ },
17
+ emptyStringAsUndefined: true,
18
+ skipValidation: process.env.SKIP_ENV_VALIDATION === "1",
19
+ });
@@ -0,0 +1,3 @@
1
+ export const ROUTES = {
2
+ home: "/",
3
+ } as const;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "@inbeat/config/tsconfig/nextjs.json",
3
+ "compilerOptions": {
4
+ "paths": {
5
+ "@/*": ["./src/*"]
6
+ }
7
+ },
8
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
9
+ "exclude": ["node_modules", ".next"]
10
+ }
@@ -0,0 +1,14 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { vitestPreset } from "@inbeat/config/vitest";
3
+ import { defineConfig } from "vitest/config";
4
+
5
+ export default defineConfig({
6
+ ...vitestPreset,
7
+ resolve: {
8
+ tsconfigPaths: true,
9
+ alias: {
10
+ // `server-only` throws outside the react-server condition, which vitest does not set.
11
+ "server-only": fileURLToPath(new URL("./src/test/server-only.ts", import.meta.url)),
12
+ },
13
+ },
14
+ });