create-sprinkles 0.2.3

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 (59) hide show
  1. package/dist/bin.mjs +295 -0
  2. package/dist/index.d.mts +46 -0
  3. package/dist/index.mjs +180 -0
  4. package/package.json +45 -0
  5. package/templates/react-router-convex/.env.local +2 -0
  6. package/templates/react-router-convex/convex/schema.ts +9 -0
  7. package/templates/react-router-rsc/app/home.tsx.hbs +31 -0
  8. package/templates/react-router-rsc/app/root.tsx.hbs +55 -0
  9. package/templates/react-router-rsc/tsconfig.json.hbs +31 -0
  10. package/templates/react-router-rsc/workers/entry.rsc.tsx +44 -0
  11. package/templates/react-router-rsc/workers/entry.ssr.tsx +41 -0
  12. package/templates/react-router-rsc/wrangler.rsc.jsonc.hbs +25 -0
  13. package/templates/react-router-rsc/wrangler.ssr.jsonc.hbs +14 -0
  14. package/templates/react-router-rsc-content-layer/app/content.config.ts.hbs +26 -0
  15. package/templates/react-router-rsc-content-layer/content-layer/api.ts +350 -0
  16. package/templates/react-router-rsc-content-layer/content-layer/codegen.ts +89 -0
  17. package/templates/react-router-rsc-content-layer/content-layer/config.ts +20 -0
  18. package/templates/react-router-rsc-content-layer/content-layer/digest.ts +6 -0
  19. package/templates/react-router-rsc-content-layer/content-layer/frontmatter.ts +19 -0
  20. package/templates/react-router-rsc-content-layer/content-layer/loaders/file.ts +55 -0
  21. package/templates/react-router-rsc-content-layer/content-layer/loaders/glob.ts +82 -0
  22. package/templates/react-router-rsc-content-layer/content-layer/loaders/index.ts +2 -0
  23. package/templates/react-router-rsc-content-layer/content-layer/plugin.ts +419 -0
  24. package/templates/react-router-rsc-content-layer/content-layer/resolve-hook.js +12 -0
  25. package/templates/react-router-rsc-content-layer/content-layer/runtime.ts +73 -0
  26. package/templates/react-router-rsc-content-layer/content-layer/store.ts +59 -0
  27. package/templates/react-router-spa/app/home.tsx.hbs +7 -0
  28. package/templates/react-router-spa/app/root.tsx.hbs +60 -0
  29. package/templates/react-router-spa/tsconfig.json.hbs +26 -0
  30. package/templates/react-router-spa/wrangler.jsonc.hbs +9 -0
  31. package/templates/react-router-ssr/app/home.tsx.hbs +21 -0
  32. package/templates/react-router-ssr/app/root.tsx.hbs +105 -0
  33. package/templates/react-router-ssr/convex/schema.ts +7 -0
  34. package/templates/react-router-ssr/tsconfig.json.hbs +28 -0
  35. package/templates/react-router-ssr/wrangler.jsonc.hbs +13 -0
  36. package/templates/react-router-ssr-convex/app/lib/client.ts +19 -0
  37. package/templates/react-router-ssr-convex/app/tanstack-query-integration/middleware.ts +18 -0
  38. package/templates/react-router-ssr-convex/app/tanstack-query-integration/query-preloader.ts +125 -0
  39. package/templates/react-shared/app/routes.ts.hbs +3 -0
  40. package/templates/react-shared/app/styles/tailwind.css +1 -0
  41. package/templates/react-shared/react-compiler.plugin.ts.hbs +10 -0
  42. package/templates/react-shared/react-router.config.ts.hbs +9 -0
  43. package/templates/shared/.gitignore.hbs +23 -0
  44. package/templates/shared/.node-version +1 -0
  45. package/templates/shared/.vscode/extensions.json.hbs +8 -0
  46. package/templates/shared/.vscode/settings.json.hbs +72 -0
  47. package/templates/shared/AGENTS.md.hbs +599 -0
  48. package/templates/shared/README.md.hbs +24 -0
  49. package/templates/shared/package.json.hbs +41 -0
  50. package/templates/shared/vite.config.ts.hbs +384 -0
  51. package/templates/ts-package/src/index.ts +3 -0
  52. package/templates/ts-package/tests/index.test.ts +9 -0
  53. package/templates/ts-package/tsconfig.json +18 -0
  54. package/templates/ts-package-cli/bin/index.ts.hbs +1 -0
  55. package/templates/ts-package-cli/src/cli.ts.hbs +37 -0
  56. package/templates/ts-package-generator/bin/create.ts.hbs +2 -0
  57. package/templates/ts-package-generator/src/template.ts.hbs +22 -0
  58. package/templates/ts-package-sea/sea-config.json.hbs +2 -0
  59. package/templates/ts-package-sea/src/sea-entry.ts.hbs +4 -0
