nextjs-studio 1.0.0 → 1.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.
@@ -769,7 +769,10 @@ var package_default = {
769
769
  lowlight: "^3.3.0",
770
770
  "lucide-react": "^0.574.0",
771
771
  mermaid: "^11.6.0",
772
+ next: "^16.1.6",
772
773
  "next-themes": "^0.4.6",
774
+ react: "^19.2.4",
775
+ "react-dom": "^19.2.4",
773
776
  "tailwind-merge": "^3.4.1",
774
777
  tailwindcss: "^4.1.18",
775
778
  "tippy.js": "^6.3.7",
@@ -786,10 +789,12 @@ var package_default = {
786
789
  chokidar: "^5.0.0",
787
790
  commander: "^14.0.3",
788
791
  "gray-matter": "^4.0.3",
789
- "lodash-es": "^4.17.23",
790
- next: "^16.1.6",
791
- react: "^19.2.4",
792
- "react-dom": "^19.2.4"
792
+ "lodash-es": "^4.17.23"
793
+ },
794
+ peerDependencies: {
795
+ next: "^16.0.0",
796
+ react: "^19.0.0",
797
+ "react-dom": "^19.0.0"
793
798
  }
794
799
  };
795
800
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/nextjs-studio.ts","../../src/shared/constants.ts","../../src/core/fs-adapter.ts","../../src/core/indexer.ts","../../src/core/parsers/parser-mdx.ts","../../src/core/frontmatter-binder.ts","../../src/core/parsers/parser-json.ts","../../src/core/schema-inferrer.ts","../../src/core/locale-parser.ts","../../src/core/content-store.ts","../../src/core/type-generator.ts","../../src/core/config-loader.ts","../../package.json"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * @context bin layer — CLI entry point at src/bin/nextjs-studio.ts\n * @does Parses CLI args, then either generates types or spawns the UI server process\n * @depends src/shared/constants.ts, src/cli/adapters/fs-adapter.ts, src/core/content-store.ts, src/core/type-generator.ts\n * @do Add new CLI flags here; keep only process bootstrap logic\n * @dont Import UI components or contain parsing/indexing business logic\n */\n\nimport { existsSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { Command } from \"commander\";\nimport { CLI_PORT, CONTENTS_DIR } from \"../shared/constants.js\";\nimport { FsAdapter } from \"../core/fs-adapter.js\";\nimport { loadContent } from \"../core/content-store.js\";\nimport { generateCollectionTypes } from \"../core/type-generator.js\";\nimport { loadStudioConfig, resolveConfigPath } from \"../core/config-loader.js\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\n\nconst { version } = pkg;\n\nconst program = new Command()\n .name(\"Nextjs Studio\")\n .description(\"Local-first CMS for Next.js projects\")\n .version(version)\n .option(\"-d, --dir <path>\", \"Path to contents directory\", CONTENTS_DIR)\n .option(\"-p, --port <number>\", \"Port to run the studio on\", String(CLI_PORT))\n .option(\"--generate-types\", \"Generate TypeScript types for content collections\")\n .parse();\n\nconst opts = program.opts<{ dir: string; port: string; generateTypes?: boolean }>();\nconst contentsDir = path.resolve(opts.dir);\nconst port = Number(opts.port);\n\nasync function runGenerateTypes(sourceDir: string): Promise<void> {\n const outDir = path.resolve(\".studio\");\n const outFile = path.join(outDir, \"studio.d.ts\");\n\n console.log(`Generating types from ${sourceDir}...`);\n\n const config = await loadStudioConfig(process.cwd());\n const fsAdapter = new FsAdapter(sourceDir);\n const index = await loadContent(fsAdapter, config);\n const schemas = index.getCollections().flatMap((c) => (c.schema ? [c.schema] : []));\n const code = generateCollectionTypes(schemas);\n\n await fs.mkdir(outDir, { recursive: true });\n await fs.writeFile(outFile, code, \"utf-8\");\n\n console.log(`Types written to ${outFile}`);\n}\n\nfunction resolveServerProcess(\n uiDir: string,\n serverPort: number,\n env: NodeJS.ProcessEnv,\n): ChildProcess | null {\n // Production: .next build output present — run via `next start`\n const buildId = path.resolve(uiDir, \".next/BUILD_ID\");\n if (existsSync(buildId)) {\n const require = createRequire(import.meta.url);\n const nextBin = require.resolve(\"next/dist/bin/next\");\n return spawn(\"node\", [nextBin, \"start\", \"--port\", String(serverPort)], {\n cwd: uiDir,\n stdio: \"inherit\",\n env,\n });\n }\n\n // Dev mode: UI source present (running from repo with `yarn dev`)\n const uiPackageJson = path.resolve(uiDir, \"package.json\");\n if (existsSync(uiPackageJson)) {\n // Resolve `next` bin from workspace root (3 levels up from src/cli/ui)\n const nextBin = path.resolve(uiDir, \"../../../node_modules/next/dist/bin/next\");\n return spawn(\"node\", [nextBin, \"dev\", \"--port\", String(serverPort), \"--webpack\"], {\n cwd: uiDir,\n stdio: \"inherit\",\n env,\n });\n }\n\n return null;\n}\n\nfunction forwardSignals(child: ChildProcess): void {\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n process.on(signal, () => child.kill(signal));\n }\n}\n\nif (opts.generateTypes) {\n await runGenerateTypes(contentsDir);\n process.exit(0);\n}\n\nconst uiDir = path.resolve(import.meta.dirname, \"../cli/ui\");\nconst configPath = resolveConfigPath(process.cwd());\nconst serverEnv: NodeJS.ProcessEnv = {\n ...process.env,\n STUDIO_CONTENTS_DIR: contentsDir,\n STUDIO_PROJECT_DIR: process.cwd(),\n PORT: String(port),\n HOSTNAME: \"0.0.0.0\",\n ...(configPath ? { STUDIO_CONFIG_PATH: configPath } : {}),\n};\nconst serverProcess = resolveServerProcess(uiDir, port, serverEnv);\n\nif (!serverProcess) {\n console.error(\"Error: Studio UI server not found.\");\n console.error(\"The pre-built UI is not included in this installation.\");\n process.exit(1);\n}\n\nconsole.log(`Nextjs Studio v${version}`);\nconsole.log(`Contents: ${contentsDir}`);\nconsole.log(`Starting on http://localhost:${port}`);\n\nserverProcess.on(\"error\", (error) => {\n console.error(\"Failed to start server:\", error.message);\n process.exit(1);\n});\n\nserverProcess.on(\"close\", (code) => process.exit(code ?? 0));\n\nforwardSignals(serverProcess);\n","/**\n * @context Shared layer — constants at src/shared/constants.ts\n * @does Defines project-wide constants shared across core, CLI, and UI layers\n * @depends none\n * @do Add new shared constants here\n * @dont Import from CLI or UI; constants must be framework-agnostic\n */\n\nexport const CONTENTS_DIR = \"contents\";\nexport const CLI_PORT = 3030;\nexport const CONFIG_FILE = \"studio.config.ts\";\nexport const CONFIG_FILENAMES = [\"studio.config.ts\", \"studio.config.js\", \"studio.config.mjs\"] as const;\nexport const SUPPORTED_EXTENSIONS = [\".mdx\", \".json\"] as const;\nexport const COLLECTION_ORDER_FILE = \"collection.json\";\nexport const WATCHER_DEBOUNCE_MS = 5_000;\nexport const MEDIA_DIR = \"media\";\n\nexport const IMAGE_MIME_TYPES = [\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"image/svg+xml\",\n \"image/avif\",\n] as const;\n\nexport const VIDEO_MIME_TYPES = [\"video/mp4\", \"video/webm\", \"video/ogg\"] as const;\n\nexport const AUDIO_MIME_TYPES = [\n \"audio/mpeg\",\n \"audio/ogg\",\n \"audio/wav\",\n \"audio/webm\",\n \"audio/aac\",\n \"audio/flac\",\n] as const;\n\nexport const MEDIA_MIME_TYPES = [...IMAGE_MIME_TYPES, ...VIDEO_MIME_TYPES, ...AUDIO_MIME_TYPES] as const;\n\nexport const IMAGE_EXTENSIONS = [\".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\", \".svg\", \".avif\"] as const;\nexport const VIDEO_EXTENSIONS = [\".mp4\", \".webm\", \".ogv\"] as const;\nexport const AUDIO_EXTENSIONS = [\".mp3\", \".ogg\", \".wav\", \".m4a\", \".aac\", \".flac\"] as const;\n","/**\n * @context Core layer — filesystem adapter at src/core/fs-adapter.ts\n * @does Implements IFsAdapter; abstracts all file read/write/list operations behind a single interface\n * @depends src/shared/types.ts, src/shared/constants.ts, src/shared/fs-adapter.interface.ts\n * @do Add new I/O operations here; all file access must go through this adapter\n * @dont Import UI components, run HTTP requests, or contain business logic\n */\n\nimport fs from \"node:fs/promises\";\nimport fsSync from \"node:fs\";\nimport path from \"node:path\";\nimport type { Dirent } from \"node:fs\";\nimport type { FileInfo, DirectoryFileEntry } from \"../shared/types.js\";\nimport type { IFsAdapter } from \"../shared/fs-adapter.interface.js\";\nimport { SUPPORTED_EXTENSIONS } from \"../shared/constants.js\";\n\nexport class FsAdapter implements IFsAdapter {\n private readonly basePath: string;\n\n constructor(basePath: string) {\n this.basePath = path.resolve(basePath);\n }\n\n private resolve(...segments: string[]): string {\n return path.resolve(this.basePath, ...segments);\n }\n\n async readFile(filePath: string): Promise<string> {\n return fs.readFile(this.resolve(filePath), \"utf-8\");\n }\n\n async writeFile(filePath: string, content: string): Promise<void> {\n const fullPath = this.resolve(filePath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, content, \"utf-8\");\n }\n\n async deleteFile(filePath: string): Promise<void> {\n await fs.unlink(this.resolve(filePath));\n }\n\n async exists(filePath: string): Promise<boolean> {\n try {\n await fs.access(this.resolve(filePath));\n return true;\n } catch {\n return false;\n }\n }\n\n async getStats(filePath: string): Promise<FileInfo> {\n const fullPath = this.resolve(filePath);\n const stats = await fs.stat(fullPath);\n return { path: filePath, size: stats.size, modifiedAt: stats.mtime };\n }\n\n async listFiles(dirPath: string, extensions?: readonly string[]): Promise<string[]> {\n const fullPath = this.resolve(dirPath);\n const filterExts = extensions ?? SUPPORTED_EXTENSIONS;\n\n let entries: Dirent[];\n try {\n entries = await fs.readdir(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n return entries\n .filter((entry) => entry.isFile() && filterExts.some((ext) => entry.name.endsWith(ext)))\n .map((entry) => this.join(dirPath, entry.name));\n }\n\n async listDirectories(dirPath: string): Promise<string[]> {\n const fullPath = this.resolve(dirPath);\n\n let entries: Dirent[];\n try {\n entries = await fs.readdir(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => this.join(dirPath, entry.name));\n }\n\n async readBuffer(filePath: string): Promise<Buffer> {\n return fs.readFile(this.resolve(filePath));\n }\n\n async writeBuffer(filePath: string, data: Buffer): Promise<void> {\n const fullPath = this.resolve(filePath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, data);\n }\n\n async listAllFiles(dirPath: string): Promise<DirectoryFileEntry[]> {\n const fullPath = this.resolve(dirPath);\n\n let entries: Dirent[];\n try {\n entries = await fs.readdir(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n const results: DirectoryFileEntry[] = [];\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n const relativePath = this.join(dirPath, entry.name);\n const stats = await fs.stat(this.resolve(relativePath));\n results.push({ name: entry.name, relativePath, size: stats.size, modifiedAt: stats.mtime });\n }\n return results;\n }\n\n join(...segments: string[]): string {\n return path.join(...segments);\n }\n\n basename(filePath: string): string {\n return path.basename(filePath);\n }\n\n extname(filePath: string): string {\n return path.extname(filePath);\n }\n\n relative(from: string, to: string): string {\n return path.relative(from, to);\n }\n\n normalizeSlug(relativePath: string, ext: string): string {\n return relativePath.replace(ext, \"\").split(path.sep).join(\"/\");\n }\n\n readFileSync(filePath: string): string {\n return fsSync.readFileSync(this.resolve(filePath), \"utf-8\");\n }\n\n existsSync(filePath: string): boolean {\n return fsSync.existsSync(this.resolve(filePath));\n }\n\n listFilesSync(dirPath: string, extensions?: readonly string[]): string[] {\n const fullPath = this.resolve(dirPath);\n const filterExts = extensions ?? SUPPORTED_EXTENSIONS;\n\n let entries: Dirent[];\n try {\n entries = fsSync.readdirSync(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n return entries\n .filter((entry) => entry.isFile() && filterExts.some((ext) => entry.name.endsWith(ext)))\n .map((entry) => this.join(dirPath, entry.name));\n }\n\n listDirectoriesSync(dirPath: string): string[] {\n const fullPath = this.resolve(dirPath);\n\n let entries: Dirent[];\n try {\n entries = fsSync.readdirSync(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => this.join(dirPath, entry.name));\n }\n}\n","/**\n * @context Core layer — content indexer at src/core/indexer.ts\n * @does Scans the contents directory, parses MDX/JSON files, and builds an in-memory index\n * @depends src/shared/types.ts, src/shared/constants.ts, src/shared/fs-adapter.interface.ts, src/core/parsers/, src/core/schema-inferrer.ts\n * @do Add new file type handling here; extend indexCollection for new collection behaviors\n * @dont Import from CLI or UI; instantiate FsAdapter; access the filesystem directly\n */\n\nimport slugify from \"@sindresorhus/slugify\";\nimport type { CollectionSchema } from \"../shared/fields.js\";\nimport type { ContentEntry, Collection, StudioConfig } from \"../shared/types.js\";\nimport type { IFsAdapter } from \"../shared/fs-adapter.interface.js\";\nimport { COLLECTION_ORDER_FILE } from \"../shared/constants.js\";\nimport { parseMdx } from \"./parsers/parser-mdx.js\";\nimport { parseJson } from \"./parsers/parser-json.js\";\nimport { inferSchema } from \"./schema-inferrer.js\";\nimport { parseLocaleFromFilename, stripLocaleFromSlug } from \"./locale-parser.js\";\n\nexport class ContentIndex {\n private readonly entries = new Map<string, ContentEntry[]>();\n private readonly collections = new Map<string, Collection>();\n private readonly fs: IFsAdapter;\n\n constructor(fsAdapter: IFsAdapter) {\n this.fs = fsAdapter;\n }\n\n async build(config?: StudioConfig): Promise<void> {\n this.clear();\n const dirs = await this.fs.listDirectories(\".\");\n\n for (const dir of dirs) {\n const dirName = this.fs.basename(dir);\n const collectionName = slugify(dirName);\n const collectionConfig = config?.collections?.[collectionName];\n await this.indexCollection(dirName, collectionName, collectionConfig?.schema);\n }\n }\n\n buildSync(config?: StudioConfig): void {\n this.clear();\n const dirs = this.fs.listDirectoriesSync(\".\");\n\n for (const dir of dirs) {\n const dirName = this.fs.basename(dir);\n const collectionName = slugify(dirName);\n const collectionConfig = config?.collections?.[collectionName];\n this.indexCollectionSync(dirName, collectionName, collectionConfig?.schema);\n }\n }\n\n getCollection(name: string): ContentEntry[] {\n return this.entries.get(name) ?? [];\n }\n\n getCollections(): Collection[] {\n return Array.from(this.collections.values());\n }\n\n clear(): void {\n this.entries.clear();\n this.collections.clear();\n }\n\n updateEntry(collectionName: string, entry: ContentEntry): void {\n const entries = this.entries.get(collectionName) ?? [];\n const idx = entries.findIndex((e) => e.slug === entry.slug);\n if (idx >= 0) {\n entries[idx] = entry;\n } else {\n entries.push(entry);\n }\n this.entries.set(collectionName, entries);\n this.updateCollectionMeta(collectionName);\n }\n\n removeEntry(collectionName: string, slug: string): void {\n const entries = this.entries.get(collectionName);\n if (!entries) return;\n const filtered = entries.filter((e) => e.slug !== slug);\n this.entries.set(collectionName, filtered);\n this.updateCollectionMeta(collectionName);\n }\n\n private updateCollectionMeta(collectionName: string): void {\n const col = this.collections.get(collectionName);\n const entries = this.entries.get(collectionName) ?? [];\n if (col) {\n this.collections.set(collectionName, {\n ...col,\n count: entries.length,\n type: this.detectCollectionType(entries),\n });\n }\n }\n\n private async indexCollection(\n dirName: string,\n collectionName: string,\n manualSchema?: CollectionSchema,\n ): Promise<void> {\n const entries: ContentEntry[] = [];\n await this.scanDir(dirName, collectionName, dirName, entries);\n\n const orderPath = this.fs.join(dirName, COLLECTION_ORDER_FILE);\n const ordering = await this.readOrdering(orderPath);\n if (ordering) {\n this.applyOrdering(entries, ordering);\n }\n\n const schema = manualSchema ?? inferSchema(entries, collectionName);\n\n this.entries.set(collectionName, entries);\n this.collections.set(collectionName, {\n name: collectionName,\n type: this.detectCollectionType(entries),\n count: entries.length,\n basePath: dirName,\n schema,\n });\n }\n\n private indexCollectionSync(\n dirName: string,\n collectionName: string,\n manualSchema?: CollectionSchema,\n ): void {\n const entries: ContentEntry[] = [];\n this.scanDirSync(dirName, collectionName, dirName, entries);\n\n const orderPath = this.fs.join(dirName, COLLECTION_ORDER_FILE);\n const ordering = this.readOrderingSync(orderPath);\n if (ordering) {\n this.applyOrdering(entries, ordering);\n }\n\n const schema = manualSchema ?? inferSchema(entries, collectionName);\n\n this.entries.set(collectionName, entries);\n this.collections.set(collectionName, {\n name: collectionName,\n type: this.detectCollectionType(entries),\n count: entries.length,\n basePath: dirName,\n schema,\n });\n }\n\n private async scanDir(\n dirName: string,\n collectionName: string,\n dirPath: string,\n entries: ContentEntry[],\n ): Promise<void> {\n const subDirs = await this.fs.listDirectories(dirPath);\n for (const subDir of subDirs) {\n await this.scanDir(dirName, collectionName, subDir, entries);\n }\n\n const files = await this.fs.listFiles(dirPath);\n for (const filePath of files) {\n const fileName = this.fs.basename(filePath);\n if (fileName === COLLECTION_ORDER_FILE) continue;\n\n const ext = this.fs.extname(fileName);\n const content = await this.fs.readFile(filePath);\n const relativePath = this.fs.relative(dirName, filePath);\n const slug = this.fs\n .normalizeSlug(relativePath, ext)\n .split(\"/\")\n .map((segment) => slugify(segment))\n .join(\"/\");\n\n if (ext === \".mdx\") {\n entries.push(this.buildMdxEntry(collectionName, slug, fileName, content));\n } else if (ext === \".json\") {\n entries.push(...this.buildJsonEntries(collectionName, slug, content));\n }\n }\n }\n\n private scanDirSync(\n dirName: string,\n collectionName: string,\n dirPath: string,\n entries: ContentEntry[],\n ): void {\n const subDirs = this.fs.listDirectoriesSync(dirPath);\n for (const subDir of subDirs) {\n this.scanDirSync(dirName, collectionName, subDir, entries);\n }\n\n const files = this.fs.listFilesSync(dirPath);\n for (const filePath of files) {\n const fileName = this.fs.basename(filePath);\n if (fileName === COLLECTION_ORDER_FILE) continue;\n\n const ext = this.fs.extname(fileName);\n const content = this.fs.readFileSync(filePath);\n const relativePath = this.fs.relative(dirName, filePath);\n const slug = this.fs\n .normalizeSlug(relativePath, ext)\n .split(\"/\")\n .map((segment) => slugify(segment))\n .join(\"/\");\n\n if (ext === \".mdx\") {\n entries.push(this.buildMdxEntry(collectionName, slug, fileName, content));\n } else if (ext === \".json\") {\n entries.push(...this.buildJsonEntries(collectionName, slug, content));\n }\n }\n }\n\n private buildMdxEntry(collectionName: string, slug: string, fileName: string, content: string): ContentEntry {\n const parsed = parseMdx(content);\n const locale = parseLocaleFromFilename(fileName);\n const normalizedSlug = stripLocaleFromSlug(slug, locale);\n return {\n collection: collectionName,\n slug: normalizedSlug,\n path: `/${collectionName}/${normalizedSlug}`,\n body: parsed.body,\n data: parsed.data,\n ...(locale ? { locale } : {}),\n };\n }\n\n private buildJsonEntries(collectionName: string, slug: string, content: string): ContentEntry[] {\n const parsed = parseJson(content);\n\n if (parsed.type === \"json-array\") {\n return parsed.entries.map((data, index) => {\n const entrySlug =\n typeof data[\"slug\"] === \"string\" ? slugify(data[\"slug\"]) : `${slug}/${index}`;\n return {\n collection: collectionName,\n slug: entrySlug,\n path: `/${collectionName}/${entrySlug}`,\n data,\n };\n });\n }\n\n return [{ collection: collectionName, slug, path: `/${collectionName}/${slug}`, data: parsed.data }];\n }\n\n private async readOrdering(orderPath: string): Promise<string[] | null> {\n if (!(await this.fs.exists(orderPath))) return null;\n\n try {\n const content = await this.fs.readFile(orderPath);\n const parsed: unknown = JSON.parse(content);\n if (Array.isArray(parsed)) return parsed as string[];\n } catch (error) {\n console.warn(`[Nextjs Studio] Failed to parse ordering file: ${orderPath}`, error);\n }\n return null;\n }\n\n private readOrderingSync(orderPath: string): string[] | null {\n if (!this.fs.existsSync(orderPath)) return null;\n\n try {\n const content = this.fs.readFileSync(orderPath);\n const parsed: unknown = JSON.parse(content);\n if (Array.isArray(parsed)) return parsed as string[];\n } catch (error) {\n console.warn(`[Nextjs Studio] Failed to parse ordering file: ${orderPath}`, error);\n }\n return null;\n }\n\n private applyOrdering(entries: ContentEntry[], ordering: string[]): void {\n const orderMap = new Map(ordering.map((slug, index) => [slug, index]));\n entries.sort((a, b) => {\n const aIndex = orderMap.get(a.slug) ?? Infinity;\n const bIndex = orderMap.get(b.slug) ?? Infinity;\n return aIndex - bIndex;\n });\n }\n\n private detectCollectionType(entries: ContentEntry[]): Collection[\"type\"] {\n if (entries.length === 0) return \"mdx\";\n const first = entries[0];\n if (first.body !== undefined) return \"mdx\";\n if (entries.length === 1 && !first.slug.includes(\"/\")) return \"json-object\";\n return \"json-array\";\n }\n}\n","/**\n * @context Core layer — MDX parser/serializer at src/core/parsers/parser-mdx.ts\n * @does Parses .mdx content into frontmatter + body, and serializes them back to MDX strings\n * @depends none (gray-matter is an external dep)\n * @do Add MDX transform steps here; both parse and serialize live here intentionally\n * @dont Access the filesystem; import from CLI or UI; handle JSON content\n */\n\nimport matter from \"gray-matter\";\nimport { bindFrontmatter } from \"../frontmatter-binder.js\";\n\nexport interface ParsedMdx {\n data: Record<string, unknown>;\n body: string;\n}\n\nexport interface ParseMdxOptions {\n /** When true, replaces {frontmatter.X} tokens in the body with actual values. */\n bindTokens?: boolean;\n}\n\n/** Convert Date objects produced by gray-matter back to ISO strings. */\nfunction normalizeDates(data: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (value instanceof Date) {\n result[key] = value.toISOString().split(\"T\")[0];\n } else if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n result[key] = normalizeDates(value as Record<string, unknown>);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nexport function parseMdx(content: string, options?: ParseMdxOptions): ParsedMdx {\n const { data: rawData, content: body } = matter(content);\n const data = normalizeDates(rawData);\n const trimmed = body.trim();\n return {\n data,\n body: options?.bindTokens ? bindFrontmatter(trimmed, data) : trimmed,\n };\n}\n\nexport function serializeMdx(data: Record<string, unknown>, body: string): string {\n return matter.stringify(body, data);\n}\n","/**\n * @context Core layer — frontmatter binder at src/core/frontmatter-binder.ts\n * @does Replaces {frontmatter.X} tokens in MDX body with actual frontmatter values\n * @depends none\n * @do Add new token patterns or transformation rules here\n * @dont Import from CLI or UI; access filesystem\n */\n\nconst TOKEN_REGEX = /\\{frontmatter\\.([a-zA-Z0-9_.]+)\\}/g;\n\n/**\n * Replaces `{frontmatter.X}` tokens in the body with values from the data object.\n * Supports dot-notation for nested values (e.g. `{frontmatter.author.name}`).\n */\nexport function bindFrontmatter(body: string, data: Record<string, unknown>): string {\n return body.replace(TOKEN_REGEX, (_match, path: string) => {\n const value = resolvePath(data, path);\n if (value === undefined || value === null) return _match;\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n });\n}\n\n/**\n * Extracts all frontmatter token paths from the body.\n */\nexport function extractFrontmatterTokens(body: string): string[] {\n const tokens: string[] = [];\n let match: RegExpExecArray | null;\n const regex = new RegExp(TOKEN_REGEX.source, \"g\");\n while ((match = regex.exec(body)) !== null) {\n tokens.push(match[1]!);\n }\n return tokens;\n}\n\nfunction resolvePath(obj: Record<string, unknown>, path: string): unknown {\n const keys = path.split(\".\");\n let current: unknown = obj;\n for (const key of keys) {\n if (typeof current !== \"object\" || current === null) return undefined;\n current = (current as Record<string, unknown>)[key];\n }\n return current;\n}\n","/**\n * @context Core layer — JSON parser at src/core/parsers/parser-json.ts\n * @does Parses JSON content strings into typed ParsedJson results (array or object)\n * @depends none\n * @do Extend ParsedJson variants here if new JSON structures are supported\n * @dont Access the filesystem; import from CLI or UI; contain serialization logic\n */\n\nexport interface ParsedJsonArray {\n type: \"json-array\";\n entries: Record<string, unknown>[];\n}\n\nexport interface ParsedJsonObject {\n type: \"json-object\";\n data: Record<string, unknown>;\n}\n\nexport type ParsedJson = ParsedJsonArray | ParsedJsonObject;\n\nexport function parseJson(content: string): ParsedJson {\n const parsed: unknown = JSON.parse(content);\n\n if (Array.isArray(parsed)) {\n return {\n type: \"json-array\",\n entries: parsed as Record<string, unknown>[],\n };\n }\n\n if (typeof parsed === \"object\" && parsed !== null) {\n return {\n type: \"json-object\",\n data: parsed as Record<string, unknown>,\n };\n }\n\n throw new Error(\"JSON content must be an array or object\");\n}\n","/**\n * @context Core layer — schema inferrer at src/core/schema-inferrer.ts\n * @does Infers a CollectionSchema from actual content entries when no manual schema is defined\n * @depends src/shared/types.ts, src/shared/fields.ts\n * @do Add new type detection heuristics here (e.g. color, phone)\n * @dont Import from CLI or UI; access the filesystem; perform I/O\n */\n\nimport type { ContentEntry } from \"../shared/types.js\";\nimport type { CollectionSchema, FieldDefinition, SelectOption } from \"../shared/fields.js\";\n\n// Value detector patterns\nconst RE_ISO_DATE = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst RE_ISO_DATETIME =\n /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?$/;\nconst RE_EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nconst RE_URL = /^https?:\\/\\/.+/;\nconst LONG_TEXT_THRESHOLD = 200;\nconst RICH_TEXT_FIELD_NAMES = [\"description\", \"descriptions\", \"text\", \"content\"];\n\nfunction isISODate(value: string): boolean {\n return RE_ISO_DATE.test(value);\n}\n\nfunction isISODateTime(value: string): boolean {\n return RE_ISO_DATETIME.test(value);\n}\n\nfunction isEmail(value: string): boolean {\n return RE_EMAIL.test(value);\n}\n\nfunction isUrl(value: string): boolean {\n return RE_URL.test(value);\n}\n\nfunction inferStringField(name: string, strings: string[]): FieldDefinition {\n if (strings.every(isEmail)) return { name, type: \"email\" };\n if (strings.every(isUrl)) return { name, type: \"url\" };\n if (strings.every(isISODateTime)) return { name, type: \"date\", includeTime: true };\n if (strings.every(isISODate)) return { name, type: \"date\" };\n\n // Fields with well-known names are always treated as long/rich text\n if (RICH_TEXT_FIELD_NAMES.includes(name.toLowerCase())) return { name, type: \"long-text\" };\n\n const isLong = strings.some((s) => s.length > LONG_TEXT_THRESHOLD || s.includes(\"\\n\"));\n return { name, type: isLong ? \"long-text\" : \"text\" };\n}\n\nfunction inferArrayField(name: string, items: unknown[]): FieldDefinition {\n if (items.length === 0) return { name, type: \"array\", itemFields: [] };\n\n if (items.every((item) => typeof item === \"string\")) {\n const unique = [...new Set(items as string[])].slice(0, 50);\n const options: SelectOption[] = unique.map((v) => ({ label: v, value: v }));\n return { name, type: \"multi-select\", options };\n }\n\n if (items.every((item) => typeof item === \"object\" && item !== null && !Array.isArray(item))) {\n return { name, type: \"array\", itemFields: inferFields(items as Record<string, unknown>[]) };\n }\n\n return { name, type: \"array\", itemFields: [] };\n}\n\nfunction inferFieldDefinition(name: string, values: unknown[]): FieldDefinition {\n const present = values.filter((v) => v !== null && v !== undefined);\n\n if (present.length === 0) return { name, type: \"text\" };\n if (present.every((v) => typeof v === \"boolean\")) return { name, type: \"boolean\" };\n\n if (present.every((v) => typeof v === \"number\")) {\n const format = present.every((v) => Number.isInteger(v)) ? \"integer\" : \"decimal\";\n return { name, type: \"number\", format };\n }\n\n if (present.every((v) => typeof v === \"string\")) {\n return inferStringField(name, present as string[]);\n }\n\n if (present.every((v) => Array.isArray(v))) {\n return inferArrayField(name, (present as unknown[][]).flat());\n }\n\n if (present.every((v) => typeof v === \"object\" && v !== null && !Array.isArray(v))) {\n return { name, type: \"object\", fields: inferFields(present as Record<string, unknown>[]) };\n }\n\n return { name, type: \"text\" };\n}\n\nfunction inferFields(rows: Record<string, unknown>[]): FieldDefinition[] {\n const keySet = new Set<string>(rows.flatMap((row) => Object.keys(row)));\n return Array.from(keySet).map((key) => inferFieldDefinition(key, rows.map((row) => row[key])));\n}\n\n/**\n * Infer a `CollectionSchema` from the data of a set of content entries.\n *\n * The result is a best-effort approximation — string fields that look like\n * emails, URLs, or ISO dates get the correct semantic type. Everything else\n * falls back to `text`.\n */\nexport function inferSchema(entries: ContentEntry[], collectionName: string): CollectionSchema {\n const rows = entries.map((entry) => entry.data as Record<string, unknown>);\n return { collection: collectionName, fields: inferFields(rows) };\n}\n","/**\n * @context Core layer — locale parser at src/core/locale-parser.ts\n * @does Extracts locale codes from filenames using the convention `slug.locale.mdx`\n * @depends none\n * @do Add new locale detection strategies here\n * @dont Import from CLI or UI; access filesystem\n */\n\nconst LOCALE_REGEX = /\\.([a-z]{2}(?:-[A-Z]{2})?)\\.mdx$/;\n\n/**\n * Parses locale from a filename.\n * Supports `post.pt.mdx`, `post.en-US.mdx` patterns.\n * Returns undefined for files without a locale suffix.\n */\nexport function parseLocaleFromFilename(filename: string): string | undefined {\n const match = LOCALE_REGEX.exec(filename);\n return match?.[1];\n}\n\n/**\n * Removes the locale suffix from a slug.\n * Handles both pre-slugify (`.pt`) and post-slugify (`-pt`) formats,\n * since `@sindresorhus/slugify` converts dots to dashes.\n * `post.pt` → `post`, `post-pt` → `post`, `post` → `post`\n */\nexport function stripLocaleFromSlug(slug: string, locale?: string): string {\n if (!locale) return slug;\n const dotSuffix = `.${locale}`;\n if (slug.endsWith(dotSuffix)) return slug.slice(0, -dotSuffix.length);\n const dashSuffix = `-${locale}`;\n if (slug.endsWith(dashSuffix)) return slug.slice(0, -dashSuffix.length);\n return slug;\n}\n","/**\n * @context Core layer — content store at src/core/content-store.ts\n * @does Manages a singleton ContentIndex; exposes loadContent() and getStore() for consumers\n * @depends src/core/indexer.ts, src/shared/types.ts\n * @do Use this as the single access point for in-memory indexed content\n * @dont Import from CLI or UI; contain parsing or I/O logic; import fs-adapter at top level\n */\n\nimport type { IFsAdapter } from \"../shared/fs-adapter.interface.js\";\nimport type { StudioConfig } from \"../shared/types.js\";\nimport { ContentIndex } from \"./indexer.js\";\n\nlet store: ContentIndex | null = null;\n\nexport function getStore(): ContentIndex {\n if (!store) {\n throw new Error(\n \"Content not loaded. Auto-init requires 'nextjs-studio/server' — \" +\n \"use loadContentSync() in a server context, or queryCollection() \" +\n \"will auto-init when imported from 'nextjs-studio/server'.\",\n );\n }\n return store;\n}\n\nexport function setStore(index: ContentIndex): void {\n store = index;\n}\n\nexport function hasStore(): boolean {\n return store !== null;\n}\n\nexport async function loadContent(\n fsAdapter: IFsAdapter,\n config?: StudioConfig,\n): Promise<ContentIndex> {\n const index = new ContentIndex(fsAdapter);\n await index.build(config);\n store = index;\n return index;\n}\n\nexport function loadContentSync(\n fsAdapter: IFsAdapter,\n config?: StudioConfig,\n): ContentIndex {\n const index = new ContentIndex(fsAdapter);\n index.buildSync(config);\n store = index;\n return index;\n}\n","/**\n * @context Core layer — type generator at src/core/type-generator.ts\n * @does Converts CollectionSchema definitions into TypeScript declaration strings for .d.ts output\n * @depends src/shared/fields.ts\n * @do Add new field-to-type mappings here as new field types are introduced\n * @dont Import from CLI or UI; access the filesystem; perform I/O\n */\n\nimport type { FieldDefinition, CollectionSchema } from \"../shared/fields.js\";\n\nfunction indent(code: string, spaces = 2): string {\n return code\n .split(\"\\n\")\n .map((line) => (line.trim() === \"\" ? \"\" : \" \".repeat(spaces) + line))\n .join(\"\\n\");\n}\n\nfunction toPascalCase(str: string): string {\n return str\n .replace(/[-_\\s]+(.)/g, (_, c: string) => c.toUpperCase())\n .replace(/^(.)/, (_, c: string) => c.toUpperCase());\n}\n\nfunction fieldToTsType(field: FieldDefinition): string {\n switch (field.type) {\n case \"text\":\n case \"long-text\":\n return \"string\";\n\n case \"email\":\n return \"Email\";\n\n case \"url\":\n return \"HttpUrl\";\n\n case \"media\":\n return \"MediaPath\";\n\n case \"id\":\n return \"ID\";\n\n case \"slug\":\n return \"Slug\";\n\n case \"date\":\n return field.includeTime ? \"Date\" : \"ISODate\";\n\n case \"created-time\":\n case \"updated-time\":\n return \"Date\";\n\n case \"number\":\n return \"number\";\n\n case \"boolean\":\n return \"boolean\";\n\n case \"select\":\n case \"status\": {\n const values = field.options.map((o) => JSON.stringify(o.value));\n return values.length > 0 ? values.join(\" | \") : \"string\";\n }\n\n case \"multi-select\": {\n const values = field.options.map((o) => JSON.stringify(o.value));\n const union = values.length > 0 ? values.join(\" | \") : \"string\";\n return `Array<${union}>`;\n }\n\n case \"object\":\n return generateObjectType(field.fields);\n\n case \"array\":\n return `Array<${generateObjectType(field.itemFields)}>`;\n\n case \"relation\":\n return field.multiple === true ? \"ID[]\" : \"ID\";\n\n case \"formula\":\n if (field.resultType === \"number\") return \"number\";\n if (field.resultType === \"boolean\") return \"boolean\";\n return \"string\";\n\n default:\n return \"unknown\";\n }\n}\n\nfunction generateObjectType(fields: FieldDefinition[]): string {\n if (fields.length === 0) return \"Record<string, unknown>\";\n\n const lines = fields.map((field) => {\n const optional = field.required === false ? \"?\" : \"\";\n const tsType = fieldToTsType(field);\n const comment = field.description ? `/** ${field.description} */\\n` : \"\";\n return `${comment}${field.name}${optional}: ${tsType};`;\n });\n\n return `{\\n${indent(lines.join(\"\\n\"))}\\n}`;\n}\n\nexport function generateInterfaceForSchema(schema: CollectionSchema): string {\n const name = toPascalCase(schema.collection) + \"Entry\";\n const label = schema.label ?? schema.collection;\n const body = generateObjectType(schema.fields);\n return `/** Data shape for the \"${label}\" collection. */\\nexport interface ${name} ${body}`;\n}\n\n/**\n * Generate a complete TypeScript declaration file for all provided schemas.\n *\n * @example\n * ```ts\n * const code = generateCollectionTypes([blogSchema, authorSchema]);\n * await fs.writeFile(\".studio/types.d.ts\", code, \"utf-8\");\n * ```\n */\nexport function generateCollectionTypes(schemas: CollectionSchema[]): string {\n const banner = [\n \"// This file is auto-generated by nextjs-studio.\",\n \"// Do not edit manually — re-run `npx nextjs-studio --generate-types` to update.\",\n \"\",\n \"// Branded scalar types — structurally strings/numbers but semantically distinct.\",\n \"declare const __brand: unique symbol;\",\n \"type Brand<T, B extends string> = T & { readonly [__brand]: B };\",\n \"\",\n \"export type Email = Brand<string, 'Email'>;\",\n \"export type HttpUrl = Brand<string, 'HttpUrl'>;\",\n \"export type ISODate = Brand<string, 'ISODate'>;\",\n \"export type MediaPath = Brand<string, 'MediaPath'>;\",\n \"export type ID = Brand<string, 'ID'>;\",\n \"export type Slug = Brand<string, 'Slug'>;\",\n ].join(\"\\n\");\n\n const interfaces = schemas.map(generateInterfaceForSchema).join(\"\\n\\n\");\n\n const collectionRegistry = [\n \"// Augment both entry points so queryCollection() is fully typed regardless of import path.\",\n \"declare module 'nextjs-studio' {\",\n \" interface CollectionTypeMap {\",\n schemas.map((schema) => ` ${JSON.stringify(schema.collection)}: ${toPascalCase(schema.collection)}Entry;`).join(\"\\n\"),\n \" }\",\n \"}\",\n \"declare module 'nextjs-studio/server' {\",\n \" interface CollectionTypeMap {\",\n schemas.map((schema) => ` ${JSON.stringify(schema.collection)}: ${toPascalCase(schema.collection)}Entry;`).join(\"\\n\"),\n \" }\",\n \"}\",\n ].join(\"\\n\");\n\n return [banner, interfaces, collectionRegistry].join(\"\\n\\n\") + \"\\n\";\n}\n","/**\n * @context Core layer — config loader at src/core/config-loader.ts\n * @does Resolves and loads studio.config.ts/.js from the project root using dynamic import\n * @depends src/shared/constants.ts, src/shared/types.ts\n * @do Add new config resolution strategies or validation here\n * @dont Import from CLI or UI; access content files\n */\n\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { StudioConfig } from \"../shared/types.js\";\nimport { CONFIG_FILENAMES } from \"../shared/constants.js\";\n\n/**\n * Resolves the config file path from the project root.\n * Returns undefined if no config file is found.\n */\nexport function resolveConfigPath(projectRoot: string): string | undefined {\n for (const filename of CONFIG_FILENAMES) {\n const fullPath = path.resolve(projectRoot, filename);\n if (existsSync(fullPath)) return fullPath;\n }\n return undefined;\n}\n\n/**\n * Loads the studio config from the project root.\n * Tries CONFIG_FILENAMES in order, uses dynamic import().\n * Returns empty config if no file found or loading fails.\n */\nexport async function loadStudioConfig(projectRoot: string): Promise<StudioConfig> {\n const configPath = resolveConfigPath(projectRoot);\n if (!configPath) return {};\n\n return loadConfigFromPath(configPath);\n}\n\n/**\n * Loads config from a specific file path.\n */\nexport async function loadConfigFromPath(configPath: string): Promise<StudioConfig> {\n try {\n const fileUrl = pathToFileURL(configPath).href;\n const mod = await import(/* webpackIgnore: true */ fileUrl);\n const config = mod.default ?? mod.config ?? mod;\n\n if (typeof config !== \"object\" || config === null || Array.isArray(config)) {\n return {};\n }\n\n return config as StudioConfig;\n } catch {\n return {};\n }\n}\n","{\n \"name\": \"nextjs-studio\",\n \"version\": \"1.0.0\",\n \"description\": \"A Git-based, local-first CMS for Next.js projects\",\n \"keywords\": [\n \"nextjs\",\n \"cms\",\n \"mdx\",\n \"content\",\n \"studio\",\n \"static-site\",\n \"local-first\"\n ],\n \"homepage\": \"https://github.com/TiagoDanin/Nextjs-Studio\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/TiagoDanin/Nextjs-Studio.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"Tiago Danin\",\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/core/index.d.ts\",\n \"import\": \"./dist/core/index.js\"\n },\n \"./server\": {\n \"types\": \"./dist/core/server.d.ts\",\n \"import\": \"./dist/core/server.js\"\n }\n },\n \"main\": \"./dist/core/index.js\",\n \"types\": \"./dist/core/index.d.ts\",\n \"bin\": \"dist/bin/nextjs-studio.js\",\n \"files\": [\n \"dist/bin\",\n \"dist/core\",\n \"dist/*.d.ts\",\n \"dist/cli/ui/package.json\",\n \"dist/cli/ui/next.config.js\",\n \"dist/cli/ui/.next/static\",\n \"dist/cli/ui/.next/server\",\n \"dist/cli/ui/.next/BUILD_ID\",\n \"dist/cli/ui/.next/app-path-routes-manifest.json\",\n \"dist/cli/ui/.next/build-manifest.json\",\n \"dist/cli/ui/.next/export-marker.json\",\n \"dist/cli/ui/.next/images-manifest.json\",\n \"dist/cli/ui/.next/next-minimal-server.js.nft.json\",\n \"dist/cli/ui/.next/next-server.js.nft.json\",\n \"dist/cli/ui/.next/package.json\",\n \"dist/cli/ui/.next/prerender-manifest.json\",\n \"dist/cli/ui/.next/react-loadable-manifest.json\",\n \"dist/cli/ui/.next/required-server-files.js\",\n \"dist/cli/ui/.next/required-server-files.json\",\n \"dist/cli/ui/.next/routes-manifest.json\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"dev\": \"tsx src/bin/nextjs-studio.ts --dir example/contents\",\n \"studio:dev\": \"cross-env STUDIO_CONTENTS_DIR=example/contents next dev --port 3030 --webpack src/cli/ui\",\n \"studio:build\": \"next build --webpack src/cli/ui && node -e \\\"const fs=require('fs');fs.copyFileSync('src/cli/ui/package.json','dist/cli/ui/package.json');fs.writeFileSync('dist/cli/ui/next.config.js','module.exports={distDir:\\\\'.next\\\\'};')\\\"\",\n \"build\": \"tsup && yarn studio:build\",\n \"lint\": \"eslint src/\",\n \"type-check\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\"\n },\n \"engines\": {\n \"node\": \">=22.10.0\"\n },\n \"packageManager\": \"yarn@4.6.0\",\n \"devDependencies\": {\n \"@radix-ui/react-collapsible\": \"^1.1.12\",\n \"@radix-ui/react-label\": \"^2.1.8\",\n \"@radix-ui/react-switch\": \"^1.2.6\",\n \"@tailwindcss/postcss\": \"^4.1.18\",\n \"@tanstack/react-table\": \"^8.21.3\",\n \"@tiptap/extension-bubble-menu\": \"^3.20.0\",\n \"@tiptap/extension-code-block-lowlight\": \"^3.20.0\",\n \"@tiptap/extension-file-handler\": \"^3.20.0\",\n \"@tiptap/extension-image\": \"^3.20.0\",\n \"@tiptap/extension-link\": \"^3.20.0\",\n \"@tiptap/extension-placeholder\": \"^3.20.0\",\n \"@tiptap/react\": \"^3.20.0\",\n \"@tiptap/starter-kit\": \"^3.20.0\",\n \"@tiptap/suggestion\": \"^3.20.0\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/node\": \"^25.2.3\",\n \"@types/react\": \"^19\",\n \"@types/react-dom\": \"^19\",\n \"class-variance-authority\": \"^0.7.1\",\n \"clsx\": \"^2.1.1\",\n \"cross-env\": \"^10.1.0\",\n \"eslint\": \"^10.0.0\",\n \"lowlight\": \"^3.3.0\",\n \"lucide-react\": \"^0.574.0\",\n \"mermaid\": \"^11.6.0\",\n \"next-themes\": \"^0.4.6\",\n \"tailwind-merge\": \"^3.4.1\",\n \"tailwindcss\": \"^4.1.18\",\n \"tippy.js\": \"^6.3.7\",\n \"tiptap-extension-global-drag-handle\": \"^0.1.18\",\n \"tiptap-markdown\": \"^0.9.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.0.18\",\n \"zustand\": \"^5.0.11\"\n },\n \"dependencies\": {\n \"@sindresorhus/slugify\": \"^3.0.0\",\n \"chokidar\": \"^5.0.0\",\n \"commander\": \"^14.0.3\",\n \"gray-matter\": \"^4.0.3\",\n \"lodash-es\": \"^4.17.23\",\n \"next\": \"^16.1.6\",\n \"react\": \"^19.2.4\",\n \"react-dom\": \"^19.2.4\"\n }\n}"],"mappings":"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","names":["existsSync","fs","path","path","path","path","path","configPath","path","fs","uiDir","existsSync","require"]}
1
+ {"version":3,"sources":["../../src/bin/nextjs-studio.ts","../../src/shared/constants.ts","../../src/core/fs-adapter.ts","../../src/core/indexer.ts","../../src/core/parsers/parser-mdx.ts","../../src/core/frontmatter-binder.ts","../../src/core/parsers/parser-json.ts","../../src/core/schema-inferrer.ts","../../src/core/locale-parser.ts","../../src/core/content-store.ts","../../src/core/type-generator.ts","../../src/core/config-loader.ts","../../package.json"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * @context bin layer — CLI entry point at src/bin/nextjs-studio.ts\n * @does Parses CLI args, then either generates types or spawns the UI server process\n * @depends src/shared/constants.ts, src/cli/adapters/fs-adapter.ts, src/core/content-store.ts, src/core/type-generator.ts\n * @do Add new CLI flags here; keep only process bootstrap logic\n * @dont Import UI components or contain parsing/indexing business logic\n */\n\nimport { existsSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { Command } from \"commander\";\nimport { CLI_PORT, CONTENTS_DIR } from \"../shared/constants.js\";\nimport { FsAdapter } from \"../core/fs-adapter.js\";\nimport { loadContent } from \"../core/content-store.js\";\nimport { generateCollectionTypes } from \"../core/type-generator.js\";\nimport { loadStudioConfig, resolveConfigPath } from \"../core/config-loader.js\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\n\nconst { version } = pkg;\n\nconst program = new Command()\n .name(\"Nextjs Studio\")\n .description(\"Local-first CMS for Next.js projects\")\n .version(version)\n .option(\"-d, --dir <path>\", \"Path to contents directory\", CONTENTS_DIR)\n .option(\"-p, --port <number>\", \"Port to run the studio on\", String(CLI_PORT))\n .option(\"--generate-types\", \"Generate TypeScript types for content collections\")\n .parse();\n\nconst opts = program.opts<{ dir: string; port: string; generateTypes?: boolean }>();\nconst contentsDir = path.resolve(opts.dir);\nconst port = Number(opts.port);\n\nasync function runGenerateTypes(sourceDir: string): Promise<void> {\n const outDir = path.resolve(\".studio\");\n const outFile = path.join(outDir, \"studio.d.ts\");\n\n console.log(`Generating types from ${sourceDir}...`);\n\n const config = await loadStudioConfig(process.cwd());\n const fsAdapter = new FsAdapter(sourceDir);\n const index = await loadContent(fsAdapter, config);\n const schemas = index.getCollections().flatMap((c) => (c.schema ? [c.schema] : []));\n const code = generateCollectionTypes(schemas);\n\n await fs.mkdir(outDir, { recursive: true });\n await fs.writeFile(outFile, code, \"utf-8\");\n\n console.log(`Types written to ${outFile}`);\n}\n\nfunction resolveServerProcess(\n uiDir: string,\n serverPort: number,\n env: NodeJS.ProcessEnv,\n): ChildProcess | null {\n // Production: .next build output present — run via `next start`\n const buildId = path.resolve(uiDir, \".next/BUILD_ID\");\n if (existsSync(buildId)) {\n // next is a peerDependency — use the consumer project's installation\n const require = createRequire(import.meta.url);\n const nextBin = require.resolve(\"next/dist/bin/next\");\n return spawn(\"node\", [nextBin, \"start\", \"--port\", String(serverPort)], {\n cwd: uiDir,\n stdio: \"inherit\",\n env,\n });\n }\n\n // Dev mode: UI source present (running from repo with `yarn dev`)\n const uiPackageJson = path.resolve(uiDir, \"package.json\");\n if (existsSync(uiPackageJson)) {\n // Resolve `next` bin from workspace root (3 levels up from src/cli/ui)\n const nextBin = path.resolve(uiDir, \"../../../node_modules/next/dist/bin/next\");\n return spawn(\"node\", [nextBin, \"dev\", \"--port\", String(serverPort), \"--webpack\"], {\n cwd: uiDir,\n stdio: \"inherit\",\n env,\n });\n }\n\n return null;\n}\n\nfunction forwardSignals(child: ChildProcess): void {\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n process.on(signal, () => child.kill(signal));\n }\n}\n\nif (opts.generateTypes) {\n await runGenerateTypes(contentsDir);\n process.exit(0);\n}\n\nconst uiDir = path.resolve(import.meta.dirname, \"../cli/ui\");\nconst configPath = resolveConfigPath(process.cwd());\nconst serverEnv: NodeJS.ProcessEnv = {\n ...process.env,\n STUDIO_CONTENTS_DIR: contentsDir,\n STUDIO_PROJECT_DIR: process.cwd(),\n PORT: String(port),\n HOSTNAME: \"0.0.0.0\",\n ...(configPath ? { STUDIO_CONFIG_PATH: configPath } : {}),\n};\nconst serverProcess = resolveServerProcess(uiDir, port, serverEnv);\n\nif (!serverProcess) {\n console.error(\"Error: Studio UI server not found.\");\n console.error(\"The pre-built UI is not included in this installation.\");\n process.exit(1);\n}\n\nconsole.log(`Nextjs Studio v${version}`);\nconsole.log(`Contents: ${contentsDir}`);\nconsole.log(`Starting on http://localhost:${port}`);\n\nserverProcess.on(\"error\", (error) => {\n console.error(\"Failed to start server:\", error.message);\n process.exit(1);\n});\n\nserverProcess.on(\"close\", (code) => process.exit(code ?? 0));\n\nforwardSignals(serverProcess);\n","/**\n * @context Shared layer — constants at src/shared/constants.ts\n * @does Defines project-wide constants shared across core, CLI, and UI layers\n * @depends none\n * @do Add new shared constants here\n * @dont Import from CLI or UI; constants must be framework-agnostic\n */\n\nexport const CONTENTS_DIR = \"contents\";\nexport const CLI_PORT = 3030;\nexport const CONFIG_FILE = \"studio.config.ts\";\nexport const CONFIG_FILENAMES = [\"studio.config.ts\", \"studio.config.js\", \"studio.config.mjs\"] as const;\nexport const SUPPORTED_EXTENSIONS = [\".mdx\", \".json\"] as const;\nexport const COLLECTION_ORDER_FILE = \"collection.json\";\nexport const WATCHER_DEBOUNCE_MS = 5_000;\nexport const MEDIA_DIR = \"media\";\n\nexport const IMAGE_MIME_TYPES = [\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"image/svg+xml\",\n \"image/avif\",\n] as const;\n\nexport const VIDEO_MIME_TYPES = [\"video/mp4\", \"video/webm\", \"video/ogg\"] as const;\n\nexport const AUDIO_MIME_TYPES = [\n \"audio/mpeg\",\n \"audio/ogg\",\n \"audio/wav\",\n \"audio/webm\",\n \"audio/aac\",\n \"audio/flac\",\n] as const;\n\nexport const MEDIA_MIME_TYPES = [...IMAGE_MIME_TYPES, ...VIDEO_MIME_TYPES, ...AUDIO_MIME_TYPES] as const;\n\nexport const IMAGE_EXTENSIONS = [\".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\", \".svg\", \".avif\"] as const;\nexport const VIDEO_EXTENSIONS = [\".mp4\", \".webm\", \".ogv\"] as const;\nexport const AUDIO_EXTENSIONS = [\".mp3\", \".ogg\", \".wav\", \".m4a\", \".aac\", \".flac\"] as const;\n","/**\n * @context Core layer — filesystem adapter at src/core/fs-adapter.ts\n * @does Implements IFsAdapter; abstracts all file read/write/list operations behind a single interface\n * @depends src/shared/types.ts, src/shared/constants.ts, src/shared/fs-adapter.interface.ts\n * @do Add new I/O operations here; all file access must go through this adapter\n * @dont Import UI components, run HTTP requests, or contain business logic\n */\n\nimport fs from \"node:fs/promises\";\nimport fsSync from \"node:fs\";\nimport path from \"node:path\";\nimport type { Dirent } from \"node:fs\";\nimport type { FileInfo, DirectoryFileEntry } from \"../shared/types.js\";\nimport type { IFsAdapter } from \"../shared/fs-adapter.interface.js\";\nimport { SUPPORTED_EXTENSIONS } from \"../shared/constants.js\";\n\nexport class FsAdapter implements IFsAdapter {\n private readonly basePath: string;\n\n constructor(basePath: string) {\n this.basePath = path.resolve(basePath);\n }\n\n private resolve(...segments: string[]): string {\n return path.resolve(this.basePath, ...segments);\n }\n\n async readFile(filePath: string): Promise<string> {\n return fs.readFile(this.resolve(filePath), \"utf-8\");\n }\n\n async writeFile(filePath: string, content: string): Promise<void> {\n const fullPath = this.resolve(filePath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, content, \"utf-8\");\n }\n\n async deleteFile(filePath: string): Promise<void> {\n await fs.unlink(this.resolve(filePath));\n }\n\n async exists(filePath: string): Promise<boolean> {\n try {\n await fs.access(this.resolve(filePath));\n return true;\n } catch {\n return false;\n }\n }\n\n async getStats(filePath: string): Promise<FileInfo> {\n const fullPath = this.resolve(filePath);\n const stats = await fs.stat(fullPath);\n return { path: filePath, size: stats.size, modifiedAt: stats.mtime };\n }\n\n async listFiles(dirPath: string, extensions?: readonly string[]): Promise<string[]> {\n const fullPath = this.resolve(dirPath);\n const filterExts = extensions ?? SUPPORTED_EXTENSIONS;\n\n let entries: Dirent[];\n try {\n entries = await fs.readdir(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n return entries\n .filter((entry) => entry.isFile() && filterExts.some((ext) => entry.name.endsWith(ext)))\n .map((entry) => this.join(dirPath, entry.name));\n }\n\n async listDirectories(dirPath: string): Promise<string[]> {\n const fullPath = this.resolve(dirPath);\n\n let entries: Dirent[];\n try {\n entries = await fs.readdir(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => this.join(dirPath, entry.name));\n }\n\n async readBuffer(filePath: string): Promise<Buffer> {\n return fs.readFile(this.resolve(filePath));\n }\n\n async writeBuffer(filePath: string, data: Buffer): Promise<void> {\n const fullPath = this.resolve(filePath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, data);\n }\n\n async listAllFiles(dirPath: string): Promise<DirectoryFileEntry[]> {\n const fullPath = this.resolve(dirPath);\n\n let entries: Dirent[];\n try {\n entries = await fs.readdir(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n const results: DirectoryFileEntry[] = [];\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n const relativePath = this.join(dirPath, entry.name);\n const stats = await fs.stat(this.resolve(relativePath));\n results.push({ name: entry.name, relativePath, size: stats.size, modifiedAt: stats.mtime });\n }\n return results;\n }\n\n join(...segments: string[]): string {\n return path.join(...segments);\n }\n\n basename(filePath: string): string {\n return path.basename(filePath);\n }\n\n extname(filePath: string): string {\n return path.extname(filePath);\n }\n\n relative(from: string, to: string): string {\n return path.relative(from, to);\n }\n\n normalizeSlug(relativePath: string, ext: string): string {\n return relativePath.replace(ext, \"\").split(path.sep).join(\"/\");\n }\n\n readFileSync(filePath: string): string {\n return fsSync.readFileSync(this.resolve(filePath), \"utf-8\");\n }\n\n existsSync(filePath: string): boolean {\n return fsSync.existsSync(this.resolve(filePath));\n }\n\n listFilesSync(dirPath: string, extensions?: readonly string[]): string[] {\n const fullPath = this.resolve(dirPath);\n const filterExts = extensions ?? SUPPORTED_EXTENSIONS;\n\n let entries: Dirent[];\n try {\n entries = fsSync.readdirSync(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n return entries\n .filter((entry) => entry.isFile() && filterExts.some((ext) => entry.name.endsWith(ext)))\n .map((entry) => this.join(dirPath, entry.name));\n }\n\n listDirectoriesSync(dirPath: string): string[] {\n const fullPath = this.resolve(dirPath);\n\n let entries: Dirent[];\n try {\n entries = fsSync.readdirSync(fullPath, { withFileTypes: true });\n } catch {\n return [];\n }\n\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => this.join(dirPath, entry.name));\n }\n}\n","/**\n * @context Core layer — content indexer at src/core/indexer.ts\n * @does Scans the contents directory, parses MDX/JSON files, and builds an in-memory index\n * @depends src/shared/types.ts, src/shared/constants.ts, src/shared/fs-adapter.interface.ts, src/core/parsers/, src/core/schema-inferrer.ts\n * @do Add new file type handling here; extend indexCollection for new collection behaviors\n * @dont Import from CLI or UI; instantiate FsAdapter; access the filesystem directly\n */\n\nimport slugify from \"@sindresorhus/slugify\";\nimport type { CollectionSchema } from \"../shared/fields.js\";\nimport type { ContentEntry, Collection, StudioConfig } from \"../shared/types.js\";\nimport type { IFsAdapter } from \"../shared/fs-adapter.interface.js\";\nimport { COLLECTION_ORDER_FILE } from \"../shared/constants.js\";\nimport { parseMdx } from \"./parsers/parser-mdx.js\";\nimport { parseJson } from \"./parsers/parser-json.js\";\nimport { inferSchema } from \"./schema-inferrer.js\";\nimport { parseLocaleFromFilename, stripLocaleFromSlug } from \"./locale-parser.js\";\n\nexport class ContentIndex {\n private readonly entries = new Map<string, ContentEntry[]>();\n private readonly collections = new Map<string, Collection>();\n private readonly fs: IFsAdapter;\n\n constructor(fsAdapter: IFsAdapter) {\n this.fs = fsAdapter;\n }\n\n async build(config?: StudioConfig): Promise<void> {\n this.clear();\n const dirs = await this.fs.listDirectories(\".\");\n\n for (const dir of dirs) {\n const dirName = this.fs.basename(dir);\n const collectionName = slugify(dirName);\n const collectionConfig = config?.collections?.[collectionName];\n await this.indexCollection(dirName, collectionName, collectionConfig?.schema);\n }\n }\n\n buildSync(config?: StudioConfig): void {\n this.clear();\n const dirs = this.fs.listDirectoriesSync(\".\");\n\n for (const dir of dirs) {\n const dirName = this.fs.basename(dir);\n const collectionName = slugify(dirName);\n const collectionConfig = config?.collections?.[collectionName];\n this.indexCollectionSync(dirName, collectionName, collectionConfig?.schema);\n }\n }\n\n getCollection(name: string): ContentEntry[] {\n return this.entries.get(name) ?? [];\n }\n\n getCollections(): Collection[] {\n return Array.from(this.collections.values());\n }\n\n clear(): void {\n this.entries.clear();\n this.collections.clear();\n }\n\n updateEntry(collectionName: string, entry: ContentEntry): void {\n const entries = this.entries.get(collectionName) ?? [];\n const idx = entries.findIndex((e) => e.slug === entry.slug);\n if (idx >= 0) {\n entries[idx] = entry;\n } else {\n entries.push(entry);\n }\n this.entries.set(collectionName, entries);\n this.updateCollectionMeta(collectionName);\n }\n\n removeEntry(collectionName: string, slug: string): void {\n const entries = this.entries.get(collectionName);\n if (!entries) return;\n const filtered = entries.filter((e) => e.slug !== slug);\n this.entries.set(collectionName, filtered);\n this.updateCollectionMeta(collectionName);\n }\n\n private updateCollectionMeta(collectionName: string): void {\n const col = this.collections.get(collectionName);\n const entries = this.entries.get(collectionName) ?? [];\n if (col) {\n this.collections.set(collectionName, {\n ...col,\n count: entries.length,\n type: this.detectCollectionType(entries),\n });\n }\n }\n\n private async indexCollection(\n dirName: string,\n collectionName: string,\n manualSchema?: CollectionSchema,\n ): Promise<void> {\n const entries: ContentEntry[] = [];\n await this.scanDir(dirName, collectionName, dirName, entries);\n\n const orderPath = this.fs.join(dirName, COLLECTION_ORDER_FILE);\n const ordering = await this.readOrdering(orderPath);\n if (ordering) {\n this.applyOrdering(entries, ordering);\n }\n\n const schema = manualSchema ?? inferSchema(entries, collectionName);\n\n this.entries.set(collectionName, entries);\n this.collections.set(collectionName, {\n name: collectionName,\n type: this.detectCollectionType(entries),\n count: entries.length,\n basePath: dirName,\n schema,\n });\n }\n\n private indexCollectionSync(\n dirName: string,\n collectionName: string,\n manualSchema?: CollectionSchema,\n ): void {\n const entries: ContentEntry[] = [];\n this.scanDirSync(dirName, collectionName, dirName, entries);\n\n const orderPath = this.fs.join(dirName, COLLECTION_ORDER_FILE);\n const ordering = this.readOrderingSync(orderPath);\n if (ordering) {\n this.applyOrdering(entries, ordering);\n }\n\n const schema = manualSchema ?? inferSchema(entries, collectionName);\n\n this.entries.set(collectionName, entries);\n this.collections.set(collectionName, {\n name: collectionName,\n type: this.detectCollectionType(entries),\n count: entries.length,\n basePath: dirName,\n schema,\n });\n }\n\n private async scanDir(\n dirName: string,\n collectionName: string,\n dirPath: string,\n entries: ContentEntry[],\n ): Promise<void> {\n const subDirs = await this.fs.listDirectories(dirPath);\n for (const subDir of subDirs) {\n await this.scanDir(dirName, collectionName, subDir, entries);\n }\n\n const files = await this.fs.listFiles(dirPath);\n for (const filePath of files) {\n const fileName = this.fs.basename(filePath);\n if (fileName === COLLECTION_ORDER_FILE) continue;\n\n const ext = this.fs.extname(fileName);\n const content = await this.fs.readFile(filePath);\n const relativePath = this.fs.relative(dirName, filePath);\n const slug = this.fs\n .normalizeSlug(relativePath, ext)\n .split(\"/\")\n .map((segment) => slugify(segment))\n .join(\"/\");\n\n if (ext === \".mdx\") {\n entries.push(this.buildMdxEntry(collectionName, slug, fileName, content));\n } else if (ext === \".json\") {\n entries.push(...this.buildJsonEntries(collectionName, slug, content));\n }\n }\n }\n\n private scanDirSync(\n dirName: string,\n collectionName: string,\n dirPath: string,\n entries: ContentEntry[],\n ): void {\n const subDirs = this.fs.listDirectoriesSync(dirPath);\n for (const subDir of subDirs) {\n this.scanDirSync(dirName, collectionName, subDir, entries);\n }\n\n const files = this.fs.listFilesSync(dirPath);\n for (const filePath of files) {\n const fileName = this.fs.basename(filePath);\n if (fileName === COLLECTION_ORDER_FILE) continue;\n\n const ext = this.fs.extname(fileName);\n const content = this.fs.readFileSync(filePath);\n const relativePath = this.fs.relative(dirName, filePath);\n const slug = this.fs\n .normalizeSlug(relativePath, ext)\n .split(\"/\")\n .map((segment) => slugify(segment))\n .join(\"/\");\n\n if (ext === \".mdx\") {\n entries.push(this.buildMdxEntry(collectionName, slug, fileName, content));\n } else if (ext === \".json\") {\n entries.push(...this.buildJsonEntries(collectionName, slug, content));\n }\n }\n }\n\n private buildMdxEntry(collectionName: string, slug: string, fileName: string, content: string): ContentEntry {\n const parsed = parseMdx(content);\n const locale = parseLocaleFromFilename(fileName);\n const normalizedSlug = stripLocaleFromSlug(slug, locale);\n return {\n collection: collectionName,\n slug: normalizedSlug,\n path: `/${collectionName}/${normalizedSlug}`,\n body: parsed.body,\n data: parsed.data,\n ...(locale ? { locale } : {}),\n };\n }\n\n private buildJsonEntries(collectionName: string, slug: string, content: string): ContentEntry[] {\n const parsed = parseJson(content);\n\n if (parsed.type === \"json-array\") {\n return parsed.entries.map((data, index) => {\n const entrySlug =\n typeof data[\"slug\"] === \"string\" ? slugify(data[\"slug\"]) : `${slug}/${index}`;\n return {\n collection: collectionName,\n slug: entrySlug,\n path: `/${collectionName}/${entrySlug}`,\n data,\n };\n });\n }\n\n return [{ collection: collectionName, slug, path: `/${collectionName}/${slug}`, data: parsed.data }];\n }\n\n private async readOrdering(orderPath: string): Promise<string[] | null> {\n if (!(await this.fs.exists(orderPath))) return null;\n\n try {\n const content = await this.fs.readFile(orderPath);\n const parsed: unknown = JSON.parse(content);\n if (Array.isArray(parsed)) return parsed as string[];\n } catch (error) {\n console.warn(`[Nextjs Studio] Failed to parse ordering file: ${orderPath}`, error);\n }\n return null;\n }\n\n private readOrderingSync(orderPath: string): string[] | null {\n if (!this.fs.existsSync(orderPath)) return null;\n\n try {\n const content = this.fs.readFileSync(orderPath);\n const parsed: unknown = JSON.parse(content);\n if (Array.isArray(parsed)) return parsed as string[];\n } catch (error) {\n console.warn(`[Nextjs Studio] Failed to parse ordering file: ${orderPath}`, error);\n }\n return null;\n }\n\n private applyOrdering(entries: ContentEntry[], ordering: string[]): void {\n const orderMap = new Map(ordering.map((slug, index) => [slug, index]));\n entries.sort((a, b) => {\n const aIndex = orderMap.get(a.slug) ?? Infinity;\n const bIndex = orderMap.get(b.slug) ?? Infinity;\n return aIndex - bIndex;\n });\n }\n\n private detectCollectionType(entries: ContentEntry[]): Collection[\"type\"] {\n if (entries.length === 0) return \"mdx\";\n const first = entries[0];\n if (first.body !== undefined) return \"mdx\";\n if (entries.length === 1 && !first.slug.includes(\"/\")) return \"json-object\";\n return \"json-array\";\n }\n}\n","/**\n * @context Core layer — MDX parser/serializer at src/core/parsers/parser-mdx.ts\n * @does Parses .mdx content into frontmatter + body, and serializes them back to MDX strings\n * @depends none (gray-matter is an external dep)\n * @do Add MDX transform steps here; both parse and serialize live here intentionally\n * @dont Access the filesystem; import from CLI or UI; handle JSON content\n */\n\nimport matter from \"gray-matter\";\nimport { bindFrontmatter } from \"../frontmatter-binder.js\";\n\nexport interface ParsedMdx {\n data: Record<string, unknown>;\n body: string;\n}\n\nexport interface ParseMdxOptions {\n /** When true, replaces {frontmatter.X} tokens in the body with actual values. */\n bindTokens?: boolean;\n}\n\n/** Convert Date objects produced by gray-matter back to ISO strings. */\nfunction normalizeDates(data: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (value instanceof Date) {\n result[key] = value.toISOString().split(\"T\")[0];\n } else if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n result[key] = normalizeDates(value as Record<string, unknown>);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nexport function parseMdx(content: string, options?: ParseMdxOptions): ParsedMdx {\n const { data: rawData, content: body } = matter(content);\n const data = normalizeDates(rawData);\n const trimmed = body.trim();\n return {\n data,\n body: options?.bindTokens ? bindFrontmatter(trimmed, data) : trimmed,\n };\n}\n\nexport function serializeMdx(data: Record<string, unknown>, body: string): string {\n return matter.stringify(body, data);\n}\n","/**\n * @context Core layer — frontmatter binder at src/core/frontmatter-binder.ts\n * @does Replaces {frontmatter.X} tokens in MDX body with actual frontmatter values\n * @depends none\n * @do Add new token patterns or transformation rules here\n * @dont Import from CLI or UI; access filesystem\n */\n\nconst TOKEN_REGEX = /\\{frontmatter\\.([a-zA-Z0-9_.]+)\\}/g;\n\n/**\n * Replaces `{frontmatter.X}` tokens in the body with values from the data object.\n * Supports dot-notation for nested values (e.g. `{frontmatter.author.name}`).\n */\nexport function bindFrontmatter(body: string, data: Record<string, unknown>): string {\n return body.replace(TOKEN_REGEX, (_match, path: string) => {\n const value = resolvePath(data, path);\n if (value === undefined || value === null) return _match;\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n });\n}\n\n/**\n * Extracts all frontmatter token paths from the body.\n */\nexport function extractFrontmatterTokens(body: string): string[] {\n const tokens: string[] = [];\n let match: RegExpExecArray | null;\n const regex = new RegExp(TOKEN_REGEX.source, \"g\");\n while ((match = regex.exec(body)) !== null) {\n tokens.push(match[1]!);\n }\n return tokens;\n}\n\nfunction resolvePath(obj: Record<string, unknown>, path: string): unknown {\n const keys = path.split(\".\");\n let current: unknown = obj;\n for (const key of keys) {\n if (typeof current !== \"object\" || current === null) return undefined;\n current = (current as Record<string, unknown>)[key];\n }\n return current;\n}\n","/**\n * @context Core layer — JSON parser at src/core/parsers/parser-json.ts\n * @does Parses JSON content strings into typed ParsedJson results (array or object)\n * @depends none\n * @do Extend ParsedJson variants here if new JSON structures are supported\n * @dont Access the filesystem; import from CLI or UI; contain serialization logic\n */\n\nexport interface ParsedJsonArray {\n type: \"json-array\";\n entries: Record<string, unknown>[];\n}\n\nexport interface ParsedJsonObject {\n type: \"json-object\";\n data: Record<string, unknown>;\n}\n\nexport type ParsedJson = ParsedJsonArray | ParsedJsonObject;\n\nexport function parseJson(content: string): ParsedJson {\n const parsed: unknown = JSON.parse(content);\n\n if (Array.isArray(parsed)) {\n return {\n type: \"json-array\",\n entries: parsed as Record<string, unknown>[],\n };\n }\n\n if (typeof parsed === \"object\" && parsed !== null) {\n return {\n type: \"json-object\",\n data: parsed as Record<string, unknown>,\n };\n }\n\n throw new Error(\"JSON content must be an array or object\");\n}\n","/**\n * @context Core layer — schema inferrer at src/core/schema-inferrer.ts\n * @does Infers a CollectionSchema from actual content entries when no manual schema is defined\n * @depends src/shared/types.ts, src/shared/fields.ts\n * @do Add new type detection heuristics here (e.g. color, phone)\n * @dont Import from CLI or UI; access the filesystem; perform I/O\n */\n\nimport type { ContentEntry } from \"../shared/types.js\";\nimport type { CollectionSchema, FieldDefinition, SelectOption } from \"../shared/fields.js\";\n\n// Value detector patterns\nconst RE_ISO_DATE = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst RE_ISO_DATETIME =\n /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?$/;\nconst RE_EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nconst RE_URL = /^https?:\\/\\/.+/;\nconst LONG_TEXT_THRESHOLD = 200;\nconst RICH_TEXT_FIELD_NAMES = [\"description\", \"descriptions\", \"text\", \"content\"];\n\nfunction isISODate(value: string): boolean {\n return RE_ISO_DATE.test(value);\n}\n\nfunction isISODateTime(value: string): boolean {\n return RE_ISO_DATETIME.test(value);\n}\n\nfunction isEmail(value: string): boolean {\n return RE_EMAIL.test(value);\n}\n\nfunction isUrl(value: string): boolean {\n return RE_URL.test(value);\n}\n\nfunction inferStringField(name: string, strings: string[]): FieldDefinition {\n if (strings.every(isEmail)) return { name, type: \"email\" };\n if (strings.every(isUrl)) return { name, type: \"url\" };\n if (strings.every(isISODateTime)) return { name, type: \"date\", includeTime: true };\n if (strings.every(isISODate)) return { name, type: \"date\" };\n\n // Fields with well-known names are always treated as long/rich text\n if (RICH_TEXT_FIELD_NAMES.includes(name.toLowerCase())) return { name, type: \"long-text\" };\n\n const isLong = strings.some((s) => s.length > LONG_TEXT_THRESHOLD || s.includes(\"\\n\"));\n return { name, type: isLong ? \"long-text\" : \"text\" };\n}\n\nfunction inferArrayField(name: string, items: unknown[]): FieldDefinition {\n if (items.length === 0) return { name, type: \"array\", itemFields: [] };\n\n if (items.every((item) => typeof item === \"string\")) {\n const unique = [...new Set(items as string[])].slice(0, 50);\n const options: SelectOption[] = unique.map((v) => ({ label: v, value: v }));\n return { name, type: \"multi-select\", options };\n }\n\n if (items.every((item) => typeof item === \"object\" && item !== null && !Array.isArray(item))) {\n return { name, type: \"array\", itemFields: inferFields(items as Record<string, unknown>[]) };\n }\n\n return { name, type: \"array\", itemFields: [] };\n}\n\nfunction inferFieldDefinition(name: string, values: unknown[]): FieldDefinition {\n const present = values.filter((v) => v !== null && v !== undefined);\n\n if (present.length === 0) return { name, type: \"text\" };\n if (present.every((v) => typeof v === \"boolean\")) return { name, type: \"boolean\" };\n\n if (present.every((v) => typeof v === \"number\")) {\n const format = present.every((v) => Number.isInteger(v)) ? \"integer\" : \"decimal\";\n return { name, type: \"number\", format };\n }\n\n if (present.every((v) => typeof v === \"string\")) {\n return inferStringField(name, present as string[]);\n }\n\n if (present.every((v) => Array.isArray(v))) {\n return inferArrayField(name, (present as unknown[][]).flat());\n }\n\n if (present.every((v) => typeof v === \"object\" && v !== null && !Array.isArray(v))) {\n return { name, type: \"object\", fields: inferFields(present as Record<string, unknown>[]) };\n }\n\n return { name, type: \"text\" };\n}\n\nfunction inferFields(rows: Record<string, unknown>[]): FieldDefinition[] {\n const keySet = new Set<string>(rows.flatMap((row) => Object.keys(row)));\n return Array.from(keySet).map((key) => inferFieldDefinition(key, rows.map((row) => row[key])));\n}\n\n/**\n * Infer a `CollectionSchema` from the data of a set of content entries.\n *\n * The result is a best-effort approximation — string fields that look like\n * emails, URLs, or ISO dates get the correct semantic type. Everything else\n * falls back to `text`.\n */\nexport function inferSchema(entries: ContentEntry[], collectionName: string): CollectionSchema {\n const rows = entries.map((entry) => entry.data as Record<string, unknown>);\n return { collection: collectionName, fields: inferFields(rows) };\n}\n","/**\n * @context Core layer — locale parser at src/core/locale-parser.ts\n * @does Extracts locale codes from filenames using the convention `slug.locale.mdx`\n * @depends none\n * @do Add new locale detection strategies here\n * @dont Import from CLI or UI; access filesystem\n */\n\nconst LOCALE_REGEX = /\\.([a-z]{2}(?:-[A-Z]{2})?)\\.mdx$/;\n\n/**\n * Parses locale from a filename.\n * Supports `post.pt.mdx`, `post.en-US.mdx` patterns.\n * Returns undefined for files without a locale suffix.\n */\nexport function parseLocaleFromFilename(filename: string): string | undefined {\n const match = LOCALE_REGEX.exec(filename);\n return match?.[1];\n}\n\n/**\n * Removes the locale suffix from a slug.\n * Handles both pre-slugify (`.pt`) and post-slugify (`-pt`) formats,\n * since `@sindresorhus/slugify` converts dots to dashes.\n * `post.pt` → `post`, `post-pt` → `post`, `post` → `post`\n */\nexport function stripLocaleFromSlug(slug: string, locale?: string): string {\n if (!locale) return slug;\n const dotSuffix = `.${locale}`;\n if (slug.endsWith(dotSuffix)) return slug.slice(0, -dotSuffix.length);\n const dashSuffix = `-${locale}`;\n if (slug.endsWith(dashSuffix)) return slug.slice(0, -dashSuffix.length);\n return slug;\n}\n","/**\n * @context Core layer — content store at src/core/content-store.ts\n * @does Manages a singleton ContentIndex; exposes loadContent() and getStore() for consumers\n * @depends src/core/indexer.ts, src/shared/types.ts\n * @do Use this as the single access point for in-memory indexed content\n * @dont Import from CLI or UI; contain parsing or I/O logic; import fs-adapter at top level\n */\n\nimport type { IFsAdapter } from \"../shared/fs-adapter.interface.js\";\nimport type { StudioConfig } from \"../shared/types.js\";\nimport { ContentIndex } from \"./indexer.js\";\n\nlet store: ContentIndex | null = null;\n\nexport function getStore(): ContentIndex {\n if (!store) {\n throw new Error(\n \"Content not loaded. Auto-init requires 'nextjs-studio/server' — \" +\n \"use loadContentSync() in a server context, or queryCollection() \" +\n \"will auto-init when imported from 'nextjs-studio/server'.\",\n );\n }\n return store;\n}\n\nexport function setStore(index: ContentIndex): void {\n store = index;\n}\n\nexport function hasStore(): boolean {\n return store !== null;\n}\n\nexport async function loadContent(\n fsAdapter: IFsAdapter,\n config?: StudioConfig,\n): Promise<ContentIndex> {\n const index = new ContentIndex(fsAdapter);\n await index.build(config);\n store = index;\n return index;\n}\n\nexport function loadContentSync(\n fsAdapter: IFsAdapter,\n config?: StudioConfig,\n): ContentIndex {\n const index = new ContentIndex(fsAdapter);\n index.buildSync(config);\n store = index;\n return index;\n}\n","/**\n * @context Core layer — type generator at src/core/type-generator.ts\n * @does Converts CollectionSchema definitions into TypeScript declaration strings for .d.ts output\n * @depends src/shared/fields.ts\n * @do Add new field-to-type mappings here as new field types are introduced\n * @dont Import from CLI or UI; access the filesystem; perform I/O\n */\n\nimport type { FieldDefinition, CollectionSchema } from \"../shared/fields.js\";\n\nfunction indent(code: string, spaces = 2): string {\n return code\n .split(\"\\n\")\n .map((line) => (line.trim() === \"\" ? \"\" : \" \".repeat(spaces) + line))\n .join(\"\\n\");\n}\n\nfunction toPascalCase(str: string): string {\n return str\n .replace(/[-_\\s]+(.)/g, (_, c: string) => c.toUpperCase())\n .replace(/^(.)/, (_, c: string) => c.toUpperCase());\n}\n\nfunction fieldToTsType(field: FieldDefinition): string {\n switch (field.type) {\n case \"text\":\n case \"long-text\":\n return \"string\";\n\n case \"email\":\n return \"Email\";\n\n case \"url\":\n return \"HttpUrl\";\n\n case \"media\":\n return \"MediaPath\";\n\n case \"id\":\n return \"ID\";\n\n case \"slug\":\n return \"Slug\";\n\n case \"date\":\n return field.includeTime ? \"Date\" : \"ISODate\";\n\n case \"created-time\":\n case \"updated-time\":\n return \"Date\";\n\n case \"number\":\n return \"number\";\n\n case \"boolean\":\n return \"boolean\";\n\n case \"select\":\n case \"status\": {\n const values = field.options.map((o) => JSON.stringify(o.value));\n return values.length > 0 ? values.join(\" | \") : \"string\";\n }\n\n case \"multi-select\": {\n const values = field.options.map((o) => JSON.stringify(o.value));\n const union = values.length > 0 ? values.join(\" | \") : \"string\";\n return `Array<${union}>`;\n }\n\n case \"object\":\n return generateObjectType(field.fields);\n\n case \"array\":\n return `Array<${generateObjectType(field.itemFields)}>`;\n\n case \"relation\":\n return field.multiple === true ? \"ID[]\" : \"ID\";\n\n case \"formula\":\n if (field.resultType === \"number\") return \"number\";\n if (field.resultType === \"boolean\") return \"boolean\";\n return \"string\";\n\n default:\n return \"unknown\";\n }\n}\n\nfunction generateObjectType(fields: FieldDefinition[]): string {\n if (fields.length === 0) return \"Record<string, unknown>\";\n\n const lines = fields.map((field) => {\n const optional = field.required === false ? \"?\" : \"\";\n const tsType = fieldToTsType(field);\n const comment = field.description ? `/** ${field.description} */\\n` : \"\";\n return `${comment}${field.name}${optional}: ${tsType};`;\n });\n\n return `{\\n${indent(lines.join(\"\\n\"))}\\n}`;\n}\n\nexport function generateInterfaceForSchema(schema: CollectionSchema): string {\n const name = toPascalCase(schema.collection) + \"Entry\";\n const label = schema.label ?? schema.collection;\n const body = generateObjectType(schema.fields);\n return `/** Data shape for the \"${label}\" collection. */\\nexport interface ${name} ${body}`;\n}\n\n/**\n * Generate a complete TypeScript declaration file for all provided schemas.\n *\n * @example\n * ```ts\n * const code = generateCollectionTypes([blogSchema, authorSchema]);\n * await fs.writeFile(\".studio/types.d.ts\", code, \"utf-8\");\n * ```\n */\nexport function generateCollectionTypes(schemas: CollectionSchema[]): string {\n const banner = [\n \"// This file is auto-generated by nextjs-studio.\",\n \"// Do not edit manually — re-run `npx nextjs-studio --generate-types` to update.\",\n \"\",\n \"// Branded scalar types — structurally strings/numbers but semantically distinct.\",\n \"declare const __brand: unique symbol;\",\n \"type Brand<T, B extends string> = T & { readonly [__brand]: B };\",\n \"\",\n \"export type Email = Brand<string, 'Email'>;\",\n \"export type HttpUrl = Brand<string, 'HttpUrl'>;\",\n \"export type ISODate = Brand<string, 'ISODate'>;\",\n \"export type MediaPath = Brand<string, 'MediaPath'>;\",\n \"export type ID = Brand<string, 'ID'>;\",\n \"export type Slug = Brand<string, 'Slug'>;\",\n ].join(\"\\n\");\n\n const interfaces = schemas.map(generateInterfaceForSchema).join(\"\\n\\n\");\n\n const collectionRegistry = [\n \"// Augment both entry points so queryCollection() is fully typed regardless of import path.\",\n \"declare module 'nextjs-studio' {\",\n \" interface CollectionTypeMap {\",\n schemas.map((schema) => ` ${JSON.stringify(schema.collection)}: ${toPascalCase(schema.collection)}Entry;`).join(\"\\n\"),\n \" }\",\n \"}\",\n \"declare module 'nextjs-studio/server' {\",\n \" interface CollectionTypeMap {\",\n schemas.map((schema) => ` ${JSON.stringify(schema.collection)}: ${toPascalCase(schema.collection)}Entry;`).join(\"\\n\"),\n \" }\",\n \"}\",\n ].join(\"\\n\");\n\n return [banner, interfaces, collectionRegistry].join(\"\\n\\n\") + \"\\n\";\n}\n","/**\n * @context Core layer — config loader at src/core/config-loader.ts\n * @does Resolves and loads studio.config.ts/.js from the project root using dynamic import\n * @depends src/shared/constants.ts, src/shared/types.ts\n * @do Add new config resolution strategies or validation here\n * @dont Import from CLI or UI; access content files\n */\n\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { StudioConfig } from \"../shared/types.js\";\nimport { CONFIG_FILENAMES } from \"../shared/constants.js\";\n\n/**\n * Resolves the config file path from the project root.\n * Returns undefined if no config file is found.\n */\nexport function resolveConfigPath(projectRoot: string): string | undefined {\n for (const filename of CONFIG_FILENAMES) {\n const fullPath = path.resolve(projectRoot, filename);\n if (existsSync(fullPath)) return fullPath;\n }\n return undefined;\n}\n\n/**\n * Loads the studio config from the project root.\n * Tries CONFIG_FILENAMES in order, uses dynamic import().\n * Returns empty config if no file found or loading fails.\n */\nexport async function loadStudioConfig(projectRoot: string): Promise<StudioConfig> {\n const configPath = resolveConfigPath(projectRoot);\n if (!configPath) return {};\n\n return loadConfigFromPath(configPath);\n}\n\n/**\n * Loads config from a specific file path.\n */\nexport async function loadConfigFromPath(configPath: string): Promise<StudioConfig> {\n try {\n const fileUrl = pathToFileURL(configPath).href;\n const mod = await import(/* webpackIgnore: true */ fileUrl);\n const config = mod.default ?? mod.config ?? mod;\n\n if (typeof config !== \"object\" || config === null || Array.isArray(config)) {\n return {};\n }\n\n return config as StudioConfig;\n } catch {\n return {};\n }\n}\n","{\n \"name\": \"nextjs-studio\",\n \"version\": \"1.0.0\",\n \"description\": \"A Git-based, local-first CMS for Next.js projects\",\n \"keywords\": [\n \"nextjs\",\n \"cms\",\n \"mdx\",\n \"content\",\n \"studio\",\n \"static-site\",\n \"local-first\"\n ],\n \"homepage\": \"https://github.com/TiagoDanin/Nextjs-Studio\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/TiagoDanin/Nextjs-Studio.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"Tiago Danin\",\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/core/index.d.ts\",\n \"import\": \"./dist/core/index.js\"\n },\n \"./server\": {\n \"types\": \"./dist/core/server.d.ts\",\n \"import\": \"./dist/core/server.js\"\n }\n },\n \"main\": \"./dist/core/index.js\",\n \"types\": \"./dist/core/index.d.ts\",\n \"bin\": \"dist/bin/nextjs-studio.js\",\n \"files\": [\n \"dist/bin\",\n \"dist/core\",\n \"dist/*.d.ts\",\n \"dist/cli/ui/package.json\",\n \"dist/cli/ui/next.config.js\",\n \"dist/cli/ui/.next/static\",\n \"dist/cli/ui/.next/server\",\n \"dist/cli/ui/.next/BUILD_ID\",\n \"dist/cli/ui/.next/app-path-routes-manifest.json\",\n \"dist/cli/ui/.next/build-manifest.json\",\n \"dist/cli/ui/.next/export-marker.json\",\n \"dist/cli/ui/.next/images-manifest.json\",\n \"dist/cli/ui/.next/next-minimal-server.js.nft.json\",\n \"dist/cli/ui/.next/next-server.js.nft.json\",\n \"dist/cli/ui/.next/package.json\",\n \"dist/cli/ui/.next/prerender-manifest.json\",\n \"dist/cli/ui/.next/react-loadable-manifest.json\",\n \"dist/cli/ui/.next/required-server-files.js\",\n \"dist/cli/ui/.next/required-server-files.json\",\n \"dist/cli/ui/.next/routes-manifest.json\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"dev\": \"tsx src/bin/nextjs-studio.ts --dir example/contents\",\n \"studio:dev\": \"cross-env STUDIO_CONTENTS_DIR=example/contents next dev --port 3030 --webpack src/cli/ui\",\n \"studio:build\": \"next build --webpack src/cli/ui && node -e \\\"const fs=require('fs');fs.copyFileSync('src/cli/ui/package.json','dist/cli/ui/package.json');fs.writeFileSync('dist/cli/ui/next.config.js','module.exports={distDir:\\\\'.next\\\\'};')\\\"\",\n \"build\": \"tsup && yarn studio:build\",\n \"lint\": \"eslint src/\",\n \"type-check\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\"\n },\n \"engines\": {\n \"node\": \">=22.10.0\"\n },\n \"packageManager\": \"yarn@4.6.0\",\n \"devDependencies\": {\n \"@radix-ui/react-collapsible\": \"^1.1.12\",\n \"@radix-ui/react-label\": \"^2.1.8\",\n \"@radix-ui/react-switch\": \"^1.2.6\",\n \"@tailwindcss/postcss\": \"^4.1.18\",\n \"@tanstack/react-table\": \"^8.21.3\",\n \"@tiptap/extension-bubble-menu\": \"^3.20.0\",\n \"@tiptap/extension-code-block-lowlight\": \"^3.20.0\",\n \"@tiptap/extension-file-handler\": \"^3.20.0\",\n \"@tiptap/extension-image\": \"^3.20.0\",\n \"@tiptap/extension-link\": \"^3.20.0\",\n \"@tiptap/extension-placeholder\": \"^3.20.0\",\n \"@tiptap/react\": \"^3.20.0\",\n \"@tiptap/starter-kit\": \"^3.20.0\",\n \"@tiptap/suggestion\": \"^3.20.0\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/node\": \"^25.2.3\",\n \"@types/react\": \"^19\",\n \"@types/react-dom\": \"^19\",\n \"class-variance-authority\": \"^0.7.1\",\n \"clsx\": \"^2.1.1\",\n \"cross-env\": \"^10.1.0\",\n \"eslint\": \"^10.0.0\",\n \"lowlight\": \"^3.3.0\",\n \"lucide-react\": \"^0.574.0\",\n \"mermaid\": \"^11.6.0\",\n \"next\": \"^16.1.6\",\n \"next-themes\": \"^0.4.6\",\n \"react\": \"^19.2.4\",\n \"react-dom\": \"^19.2.4\",\n \"tailwind-merge\": \"^3.4.1\",\n \"tailwindcss\": \"^4.1.18\",\n \"tippy.js\": \"^6.3.7\",\n \"tiptap-extension-global-drag-handle\": \"^0.1.18\",\n \"tiptap-markdown\": \"^0.9.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.0.18\",\n \"zustand\": \"^5.0.11\"\n },\n \"dependencies\": {\n \"@sindresorhus/slugify\": \"^3.0.0\",\n \"chokidar\": \"^5.0.0\",\n \"commander\": \"^14.0.3\",\n \"gray-matter\": \"^4.0.3\",\n \"lodash-es\": \"^4.17.23\"\n },\n \"peerDependencies\": {\n \"next\": \"^16.0.0\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\"\n }\n}"],"mappings":"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","names":["existsSync","fs","path","path","path","path","path","configPath","path","fs","uiDir","existsSync","require"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextjs-studio",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "A Git-based, local-first CMS for Next.js projects",
5
5
  "keywords": [
6
6
  "nextjs",
@@ -96,7 +96,10 @@
96
96
  "lowlight": "^3.3.0",
97
97
  "lucide-react": "^0.574.0",
98
98
  "mermaid": "^11.6.0",
99
+ "next": "^16.1.6",
99
100
  "next-themes": "^0.4.6",
101
+ "react": "^19.2.4",
102
+ "react-dom": "^19.2.4",
100
103
  "tailwind-merge": "^3.4.1",
101
104
  "tailwindcss": "^4.1.18",
102
105
  "tippy.js": "^6.3.7",
@@ -113,9 +116,11 @@
113
116
  "chokidar": "^5.0.0",
114
117
  "commander": "^14.0.3",
115
118
  "gray-matter": "^4.0.3",
116
- "lodash-es": "^4.17.23",
117
- "next": "^16.1.6",
118
- "react": "^19.2.4",
119
- "react-dom": "^19.2.4"
119
+ "lodash-es": "^4.17.23"
120
+ },
121
+ "peerDependencies": {
122
+ "next": "^16.0.0",
123
+ "react": "^19.0.0",
124
+ "react-dom": "^19.0.0"
120
125
  }
121
126
  }
@@ -1 +0,0 @@
1
- module.exports={distDir:'.next'};
@@ -1,4 +0,0 @@
1
- {
2
- "name": "nextjs-studio-ui",
3
- "private": true
4
- }