@@ -0,0 +1,59 @@
1
+ import type { DataEntry, DataStore, MetaStore } from "./api.ts";
2
+
3
+ export function createDataStore<
4
+ D extends Record<string, unknown> = Record<string, unknown>,
5
+ >(): DataStore<D> {
6
+ const map = new Map<string, DataEntry>();
7
+
8
+ return {
9
+ clear() {
10
+ map.clear();
11
+ },
12
+ delete(key) {
13
+ map.delete(key);
14
+ },
15
+ entries() {
16
+ return [...map.entries()] as [string, DataEntry<D>][];
17
+ },
18
+ get(key) {
19
+ return map.get(key) as DataEntry<D> | undefined;
20
+ },
21
+ has(key) {
22
+ return map.has(key);
23
+ },
24
+ keys() {
25
+ return [...map.keys()];
26
+ },
27
+ set(entry) {
28
+ let existing = map.get(entry.id);
29
+ // Skip update if both entries have a digest and they match
30
+ if (existing?.digest && entry.digest && existing.digest === entry.digest) {
31
+ return false;
32
+ }
33
+ map.set(entry.id, entry);
34
+ return true;
35
+ },
36
+ values() {
37
+ return [...map.values()] as DataEntry<D>[];
38
+ },
39
+ };
40
+ }
41
+
42
+ export function createMetaStore(): MetaStore {
43
+ const map = new Map<string, string>();
44
+
45
+ return {
46
+ delete(key) {
47
+ map.delete(key);
48
+ },
49
+ get(key) {
50
+ return map.get(key);
51
+ },
52
+ has(key) {
53
+ return map.has(key);
54
+ },
55
+ set(key, value) {
56
+ map.set(key, value);
57
+ },
58
+ };
59
+ }
@@ -0,0 +1,7 @@
1
+ export default function Home() {
2
+ return (
3
+ <main>
4
+ <h1>Welcome to {{repository}}</h1>
5
+ </main>
6
+ );
7
+ }
@@ -0,0 +1,60 @@
1
+ import type { PropsWithChildren } from "react";
2
+
3
+ {{#if hasConvex}}
4
+ import { ConvexQueryClient } from "@convex-dev/react-query";
5
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
6
+ import { ConvexProvider, ConvexReactClient } from "convex/react";
7
+ {{/if}}
8
+ import { Outlet, Scripts } from "react-router";
9
+
10
+ {{#if hasConvex}}
11
+ const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
12
+ const convexQueryClient = new ConvexQueryClient(convex);
13
+
14
+ const queryClient = new QueryClient({
15
+ defaultOptions: {
16
+ queries: {
17
+ queryKeyHashFn: convexQueryClient.hashFn(),
18
+ queryFn: convexQueryClient.queryFn(),
19
+ experimental_prefetchInRender: true,
20
+ },
21
+ },
22
+ });
23
+
24
+ convexQueryClient.connect(queryClient);
25
+
26
+ {{/if}}
27
+ export function Layout({ children }: PropsWithChildren) {
28
+ return (
29
+ <html lang="en">
30
+ <head>
31
+ <meta charSet="utf-8" />
32
+ <meta content="width=device-width, initial-scale=1" name="viewport" />
33
+ <meta content="#000000" name="theme-color" />
34
+ <title>{{repository}}</title>
35
+ </head>
36
+ <body>
37
+ {children}
38
+ <Scripts />
39
+ </body>
40
+ </html>
41
+ );
42
+ }
43
+
44
+ export function HydrateFallback() {
45
+ return <div>Loading...</div>;
46
+ }
47
+
48
+ export default function App() {
49
+ return (
50
+ {{#if hasConvex}}
51
+ <ConvexProvider client={convex}>
52
+ <QueryClientProvider client={queryClient}>
53
+ <Outlet />
54
+ </QueryClientProvider>
55
+ </ConvexProvider>
56
+ {{else}}
57
+ <Outlet />
58
+ {{/if}}
59
+ );
60
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "include": [
3
+ "**/*.ts",
4
+ "**/*.tsx",
5
+ "./.react-router/types/**/*"
6
+ ],
7
+ "compilerOptions": {
8
+ "allowImportingTsExtensions": true,
9
+ "strict": true,
10
+ "noUnusedLocals": true,
11
+ "noUnusedParameters": true,
12
+ "skipLibCheck": true,
13
+ "verbatimModuleSyntax": true,
14
+ "noEmit": true,
15
+ "moduleResolution": "Bundler",
16
+ "module": "ESNext",
17
+ "target": "ESNext",
18
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
19
+ "types": ["vite/client"],
20
+ "jsx": "react-jsx",
21
+ "rootDirs": [".", "./.react-router/types"],
22
+ "paths": {
23
+ "~/*": ["./app/*"]
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "{{repository}}",
3
+ "compatibility_date": "2025-04-01",
4
+ "assets": {
5
+ "directory": "./build/client",
6
+ "not_found_handling": "single-page-application",
7
+ "binding": "ASSETS"
8
+ }
9
+ }
@@ -0,0 +1,21 @@
1
+ {{#if hasConvex}}
2
+ import { createPreloader } from "~/tanstack-query-integration/query-preloader.ts";
3
+ import type { QueryLoaderArgs } from "~/tanstack-query-integration/query-preloader.ts";
4
+
5
+ import type { Route } from "./+types/home.ts";
6
+
7
+ // TODO: Remove @ts-expect-error once preload is used
8
+ // @ts-expect-error TS6133 — preload is unused until you call it with your query options
9
+ export const loader = createPreloader(async ({ preload }: QueryLoaderArgs<Route.LoaderArgs>) => {
10
+ // Pre-populate query cache before render
11
+ // await preload(yourQueryOptions);
12
+ });
13
+
14
+ {{/if}}
15
+ export default function Home() {
16
+ return (
17
+ <main>
18
+ <h1>Welcome to {{repository}}</h1>
19
+ </main>
20
+ );
21
+ }
@@ -0,0 +1,105 @@
1
+ {{#if hasConvex}}
2
+ import { useState, type PropsWithChildren } from "react";
3
+ import { ConvexQueryClient } from "@convex-dev/react-query";
4
+ import { HydrationBoundary, QueryClientProvider } from "@tanstack/react-query";
5
+ import { ConvexProvider, ConvexReactClient } from "convex/react";
6
+ {{else}}
7
+ import type { PropsWithChildren } from "react";
8
+ {{/if}}
9
+ import {
10
+ isRouteErrorResponse,
11
+ Outlet,
12
+ Scripts,
13
+ ScrollRestoration,
14
+ } from "react-router";
15
+
16
+ {{#if hasConvex}}
17
+ import { useDehydratedState } from "./tanstack-query-integration/query-preloader.ts";
18
+ import { setQueryClient } from "~/tanstack-query-integration/middleware.ts";
19
+ import { createQueryClient } from "~/lib/client.ts";
20
+
21
+ import type { Route } from "./+types/root.ts";
22
+
23
+ const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
24
+ const convexQueryClient = new ConvexQueryClient(convex);
25
+
26
+ function createConvexQueryClient() {
27
+ const queryClient = createQueryClient({
28
+ queryKeyHashFn: convexQueryClient.hashFn(),
29
+ queryFn: convexQueryClient.queryFn(),
30
+ });
31
+ convexQueryClient.connect(queryClient);
32
+ return queryClient;
33
+ }
34
+
35
+ export const middleware = [setQueryClient(() => createConvexQueryClient())];
36
+
37
+ {{/if}}
38
+ export function Layout({ children }: PropsWithChildren) {
39
+ return (
40
+ <html lang="en">
41
+ <head>
42
+ <meta charSet="utf-8" />
43
+ <meta
44
+ content="width=device-width, initial-scale=1"
45
+ name="viewport"
46
+ />
47
+ <meta content="#000000" name="theme-color" />
48
+ <title>{{repository}}</title>
49
+ </head>
50
+ <body>
51
+ {children}
52
+ <ScrollRestoration />
53
+ <Scripts />
54
+ </body>
55
+ </html>
56
+ );
57
+ }
58
+
59
+ export default function App() {
60
+ {{#if hasConvex}}
61
+ const [queryClient] = useState(() => createConvexQueryClient());
62
+ const state = useDehydratedState();
63
+
64
+ return (
65
+ <ConvexProvider client={convex}>
66
+ <QueryClientProvider client={queryClient}>
67
+ <HydrationBoundary state={state}>
68
+ <Outlet />
69
+ </HydrationBoundary>
70
+ </QueryClientProvider>
71
+ </ConvexProvider>
72
+ );
73
+ {{else}}
74
+ return <Outlet />;
75
+ {{/if}}
76
+ }
77
+
78
+ export function ErrorBoundary({ error }: {{#if hasConvex}}Route.ErrorBoundaryProps{{else}}{ error: unknown }{{/if}}) {
79
+ let message = "Oops!";
80
+ let details = "An unexpected error occurred.";
81
+ let stack: string | undefined;
82
+
83
+ if (isRouteErrorResponse(error)) {
84
+ message = error.status === 404 ? "404" : "Error";
85
+ details =
86
+ error.status === 404
87
+ ? "The requested page could not be found."
88
+ : error.statusText || details;
89
+ } else if (import.meta.env.DEV && error && error instanceof Error) {
90
+ details = error.message;
91
+ stack = error.stack;
92
+ }
93
+
94
+ return (
95
+ <main className="pt-16 p-4 container mx-auto">
96
+ <h1>{message}</h1>
97
+ <p>{details}</p>
98
+ {stack && (
99
+ <pre className="w-full p-4 overflow-x-auto">
100
+ <code>{stack}</code>
101
+ </pre>
102
+ )}
103
+ </main>
104
+ );
105
+ }
@@ -0,0 +1,7 @@
1
+ import { defineSchema, defineTable } from "convex/server";
2
+ import { v } from "convex/values";
3
+
4
+ export default defineSchema({
5
+ // Define your tables here
6
+ // Example: defineTable({ name: v.string() }),
7
+ });
@@ -0,0 +1,28 @@
1
+ {
2
+ "include": [
3
+ "**/*.ts",
4
+ "**/*.tsx",
5
+ "**/.server/**/*",
6
+ "**/.client/**/*",
7
+ ".react-router/types/**/*"
8
+ ],
9
+ "compilerOptions": {
10
+ "allowImportingTsExtensions": true,
11
+ "strict": true,
12
+ "noUnusedLocals": true,
13
+ "noUnusedParameters": true,
14
+ "skipLibCheck": true,
15
+ "verbatimModuleSyntax": true,
16
+ "noEmit": true,
17
+ "moduleResolution": "Bundler",
18
+ "module": "ESNext",
19
+ "target": "ESNext",
20
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
21
+ "types": ["vite/client"],
22
+ "jsx": "react-jsx",
23
+ "rootDirs": [".", "./.react-router/types"],
24
+ "paths": {
25
+ "~/*": ["./app/*"]
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "node_modules/wrangler/config-schema.json",
3
+ "name": "{{repository}}",
4
+ "compatibility_date": "2025-04-01",
5
+ "compatibility_flags": ["nodejs_compat"],
6
+ "assets": {
7
+ "directory": "./build/client",
8
+ "binding": "ASSETS"
9
+ },
10
+ "observability": {
11
+ "enabled": true
12
+ }
13
+ }
@@ -0,0 +1,19 @@
1
+ import type { DefaultOptions } from "@tanstack/react-query";
2
+
3
+ import { QueryClient } from "@tanstack/react-query";
4
+
5
+ export function createQueryClient(overrides: DefaultOptions["queries"] = {}) {
6
+ return new QueryClient({
7
+ defaultOptions: {
8
+ queries: {
9
+ // With SSR, we usually want to set some default staleTime
10
+ // Above 0 to avoid refetching immediately on the client
11
+ staleTime: 60 * 1000,
12
+ // Allows us to use `const { promise } = useQuery(...)`
13
+ // Along with `React.use(promise)`
14
+ experimental_prefetchInRender: true,
15
+ ...overrides,
16
+ },
17
+ },
18
+ });
19
+ }
@@ -0,0 +1,18 @@
1
+ import type { QueryClient } from "@tanstack/react-query";
2
+
3
+ import type { MiddlewareFunction } from "react-router";
4
+
5
+ import assert from "node:assert";
6
+ import { createContext, RouterContextProvider } from "react-router";
7
+
8
+ const QUERY_CLIENT = createContext<QueryClient | null>(null);
9
+
10
+ export function setQueryClient(createClient: () => QueryClient): MiddlewareFunction {
11
+ return ({ context }) => context.set(QUERY_CLIENT, createClient());
12
+ }
13
+
14
+ export function getQueryClient(context: Readonly<RouterContextProvider>): QueryClient {
15
+ const client = context.get(QUERY_CLIENT);
16
+ assert(client, "must use `setQueryClient` to set the query client for this application");
17
+ return client;
18
+ }
@@ -0,0 +1,125 @@
1
+ import type {
2
+ DefaultError,
3
+ DehydratedState,
4
+ EnsureQueryDataOptions,
5
+ QueryKey,
6
+ } from "@tanstack/react-query";
7
+ import type { LoaderFunctionArgs } from "react-router";
8
+
9
+ import { dehydrate } from "@tanstack/react-query";
10
+ import { useMatches } from "react-router";
11
+
12
+ import { getQueryClient } from "./middleware.ts";
13
+
14
+ const DEHYDRATED_STATE_KEY = "@tanstack/react-query:dehydrated-state";
15
+
16
+ type MaybePromise<T> = T | Promise<T>;
17
+
18
+ function mergeDehydratedStates(states: DehydratedState[]): DehydratedState {
19
+ const allMutations = states.flatMap(s => s.mutations ?? []);
20
+ const allQueries = states.flatMap(s => s.queries ?? []);
21
+
22
+ // Last-write-wins de-dupe by queryHash
23
+ const byHash = new Map<string, (typeof allQueries)[number]>();
24
+
25
+ for (const query of allQueries) {
26
+ if (!query) {
27
+ continue;
28
+ }
29
+ byHash.set(query.queryHash, query);
30
+ }
31
+
32
+ return {
33
+ mutations: allMutations,
34
+ queries: Array.from(byHash.values()),
35
+ };
36
+ }
37
+
38
+ export function useDehydratedState() {
39
+ const matches = useMatches();
40
+ const states = matches
41
+ .map(m => (m.loaderData as any)?.[DEHYDRATED_STATE_KEY] as DehydratedState | undefined)
42
+ .filter((s): s is DehydratedState => Boolean(s));
43
+
44
+ return states.length ? mergeDehydratedStates(states) : undefined;
45
+ }
46
+
47
+ export function createPreloader<
48
+ TLoaderArgs extends LoaderFunctionArgs,
49
+ TData extends Record<string, unknown> | void,
50
+ >(
51
+ fn: (args: QueryLoaderArgs<TLoaderArgs>) => MaybePromise<TData | Response>,
52
+ ): QueryLoader<TLoaderArgs, TData> {
53
+ return (async args => {
54
+ const prefetches: Promise<any>[] = [];
55
+ const query = getQueryClient(args.context);
56
+
57
+ // If the navigation is aborted, cancel any in-flight queries
58
+ if (args.request.signal) {
59
+ if (args.request.signal.aborted) {
60
+ query.cancelQueries();
61
+ } else {
62
+ args.request.signal.addEventListener("abort", () => query.cancelQueries(), {
63
+ once: true,
64
+ });
65
+ }
66
+ }
67
+
68
+ function preload<
69
+ TQueryFnData,
70
+ TError = DefaultError,
71
+ TData = TQueryFnData,
72
+ TQueryKey extends QueryKey = QueryKey,
73
+ >(options: EnsureQueryDataOptions<TQueryFnData, TError, TData, TQueryKey>): Promise<TData> {
74
+ const result = query.ensureQueryData(options);
75
+ prefetches.push(result);
76
+ return result;
77
+ }
78
+
79
+ const result = await fn({ ...args, preload });
80
+
81
+ if (result instanceof Response) {
82
+ return result;
83
+ }
84
+
85
+ if (args.request.signal.aborted) {
86
+ throw args.request.signal.reason ?? new DOMException("Aborted", "AbortError");
87
+ }
88
+
89
+ await Promise.all(prefetches);
90
+
91
+ if (args.request.signal.aborted) {
92
+ throw args.request.signal.reason ?? new DOMException("Aborted", "AbortError");
93
+ }
94
+
95
+ const dehydratedState = { [DEHYDRATED_STATE_KEY]: dehydrate(query) };
96
+
97
+ return {
98
+ ...result,
99
+ ...dehydratedState,
100
+ };
101
+ }) as QueryLoader<TLoaderArgs, TData>;
102
+ }
103
+
104
+ type WithDehydratedState<TData extends object | void> = (TData extends void ? {} : TData) & {
105
+ [DEHYDRATED_STATE_KEY]: DehydratedState;
106
+ };
107
+
108
+ export type QueryLoaderReturn<TData extends object | void> = Promise<
109
+ WithDehydratedState<TData> | Response
110
+ >;
111
+
112
+ export type QueryLoader<LoaderArgs, TData extends object | void> = (
113
+ ctx: LoaderArgs,
114
+ ) => QueryLoaderReturn<TData>;
115
+
116
+ export type QueryLoaderArgs<Args extends LoaderFunctionArgs = LoaderFunctionArgs> = Args & {
117
+ preload<
118
+ TQueryFnData,
119
+ TError = DefaultError,
120
+ TData = TQueryFnData,
121
+ TQueryKey extends QueryKey = QueryKey,
122
+ >(
123
+ options: EnsureQueryDataOptions<TQueryFnData, TError, TData, TQueryKey>,
124
+ ): Promise<TData>;
125
+ };
@@ -0,0 +1,3 @@
1
+ import { index, type RouteConfig } from "@react-router/dev/routes";
2
+
3
+ export default [index("home.tsx")] satisfies RouteConfig;
@@ -0,0 +1 @@
1
+ @import "tailwindcss";
@@ -0,0 +1,10 @@
1
+ import babel from "@rolldown/plugin-babel";
2
+ import { reactCompilerPreset } from "@vitejs/plugin-react";
3
+
4
+ export type ReactCompilerConfig = Partial<Parameters<typeof reactCompilerPreset>[0]>;
5
+
6
+ export function reactCompiler(config: ReactCompilerConfig = {}) {
7
+ return babel({
8
+ presets: [reactCompilerPreset(config as Parameters<typeof reactCompilerPreset>[0])],
9
+ } as Parameters<typeof babel>[0]);
10
+ }
@@ -0,0 +1,9 @@
1
+ import type { Config } from "@react-router/dev/config";
2
+
3
+ export default {
4
+ future: {
5
+ v8_middleware: true,
6
+ v8_viteEnvironmentApi: true,
7
+ },
8
+ ssr: {{ssr}},
9
+ } satisfies Config;
@@ -0,0 +1,23 @@
1
+ .DS_Store
2
+ .env
3
+ .env.local
4
+ /node_modules/
5
+ {{#if isReactRouter}}
6
+
7
+ # React Router
8
+ /.react-router/
9
+ /build/
10
+ {{/if}}
11
+ {{#if isRSC}}
12
+
13
+ # Content Layer
14
+ /.sprinkles/
15
+
16
+ # Cloudflare
17
+ .wrangler
18
+ {{/if}}
19
+ {{#if isPackage}}
20
+
21
+ # Build
22
+ /dist/
23
+ {{/if}}
@@ -0,0 +1 @@
1
+ 24
@@ -0,0 +1,8 @@
1
+ {
2
+ "recommendations": [
3
+ "VoidZero.vite-plus-extension-pack",
4
+ "TypeScriptTeam.native-preview"{{#if isReactRouter}},
5
+ "bradlc.vscode-tailwindcss"{{/if}}{{#if hasContentLayer}},
6
+ "unifiedjs.vscode-mdx"{{/if}}
7
+ ]
8
+ }
@@ -0,0 +1,72 @@
1
+ {
2
+ "js/ts.preferences.importModuleSpecifierEnding": "js",
3
+ "js/ts.experimental.useTsgo": true,
4
+
5
+ "oxc.enable.oxlint": true,
6
+ "oxc.enable.oxfmt": true,
7
+
8
+ "editor.codeActionsOnSave": {
9
+ "source.fixAll.oxc": "always",
10
+ "source.addMissingImports.ts": "explicit",
11
+ "source.removeUnused.ts": "never"
12
+ },
13
+ "editor.defaultFormatter": "oxc.oxc-vscode",
14
+ "editor.formatOnSave": true,
15
+ "editor.formatOnSaveMode": "file",
16
+
17
+ "[typescript]": {
18
+ "editor.defaultFormatter": "oxc.oxc-vscode"
19
+ },
20
+ "[tsx]": {
21
+ "editor.defaultFormatter": "oxc.oxc-vscode"
22
+ },
23
+ "[javascript]": {
24
+ "editor.defaultFormatter": "oxc.oxc-vscode"
25
+ },
26
+ "[jsx]": {
27
+ "editor.defaultFormatter": "oxc.oxc-vscode"
28
+ },
29
+ "[css]": {
30
+ "editor.defaultFormatter": "oxc.oxc-vscode"
31
+ },
32
+ "[json]": {
33
+ "editor.defaultFormatter": "oxc.oxc-vscode"
34
+ },
35
+ "[jsonc]": {
36
+ "editor.defaultFormatter": "oxc.oxc-vscode"
37
+ },
38
+ "[markdown]": {
39
+ "editor.defaultFormatter": "oxc.oxc-vscode"
40
+ },
41
+ {{#if hasContentLayer}}
42
+ "[mdx]": {
43
+ "editor.defaultFormatter": "oxc.oxc-vscode"
44
+ },
45
+ "mdx.server.enable": true,
46
+
47
+ {{/if}}
48
+ "explorer.fileNesting.enabled": true,
49
+ "explorer.fileNesting.expand": false,
50
+ "explorer.fileNesting.patterns": {
51
+ "package.json": ".github*, .npmrc, .prettierignore, .vscode*, biome.json*, bun.lock*, components.json, eslint.config.*, .node-version,.oxfmtrc.jsonc, .oxlintrc.jsonc, pnpm-*.yaml, prettier.config.*, tsconfig.*, wrangler.toml, wrangler.*.toml, wrangler.json*, wrangler.*.json, wrangler.*.jsonc, workspace.json",
52
+ "readme*": "agent*, authors, backers*, changelog*, citation*, claude*, code_of_conduct*, codeowners, contributing*, contributors, copying, credits, governance.md, history.md, license*, maintainers, readme*, security.md, sponsors*"{{#if isReactRouter}},
53
+ "vite.config.*": "react-router.config.*, vitest.config.*, *.plugin.ts"{{/if}}
54
+ },
55
+ {{#if isReactRouter}}
56
+ "files.exclude": {
57
+ "**/.react-router": true,
58
+ "**/.wrangler": true{{#if hasContentLayer}},
59
+ "**/.sprinkles": true{{/if}}
60
+ },
61
+
62
+ "tailwindCSS.classFunctions": ["cva", "cx"],
63
+
64
+ {{/if}}
65
+ "biome.enabled": false,
66
+ "prettier.enable": false,
67
+ "eslint.enable": false,
68
+ "dprint.experimentalLsp": false,
69
+ "deno.enable": false,
70
+ "unocss.disable": true,
71
+ "vitest.ignoreWorkspace": true
72
+ }