From 8ed4f9575e39318dce3e17ac78ef25d839da3616 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 8 Aug 2025 20:28:25 +0000 Subject: [PATCH 1/5] Checkpoint before follow-up message Co-authored-by: eric.luce --- .changeset/ui-default-shadcn.md | 5 + my-shadcn-app/.cursor/rules/cursor-rules.mdc | 88 +++++++ my-shadcn-app/.cursor/rules/filemaker-api.mdc | 176 +++++++++++++ .../.cursor/rules/package-manager.mdc | 65 +++++ .../rules/troubleshooting-patterns.mdc | 240 ++++++++++++++++++ my-shadcn-app/.cursor/rules/ui-components.mdc | 57 +++++ my-shadcn-app/.eslintrc.cjs | 44 ++++ my-shadcn-app/.gitignore | 37 +++ my-shadcn-app/.prettierrc | 3 + my-shadcn-app/README.md | 27 ++ my-shadcn-app/components.json | 21 ++ my-shadcn-app/next.config.ts | 12 + my-shadcn-app/package.json | 65 +++++ my-shadcn-app/postcss.config.cjs | 15 ++ my-shadcn-app/proofkit.json | 14 + my-shadcn-app/public/favicon.ico | Bin 0 -> 32603 bytes my-shadcn-app/public/proofkit.png | Bin 0 -> 93051 bytes my-shadcn-app/src/app/(main)/layout.tsx | 6 + my-shadcn-app/src/app/(main)/page.tsx | 90 +++++++ my-shadcn-app/src/app/layout.tsx | 39 +++ my-shadcn-app/src/app/navigation.tsx | 12 + my-shadcn-app/src/components/AppLogo.tsx | 6 + .../components/AppShell/internal/AppShell.tsx | 21 ++ .../AppShell/internal/Header.module.css | 40 +++ .../components/AppShell/internal/Header.tsx | 34 +++ .../AppShell/internal/HeaderMobileMenu.tsx | 27 ++ .../AppShell/internal/HeaderNavLink.tsx | 31 +++ .../components/AppShell/internal/config.ts | 1 + .../AppShell/slot-header-center.tsx | 13 + .../components/AppShell/slot-header-left.tsx | 23 ++ .../AppShell/slot-header-mobile-content.tsx | 43 ++++ .../components/AppShell/slot-header-right.tsx | 26 ++ my-shadcn-app/src/config/env.ts | 13 + my-shadcn-app/src/config/theme/globals.css | 125 +++++++++ .../src/config/theme/mantine-theme.ts | 22 ++ my-shadcn-app/src/server/safe-action.ts | 3 + .../src/utils/notification-helpers.ts | 32 +++ my-shadcn-app/src/utils/styles.ts | 6 + my-shadcn-app/tsconfig.json | 40 +++ packages/cli/src/cli/add/auth.ts | 5 + packages/cli/src/cli/add/index.ts | 9 + packages/cli/src/cli/add/page/index.ts | 5 + packages/cli/src/cli/init.ts | 21 ++ packages/cli/src/helpers/createProject.ts | 35 ++- packages/cli/src/state.ts | 1 + packages/cli/src/utils/parseSettings.ts | 36 ++- packages/cli/template/nextjs/proofkit.json | 1 + pnpm-lock.yaml | 20 +- 48 files changed, 1634 insertions(+), 21 deletions(-) create mode 100644 .changeset/ui-default-shadcn.md create mode 100644 my-shadcn-app/.cursor/rules/cursor-rules.mdc create mode 100644 my-shadcn-app/.cursor/rules/filemaker-api.mdc create mode 100644 my-shadcn-app/.cursor/rules/package-manager.mdc create mode 100644 my-shadcn-app/.cursor/rules/troubleshooting-patterns.mdc create mode 100644 my-shadcn-app/.cursor/rules/ui-components.mdc create mode 100644 my-shadcn-app/.eslintrc.cjs create mode 100644 my-shadcn-app/.gitignore create mode 100644 my-shadcn-app/.prettierrc create mode 100644 my-shadcn-app/README.md create mode 100644 my-shadcn-app/components.json create mode 100644 my-shadcn-app/next.config.ts create mode 100644 my-shadcn-app/package.json create mode 100644 my-shadcn-app/postcss.config.cjs create mode 100644 my-shadcn-app/proofkit.json create mode 100644 my-shadcn-app/public/favicon.ico create mode 100644 my-shadcn-app/public/proofkit.png create mode 100644 my-shadcn-app/src/app/(main)/layout.tsx create mode 100644 my-shadcn-app/src/app/(main)/page.tsx create mode 100644 my-shadcn-app/src/app/layout.tsx create mode 100644 my-shadcn-app/src/app/navigation.tsx create mode 100644 my-shadcn-app/src/components/AppLogo.tsx create mode 100644 my-shadcn-app/src/components/AppShell/internal/AppShell.tsx create mode 100644 my-shadcn-app/src/components/AppShell/internal/Header.module.css create mode 100644 my-shadcn-app/src/components/AppShell/internal/Header.tsx create mode 100644 my-shadcn-app/src/components/AppShell/internal/HeaderMobileMenu.tsx create mode 100644 my-shadcn-app/src/components/AppShell/internal/HeaderNavLink.tsx create mode 100644 my-shadcn-app/src/components/AppShell/internal/config.ts create mode 100644 my-shadcn-app/src/components/AppShell/slot-header-center.tsx create mode 100644 my-shadcn-app/src/components/AppShell/slot-header-left.tsx create mode 100644 my-shadcn-app/src/components/AppShell/slot-header-mobile-content.tsx create mode 100644 my-shadcn-app/src/components/AppShell/slot-header-right.tsx create mode 100644 my-shadcn-app/src/config/env.ts create mode 100644 my-shadcn-app/src/config/theme/globals.css create mode 100644 my-shadcn-app/src/config/theme/mantine-theme.ts create mode 100644 my-shadcn-app/src/server/safe-action.ts create mode 100644 my-shadcn-app/src/utils/notification-helpers.ts create mode 100644 my-shadcn-app/src/utils/styles.ts create mode 100644 my-shadcn-app/tsconfig.json diff --git a/.changeset/ui-default-shadcn.md b/.changeset/ui-default-shadcn.md new file mode 100644 index 00000000..6a54d283 --- /dev/null +++ b/.changeset/ui-default-shadcn.md @@ -0,0 +1,5 @@ +--- +"@proofkit/cli": minor +--- + +CLI defaults to shadcn/ui for new projects. Legacy Mantine templates are still available via a hidden `--ui mantine` flag during `init`. The selected UI is persisted in `proofkit.json` as `ui`. Existing projects using Mantine are auto-detected and remain fully supported. For shadcn-based projects, adding new pages or auth via `proofkit add` is temporarily disabled while we work on a new component system. \ No newline at end of file diff --git a/my-shadcn-app/.cursor/rules/cursor-rules.mdc b/my-shadcn-app/.cursor/rules/cursor-rules.mdc new file mode 100644 index 00000000..061da499 --- /dev/null +++ b/my-shadcn-app/.cursor/rules/cursor-rules.mdc @@ -0,0 +1,88 @@ +--- +description: | + This rule documents how to manage and organize Cursor rules. It should be included when: + 1. Creating or modifying Cursor rules + 2. Organizing documentation for the codebase + 3. Setting up new development patterns + 4. Adding project-wide conventions + 5. Managing rule file locations + 6. Updating rule descriptions or globs + 7. Working with .cursor directory structure +globs: + - ".cursor/rules/*.mdc" + - ".cursor/config/*.json" + - ".cursor/settings/*.json" +alwaysApply: true +--- +# Cursor Rules Location + +Rules for placing and organizing Cursor rule files in the repository. + + +name: cursor_rules_location +description: Standards for placing Cursor rule files in the correct directory +filters: + # Match any .mdc files + - type: file_extension + pattern: "\\.mdc$" + # Match files that look like Cursor rules + - type: content + pattern: "(?s).*?" + # Match file creation events + - type: event + pattern: "file_create" + +actions: + - type: reject + conditions: + - pattern: "^(?!\\.\\/\\.cursor\\/rules\\/.*\\.mdc$)" + message: "Cursor rule files (.mdc) must be placed in the .cursor/rules directory" + + - type: suggest + message: | + When creating Cursor rules: + + 1. Always place rule files in PROJECT_ROOT/.cursor/rules/: + ``` + .cursor/rules/ + ├── your-rule-name.mdc + ├── another-rule.mdc + └── ... + ``` + + 2. Follow the naming convention: + - Use kebab-case for filenames + - Always use .mdc extension + - Make names descriptive of the rule's purpose + + 3. Directory structure: + ``` + PROJECT_ROOT/ + ├── .cursor/ + │ └── rules/ + │ ├── your-rule-name.mdc + │ └── ... + └── ... + ``` + + 4. Never place rule files: + - In the project root + - In subdirectories outside .cursor/rules + - In any other location + - Inside of the cursor-rules.mdc file + +examples: + - input: | + # Bad: Rule file in wrong location + rules/my-rule.mdc + my-rule.mdc + .rules/my-rule.mdc + + # Good: Rule file in correct location + .cursor/rules/my-rule.mdc + output: "Correctly placed Cursor rule file" + +metadata: + priority: high + version: 1.0 + \ No newline at end of file diff --git a/my-shadcn-app/.cursor/rules/filemaker-api.mdc b/my-shadcn-app/.cursor/rules/filemaker-api.mdc new file mode 100644 index 00000000..dd6d6716 --- /dev/null +++ b/my-shadcn-app/.cursor/rules/filemaker-api.mdc @@ -0,0 +1,176 @@ +--- +description: | + This rule provides guidance for working with the FileMaker Data API in this project. It should be included when: + 1. Working with database operations or data fetching + 2. Encountering database-related errors or type issues + 3. Making changes to FileMaker schemas or layouts + 4. Implementing new data access patterns + 5. Discussing alternative data storage solutions + 6. Working with server-side API routes or actions +globs: + - "src/**/*.ts" + - "src/**/*.tsx" + - "**/fmschema.config.mjs" + - "src/**/actions/*.ts" +alwaysApply: true +--- +# FileMaker Data API Integration + +This rule documents how the FileMaker Data API is integrated and used in the project. + + +name: filemaker_api +description: Documents FileMaker Data API integration patterns and conventions. FileMaker is the ONLY data source for this application - no SQL or other databases should be used. +filters: + - type: file_extension + pattern: "\\.(ts|tsx)$" + - type: directory + pattern: "src/server/" + - type: content + pattern: "(@proofkit/cli|ZodError|typegen)" + +data_source_policy: + exclusive_source: "FileMaker Data API" + prohibited: + - "SQL databases" + - "NoSQL databases" + - "Local storage for persistent data" + - "Direct file system storage" + reason: "All data operations must go through FileMaker to maintain data integrity and business logic" + +troubleshooting: + priority_order: + - "ALWAYS run `{package-manager} typegen` first for ANY data loading issues" + - "DO NOT check environment variables unless you have a specific error message pointing to them" + - "Check for FileMaker schema changes" + - "Verify type definitions match current schema" + - "Review Zod validation errors" + rationale: "Most data loading issues are resolved by running typegen. Environment variables are rarely the cause of data loading problems and should not be investigated unless specific error messages indicate an authentication or connection issue." + +conventions: + api_setup: + - Uses @proofkit/fmdapi package version ^5.0.0 + - Configuration in fmschema.config.mjs + - Environment variables in .env for connection details + - Type generation via `{package-manager} typegen` command + + data_access: + - ALL data operations MUST use FileMaker Data API + - Server-side only API calls via @proofkit/fmdapi + - Type-safe database operations + - Centralized error handling + - Connection pooling and session management + - No direct database connections outside FileMaker + + data_operations: + create: + - Use layout.create({ fieldData: {...} }) + - Validate input against Zod schemas + - Returns recordId of created record + - Handle duplicates via FileMaker business logic + read: + - Use layout.get({ recordId }) for single record by ID + - Use layout.find({ query, limit, offset, sort }) for multiple records + - Use layout.maybeFindFirst({ query }) for optional single record + - Support for complex queries and sorting + update: + - Use layout.update({ recordId, fieldData }) + - Follow FileMaker field naming conventions + - Respect FileMaker validation rules + delete: + - Use layout.delete({ recordId }) + - Respect FileMaker deletion rules + - Handle cascading deletes via FileMaker + query_options: + - Limit and offset for pagination + - Sort by multiple fields with ascend/descend + - Complex query criteria with operators (==, *, etc.) + - Optional type-safe responses with Zod validation + + security: + - Credentials stored in environment variables + - No direct client-side FM API access + - API routes validate authentication + - Data sanitization before queries + - All database access through FileMaker only + +type_generation: + process: + - "IMPORTANT: Running `{package-manager} typegen` solves almost all data loading problems" + - "Run `{package-manager} typegen` after any FileMaker schema changes" + - "Run `{package-manager} typegen` as first step when troubleshooting data issues" + - "Types are generated from FileMaker database schema" + - "Generated types are used in server actions and components" + - "Zod schemas validate runtime data against types" + + common_issues: + schema_changes: + symptoms: + - "No data appearing in tables" + - "ZodError during runtime" + - "Missing or renamed fields" + - "Type mismatches in responses" + - "Empty query results" + solution: "ALWAYS run `{package-manager} typegen && {package-manager} tsc` first" + important_note: "Do NOT check environment variables as a cause for data loading problems unless you have a specific known error that points to environment variables. Most data loading issues are resolved by running typegen." + + field_types: + symptoms: + - "Unexpected null values" + - "Type conversion errors" + - "Invalid date formats" + solution: "Update Zod schemas and type definitions" + + security_notes: + - "Never display, log, or commit environment variables" + - "Never check environment variable values directly" + - "Keep .env files out of version control" + - "When troubleshooting, only verify if variables exist, never their values" + +patterns: + - Server actions wrap FM API calls + - Type definitions generated from FM schema + - Error boundaries for FM API errors + - Rate limiting on API routes + - Caching strategies for frequent queries + +dependencies: + fmdapi: "@proofkit/fmdapi@^5.0.0" + proofkit: "@proofkit/cli@^1.0.0" + +keywords: + database: + - "FileMaker" + - "FMREST" + - "Database schema" + - "Field types" + - "Type generation" + - "Schema changes" + - "Exclusive data source" + - "No SQL" + - "FileMaker only" + - "Data API" + errors: + - "ZodError" + - "TypeError" + - "ValidationError" + - "Missing field" + - "Runtime error" + commands: + - "typegen" + - "tsc" + - "type checking" + - "schema update" + operations: + - "FM.create" + - "FM.find" + - "FM.get" + - "FM.update" + - "FM.delete" + - "FileMaker layout" + - "FileMaker query" + +metadata: + priority: high + version: 1.0 + \ No newline at end of file diff --git a/my-shadcn-app/.cursor/rules/package-manager.mdc b/my-shadcn-app/.cursor/rules/package-manager.mdc new file mode 100644 index 00000000..d25da047 --- /dev/null +++ b/my-shadcn-app/.cursor/rules/package-manager.mdc @@ -0,0 +1,65 @@ +--- +description: | +globs: +alwaysApply: true +--- +--- +description: | + This rule documents the package manager configuration and usage. It should be included when: + 1. Installing dependencies + 2. Running scripts + 3. Managing project packages + 4. Running development commands + 5. Executing build or test operations +globs: + - "package.json" + - "pnpm-lock.yaml" + - ".npmrc" +alwaysApply: true +--- +# Package Manager Configuration + +This rule documents the package manager setup and usage requirements. + + +name: package_manager +description: Documents package manager configuration and usage requirements + +configuration: + name: "pnpm" + version: "latest" + commands: + install: "pnpm install" + build: "pnpm build" + dev: "pnpm dev" + typegen: "pnpm typegen" + typecheck: "pnpm tsc" + notes: "Always use pnpm instead of npm or yarn for consistency" + dev_server_guidelines: + - "Never relaunch the dev server command if it may already be running" + - "Use pnpm dev only when explicitly needed to start the server for the first time" + - "For code changes, just save the files and the server will automatically reload" + +examples: + - description: "Installing dependencies" + correct: "pnpm install" + incorrect: + - "npm install" + - "yarn install" + + - description: "Running scripts" + correct: "pnpm run script-name" + incorrect: + - "npm run script-name" + - "yarn script-name" + + - description: "Adding dependencies" + correct: "pnpm add package-name" + incorrect: + - "npm install package-name" + - "yarn add package-name" + +metadata: + priority: high + version: 1.0 + \ No newline at end of file diff --git a/my-shadcn-app/.cursor/rules/troubleshooting-patterns.mdc b/my-shadcn-app/.cursor/rules/troubleshooting-patterns.mdc new file mode 100644 index 00000000..797fd3cc --- /dev/null +++ b/my-shadcn-app/.cursor/rules/troubleshooting-patterns.mdc @@ -0,0 +1,240 @@ +--- +description: | +globs: +alwaysApply: false +--- +# Troubleshooting and Maintenance Patterns + +This rule documents common issues, error patterns, and their solutions in the project. + + +name: troubleshooting_patterns +description: Documents common runtime errors, type errors, and solutions. All data operations MUST use FileMaker Data API exclusively. +filters: + - type: file_extension + pattern: "\\.(ts|tsx)$" + - type: content + pattern: "(Error|error|ZodError|TypeError|ValidationError|@proofkit/fmdapi)" + +initial_debugging_steps: + priority: "ALWAYS run `{package-manager} typegen` first for any data-related issues" + steps: + - "Run `{package-manager} typegen` to ensure types match FileMaker schema" + - "Check if error persists after typegen" + - "If error persists, check console for exact error messages" + - "Look for patterns in the troubleshooting guide below" + common_console_errors: + zod_errors: + pattern: "ZodError: [path] invalid_type..." + likely_cause: "Field name mismatch or missing field" + example: "ZodError: nameFirst expected string, got undefined" + solution: "Run typegen first, then check field names in FileMaker schema" + type_errors: + pattern: "TypeError: Cannot read property 'X' of undefined" + likely_cause: "Accessing field before data is loaded or field name mismatch" + solution: "Run typegen first, then add null checks or loading states" + network_errors: + pattern: "Failed to fetch" or "Network error" + likely_cause: "FileMaker connection issues" + solution: "Run typegen first, then check FileMaker server status and credentials" + +data_source_validation: + requirement: "All data operations must use FileMaker Data API exclusively" + first_step_for_data_issues: "ALWAYS run `{package-manager} typegen` first" + common_mistakes: + - "Attempting to use SQL queries" + - "Adding direct database connections" + - "Using local storage for persistent data" + - "Implementing alternative data stores" + - "Skipping typegen after FileMaker schema changes" + - "Using incorrect field names from old schema" + correct_approach: + - "Run typegen first" + - "Use @proofkit/fmdapi for all data operations" + - "Follow FileMaker layout and field conventions" + - "Use layout.create, layout.find, layout.get, layout.update, layout.delete" + - "Use layout.maybeFindFirst for optional records" + +error_patterns: + field_name_mismatches: + symptoms: + - "ZodError: invalid_type at path [fieldName]" + - "Property 'X' does not exist on type 'Y'" + - "TypeScript errors about missing properties" + common_examples: + - "nameFirst vs firstName" + - "lastName vs nameLast" + - "postalCode vs postal_code" + - "phoneNumber vs phone" + cause: "Mismatch between component field names and FileMaker schema" + solution: + steps: + - "Run `{package-manager} typegen` to update types" + - "Look at generated types in src/config/schemas/filemaker/" + - "Update component field names to match schema" + - "Check console for exact field name in error" + files_to_check: + - "src/config/schemas/filemaker/*.ts" + - "Component files using the fields" + + zod_validation_errors: + symptoms: + - "Runtime ZodError: invalid_type" + - "Zod schema validation failed" + - "Property not found in schema" + - "Unexpected field in response" + cause: "FileMaker database schema changes not reflected in TypeScript types" + solution: + steps: + - "Run `{package-manager} typegen` to regenerate types from FileMaker schema" + - "Run `{package-manager} tsc` to identify type mismatches" + - "Check console for exact error message" + - "Update affected components and server actions" + commands: + - "{package-manager} typegen" + - "{package-manager} tsc" + files_to_check: + - "src/server/actions/*" + - "src/server/schema/*" + - "fmschema.config.mjs" + + filemaker_connection: + symptoms: + - "ETIMEDOUT connecting to FileMaker" + - "Invalid FileMaker credentials" + - "Session token expired" + - "Layout not found" + - "Field not found in layout" + - "Invalid find criteria" + - "No data appearing or queries returning empty" + cause: "FileMaker connection, authentication, or query issues" + solution: + steps: + - "Run `{package-manager} typegen` to ensure schema is up to date" + - "Check FileMaker Server status" + - "Validate credentials and permissions" + - "Note: As an AI, you cannot directly check environment variables - always ask the user to verify them if this is determined to be the issue" + - "Verify layout names and field access" + - "Check FileMaker query syntax" + files_to_check: + - "src/server/lib/fm.ts" + - "fmschema.config.mjs" + + data_access_errors: + symptoms: + - "Invalid operation on FileMaker record" + - "Record not found" + - "Insufficient permissions" + - "Invalid find request" + cause: "Incorrect FileMaker Data API usage or permissions" + solution: + steps: + - "Run `{package-manager} typegen` to ensure schema is up to date" + - "Verify FileMaker layout privileges" + - "Check record existence before operations" + - "Validate find criteria format" + - "Use proper FM API methods" + files_to_check: + - "src/server/actions/*" + - "src/server/lib/fm.ts" + + type_errors: + symptoms: + - "Type ... is not assignable to type ..." + - "Property ... does not exist on type ..." + - "Argument of type ... is not assignable" + cause: "Mismatch between FileMaker schema and TypeScript types" + solution: + steps: + - "Run `{package-manager} typegen` to regenerate types" + - "Run `{package-manager} tsc` to identify type mismatches" + - "Update type definitions if needed" + - "Check for null/undefined handling" + commands: + - "{package-manager} typegen && {package-manager} tsc" + + data_sync_issues: + symptoms: + - "Missing fields in table" + - "Unexpected null values" + - "Fields showing as blank" + - "Type mismatches between FM and frontend" + first_step: "ALWAYS run `{package-manager} typegen` first" + cause: "Mismatch between FileMaker schema and TypeScript types, or outdated type definitions" + solution: + steps: + - "Run `{package-manager} typegen` to regenerate types from FileMaker schema" + - "Check for any type errors in the console" + - "Verify field names match exactly between FM and generated types" + - "Update components if field names have changed" + commands: + - "{package-manager} typegen" + - "{package-manager} tsc" + files_to_check: + - "src/config/schemas/filemaker/*.ts" + - "fmschema.config.mjs" + +maintenance_tasks: + schema_sync: + description: "Keep FileMaker schema and TypeScript types in sync" + frequency: "After any FileMaker schema changes" + steps: + - "Run typegen to update types" + - "Run TypeScript compiler" + - "Update affected components" + impact: "Prevents runtime errors and type mismatches" + + type_checking: + description: "Regular type checking for early error detection" + frequency: "Before deployments and after schema changes" + commands: + - "{package-manager} tsc --noEmit" + impact: "Catches type errors before runtime" + +keywords: + errors: + - "ZodError" + - "TypeError" + - "ValidationError" + - "Schema mismatch" + - "Type mismatch" + - "Runtime error" + - "Database schema" + - "Type generation" + - "FileMaker fields" + - "Missing property" + - "Invalid type" + - "Layout not found" + - "Field not found" + - "Invalid find request" + solutions: + - "typegen" + - "tsc" + - "type checking" + - "schema update" + - "validation fix" + - "error handling" + - "FM API methods" + - "FileMaker layout" + operations: + - "layout.create" + - "layout.find" + - "layout.get" + - "layout.update" + - "layout.delete" + - "layout.maybeFindFirst" + - "recordId" + - "fieldData" + - "query parameters" + - "sort options" + data_source: + - "FileMaker only" + - "No SQL" + - "FM Data API" + - "Exclusive data source" + - "@proofkit/fmdapi" + +metadata: + priority: high + version: 1.0 + \ No newline at end of file diff --git a/my-shadcn-app/.cursor/rules/ui-components.mdc b/my-shadcn-app/.cursor/rules/ui-components.mdc new file mode 100644 index 00000000..78ec63ad --- /dev/null +++ b/my-shadcn-app/.cursor/rules/ui-components.mdc @@ -0,0 +1,57 @@ +--- +description: +globs: +alwaysApply: false +--- +# UI Components and Styling + +This rule documents the UI component library and styling conventions used in the project. + + +name: ui_components +description: Documents UI component library usage and styling conventions +filters: + - type: file_extension + pattern: "\\.(ts|tsx)$" + - type: directory + pattern: "src/components/" + - type: content + pattern: "@mantine/" + +conventions: + component_library: + - Mantine v7 as primary UI framework + - Tabler icons for iconography + - Mantine React Table for data grids + - Custom components extend Mantine base + + styling: + - PostCSS for processing + - Mantine theme customization + - CSS modules for component styles + - CSS variables for theming + + components: + - Atomic design principles + - Consistent prop interfaces + - Accessibility first + - Responsive design patterns + + forms: + - React Hook Form for form state + - Zod for validation schemas + - Mantine form components + - Custom form layouts + +dependencies: + mantine_core: "^7.17.0" + mantine_hooks: "^7.17.0" + mantine_dates: "^7.17.0" + mantine_notifications: "^7.17.0" + react_hook_form: "^7.54.2" + zod: "^3.24.2" + +metadata: + priority: high + version: 1.0 + \ No newline at end of file diff --git a/my-shadcn-app/.eslintrc.cjs b/my-shadcn-app/.eslintrc.cjs new file mode 100644 index 00000000..2c5996ec --- /dev/null +++ b/my-shadcn-app/.eslintrc.cjs @@ -0,0 +1,44 @@ +/** @type {import("eslint").Linter.Config} */ +const config = { + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": true + }, + "plugins": [ + "@typescript-eslint" + ], + "extends": [ + "next/core-web-vitals", + "plugin:@typescript-eslint/recommended-type-checked", + "plugin:@typescript-eslint/stylistic-type-checked" + ], + "rules": { + "@typescript-eslint/array-type": "off", + "@typescript-eslint/consistent-type-definitions": "off", + "@typescript-eslint/consistent-type-imports": [ + "warn", + { + "prefer": "type-imports", + "fixStyle": "inline-type-imports" + } + ], + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_" + } + ], + "@typescript-eslint/require-await": "off", + "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-misused-promises": [ + "error", + { + "checksVoidReturn": { + "attributes": false + } + } + ], + "@typescript-eslint/no-floating-promises": "warn" + } +} +module.exports = config; \ No newline at end of file diff --git a/my-shadcn-app/.gitignore b/my-shadcn-app/.gitignore new file mode 100644 index 00000000..00bba9bb --- /dev/null +++ b/my-shadcn-app/.gitignore @@ -0,0 +1,37 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/my-shadcn-app/.prettierrc b/my-shadcn-app/.prettierrc new file mode 100644 index 00000000..b4bfed35 --- /dev/null +++ b/my-shadcn-app/.prettierrc @@ -0,0 +1,3 @@ +{ + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/my-shadcn-app/README.md b/my-shadcn-app/README.md new file mode 100644 index 00000000..4f416a4a --- /dev/null +++ b/my-shadcn-app/README.md @@ -0,0 +1,27 @@ +# ProofKit NextJS Template + +This is a [NextJS](https://nextjs.org/) project bootstrapped with `@proofkit/cli`. Learn more at [proofkit.dev](https://proofkit.dev) + +## What's next? How do I make an app with this? + +While this template is designed to be a minimal starting point, the proofkit CLI will guide you through adding additional features and pages. + +To add new things to your project, simply run the `proofkit` script from the project's root directory. + +e.g. `npm run proofkit` or `pnpm proofkit` etc. + +For more information, see the full [ProofKit documentation](https://proofkit.dev). + +## Project Structure + +ProofKit projects have an opinionated structure to help you get started and some conventions must be maintained to ensure that the CLI can properly inject new features and components. + +The `src` directory is the home for your application code. It is used for most things except for configuration and is organized as follows: + +- `app` - NextJS app router, where your pages and routes are defined +- `components` - Shared components used throughout the app +- `server` - Code that connects to backend databases and services that should not be exposed in the browser + +Anytime you see an `internal` folder, you should not modify any files inside. These files are maintained exclusively by the ProofKit CLI and changes to them may be overwritten. + +Anytime you see a componet file that begins with `slot-`, you _may_ modify the content, but do not rename, remove, or move them. These are desigend to be customized, but are still used by the CLI to inject additional content. If a slot is not needed by your app, you can have the compoment return `null` or an empty fragment: `<>` diff --git a/my-shadcn-app/components.json b/my-shadcn-app/components.json new file mode 100644 index 00000000..0d27c449 --- /dev/null +++ b/my-shadcn-app/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/config/theme/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "tw:" + }, + "aliases": { + "components": "@/components", + "utils": "@/utils/styles", + "ui": "@/components/ui", + "lib": "@/utils", + "hooks": "@/utils/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/my-shadcn-app/next.config.ts b/my-shadcn-app/next.config.ts new file mode 100644 index 00000000..9555317e --- /dev/null +++ b/my-shadcn-app/next.config.ts @@ -0,0 +1,12 @@ +import { type NextConfig } from "next"; + +// Import env here to validate during build. +import "./src/config/env"; + +const nextConfig: NextConfig = { + experimental: { + optimizePackageImports: ["@mantine/core", "@mantine/hooks"], + }, +}; + +export default nextConfig; diff --git a/my-shadcn-app/package.json b/my-shadcn-app/package.json new file mode 100644 index 00000000..6dbfc035 --- /dev/null +++ b/my-shadcn-app/package.json @@ -0,0 +1,65 @@ +{ + "name": "my-shadcn-app", + "version": "0.1.0", + "private": true, + "scripts": { + "build": "next build", + "deploy": "proofkit deploy", + "dev": "next dev --turbopack", + "lint": "next lint", + "proofkit": "proofkit", + "start": "next start", + "typegen": "proofkit typegen" + }, + "dependencies": { + "@hookform/resolvers": "^5.1.1", + "@mantine/core": "^7.17.0", + "@mantine/dates": "^7.17.0", + "@mantine/hooks": "^7.17.0", + "@mantine/modals": "^7.17.0", + "@mantine/notifications": "^7.17.0", + "@next-safe-action/adapter-react-hook-form": "^2.0.0", + "@radix-ui/react-slot": "^1.2.3", + "@t3-oss/env-nextjs": "^0.12.0", + "@tabler/icons-react": "^3.30.0", + "@tailwindcss/postcss": "^4.1.10", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "dayjs": "^1.11.13", + "lucide-react": "^0.518.0", + "mantine-react-table": "2.0.0-beta.9", + "next": "^15.2.3", + "next-safe-action": "^8.0.4", + "react": "19.0.0", + "react-dom": "19.0.0", + "react-hook-form": "^7.54.2", + "tailwind-merge": "^3.3.1", + "tailwindcss": "^4.1.10", + "tw-animate-css": "^1.3.4", + "zod": "^3.24.2" + }, + "devDependencies": { + "@proofkit/cli": "^1.1.6", + "@types/node": "^22", + "@types/react": "npm:types-react@19.0.12", + "@types/react-dom": "npm:types-react-dom@19.0.4", + "eslint": "^9.14.0", + "eslint-config-next": "15.2.3", + "postcss": "^8.4.41", + "postcss-preset-mantine": "^1.17.0", + "postcss-simple-vars": "^7.0.1", + "prettier": "^3.5.3", + "prettier-plugin-tailwindcss": "^0.6.12", + "typescript": "^5" + }, + "pnpm": { + "overrides": { + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" + } + }, + "proofkitMetadata": { + "initVersion": "1.1.6" + }, + "packageManager": "pnpm@10.11.1" +} diff --git a/my-shadcn-app/postcss.config.cjs b/my-shadcn-app/postcss.config.cjs new file mode 100644 index 00000000..085a0ef9 --- /dev/null +++ b/my-shadcn-app/postcss.config.cjs @@ -0,0 +1,15 @@ +module.exports = { + plugins: { + "@tailwindcss/postcss": {}, + "postcss-preset-mantine": {}, + "postcss-simple-vars": { + variables: { + "mantine-breakpoint-xs": "36em", + "mantine-breakpoint-sm": "48em", + "mantine-breakpoint-md": "62em", + "mantine-breakpoint-lg": "75em", + "mantine-breakpoint-xl": "88em", + }, + }, + }, +}; diff --git a/my-shadcn-app/proofkit.json b/my-shadcn-app/proofkit.json new file mode 100644 index 00000000..87c5ee11 --- /dev/null +++ b/my-shadcn-app/proofkit.json @@ -0,0 +1,14 @@ +{ + "appType": "browser", + "ui": "shadcn", + "auth": { + "type": "none" + }, + "envFile": ".env", + "dataSources": [], + "tanstackQuery": false, + "replacedMainPage": false, + "appliedUpgrades": [ + "cursorRules" + ] +} diff --git a/my-shadcn-app/public/favicon.ico b/my-shadcn-app/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f9227c6e68b9acab3b23c293c3174f71eb9db61d GIT binary patch literal 32603 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 literal 0 HcmV?d00001 diff --git a/my-shadcn-app/src/app/(main)/layout.tsx b/my-shadcn-app/src/app/(main)/layout.tsx new file mode 100644 index 00000000..57a8452b --- /dev/null +++ b/my-shadcn-app/src/app/(main)/layout.tsx @@ -0,0 +1,6 @@ +import AppShell from "@/components/AppShell/internal/AppShell"; +import React from "react"; + +export default function Layout({ children }: { children: React.ReactNode }) { + return {children}; +} diff --git a/my-shadcn-app/src/app/(main)/page.tsx b/my-shadcn-app/src/app/(main)/page.tsx new file mode 100644 index 00000000..68340a69 --- /dev/null +++ b/my-shadcn-app/src/app/(main)/page.tsx @@ -0,0 +1,90 @@ +import { + ActionIcon, + Anchor, + AppShellFooter, + Box, + Code, + Container, + Group, + Image, + px, + Stack, + Text, + Title, +} from "@mantine/core"; +import { IconBrandGithub, IconExternalLink } from "@tabler/icons-react"; + +export default function Home() { + return ( + <> + + + ProofKit + Welcome! + + + This is the base template home page. To add more pages, components, + or other features, run the ProofKit CLI from within your project. + + pnpm proofkit + + + To change this page, open src/app/(main)/page.tsx + + + + ProofKit Docs + + + + + + + + + + Sponsored by{" "} + + Proof+Geist + {" "} + and{" "} + + Ottomatic + + + + + + + + + + + + + + + ); +} diff --git a/my-shadcn-app/src/app/layout.tsx b/my-shadcn-app/src/app/layout.tsx new file mode 100644 index 00000000..9512cb63 --- /dev/null +++ b/my-shadcn-app/src/app/layout.tsx @@ -0,0 +1,39 @@ +import { Suspense } from "react"; +import { theme } from "@/config/theme/mantine-theme"; +import { ColorSchemeScript, MantineProvider } from "@mantine/core"; +import { ModalsProvider } from "@mantine/modals"; +import { Notifications } from "@mantine/notifications"; + +import "@mantine/core/styles.css"; +import "@mantine/notifications/styles.css"; +import "@mantine/dates/styles.css"; +import "mantine-react-table/styles.css"; +import "@/config/theme/globals.css"; + +import { type Metadata } from "next"; + +export const metadata: Metadata = { + title: "My ProofKit App", + description: "Generated by proofkit", + icons: [{ rel: "icon", url: "/favicon.ico" }], +}; + +export default function RootLayout({ + children, +}: Readonly<{ children: React.ReactNode }>) { + return ( + + + + + + + + + + {children} + + + + ); +} diff --git a/my-shadcn-app/src/app/navigation.tsx b/my-shadcn-app/src/app/navigation.tsx new file mode 100644 index 00000000..887073db --- /dev/null +++ b/my-shadcn-app/src/app/navigation.tsx @@ -0,0 +1,12 @@ +import { type ProofKitRoute } from "@proofkit/cli"; + +export const primaryRoutes: ProofKitRoute[] = [ + { + label: "Dashboard", + type: "link", + href: "/", + exactMatch: true, + }, +]; + +export const secondaryRoutes: ProofKitRoute[] = []; diff --git a/my-shadcn-app/src/components/AppLogo.tsx b/my-shadcn-app/src/components/AppLogo.tsx new file mode 100644 index 00000000..f5ea4966 --- /dev/null +++ b/my-shadcn-app/src/components/AppLogo.tsx @@ -0,0 +1,6 @@ +import { IconInfinity } from "@tabler/icons-react"; +import React from "react"; + +export default function AppLogo() { + return ; +} diff --git a/my-shadcn-app/src/components/AppShell/internal/AppShell.tsx b/my-shadcn-app/src/components/AppShell/internal/AppShell.tsx new file mode 100644 index 00000000..8c4270df --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/internal/AppShell.tsx @@ -0,0 +1,21 @@ +import { Header } from "@/components/AppShell/internal/Header"; +import { AppShell, AppShellHeader, AppShellMain } from "@mantine/core"; +import React from "react"; + +import { headerHeight } from "./config"; + +export default function MainAppShell({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + +
+ + + {children} + + ); +} diff --git a/my-shadcn-app/src/components/AppShell/internal/Header.module.css b/my-shadcn-app/src/components/AppShell/internal/Header.module.css new file mode 100644 index 00000000..79d81bad --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/internal/Header.module.css @@ -0,0 +1,40 @@ +.header { + /* height: rem(56px); */ + margin-bottom: rem(120px); + background-color: var(--mantine-color-body); + border-bottom: rem(1px) solid + light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); +} + +.inner { + /* height: rem(56px); */ + display: flex; + justify-content: space-between; + align-items: center; +} + +.link { + display: block; + line-height: 1; + padding: rem(8px) rem(12px); + border-radius: var(--mantine-radius-sm); + text-decoration: none; + color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); + font-size: var(--mantine-font-size-sm); + font-weight: 500; + cursor: pointer; + background: none; + border: none; + + @mixin hover { + background-color: light-dark( + var(--mantine-color-gray-0), + var(--mantine-color-dark-6) + ); + } + + [data-mantine-color-scheme] &[data-active] { + background-color: var(--mantine-primary-color-filled); + color: var(--mantine-color-white); + } +} diff --git a/my-shadcn-app/src/components/AppShell/internal/Header.tsx b/my-shadcn-app/src/components/AppShell/internal/Header.tsx new file mode 100644 index 00000000..4409b1d6 --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/internal/Header.tsx @@ -0,0 +1,34 @@ +import { Box, Container, Group } from "@mantine/core"; + +import SlotHeaderCenter from "../slot-header-center"; +import SlotHeaderLeft from "../slot-header-left"; +import SlotHeaderRight from "../slot-header-right"; +import { headerHeight } from "./config"; +import classes from "./Header.module.css"; +import HeaderMobileMenu from "./HeaderMobileMenu"; + +export function Header() { + return ( +
+ + + + + + + + + + + + + + +
+ ); +} diff --git a/my-shadcn-app/src/components/AppShell/internal/HeaderMobileMenu.tsx b/my-shadcn-app/src/components/AppShell/internal/HeaderMobileMenu.tsx new file mode 100644 index 00000000..910104fb --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/internal/HeaderMobileMenu.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { Burger, Menu } from "@mantine/core"; +import { useDisclosure } from "@mantine/hooks"; + +import SlotHeaderMobileMenuContent from "../slot-header-mobile-content"; + +export default function HeaderMobileMenu() { + const [opened, { toggle }] = useDisclosure(false); + + return ( + + + + + + + + + ); +} diff --git a/my-shadcn-app/src/components/AppShell/internal/HeaderNavLink.tsx b/my-shadcn-app/src/components/AppShell/internal/HeaderNavLink.tsx new file mode 100644 index 00000000..5da52246 --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/internal/HeaderNavLink.tsx @@ -0,0 +1,31 @@ +"use client"; + +import { type ProofKitRoute } from "@proofkit/cli"; +import { usePathname } from "next/navigation"; +import React from "react"; + +import classes from "./Header.module.css"; + +export default function HeaderNavLink(route: ProofKitRoute) { + const pathname = usePathname(); + + if (route.type === "function") { + return ; + } + + const isActive = route.exactMatch + ? pathname === route.href + : pathname.startsWith(route.href); + + if (route.type === "link") { + return ( + + {route.label} + + ); + } +} diff --git a/my-shadcn-app/src/components/AppShell/internal/config.ts b/my-shadcn-app/src/components/AppShell/internal/config.ts new file mode 100644 index 00000000..ded639d0 --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/internal/config.ts @@ -0,0 +1 @@ +export const headerHeight = 56; diff --git a/my-shadcn-app/src/components/AppShell/slot-header-center.tsx b/my-shadcn-app/src/components/AppShell/slot-header-center.tsx new file mode 100644 index 00000000..2de3b630 --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/slot-header-center.tsx @@ -0,0 +1,13 @@ +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects + * this file to exist and may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderCenter() { + return null; +} + +export default SlotHeaderCenter; diff --git a/my-shadcn-app/src/components/AppShell/slot-header-left.tsx b/my-shadcn-app/src/components/AppShell/slot-header-left.tsx new file mode 100644 index 00000000..781fcbce --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/slot-header-left.tsx @@ -0,0 +1,23 @@ +import Link from "next/link"; + +import AppLogo from "../AppLogo"; + +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects this file to exist and + * may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderLeft() { + return ( + <> + + + + + ); +} + +export default SlotHeaderLeft; diff --git a/my-shadcn-app/src/components/AppShell/slot-header-mobile-content.tsx b/my-shadcn-app/src/components/AppShell/slot-header-mobile-content.tsx new file mode 100644 index 00000000..9943f8a0 --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/slot-header-mobile-content.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { primaryRoutes } from "@/app/navigation"; +import { Menu } from "@mantine/core"; +import { useRouter } from "next/navigation"; + +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects + * this file to exist and may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderMobileMenuContent({ + closeMenu, +}: { + closeMenu: () => void; +}) { + const router = useRouter(); + return ( + <> + {primaryRoutes.map((route) => ( + { + closeMenu(); + if (route.type === "function") { + route.onClick(); + } else if (route.type === "link") { + router.push(route.href); + } + }} + > + {route.label} + + ))} + + ); +} + +export default SlotHeaderMobileMenuContent; diff --git a/my-shadcn-app/src/components/AppShell/slot-header-right.tsx b/my-shadcn-app/src/components/AppShell/slot-header-right.tsx new file mode 100644 index 00000000..6c392c95 --- /dev/null +++ b/my-shadcn-app/src/components/AppShell/slot-header-right.tsx @@ -0,0 +1,26 @@ +import { primaryRoutes } from "@/app/navigation"; +import { Group } from "@mantine/core"; + +import HeaderNavLink from "./internal/HeaderNavLink"; + +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects + * this file to exist and may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderRight() { + return ( + <> + + {primaryRoutes.map((route) => ( + + ))} + + + ); +} + +export default SlotHeaderRight; diff --git a/my-shadcn-app/src/config/env.ts b/my-shadcn-app/src/config/env.ts new file mode 100644 index 00000000..3c50ef8d --- /dev/null +++ b/my-shadcn-app/src/config/env.ts @@ -0,0 +1,13 @@ +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod/v4"; + +export const env = createEnv({ + server: { + NODE_ENV: z + .enum(["development", "test", "production"]) + .default("development"), + }, + client: {}, + // For Next.js >= 13.4.4, you only need to destructure client variables: + experimental__runtimeEnv: {}, +}); diff --git a/my-shadcn-app/src/config/theme/globals.css b/my-shadcn-app/src/config/theme/globals.css new file mode 100644 index 00000000..0e2f76bb --- /dev/null +++ b/my-shadcn-app/src/config/theme/globals.css @@ -0,0 +1,125 @@ +/* Add global styles here */ + +@import "tailwindcss" prefix(tw); +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.145 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.145 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.985 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.396 0.141 25.723); + --destructive-foreground: oklch(0.637 0.237 25.331); + --border: oklch(0.269 0 0); + --input: oklch(0.269 0 0); + --ring: oklch(0.439 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(0.269 0 0); + --sidebar-ring: oklch(0.439 0 0); +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +@layer base { + * { + @apply tw:border-border tw:outline-ring/50; + } + body { + @apply tw:bg-background tw:text-foreground; + } +} diff --git a/my-shadcn-app/src/config/theme/mantine-theme.ts b/my-shadcn-app/src/config/theme/mantine-theme.ts new file mode 100644 index 00000000..890db89c --- /dev/null +++ b/my-shadcn-app/src/config/theme/mantine-theme.ts @@ -0,0 +1,22 @@ +import { createTheme, type MantineColorsTuple } from "@mantine/core"; + +// generate your own set of colors here: https://mantine.dev/colors-generator +const brandColor: MantineColorsTuple = [ + "#ffebff", + "#f5d5fb", + "#e6a8f3", + "#d779eb", + "#cb51e4", + "#c337e0", + "#c029df", + "#a91cc6", + "#9715b1", + "#84099c", +]; + +export const theme = createTheme({ + primaryColor: "brand", + colors: { + brand: brandColor, + }, +}); diff --git a/my-shadcn-app/src/server/safe-action.ts b/my-shadcn-app/src/server/safe-action.ts new file mode 100644 index 00000000..7f62198a --- /dev/null +++ b/my-shadcn-app/src/server/safe-action.ts @@ -0,0 +1,3 @@ +import { createSafeActionClient } from "next-safe-action"; + +export const actionClient = createSafeActionClient(); diff --git a/my-shadcn-app/src/utils/notification-helpers.ts b/my-shadcn-app/src/utils/notification-helpers.ts new file mode 100644 index 00000000..771fdffe --- /dev/null +++ b/my-shadcn-app/src/utils/notification-helpers.ts @@ -0,0 +1,32 @@ +import { + showNotification, + type NotificationData, +} from "@mantine/notifications"; + +export function showErrorNotification(): void; +export function showErrorNotification(props: NotificationData): void; +export function showErrorNotification(message: string): void; +export function showErrorNotification(args?: string | NotificationData): void { + const message = + typeof args === "string" ? args : "An unexpected error occurred."; + const defaultProps = typeof args === "string" ? {} : (args ?? {}); + + showNotification({ color: "red", title: "Error", message, ...defaultProps }); +} + +export function showSuccessNotification(): void; +export function showSuccessNotification(props: NotificationData): void; +export function showSuccessNotification(message: string): void; +export function showSuccessNotification( + args?: string | NotificationData +): void { + const message = typeof args === "string" ? args : "Success!"; + const defaultProps = typeof args === "string" ? {} : (args ?? {}); + + showNotification({ + color: "green", + title: "Success", + message, + ...defaultProps, + }); +} diff --git a/my-shadcn-app/src/utils/styles.ts b/my-shadcn-app/src/utils/styles.ts new file mode 100644 index 00000000..1f4cd38e --- /dev/null +++ b/my-shadcn-app/src/utils/styles.ts @@ -0,0 +1,6 @@ +import { clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: any[]) { + return twMerge(clsx(inputs)); +} diff --git a/my-shadcn-app/tsconfig.json b/my-shadcn-app/tsconfig.json new file mode 100644 index 00000000..f48e7ee6 --- /dev/null +++ b/my-shadcn-app/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./src/*" + ] + }, + "target": "ES2017" + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/packages/cli/src/cli/add/auth.ts b/packages/cli/src/cli/add/auth.ts index 8b389ba0..9e5208dd 100644 --- a/packages/cli/src/cli/add/auth.ts +++ b/packages/cli/src/cli/add/auth.ts @@ -14,6 +14,11 @@ export async function runAddAuthAction() { if (settings.appType !== "browser") { return p.cancel(`Auth is not supported for your app type.`); } + if (settings.ui === "shadcn") { + return p.cancel( + "Adding auth is not yet supported for shadcn-based projects." + ); + } const authType = state.authType ?? diff --git a/packages/cli/src/cli/add/index.ts b/packages/cli/src/cli/add/index.ts index 5989d7b5..2d1301de 100644 --- a/packages/cli/src/cli/add/index.ts +++ b/packages/cli/src/cli/add/index.ts @@ -47,6 +47,15 @@ export const runAdd = async (name: string | undefined) => { }) ); + // For shadcn projects, block adding new pages or auth for now + if (settings.ui === "shadcn") { + if (addType === "page" || addType === "auth") { + return p.cancel( + "Adding new pages or auth is not yet supported for shadcn-based projects." + ); + } + } + if (addType === "auth") { await runAddAuthAction(); } else if (addType === "data") { diff --git a/packages/cli/src/cli/add/page/index.ts b/packages/cli/src/cli/add/page/index.ts index a4eec2dd..79c9ca6f 100644 --- a/packages/cli/src/cli/add/page/index.ts +++ b/packages/cli/src/cli/add/page/index.ts @@ -29,6 +29,11 @@ export const runAddPageAction = async (opts?: { const projectDir = state.projectDir; const settings = getSettings(); + if (settings.ui === "shadcn") { + return p.cancel( + "Adding pages is not yet supported for shadcn-based projects." + ); + } const templates = state.appType === "browser" diff --git a/packages/cli/src/cli/init.ts b/packages/cli/src/cli/init.ts index e8e05c09..87c8c468 100644 --- a/packages/cli/src/cli/init.ts +++ b/packages/cli/src/cli/init.ts @@ -24,6 +24,7 @@ import { parseNameAndPath } from "~/utils/parseNameAndPath.js"; import { validateAppName } from "~/utils/validateAppName.js"; import { promptForFileMakerDataSource } from "./add/data-source/filemaker.js"; import { abortIfCancel } from "./utils.js"; +import { setSettings, type Settings } from "~/utils/parseSettings.js"; interface CliFlags { noGit: boolean; @@ -39,6 +40,8 @@ interface CliFlags { fmServerURL: string; auth: "none" | "next-auth" | "clerk"; dataSource?: "filemaker" | "none" | "supabase"; + /** @internal UI library selection; hidden flag */ + ui?: "shadcn" | "mantine"; /** @internal Used in CI. */ CI: boolean; /** @internal Used in CI. */ @@ -72,6 +75,7 @@ const defaultOptions: CliFlags = { dataApiKey: "", fmServerURL: "", dataSource: undefined, + ui: "shadcn", }; export const makeInitCommand = () => { @@ -82,6 +86,8 @@ export const makeInitCommand = () => { "The name of the application, as well as the name of the directory to create" ) .option("--appType [type]", "The type of app to create", undefined) + // hidden UI selector; default is shadcn; pass --ui mantine to opt-in legacy Mantine templates + .option("--ui [ui]", undefined, undefined) .option("--server [url]", "The URL of your FileMaker Server", undefined) .option( "--adminApiKey [key]", @@ -166,6 +172,8 @@ type ProofKitPackageJSON = PackageJson & { export const runInit = async (name?: string, opts?: CliFlags) => { const pkgManager = getUserPkgManager(); const cliOptions = opts ?? defaultOptions; + // capture ui choice early into state + state.ui = (cliOptions.ui ?? "shadcn") as "shadcn" | "mantine"; const projectName = name || @@ -238,6 +246,19 @@ export const runInit = async (name?: string, opts?: CliFlags) => { spaces: 2, }); + // Ensure proofkit.json exists with initial settings including ui + const initialSettings: Settings = { + appType: state.appType ?? "browser", + ui: (state.ui as "shadcn" | "mantine") ?? "shadcn", + auth: { type: "none" }, + envFile: ".env", + dataSources: [], + tanstackQuery: false, + replacedMainPage: false, + appliedUpgrades: ["cursorRules"], + }; + setSettings(initialSettings); + // for webviewer apps FM is required, so don't ask let dataSource = state.appType === "webviewer" ? "filemaker" : cliOptions.dataSource; diff --git a/packages/cli/src/helpers/createProject.ts b/packages/cli/src/helpers/createProject.ts index ea397701..1f810c04 100644 --- a/packages/cli/src/helpers/createProject.ts +++ b/packages/cli/src/helpers/createProject.ts @@ -34,9 +34,9 @@ export const createBareProject = async ({ noInstall, }); - // Add new base dependencies for Tailwind v4 and shadcn/ui + // Add new base dependencies for Tailwind v4 and shadcn/ui or legacy Mantine // These should match the plan and dependencyVersionMap - const BASE_DEPS = [ + const SHADCN_BASE_DEPS = [ "@radix-ui/react-slot", "@tailwindcss/postcss", "class-variance-authority", @@ -46,18 +46,43 @@ export const createBareProject = async ({ "tailwindcss", "tw-animate-css", ] as AvailableDependencies[]; - const BASE_DEV_DEPS = [ + const SHADCN_BASE_DEV_DEPS = [ "prettier", "prettier-plugin-tailwindcss", ] as AvailableDependencies[]; + const MANTINE_DEPS = [ + "@mantine/core", + "@mantine/dates", + "@mantine/hooks", + "@mantine/modals", + "@mantine/notifications", + "mantine-react-table", + ] as AvailableDependencies[]; + const MANTINE_DEV_DEPS = [ + "postcss", + "postcss-preset-mantine", + "postcss-simple-vars", + ] as AvailableDependencies[]; + + // Transitional: until all templates/components are fully shadcn, include Mantine deps as well + addPackageDependency({ + dependencies: SHADCN_BASE_DEPS, + devMode: false, + projectDir: state.projectDir, + }); + addPackageDependency({ + dependencies: SHADCN_BASE_DEV_DEPS, + devMode: true, + projectDir: state.projectDir, + }); addPackageDependency({ - dependencies: BASE_DEPS, + dependencies: MANTINE_DEPS, devMode: false, projectDir: state.projectDir, }); addPackageDependency({ - dependencies: BASE_DEV_DEPS, + dependencies: MANTINE_DEV_DEPS, devMode: true, projectDir: state.projectDir, }); diff --git a/packages/cli/src/state.ts b/packages/cli/src/state.ts index e4c8ac78..14101099 100644 --- a/packages/cli/src/state.ts +++ b/packages/cli/src/state.ts @@ -10,6 +10,7 @@ const schema = z .optional() .catch(undefined), appType: z.enum(["browser", "webviewer"]).optional().catch(undefined), + ui: z.enum(["shadcn", "mantine"]).optional().catch(undefined), projectDir: z.string().default(process.cwd()), authType: z.enum(["clerk", "fmaddon"]).optional(), emailProvider: z.enum(["plunk", "resend", "none"]).optional(), diff --git a/packages/cli/src/utils/parseSettings.ts b/packages/cli/src/utils/parseSettings.ts index 5bd0f4a0..58d3b24f 100644 --- a/packages/cli/src/utils/parseSettings.ts +++ b/packages/cli/src/utils/parseSettings.ts @@ -44,8 +44,12 @@ export type DataSource = z.infer; export const appTypes = ["browser", "webviewer"] as const; +export const uiTypes = ["shadcn", "mantine"] as const; +export type Ui = (typeof uiTypes)[number]; + const settingsSchema = z.object({ appType: z.enum(appTypes).default("browser"), + ui: z.enum(uiTypes).default("shadcn"), auth: authSchema, envFile: z.string().default(".env"), dataSources: z.array(dataSourceSchema).default([]), @@ -60,11 +64,37 @@ let settings: Settings | undefined; export const getSettings = () => { if (settings) return settings; - const settingsFile: unknown = fs.readJSONSync( - path.join(state.projectDir, "proofkit.json") - ); + const settingsPath = path.join(state.projectDir, "proofkit.json"); + const settingsFile: unknown = fs.readJSONSync(settingsPath); const parsed = settingsSchema.parse(settingsFile); + + // Persist missing ui field for older projects; auto-detect mantine if present + const hasUiInFile = typeof (settingsFile as Record)?.ui === "string"; + if (!hasUiInFile) { + try { + const pkgJson = fs.readJSONSync(path.join(state.projectDir, "package.json")) as { + dependencies?: Record; + devDependencies?: Record; + }; + const depHas = (name: string) => + Boolean(pkgJson.dependencies?.[name] || pkgJson.devDependencies?.[name]); + const detectedUi: Ui = depHas("@mantine/core") ? "mantine" : "shadcn"; + const nextSettings = { ...parsed, ui: detectedUi } as Settings; + fs.writeJSONSync(settingsPath, nextSettings, { spaces: 2 }); + settings = nextSettings; + state.appType = nextSettings.appType; + return settings; + } catch { + // If detection fails, just persist default + const nextSettings = { ...parsed } as Settings; + fs.writeJSONSync(settingsPath, nextSettings, { spaces: 2 }); + settings = nextSettings; + state.appType = nextSettings.appType; + return settings; + } + } + settings = parsed; state.appType = parsed.appType; return settings; diff --git a/packages/cli/template/nextjs/proofkit.json b/packages/cli/template/nextjs/proofkit.json index daca7e48..6aca1027 100644 --- a/packages/cli/template/nextjs/proofkit.json +++ b/packages/cli/template/nextjs/proofkit.json @@ -2,5 +2,6 @@ "auth": { "type": "none" }, "envFile": ".env", "appType": "browser", + "ui": "shadcn", "appliedUpgrades": ["shadcn", "cursorRules"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 42a442e1..b1eccb95 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,10 +10,6 @@ overrides: importers: .: - dependencies: - '@proofkit/better-auth': - specifier: link:../../../../Library/pnpm/global/5/node_modules/@proofkit/better-auth - version: link:../../../../Library/pnpm/global/5/node_modules/@proofkit/better-auth devDependencies: '@changesets/cli': specifier: ^2.29.3 @@ -46,8 +42,8 @@ importers: specifier: ^1.2.10 version: 1.2.10(@libsql/client@0.6.2)(@planetscale/database@1.19.0)(@types/react@19.1.8)(kysely@0.28.2)(magicast@0.3.5)(mysql2@3.14.1)(postgres@3.4.5)(react@19.1.0) '@proofkit/better-auth': - specifier: link:../../../../../../Library/pnpm/global/5/node_modules/@proofkit/better-auth - version: link:../../../../../../Library/pnpm/global/5/node_modules/@proofkit/better-auth + specifier: link:../../../Library/pnpm/global/5/node_modules/@proofkit/better-auth + version: link:../../../Library/pnpm/global/5/node_modules/@proofkit/better-auth '@proofkit/fmdapi': specifier: workspace:* version: link:../../packages/fmdapi @@ -552,8 +548,6 @@ importers: specifier: ^3.2.3 version: 3.2.3(@types/debug@4.1.12)(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@22.15.32)(typescript@5.8.3))(yaml@2.8.0) - packages/tmp: {} - packages/typegen: dependencies: '@clack/prompts': @@ -11568,7 +11562,7 @@ snapshots: '@typescript-eslint/parser': 8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3) eslint: 9.27.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2)))(eslint@9.27.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@9.27.0(jiti@2.4.2)) eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.27.0(jiti@2.4.2)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.27.0(jiti@2.4.2)) eslint-plugin-react: 7.37.5(eslint@9.27.0(jiti@2.4.2)) @@ -11588,7 +11582,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2)))(eslint@9.27.0(jiti@2.4.2)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0)(eslint@9.27.0(jiti@2.4.2)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 @@ -11603,14 +11597,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2)))(eslint@9.27.0(jiti@2.4.2)))(eslint@9.27.0(jiti@2.4.2)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.27.0(jiti@2.4.2)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3) eslint: 9.27.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2)))(eslint@9.27.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@9.27.0(jiti@2.4.2)) transitivePeerDependencies: - supports-color @@ -11625,7 +11619,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.27.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2)))(eslint@9.27.0(jiti@2.4.2)))(eslint@9.27.0(jiti@2.4.2)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.33.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.27.0(jiti@2.4.2)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 From ead936d7852d882a1deffc51f2a98920cd1f18dc Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 8 Aug 2025 20:46:42 +0000 Subject: [PATCH 2/5] Add Mantine and Shadcn UI templates with core project structure Co-authored-by: eric.luce --- packages/cli/src/helpers/createProject.ts | 44 +++--- packages/cli/src/helpers/scaffoldProject.ts | 4 +- .../cli/template/nextjs-mantine/.prettierrc | 3 + .../cli/template/nextjs-mantine/README.md | 27 ++++ .../cli/template/nextjs-mantine/_gitignore | 37 ++++++ .../template/nextjs-mantine/components.json | 21 +++ .../template/nextjs-mantine/next.config.ts | 12 ++ .../cli/template/nextjs-mantine/package.json | 50 +++++++ .../nextjs-mantine/postcss.config.cjs | 15 +++ .../cli/template/nextjs-mantine/proofkit.json | 7 + .../nextjs-mantine/public/favicon.ico | Bin 0 -> 15086 bytes .../nextjs-mantine/public/proofkit.png | Bin 0 -> 52140 bytes .../nextjs-mantine/src/app/(main)/layout.tsx | 6 + .../nextjs-mantine/src/app/(main)/page.tsx | 90 +++++++++++++ .../nextjs-mantine/src/app/layout.tsx | 39 ++++++ .../nextjs-mantine/src/app/navigation.tsx | 12 ++ .../nextjs-mantine/src/components/AppLogo.tsx | 6 + .../components/AppShell/internal/AppShell.tsx | 21 +++ .../AppShell/internal/Header.module.css | 40 ++++++ .../components/AppShell/internal/Header.tsx | 34 +++++ .../AppShell/internal/HeaderMobileMenu.tsx | 27 ++++ .../AppShell/internal/HeaderNavLink.tsx | 31 +++++ .../components/AppShell/internal/config.ts | 1 + .../AppShell/slot-header-center.tsx | 13 ++ .../components/AppShell/slot-header-left.tsx | 23 ++++ .../AppShell/slot-header-mobile-content.tsx | 43 ++++++ .../components/AppShell/slot-header-right.tsx | 26 ++++ .../template/nextjs-mantine/src/config/env.ts | 13 ++ .../src/config/theme/globals.css | 125 ++++++++++++++++++ .../src/config/theme/mantine-theme.ts | 22 +++ .../nextjs-mantine/src/server/safe-action.ts | 3 + .../src/utils/notification-helpers.ts | 32 +++++ .../nextjs-mantine/src/utils/styles.ts | 6 + .../cli/template/nextjs-mantine/tsconfig.json | 40 ++++++ .../cli/template/nextjs-shadcn/.prettierrc | 3 + packages/cli/template/nextjs-shadcn/README.md | 27 ++++ .../cli/template/nextjs-shadcn/_gitignore | 37 ++++++ .../template/nextjs-shadcn/components.json | 21 +++ .../cli/template/nextjs-shadcn/next.config.ts | 12 ++ .../cli/template/nextjs-shadcn/package.json | 42 ++++++ .../template/nextjs-shadcn/postcss.config.cjs | 15 +++ .../cli/template/nextjs-shadcn/proofkit.json | 7 + .../template/nextjs-shadcn/public/favicon.ico | Bin 0 -> 15086 bytes .../nextjs-shadcn/public/proofkit.png | Bin 0 -> 52140 bytes .../nextjs-shadcn/src/app/(main)/layout.tsx | 6 + .../nextjs-shadcn/src/app/(main)/page.tsx | 90 +++++++++++++ .../template/nextjs-shadcn/src/app/layout.tsx | 20 +++ .../nextjs-shadcn/src/app/navigation.tsx | 12 ++ .../nextjs-shadcn/src/components/AppLogo.tsx | 6 + .../components/AppShell/internal/AppShell.tsx | 21 +++ .../AppShell/internal/Header.module.css | 40 ++++++ .../components/AppShell/internal/Header.tsx | 34 +++++ .../AppShell/internal/HeaderMobileMenu.tsx | 27 ++++ .../AppShell/internal/HeaderNavLink.tsx | 31 +++++ .../components/AppShell/internal/config.ts | 1 + .../AppShell/slot-header-center.tsx | 13 ++ .../components/AppShell/slot-header-left.tsx | 23 ++++ .../AppShell/slot-header-mobile-content.tsx | 43 ++++++ .../components/AppShell/slot-header-right.tsx | 26 ++++ .../template/nextjs-shadcn/src/config/env.ts | 13 ++ .../src/config/theme/globals.css | 125 ++++++++++++++++++ .../src/config/theme/mantine-theme.ts | 22 +++ .../nextjs-shadcn/src/server/safe-action.ts | 3 + .../src/utils/notification-helpers.ts | 32 +++++ .../nextjs-shadcn/src/utils/styles.ts | 6 + .../cli/template/nextjs-shadcn/tsconfig.json | 40 ++++++ 66 files changed, 1649 insertions(+), 22 deletions(-) create mode 100644 packages/cli/template/nextjs-mantine/.prettierrc create mode 100644 packages/cli/template/nextjs-mantine/README.md create mode 100644 packages/cli/template/nextjs-mantine/_gitignore create mode 100644 packages/cli/template/nextjs-mantine/components.json create mode 100644 packages/cli/template/nextjs-mantine/next.config.ts create mode 100644 packages/cli/template/nextjs-mantine/package.json create mode 100644 packages/cli/template/nextjs-mantine/postcss.config.cjs create mode 100644 packages/cli/template/nextjs-mantine/proofkit.json create mode 100644 packages/cli/template/nextjs-mantine/public/favicon.ico create mode 100644 packages/cli/template/nextjs-mantine/public/proofkit.png create mode 100644 packages/cli/template/nextjs-mantine/src/app/(main)/layout.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/app/(main)/page.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/app/layout.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/app/navigation.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppLogo.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/internal/AppShell.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/internal/Header.module.css create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/internal/Header.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/internal/HeaderMobileMenu.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/internal/HeaderNavLink.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/internal/config.ts create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-center.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-left.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-mobile-content.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-right.tsx create mode 100644 packages/cli/template/nextjs-mantine/src/config/env.ts create mode 100644 packages/cli/template/nextjs-mantine/src/config/theme/globals.css create mode 100644 packages/cli/template/nextjs-mantine/src/config/theme/mantine-theme.ts create mode 100644 packages/cli/template/nextjs-mantine/src/server/safe-action.ts create mode 100644 packages/cli/template/nextjs-mantine/src/utils/notification-helpers.ts create mode 100644 packages/cli/template/nextjs-mantine/src/utils/styles.ts create mode 100644 packages/cli/template/nextjs-mantine/tsconfig.json create mode 100644 packages/cli/template/nextjs-shadcn/.prettierrc create mode 100644 packages/cli/template/nextjs-shadcn/README.md create mode 100644 packages/cli/template/nextjs-shadcn/_gitignore create mode 100644 packages/cli/template/nextjs-shadcn/components.json create mode 100644 packages/cli/template/nextjs-shadcn/next.config.ts create mode 100644 packages/cli/template/nextjs-shadcn/package.json create mode 100644 packages/cli/template/nextjs-shadcn/postcss.config.cjs create mode 100644 packages/cli/template/nextjs-shadcn/proofkit.json create mode 100644 packages/cli/template/nextjs-shadcn/public/favicon.ico create mode 100644 packages/cli/template/nextjs-shadcn/public/proofkit.png create mode 100644 packages/cli/template/nextjs-shadcn/src/app/(main)/layout.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/app/layout.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/app/navigation.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppLogo.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.module.css create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderMobileMenu.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderNavLink.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/config.ts create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-center.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-left.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-mobile-content.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/config/env.ts create mode 100644 packages/cli/template/nextjs-shadcn/src/config/theme/globals.css create mode 100644 packages/cli/template/nextjs-shadcn/src/config/theme/mantine-theme.ts create mode 100644 packages/cli/template/nextjs-shadcn/src/server/safe-action.ts create mode 100644 packages/cli/template/nextjs-shadcn/src/utils/notification-helpers.ts create mode 100644 packages/cli/template/nextjs-shadcn/src/utils/styles.ts create mode 100644 packages/cli/template/nextjs-shadcn/tsconfig.json diff --git a/packages/cli/src/helpers/createProject.ts b/packages/cli/src/helpers/createProject.ts index 1f810c04..32231e27 100644 --- a/packages/cli/src/helpers/createProject.ts +++ b/packages/cli/src/helpers/createProject.ts @@ -65,27 +65,29 @@ export const createBareProject = async ({ "postcss-simple-vars", ] as AvailableDependencies[]; - // Transitional: until all templates/components are fully shadcn, include Mantine deps as well - addPackageDependency({ - dependencies: SHADCN_BASE_DEPS, - devMode: false, - projectDir: state.projectDir, - }); - addPackageDependency({ - dependencies: SHADCN_BASE_DEV_DEPS, - devMode: true, - projectDir: state.projectDir, - }); - addPackageDependency({ - dependencies: MANTINE_DEPS, - devMode: false, - projectDir: state.projectDir, - }); - addPackageDependency({ - dependencies: MANTINE_DEV_DEPS, - devMode: true, - projectDir: state.projectDir, - }); + if (state.ui === "mantine") { + addPackageDependency({ + dependencies: MANTINE_DEPS, + devMode: false, + projectDir: state.projectDir, + }); + addPackageDependency({ + dependencies: MANTINE_DEV_DEPS, + devMode: true, + projectDir: state.projectDir, + }); + } else { + addPackageDependency({ + dependencies: SHADCN_BASE_DEPS, + devMode: false, + projectDir: state.projectDir, + }); + addPackageDependency({ + dependencies: SHADCN_BASE_DEV_DEPS, + devMode: true, + projectDir: state.projectDir, + }); + } // Install the selected packages installPackages({ diff --git a/packages/cli/src/helpers/scaffoldProject.ts b/packages/cli/src/helpers/scaffoldProject.ts index 8ea7ed4c..c185197e 100644 --- a/packages/cli/src/helpers/scaffoldProject.ts +++ b/packages/cli/src/helpers/scaffoldProject.ts @@ -20,7 +20,9 @@ export const scaffoldProject = async ({ const srcDir = path.join( PKG_ROOT, - state.appType === "browser" ? "template/nextjs" : "template/vite-wv" + state.appType === "browser" + ? `template/${state.ui === "mantine" ? "nextjs-mantine" : "nextjs-shadcn"}` + : "template/vite-wv" ); if (!noInstall) { diff --git a/packages/cli/template/nextjs-mantine/.prettierrc b/packages/cli/template/nextjs-mantine/.prettierrc new file mode 100644 index 00000000..b4bfed35 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/.prettierrc @@ -0,0 +1,3 @@ +{ + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/packages/cli/template/nextjs-mantine/README.md b/packages/cli/template/nextjs-mantine/README.md new file mode 100644 index 00000000..4f416a4a --- /dev/null +++ b/packages/cli/template/nextjs-mantine/README.md @@ -0,0 +1,27 @@ +# ProofKit NextJS Template + +This is a [NextJS](https://nextjs.org/) project bootstrapped with `@proofkit/cli`. Learn more at [proofkit.dev](https://proofkit.dev) + +## What's next? How do I make an app with this? + +While this template is designed to be a minimal starting point, the proofkit CLI will guide you through adding additional features and pages. + +To add new things to your project, simply run the `proofkit` script from the project's root directory. + +e.g. `npm run proofkit` or `pnpm proofkit` etc. + +For more information, see the full [ProofKit documentation](https://proofkit.dev). + +## Project Structure + +ProofKit projects have an opinionated structure to help you get started and some conventions must be maintained to ensure that the CLI can properly inject new features and components. + +The `src` directory is the home for your application code. It is used for most things except for configuration and is organized as follows: + +- `app` - NextJS app router, where your pages and routes are defined +- `components` - Shared components used throughout the app +- `server` - Code that connects to backend databases and services that should not be exposed in the browser + +Anytime you see an `internal` folder, you should not modify any files inside. These files are maintained exclusively by the ProofKit CLI and changes to them may be overwritten. + +Anytime you see a componet file that begins with `slot-`, you _may_ modify the content, but do not rename, remove, or move them. These are desigend to be customized, but are still used by the CLI to inject additional content. If a slot is not needed by your app, you can have the compoment return `null` or an empty fragment: `<>` diff --git a/packages/cli/template/nextjs-mantine/_gitignore b/packages/cli/template/nextjs-mantine/_gitignore new file mode 100644 index 00000000..00bba9bb --- /dev/null +++ b/packages/cli/template/nextjs-mantine/_gitignore @@ -0,0 +1,37 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/packages/cli/template/nextjs-mantine/components.json b/packages/cli/template/nextjs-mantine/components.json new file mode 100644 index 00000000..0d27c449 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/config/theme/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "tw:" + }, + "aliases": { + "components": "@/components", + "utils": "@/utils/styles", + "ui": "@/components/ui", + "lib": "@/utils", + "hooks": "@/utils/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/packages/cli/template/nextjs-mantine/next.config.ts b/packages/cli/template/nextjs-mantine/next.config.ts new file mode 100644 index 00000000..9555317e --- /dev/null +++ b/packages/cli/template/nextjs-mantine/next.config.ts @@ -0,0 +1,12 @@ +import { type NextConfig } from "next"; + +// Import env here to validate during build. +import "./src/config/env"; + +const nextConfig: NextConfig = { + experimental: { + optimizePackageImports: ["@mantine/core", "@mantine/hooks"], + }, +}; + +export default nextConfig; diff --git a/packages/cli/template/nextjs-mantine/package.json b/packages/cli/template/nextjs-mantine/package.json new file mode 100644 index 00000000..70024ab7 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/package.json @@ -0,0 +1,50 @@ +{ + "name": "template", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev --turbopack", + "build": "next build", + "start": "next start", + "lint": "next lint", + "proofkit": "proofkit", + "typegen": "proofkit typegen", + "deploy": "proofkit deploy" + }, + "dependencies": { + "@hookform/resolvers": "^5.1.1", + "@next-safe-action/adapter-react-hook-form": "^2.0.0", + "next-safe-action": "^8.0.4", + "react-hook-form": "^7.54.2", + "@tabler/icons-react": "^3.30.0", + "@mantine/core": "^7.17.0", + "@mantine/dates": "^7.17.0", + "@mantine/hooks": "^7.17.0", + "@mantine/modals": "^7.17.0", + "@mantine/notifications": "^7.17.0", + "mantine-react-table": "2.0.0-beta.9", + "@t3-oss/env-nextjs": "^0.12.0", + "dayjs": "^1.11.13", + "next": "^15.2.3", + "react": "19.0.0", + "react-dom": "19.0.0", + "zod": "^3.24.2" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "npm:types-react@19.0.12", + "@types/react-dom": "npm:types-react-dom@19.0.4", + "eslint": "^9.14.0", + "eslint-config-next": "15.2.3", + "postcss": "^8.4.41", + "postcss-preset-mantine": "^1.17.0", + "postcss-simple-vars": "^7.0.1", + "typescript": "^5" + }, + "pnpm": { + "overrides": { + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" + } + } +} diff --git a/packages/cli/template/nextjs-mantine/postcss.config.cjs b/packages/cli/template/nextjs-mantine/postcss.config.cjs new file mode 100644 index 00000000..085a0ef9 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/postcss.config.cjs @@ -0,0 +1,15 @@ +module.exports = { + plugins: { + "@tailwindcss/postcss": {}, + "postcss-preset-mantine": {}, + "postcss-simple-vars": { + variables: { + "mantine-breakpoint-xs": "36em", + "mantine-breakpoint-sm": "48em", + "mantine-breakpoint-md": "62em", + "mantine-breakpoint-lg": "75em", + "mantine-breakpoint-xl": "88em", + }, + }, + }, +}; diff --git a/packages/cli/template/nextjs-mantine/proofkit.json b/packages/cli/template/nextjs-mantine/proofkit.json new file mode 100644 index 00000000..c536f9bf --- /dev/null +++ b/packages/cli/template/nextjs-mantine/proofkit.json @@ -0,0 +1,7 @@ +{ + "auth": { "type": "none" }, + "envFile": ".env", + "appType": "browser", + "ui": "mantine", + "appliedUpgrades": ["cursorRules"] +} diff --git a/packages/cli/template/nextjs-mantine/public/favicon.ico b/packages/cli/template/nextjs-mantine/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ba9355b8d3f888ad3a93c0f254b6776a0c2aed92 GIT binary patch literal 15086 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 DtPcMKfsh_-A)LFM)6iMLm_0IRoy0b^RZ#+}< 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 b29HP@D9EFJDBd}ZfIn(VT8gjb%^v(OKI6J9 literal 0 HcmV?d00001 diff --git a/packages/cli/template/nextjs-mantine/src/app/(main)/layout.tsx b/packages/cli/template/nextjs-mantine/src/app/(main)/layout.tsx new file mode 100644 index 00000000..57a8452b --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/app/(main)/layout.tsx @@ -0,0 +1,6 @@ +import AppShell from "@/components/AppShell/internal/AppShell"; +import React from "react"; + +export default function Layout({ children }: { children: React.ReactNode }) { + return {children}; +} diff --git a/packages/cli/template/nextjs-mantine/src/app/(main)/page.tsx b/packages/cli/template/nextjs-mantine/src/app/(main)/page.tsx new file mode 100644 index 00000000..0f180c04 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/app/(main)/page.tsx @@ -0,0 +1,90 @@ +import { + ActionIcon, + Anchor, + AppShellFooter, + Box, + Code, + Container, + Group, + Image, + px, + Stack, + Text, + Title, +} from "@mantine/core"; +import { IconBrandGithub, IconExternalLink } from "@tabler/icons-react"; + +export default function Home() { + return ( + <> + + + ProofKit + Welcome! + + + This is the base template home page. To add more pages, components, + or other features, run the ProofKit CLI from within your project. + + __PNPM_COMMAND__ proofkit + + + To change this page, open src/app/(main)/page.tsx + + + + ProofKit Docs + + + + + + + + + + Sponsored by{" "} + + Proof+Geist + {" "} + and{" "} + + Ottomatic + + + + + + + + + + + + + + + ); +} diff --git a/packages/cli/template/nextjs-mantine/src/app/layout.tsx b/packages/cli/template/nextjs-mantine/src/app/layout.tsx new file mode 100644 index 00000000..9512cb63 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/app/layout.tsx @@ -0,0 +1,39 @@ +import { Suspense } from "react"; +import { theme } from "@/config/theme/mantine-theme"; +import { ColorSchemeScript, MantineProvider } from "@mantine/core"; +import { ModalsProvider } from "@mantine/modals"; +import { Notifications } from "@mantine/notifications"; + +import "@mantine/core/styles.css"; +import "@mantine/notifications/styles.css"; +import "@mantine/dates/styles.css"; +import "mantine-react-table/styles.css"; +import "@/config/theme/globals.css"; + +import { type Metadata } from "next"; + +export const metadata: Metadata = { + title: "My ProofKit App", + description: "Generated by proofkit", + icons: [{ rel: "icon", url: "/favicon.ico" }], +}; + +export default function RootLayout({ + children, +}: Readonly<{ children: React.ReactNode }>) { + return ( + + + + + + + + + + {children} + + + + ); +} diff --git a/packages/cli/template/nextjs-mantine/src/app/navigation.tsx b/packages/cli/template/nextjs-mantine/src/app/navigation.tsx new file mode 100644 index 00000000..887073db --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/app/navigation.tsx @@ -0,0 +1,12 @@ +import { type ProofKitRoute } from "@proofkit/cli"; + +export const primaryRoutes: ProofKitRoute[] = [ + { + label: "Dashboard", + type: "link", + href: "/", + exactMatch: true, + }, +]; + +export const secondaryRoutes: ProofKitRoute[] = []; diff --git a/packages/cli/template/nextjs-mantine/src/components/AppLogo.tsx b/packages/cli/template/nextjs-mantine/src/components/AppLogo.tsx new file mode 100644 index 00000000..f5ea4966 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppLogo.tsx @@ -0,0 +1,6 @@ +import { IconInfinity } from "@tabler/icons-react"; +import React from "react"; + +export default function AppLogo() { + return ; +} diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/AppShell.tsx b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/AppShell.tsx new file mode 100644 index 00000000..8c4270df --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/AppShell.tsx @@ -0,0 +1,21 @@ +import { Header } from "@/components/AppShell/internal/Header"; +import { AppShell, AppShellHeader, AppShellMain } from "@mantine/core"; +import React from "react"; + +import { headerHeight } from "./config"; + +export default function MainAppShell({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + +
+ + + {children} + + ); +} diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/Header.module.css b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/Header.module.css new file mode 100644 index 00000000..79d81bad --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/Header.module.css @@ -0,0 +1,40 @@ +.header { + /* height: rem(56px); */ + margin-bottom: rem(120px); + background-color: var(--mantine-color-body); + border-bottom: rem(1px) solid + light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); +} + +.inner { + /* height: rem(56px); */ + display: flex; + justify-content: space-between; + align-items: center; +} + +.link { + display: block; + line-height: 1; + padding: rem(8px) rem(12px); + border-radius: var(--mantine-radius-sm); + text-decoration: none; + color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); + font-size: var(--mantine-font-size-sm); + font-weight: 500; + cursor: pointer; + background: none; + border: none; + + @mixin hover { + background-color: light-dark( + var(--mantine-color-gray-0), + var(--mantine-color-dark-6) + ); + } + + [data-mantine-color-scheme] &[data-active] { + background-color: var(--mantine-primary-color-filled); + color: var(--mantine-color-white); + } +} diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/Header.tsx b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/Header.tsx new file mode 100644 index 00000000..4409b1d6 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/Header.tsx @@ -0,0 +1,34 @@ +import { Box, Container, Group } from "@mantine/core"; + +import SlotHeaderCenter from "../slot-header-center"; +import SlotHeaderLeft from "../slot-header-left"; +import SlotHeaderRight from "../slot-header-right"; +import { headerHeight } from "./config"; +import classes from "./Header.module.css"; +import HeaderMobileMenu from "./HeaderMobileMenu"; + +export function Header() { + return ( +
+ + + + + + + + + + + + + + +
+ ); +} diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/HeaderMobileMenu.tsx b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/HeaderMobileMenu.tsx new file mode 100644 index 00000000..910104fb --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/HeaderMobileMenu.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { Burger, Menu } from "@mantine/core"; +import { useDisclosure } from "@mantine/hooks"; + +import SlotHeaderMobileMenuContent from "../slot-header-mobile-content"; + +export default function HeaderMobileMenu() { + const [opened, { toggle }] = useDisclosure(false); + + return ( + + + + + + + + + ); +} diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/HeaderNavLink.tsx b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/HeaderNavLink.tsx new file mode 100644 index 00000000..5da52246 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/HeaderNavLink.tsx @@ -0,0 +1,31 @@ +"use client"; + +import { type ProofKitRoute } from "@proofkit/cli"; +import { usePathname } from "next/navigation"; +import React from "react"; + +import classes from "./Header.module.css"; + +export default function HeaderNavLink(route: ProofKitRoute) { + const pathname = usePathname(); + + if (route.type === "function") { + return ; + } + + const isActive = route.exactMatch + ? pathname === route.href + : pathname.startsWith(route.href); + + if (route.type === "link") { + return ( + + {route.label} + + ); + } +} diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/config.ts b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/config.ts new file mode 100644 index 00000000..ded639d0 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/internal/config.ts @@ -0,0 +1 @@ +export const headerHeight = 56; diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-center.tsx b/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-center.tsx new file mode 100644 index 00000000..2de3b630 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-center.tsx @@ -0,0 +1,13 @@ +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects + * this file to exist and may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderCenter() { + return null; +} + +export default SlotHeaderCenter; diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-left.tsx b/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-left.tsx new file mode 100644 index 00000000..781fcbce --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-left.tsx @@ -0,0 +1,23 @@ +import Link from "next/link"; + +import AppLogo from "../AppLogo"; + +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects this file to exist and + * may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderLeft() { + return ( + <> + + + + + ); +} + +export default SlotHeaderLeft; diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-mobile-content.tsx b/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-mobile-content.tsx new file mode 100644 index 00000000..9943f8a0 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-mobile-content.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { primaryRoutes } from "@/app/navigation"; +import { Menu } from "@mantine/core"; +import { useRouter } from "next/navigation"; + +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects + * this file to exist and may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderMobileMenuContent({ + closeMenu, +}: { + closeMenu: () => void; +}) { + const router = useRouter(); + return ( + <> + {primaryRoutes.map((route) => ( + { + closeMenu(); + if (route.type === "function") { + route.onClick(); + } else if (route.type === "link") { + router.push(route.href); + } + }} + > + {route.label} + + ))} + + ); +} + +export default SlotHeaderMobileMenuContent; diff --git a/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-right.tsx b/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-right.tsx new file mode 100644 index 00000000..6c392c95 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/components/AppShell/slot-header-right.tsx @@ -0,0 +1,26 @@ +import { primaryRoutes } from "@/app/navigation"; +import { Group } from "@mantine/core"; + +import HeaderNavLink from "./internal/HeaderNavLink"; + +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects + * this file to exist and may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderRight() { + return ( + <> + + {primaryRoutes.map((route) => ( + + ))} + + + ); +} + +export default SlotHeaderRight; diff --git a/packages/cli/template/nextjs-mantine/src/config/env.ts b/packages/cli/template/nextjs-mantine/src/config/env.ts new file mode 100644 index 00000000..3c50ef8d --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/config/env.ts @@ -0,0 +1,13 @@ +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod/v4"; + +export const env = createEnv({ + server: { + NODE_ENV: z + .enum(["development", "test", "production"]) + .default("development"), + }, + client: {}, + // For Next.js >= 13.4.4, you only need to destructure client variables: + experimental__runtimeEnv: {}, +}); diff --git a/packages/cli/template/nextjs-mantine/src/config/theme/globals.css b/packages/cli/template/nextjs-mantine/src/config/theme/globals.css new file mode 100644 index 00000000..0e2f76bb --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/config/theme/globals.css @@ -0,0 +1,125 @@ +/* Add global styles here */ + +@import "tailwindcss" prefix(tw); +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.145 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.145 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.985 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.396 0.141 25.723); + --destructive-foreground: oklch(0.637 0.237 25.331); + --border: oklch(0.269 0 0); + --input: oklch(0.269 0 0); + --ring: oklch(0.439 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(0.269 0 0); + --sidebar-ring: oklch(0.439 0 0); +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +@layer base { + * { + @apply tw:border-border tw:outline-ring/50; + } + body { + @apply tw:bg-background tw:text-foreground; + } +} diff --git a/packages/cli/template/nextjs-mantine/src/config/theme/mantine-theme.ts b/packages/cli/template/nextjs-mantine/src/config/theme/mantine-theme.ts new file mode 100644 index 00000000..890db89c --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/config/theme/mantine-theme.ts @@ -0,0 +1,22 @@ +import { createTheme, type MantineColorsTuple } from "@mantine/core"; + +// generate your own set of colors here: https://mantine.dev/colors-generator +const brandColor: MantineColorsTuple = [ + "#ffebff", + "#f5d5fb", + "#e6a8f3", + "#d779eb", + "#cb51e4", + "#c337e0", + "#c029df", + "#a91cc6", + "#9715b1", + "#84099c", +]; + +export const theme = createTheme({ + primaryColor: "brand", + colors: { + brand: brandColor, + }, +}); diff --git a/packages/cli/template/nextjs-mantine/src/server/safe-action.ts b/packages/cli/template/nextjs-mantine/src/server/safe-action.ts new file mode 100644 index 00000000..7f62198a --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/server/safe-action.ts @@ -0,0 +1,3 @@ +import { createSafeActionClient } from "next-safe-action"; + +export const actionClient = createSafeActionClient(); diff --git a/packages/cli/template/nextjs-mantine/src/utils/notification-helpers.ts b/packages/cli/template/nextjs-mantine/src/utils/notification-helpers.ts new file mode 100644 index 00000000..771fdffe --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/utils/notification-helpers.ts @@ -0,0 +1,32 @@ +import { + showNotification, + type NotificationData, +} from "@mantine/notifications"; + +export function showErrorNotification(): void; +export function showErrorNotification(props: NotificationData): void; +export function showErrorNotification(message: string): void; +export function showErrorNotification(args?: string | NotificationData): void { + const message = + typeof args === "string" ? args : "An unexpected error occurred."; + const defaultProps = typeof args === "string" ? {} : (args ?? {}); + + showNotification({ color: "red", title: "Error", message, ...defaultProps }); +} + +export function showSuccessNotification(): void; +export function showSuccessNotification(props: NotificationData): void; +export function showSuccessNotification(message: string): void; +export function showSuccessNotification( + args?: string | NotificationData +): void { + const message = typeof args === "string" ? args : "Success!"; + const defaultProps = typeof args === "string" ? {} : (args ?? {}); + + showNotification({ + color: "green", + title: "Success", + message, + ...defaultProps, + }); +} diff --git a/packages/cli/template/nextjs-mantine/src/utils/styles.ts b/packages/cli/template/nextjs-mantine/src/utils/styles.ts new file mode 100644 index 00000000..1f4cd38e --- /dev/null +++ b/packages/cli/template/nextjs-mantine/src/utils/styles.ts @@ -0,0 +1,6 @@ +import { clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: any[]) { + return twMerge(clsx(inputs)); +} diff --git a/packages/cli/template/nextjs-mantine/tsconfig.json b/packages/cli/template/nextjs-mantine/tsconfig.json new file mode 100644 index 00000000..f48e7ee6 --- /dev/null +++ b/packages/cli/template/nextjs-mantine/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./src/*" + ] + }, + "target": "ES2017" + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/packages/cli/template/nextjs-shadcn/.prettierrc b/packages/cli/template/nextjs-shadcn/.prettierrc new file mode 100644 index 00000000..b4bfed35 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/.prettierrc @@ -0,0 +1,3 @@ +{ + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/packages/cli/template/nextjs-shadcn/README.md b/packages/cli/template/nextjs-shadcn/README.md new file mode 100644 index 00000000..4f416a4a --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/README.md @@ -0,0 +1,27 @@ +# ProofKit NextJS Template + +This is a [NextJS](https://nextjs.org/) project bootstrapped with `@proofkit/cli`. Learn more at [proofkit.dev](https://proofkit.dev) + +## What's next? How do I make an app with this? + +While this template is designed to be a minimal starting point, the proofkit CLI will guide you through adding additional features and pages. + +To add new things to your project, simply run the `proofkit` script from the project's root directory. + +e.g. `npm run proofkit` or `pnpm proofkit` etc. + +For more information, see the full [ProofKit documentation](https://proofkit.dev). + +## Project Structure + +ProofKit projects have an opinionated structure to help you get started and some conventions must be maintained to ensure that the CLI can properly inject new features and components. + +The `src` directory is the home for your application code. It is used for most things except for configuration and is organized as follows: + +- `app` - NextJS app router, where your pages and routes are defined +- `components` - Shared components used throughout the app +- `server` - Code that connects to backend databases and services that should not be exposed in the browser + +Anytime you see an `internal` folder, you should not modify any files inside. These files are maintained exclusively by the ProofKit CLI and changes to them may be overwritten. + +Anytime you see a componet file that begins with `slot-`, you _may_ modify the content, but do not rename, remove, or move them. These are desigend to be customized, but are still used by the CLI to inject additional content. If a slot is not needed by your app, you can have the compoment return `null` or an empty fragment: `<>` diff --git a/packages/cli/template/nextjs-shadcn/_gitignore b/packages/cli/template/nextjs-shadcn/_gitignore new file mode 100644 index 00000000..00bba9bb --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/_gitignore @@ -0,0 +1,37 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/packages/cli/template/nextjs-shadcn/components.json b/packages/cli/template/nextjs-shadcn/components.json new file mode 100644 index 00000000..0d27c449 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/config/theme/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "tw:" + }, + "aliases": { + "components": "@/components", + "utils": "@/utils/styles", + "ui": "@/components/ui", + "lib": "@/utils", + "hooks": "@/utils/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/packages/cli/template/nextjs-shadcn/next.config.ts b/packages/cli/template/nextjs-shadcn/next.config.ts new file mode 100644 index 00000000..9555317e --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/next.config.ts @@ -0,0 +1,12 @@ +import { type NextConfig } from "next"; + +// Import env here to validate during build. +import "./src/config/env"; + +const nextConfig: NextConfig = { + experimental: { + optimizePackageImports: ["@mantine/core", "@mantine/hooks"], + }, +}; + +export default nextConfig; diff --git a/packages/cli/template/nextjs-shadcn/package.json b/packages/cli/template/nextjs-shadcn/package.json new file mode 100644 index 00000000..5c9833a7 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/package.json @@ -0,0 +1,42 @@ +{ + "name": "template", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev --turbopack", + "build": "next build", + "start": "next start", + "lint": "next lint", + "proofkit": "proofkit", + "typegen": "proofkit typegen", + "deploy": "proofkit deploy" + }, + "dependencies": { + "@hookform/resolvers": "^5.1.1", + "@next-safe-action/adapter-react-hook-form": "^2.0.0", + "next-safe-action": "^8.0.4", + "react-hook-form": "^7.54.2", + "@tabler/icons-react": "^3.30.0", + "@t3-oss/env-nextjs": "^0.12.0", + "dayjs": "^1.11.13", + "next": "^15.2.3", + "react": "19.0.0", + "react-dom": "19.0.0", + "zod": "^3.24.2" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "npm:types-react@19.0.12", + "@types/react-dom": "npm:types-react-dom@19.0.4", + "eslint": "^9.14.0", + "eslint-config-next": "15.2.3", + "postcss": "^8.4.41", + "typescript": "^5" + }, + "pnpm": { + "overrides": { + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" + } + } +} diff --git a/packages/cli/template/nextjs-shadcn/postcss.config.cjs b/packages/cli/template/nextjs-shadcn/postcss.config.cjs new file mode 100644 index 00000000..085a0ef9 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/postcss.config.cjs @@ -0,0 +1,15 @@ +module.exports = { + plugins: { + "@tailwindcss/postcss": {}, + "postcss-preset-mantine": {}, + "postcss-simple-vars": { + variables: { + "mantine-breakpoint-xs": "36em", + "mantine-breakpoint-sm": "48em", + "mantine-breakpoint-md": "62em", + "mantine-breakpoint-lg": "75em", + "mantine-breakpoint-xl": "88em", + }, + }, + }, +}; diff --git a/packages/cli/template/nextjs-shadcn/proofkit.json b/packages/cli/template/nextjs-shadcn/proofkit.json new file mode 100644 index 00000000..6aca1027 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/proofkit.json @@ -0,0 +1,7 @@ +{ + "auth": { "type": "none" }, + "envFile": ".env", + "appType": "browser", + "ui": "shadcn", + "appliedUpgrades": ["shadcn", "cursorRules"] +} diff --git a/packages/cli/template/nextjs-shadcn/public/favicon.ico b/packages/cli/template/nextjs-shadcn/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ba9355b8d3f888ad3a93c0f254b6776a0c2aed92 GIT binary patch literal 15086 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 DtPcMKfsh_-A)LFM)6iMLm_0IRoy0b^RZ#+}< zi!bLut%2o?|K58mAIkLAGYnAH0<+q{5T*Z_{;{|^gi0Jnq^GA@JxQqtmY9eq8qay! zO9PJSSvYy5L-*71;XvO?minoHci?`$*ErTT)r;&5d)*7fST2hTv9C=eK-j==kky7D zAUwps{~#iyWjsMZphl3BeEG&bV>{Dh##GAXtaUsf^jqDFNEn%wBp)J$iXMX03+R_G zb?kWBXzMAG_@mNM!*xye7Q>b!?U8L<5WU2E{b`mrTvAH!pztilb8Ak` zWsm!)zfzsOb#HBS^k$}HaHn)bv{i8JjX$n9I!)mJ`t`(34~+cJFiXcr7!0$Hy&Q5; z$6p@hVQZIVkL*)bA>+$)J)mkAhk*ANC}Yeg&YovT*bh$8ToHF=Xh2D$Yj-F?PwKHj ztzLSgR9I_7?+`I?|K9Z3hnKZ(%9w3@V3Vx)6#-N3P3^nXL?d=G4?ix7e&gDiufyIO4-KNBEMFG5y_ zGC8=L@Efm3B+i~NMD_xid=%!f+=kmoSGUQT)cO+wWy$A7##<{=J^l=21g41G1q}cPAPn67648JBv8iPX(c^$iDHgB)#7-D=-rlm)^k7 zXKI!ue`8CSPe4WHX99u6k^M$g!Y5y z{h35-ws0Y~R%7z`!*5A#2;Z zpDjS06yr;n0>A6~>H9VR=$V6hBi25l`-86VQkKsN3S0y#bD6W?M*L3Im*<#Z_=6$h zJX#B82E{2(LvxA03{ng-CC-e+rwM}u>woOx7odN>ukb{k$Yfu7!PSAi+7rQFB9pdX z(nwOGZOde~xXAnR%nVYNp@;r$kP%BSx|O}I$w3Wbq&^PSq^vnlClX@X0A8>-JPD$n zViz&^EzGWi?=z_MdPu^Rz*M0EJOH|Rcvab10!ydN9~ObS<@~(x+!X+WbpcDT0&`+E zY8)SuVEko9oTmW8DEzWlYjT!tpmbL`3wNu0rZko`;(uEiU-k`z?6nh_!*XsY&L1{% z3e(miJ|zQq!4Dy;5csp##f(@jBDBn3bB)g!68l@SM^kLT(=7mY3^2R?&ukK4>k>b( zIkyk$wT(F$QP6{bSdiZHd^uau^(PgUZ|YRA)E{kL<;335TwCUQTk!{m$97!(%^o7Z zd5zKVe?0t9e{*!1^J&Po6kaS_5Bz2!g8eFH8lV>_zzf%uaS1j zUN>les1aB`&bI$CdHU@S!`ijuD|W;HB&Yr$xghJuiuaocqUZpvzlqS%D}+1erDeYNBtYXQA#)1m!iwB&hj+5YVK4EguookgEW{|N}d z&)?c_JpLO~@nX_fZIAzPY^34;_+c6itbYOgrZZ5B_YLyj9uN3QfcUrV0RVja?VwK7 zznN_chme(%|Hk=$gY=sU+^>IF{a;A^rYltacQ8S(u>SuKXoVCQSrYIDTL`ttKJ!#q z-eAwbCk&{wb31;pV_%bR7yTVEt(j-LErSEU`bk=)t!WF@tN0h?yp%wfMaqkq{)D z(>f7yADo!0`0{zo=%05ZqLrA}xOLc}2faqPJG|=qi7|-SE zFNxWR*{Gt3UPWT0xAc`F#=$`R(M427{Dp{CY&<%TB#P9OCq`<}7`~&#M!fCTgnWvM zedtimB099=wQ*4(-Vu($!n4{G5hFisg-^3k_oE`0NpiYI2tpYIClNT03mHP9dben{ zWp4oAiFouEwg|$QpngwmWY;pOppJzDv!QRs1egn(mf>TMt{;H1#UnE&sIct6n*?iN z)4xapJPs0L4tb->!)Rp2P2OiH%AAjn!VVp+fcRu$5Z}rAT3Sd6Axl|+IV*Muk<70W z2pjg?FfJ7@@ZC}^a@OKP1%XO51+7tRXykqdCSGHS1FF7mC#_GWdjwfTAm|4{$>IA# zw(;sESNkJ}PiGleUhv*z7C|oTrUM^_y$z9&1<<1*M5sm$JE2OoxEDhI!a6+lp?IeR zLzq|bTjpQJ=h#6{E}rZU-&%g*X~PglGTo@c{O}D9`Kn&?bidK@A_la6+5nYd6(=uO+?_XwW?OAbM0Vsnxe?P;EEQ}@#bp>lD zJzpMS5jB_*Uy+1g>jTQ6W0|lPoF)`d37}9MwVajx02J!|PK5#cMslh6mAmXE#?Bu7 zWZUr{5bXW%TT6FEutaxI1UAS=8O{iwnu83p<+qc`%KUa<|O>|zK<|ZT&cS${#v&5wpeI9+U#7TpXQ*o!6`A7 z$Be$PFwT$)WowNqRG;^9`{PEr_FAdetYbBV_%shMTsCl$_W0ZLTw#&4iyu$L+kc>0 z+?5;WDvz>3i?rU>1!_BVmk5~5VqsW;#u`L#gmv zAabprx}w}-x>I&J*H!)?f~xiPoB&z;8@S!g@N39cgd#9O32Cm=)TaOhuZMC2l#xKc z0=9I<4Xa}II*9F=#d425%h)D|C8f#@%rFH|h+s!&K`Klv3B?lxSNiA2>qYSxpMwjg zDIcc2c&emu6$?q5G`L&nJJPS3A9mL9j>SH<-gCbYxGENUIOI#|(RC@0m)>%;hqJejr#yFynKSKn!q#k4*y7!AZY7FT+qDWn zv)`@d`N|Ax34!6eWyiC_{WI)nwB4Vit{lTLKQ8zu(0vP{eO$231MsjkI3`!qazHvw`F4DEo{(FEpRd}<`iTVS;bIkfx`riQO z%l;X3y;xXiB79MXV&Wt#8Psz`VJom^awq&4bubyb^=pkxbR!VhjE<);gL(6o zG#{dC=1FQBsaD74&Qw)X3FKRuK9h8RWMn#H!2Z~vx5E6`%WzNNDg&*g(G=U@aE#@b zpGs`VW3qEbDK&85it&37~K@o=Bv@ER9_Eo7+ zur1Ct_kJzF_EtasW0{U@vl_WjDNb&r+>BRe=JOzw1Ut8MhA^hNo-EVKeKh8A=8D+X@Fho-J&)AxISxnl zN=f|<-%5UYFWG^bE}?X3&hX)wL0YsOv*<_Hw>d}eV>_ANKDmmAe_)IDvFvfYox;&M zlY>81t~b6>XR{wraQp#gC~@rCwkku~o#o87kf5#!#U*pGkw=`F>_o!ORv6YjHDLMd zoe`IKnv4Ngg7*2fGL7clN!fUZ$>qeu{KoH(%6`TzJ2ozk3&ts*4<`8ovYAjX(2GHp-I zW#@7Z`^;hGYNFJ04IpsBOj^4YCa3J+kQgvZF(Z^Y{wVE+n)!u&z4b6q$YATN{vu=2*Tv2lv^z4NGHeOOzX%eefwuVcyYE1-K@ zKN9#j=@R1kGSFt&YS~yi`|_U-?2jPFcs2!;A+w{@1WsDjE>gSnBef0J`lOOvlsTLt z@d>{0zInr;wN^R0crLJ(exceKZK)$4XV8HuDT_D=eP=We(%42q%?O1+ElT(MOVYez~C(1tW=mjTsS8h7I`Tgy2yVq z1_XiRnQrt7&U{rrz?>{p2x51EvJnaVC6v(Y+>QAv9;jSRv_@*#wm;%rNMWj_ zd{#0W<@r{|<1YH#;cc7!96Ae4Ey)GE= z>&=zmWLdb6S{G(FUvW)(-Uvhjr-UtlQc|h5l3&Yl~0lt z$L!6P0{ph#PTR;J3+C75(DkyXp^wUYMt*-+{O#G8ZzmhNj8;{o z??@>WR2-EiIZ+fH1G6S{kM0?2~Ly+U^Oy49zTL zB_w`$OXz0z`NKQk979k1Uat4w2gB7fG|R9bPi>@ac)Mn1U|5jB^#Ov|fDd+k z6dqFki+jUsMVXV1MWyc!0e%#)H}(RDL6IBj0@Cv`VK2r0;0>E$trj%K-uC9 zxE7)6nQkqI?i*#n2X)hJZ7+^5bZmVcOGSdLTUtz{^5jo7ClqS(dfp6$p%-2n(Z3h> zG-Ech%2k|@zbjMN@7H4TL`(*#0xE`*{e1XLFMf<=@pFFifN^(sFy^DY!J7#L4*$ED zUZJ$MVgoa%O+*2)K=e@U0U?UKXla*$ni{E_P5iBbXpte6 zagzsA+-v$BDv{D{@pk?^E`8yFvY}e>KfWlxQ~pW7gO$F05-D50mK*I*CGP1oP?I>` z5mgnHA;T?6nB6u9HQUo|+#O1nSz9SN6Wh=(l|5?wdXr&$S0R~Aa&RST`0DLJYNuvV zbXlOqO;(=P@XvR4i=rCJey?v0nF!TE-T9;%!(?=?^Cbgqk((etcQW%?QDP&)@BvZU zKMemo+1hUxp~Z2Qhf8y{#wTf;adfmM>>ad539S)4#J|0~0Gq;7W+o^wxV_FS#&tk!v*J?yBH zc+s7>RIl^f45es%y$AUrwRMi&3R;5C?un1#Lo1!jLi;Q=nXa_GBd;CF3D&c~=?||v z;(mRTq&2++5!G4#+)p%z;qh^ z^N3}GcAesNmv9p*Os_W2U6ZahFYZT#^~WyG)REF5D!yA^UD`2v(S6ie!JSHihlWC< zlra$~lCm4$_-Z0kLQF}n-*vTZVfdq)yrs@`#8jB)$o8bC*YCT^ zgg^FAR^oW^&3=hEVyL!r!;5C1w5s*GpxRI=8`lGOKgg+sfkq=L4Da5nMnh%%8CGkg zSku`2&mJ|1cn6yR!Nikt|MQG%@nd_Sm^D9S*O^~;`N0GSZ4jkqetrA()54BNauFz2Tw>B2}buc(mvf1C9BUPT<8~3oI`e1e6r5A$u*gZ2pP&#X_O$xlMB=*@ODh$X_6IA zovMht!d%OXZDumIfJXp?A_88gvO^O6!?)EXyFgkHXK(SR6bkw5754+Kw-SI%!*u=c zl3}5WjwdudqG&@QjXV`r{k1E}(n4dv!qCc<>pSV5P>2X;L3qt+G|M%ClE+Mmqk`!0mf z+S_oDKCVKOo*eF#+WY! z9Z_6`v1lxF!$=-30kGf`zyd;cL@;n~r@n{@O5Ac~u$-*Jr&pgV6EC zH3A!wNH#-}t7|MsI@Ttm- z>HOq`l~h{s2VP zT`g+l>1CU?o1`>5^AlYzkUjcA@c4+ghuu7AFdTk-&9rbz5P?zF2T%v@*169ULXa(% zYb1)FxFL#)0JRz*LrNjJ1xl~C!nJru2h}~~SLX1&oCLxvTj`%72gZWhH}QXZ0isL> zTz0;ASIrJBDUi4fJFF^tTD?njF^KRE%FC=Wid0K|vdzJ*Ud=!2z+v-gHOFKJM~|87 zeH2CH{;OU7?Mk)w;N+8c)YUn*WfY}mL8>tC^Yh#z@+O+*y~ITd&un)Y%`uJL5e>M$ z&{b);rFx-lA)`WPv3%)xu=1Sql}}!Q5ve1<_K zc=KjoN(^J7ve5mxK!N2vVbI+XLH^Zdc7vFDp$pp`gLtFLG3#-!tN`EbndG7{VPYXP zgZ9=AsCHF}kq)+ht};#}k^d`xuBL%9 z>=x~yuH!umMc{8kk82KuO3%G5-F*smX{#n;jcJl zZJjptx9eQuY;-=Ufa*`yt3`(JCvb8rWj!Ee+Mf$Mc*2ObAnsa#VU zFC4Ablp4)68yt~UD@aRp|Cka_q6Hz=AZhF{-(i}dL}CsVIS3*mbcj_wN)@#)gfFsR z-H{j_Ei>2@MVf#XOcLz%T_|mjv^Ugwg+MnwjE?kE^k=6_MU{72Peq+H2Chgk9xjpd z=YO|TF^(D}C-UdvHk~^AtY$FO*j>Np@q=({KHdPF=e{<_(1LKj70tc(wf-#H1`mDQ z6OX9DneFO}n3(Y=b16o1!;f}EUpG@^Lp!e|?i5f|>gK$LF+5{Vr)%~GJT$}Bm8u7- zjP@!NEtSx8UylWnj{uop0_+K=NMsHINl$yhJmOxS7R_ZlP(t0(3kK?Wx_&WPil<)f6DCagl1{{I*m_s;z?t9*J=RA2!4s~7@b^MU?U7S|5c+{Ta`iCPo z8o%^SJlPkDLyiHfg)j}e?+Y1YG(2ai2CX`cfs$Tt7?Npo%~lS(uM(STf(8|1jcn21 z(>8=8iMwx2@`<&kQ#5_-DkfZ*#Q`0l?_J=S=t$`>QeG-iL>;dB479c#V1MSv3nY@^ zZjh>z_IRO7|A}p2fRaf3bB)-P;D@R*O}l5_J(%ufh)m{uN6r~v?^^3F4YqXzM}hO6 zkm{pba-a>NH4ESw#XZj$zz9l+bH4yOlVB-)fIcb`cr@*iI(y!sxl`_Yg_Fj~EhhjK z3^PCtnE`eU7Z*63YdTW|s77WBub&PgDWNqSkzXpp`xC3oIQ2Z&Ij`K$5xT0za+y>Y zq&f=ar2SwTAmtqDwyAU$ibLa^vQ4^aqL9kr58vf@2A49vJ`Ym-6n4$7oGPj&7(1xm zHDM(p`-H|V%MiKNU27?vx_Uaej9%sl(GidJoC$@EXR+xqkMPC#64JAbd&x>9(iq% z<2O4SsRP=N=8-6804~SEK8yoy&l@*oS$)wLksN3x8`9nh1`_>W&@IMGugm7s?ORKb z#=OP7$_+w^{TioKjI#;O^2-ocKYw_6lyZDtv;N{qq4H2zw48J~Y$VQ>jH!lE1XPNB zhZfTqYaAE7<-gUmmJS_&bUmP`1)Y!6vA>glBjL8-)8pnPpwg3JVH19W>5A%_eY8F2 zxXrgV)g@449TiMJx;%ZQv?uT_eHstDY^^_a@D)z%jdw!u_gc$j!hp+Qz4QmD*D*Pw71R zOmB^R!gJ^Z$}ckW=z64so#Ohito34*QT#GEQ+W<)vfHx;rRJz^hr%aWULQiB zrTWWMr$RKSnmTFA@21D)wJQyfi0t@#vLA3UB*l=EW9g+9?sRbh*RieE{IY(XUWn(7 zK&Ws8OC&`&Wk&fTWyQgg2A0X;g%KqrDU#3h{PeJen}NQ&l+jS&re92Ip!ep7q9F<; zNC_EZg2J_*&;9vPxy=(Pl&$ri_K&0(u12jSE_RNA9j@t1ltK|!(~4@xFSaEI)|@>n zXAL?tF1g`IIBST+@QZGrY_Xjh#TK~;_>2tsJYvIKWekLTQzXP=$@Dyl_FDE)Rg>np zqn$V%o}Zm~C&Px;rOWK-89d6w%%DnrLJ^u+MTd*&zur@Db z)*qS4nu`i$rgv^M!3ojfyD9@L)f8}pVk)e0nE}XvolB)o8}KE(SKr6_h~s5BO+KgU zDCz>l;}45seYv1I86jSmd5`!#I zaUyq0F4a`~LISpwb;1qpLngX~>o3hCvGR0?DnH~Lc0*;_)ndkp^E3D0_<8H+Kj=i= zri;7^D6hL}`&DuW<`9~2;FUOHK5lRhoDhLEsxUXVP7mP9e(vnU;3%IE5szB@=S)%8 zX|{1sT@jh+Lm^EGuLQmpygIR}T=A!i9~F==vaZOh>A=u!v*e&WCLq93_?O4& zyzE(uDR%CYNw2PF(fGy&<|0Uk@^C7@S|FN;E%TZ40&SW&$aC%IgIwkp$X)9v3IxrH zmJgPjp^$DzdRyQg1yv6Q0q&_+P}j@ku%blA0V784_G$yOww zmX~G&-Lu5;cJBgT++sBD{AAfbF`@MAauTD;cy zOdp?j8})2s=`9+u$bQD^jGoGHi(8Al|a6oL3TvK2Xd~=N}Wt++lQb)#v5eg(0n;BW7Eg z!VOn*Xr+y4`{M$8H4Ky6mV_8&@+5~VVxMq$3ktD%#>MH=I-wcdhA_KPO3lv&qPsZI zE3a5{k6XEkOfJ5Fhv`5Sen*B=ccqf)nMMk#k2t4n-DmvhNV><=@)n#C9*Tm#2)C3V zccLz|7eFhAw=a*^({dcC-CIzl7*O!0lMIMpw05Q!C4%x}3z?IJSA8sLuiL#?(ec_#rcr{17A=YbwGESDzQt-T~U~agu0QojJ$KcE?&wUSh zLLkO7y?}sfp<97~LHMf1j^|2gx~H9#WcW78Cb#hYuxO=N+U=yw+AL}Y>dao}mXgOV zK)ur(eHhODC36tqE0N0Sx&ldB`)!85Iq<`0fm+)%kqpsSXfehI8@~`h<$Wo75@N^m zfodt1@FRDDBOIS7I#7b#G^Gm4}UoyMz^1_}U1(j2qRhjoXN`c}vtIIvr6Zc;wEsXTL9z!uZ z%^~W;YTF52QD;A@LlZ!myV=?9Q+Vq?>~QytfZ8vdIt@#y-@jDpft)0VQA zlz}zdp6NC7BYR-vIn3>EyVGjXVh0Us&wPHC0}g+T3d<06CggMU;%fghwnXG!VhmjT zepZYRI7nC4-eD;KCv*V`v+cWgyGgDNLdl%SXqcmco{RX~oO)}oqkWU;vwhpg1>Tr5*TQ|E&hxoYU6-ibwg&$fUIktgj(us)5s>*8| z!;2Hd`noKF?drLIQP8|VL!41VtCkv#f3M0VA^J@V)lj9u11hKO;w za_>X;Jp<29z=C-$Z(FLjz{(Y%9SzsUT2#DbL0a^|@#_ZkKlN;m z*9)MP(N~vD%Akd5weFKM%PF9L2#1bh)O z^NRH-puaZ$-u@5>j0?w}(%I9k->&l!gl>OvMq1(VAm?$pI**e<5n|(JO;6-w1|{v# z*HtUa6Ifle^cio}g2?kf&S-}8*E$`YKxwWre5WhV1n#O*SvW+t7qR%MTn~bYkzx*8 zo+QX+I$sG$;nAt##7W|}NYOmfAkZ8m-p-t!EZkICOp7_LEK~iiv-{~4VI-}kV=FVQ zXG@F5m&X-*i7ZKVwc|G{yKbICls&#T34}3^qsVTC9RPi$!VxAp2ZKF{+GhP;g6TS! zIR=oH`JwT^`Pdg|X^vx5v%$6?^kF1^nQT058XJNS_~?^5U zZM03?A<`QqZC>MTef7>6&e#tgT*gK6Jkm+=7K|BC)1I zc9A_tqD06bt;u6@VEP2kRcXRvp}Yav>@?g6H~kDBc&k=T+I$ps`3biR!<{OdYPXHc z5KC@$Kw?_c%bYhr15{VOV*$m#7uk@&?X((LXL44F0Z`2V0$w@$w@o(OFpxQ*nY4gr za;0b>9-?6$94yQPE6@US_}~}C;-!bQ=jlL(1{6rmKO6xR13CD^mF^zO%1lU;=<)y> zo@&$ww0_wt7i$SYpy5uxKx!bBH0ldu$~lrsC(7qSWzMT@%bEZxL6Bwkk&^F<=vrp! z)W9q3R#QMX4ZkhWhx?~e<>I4Ov7x4xS}iO{qwVR*2@UBqmLgwU{H*#_+OS)YQvE~a zn29VL#x*^Z|hO!=KCGbpOT5Lkb8Oz zF;E<|yGLo~GZVfR7L1+{x$PqZ>l)$5p#9R|`*}SRu|tzr#_`RrXthZBvW{ccfV&tx zmy~a&HrhT;tD+_|J9t<=&pDBCxHHf?yHNo2+y^dl->8Ch`2w2#TYuOEKJm?0@w-2w z^bA;K$pYxJ!X*Io-S32jA~Rr7GNf?BnC? ztUY9VL%GJeyN@nzj?oiUVX*y+o~?$uSE2pHyp_3XtMB5vNaHQ#zXhXBZg@oWWCSEr zcn&Zri=C#a<%2bpw`j!ES;TeVl?qglNG)P~d+puzx*f%BHQ!C{LT4V6AjU=we9|NBggSwiJ`_)e zJ6jBtXH@mB^a;(KK~Kfq+*+2;!Q!3wcxPA<4z%`qJ~+{SHFj_M>MC zoh8%c;eMf4$bq6N`A5TgUw)o8z98*IAM8j=!qv+;Z<=&V?-1L%FcexT9;g$Fef_JJ z@_|CTt&u&sv*+ldMYx$csbKdV!VsfcP$#BpDXp&_Sm+T0Q0N7^rHsQb2&pZM{M~1I zA#-+yCEjp_8x%+8H!w?=gU>#gYmyV3We252C|2mCTaIbMpQ4v^_NMI1hO&HizRjLT z9!<*g=^W=iBYu{6U{dwJyk#V*_b920D80EZGtgBLG2w z;V1Pwj8mBIMgZ$m?tV2;JzRqM`W#dE5xeMd#tE-cSkZT4hW~1xKlH1)Nn$27#vC5~ zd>kyHBiyn=j<)N)yD_gjrWo!aa2iG>$guGq}sp)n?%m5WPA9 zpVx{-j(ROz$wX$N4412q!d>d2fB1o2RY9IXBh~5M+!DH2mB*C-XFe%bb}`iFy>^}S z`?Eb1%}=9=3m!J36sdpF)f?^>q+pAE$Wh6hO7YS;PzI(T{j?S8cy5p_;+^pGzI~5QKDY2YBrEJ|{Bj?ie{jYF`8;AU%TAW2LGC837@*bq#nGDsTo> zfrj{4MnZ9*0YR92=VQuI%hO>fX3UsTrDSYW5>K&1lm2ok9$`h!RFGXOO7!FrcY$HE zHvdzifrVsScN;WpukEK~8m!aD{@%YR9thXPf(b`*H^&&rSD4q>tkhg}=Av0t(MI1p zLpH)+ff&R=+blS@MQ6fi9)=?7^K>lt?`sKnDI_j&Fiv)h0!7w}d!BaXVt#lDloo*` z^}Qw{|1uwv`!Uc|^t2XFt@{FS$q!nt>T+s7X84!sth0r^m)y`AGj0=f++dY*4WDyP zn{_rX5mfAx63_LzX%Z3386VJ02XvtPGmEBB&-@VatgNBu;)x+S88Pi!B4+0!9$xeJwCRPe0%XMDe~qM$YAsILZJI0y=b7EyS}hE{bbmE3p7 z3w%6>`I(5MfUb2EcV)29>cRrRtB*6%p$A5fQN9B;YS3VPH23{DmAfHW=r!l1(;+fk zw>~Q60eKVs@{EjOeoM61nA+jxtJk?(EN|5E8wBGl*CVu7@auO=6U@53cfNKRw|WJ%+oS?e9l2ju>V5 z>XKDeSjw*ZLRvg*Q>xhrsazKW7^fHL4ggx&llP*#R#lZUZ+W^a8E-xUd7=rBAG>o{ zA>D^@Ttz_btD%h$SerXr9H>|C1CV4bcq~XIARE4OwrY?kYrFWGzwUCR;9`BWqwh8K zDtiojk+aeF^3i}hZ;*3_Z*Tw`>BHBTt1%vFn-)11pX^=ZZcd-9g@%tv2pTceE8+I$ zp$qH^Xl4rzsb4eTs%mw1APlxl&>^VjQ9&X&5$G)>sNbi+T^R{fZ%vb7@J-M1*SMI|=a zNBg+-cy-lP8yBX#tf&d;$30F-xTDHqa;WDfJ|!|+8<$QvHmyu)W?uF_o&Tgo1W=C( z&#B+BTwuR<2?26=)RgB1fC60r$Ju$LxumH`UcdZHUDEkHtu}4j3jjv<7E!y@^H|b46~GJX0LuDaJG=g7#}Anc z#?i|-Qink<+#~QScR1X-6_3m=IwNzOxd@|8FsWK?10V0PVt|g`bqrLl(P#6KRB3)f zjOcQpzF)O#I)w6v4lZLudm25dCWX96>Py{M*)~lnVw)N&t0eD~?@~20i%2HA6M$U6 z6TUp-NV@*Z8jz(!y&@YCJkm8pvSpPR>^U!^p*P$$Vudpwk&YFe&|jB5qmV>D%5BM& zYSE}l8Dmb4)U{U-kwNM?*wq&;BPOIc^~3AHV}4Jn(|7=d8?uslQ%hlJ+!t#L_-h*KpG;Hln-o2 zQ$A1&3mFcmnjzb&G!PBYLOee)zO%T}quVsvKD^#C-jy+38L!8Z1%YZ2X{nZ2UzBbG z+kLkS)Z(G)ow=3Zt`!TL0nVe2t35L0&8Y4KxFwtBQeEAfFLiQAOGACM@Kp2KQjSxU zyz9J0ZIYF$P_umGmq|$>4ee(Y+6F5t@z$w$2R$ zHM}#9%nuh^UbM;6n)L{z?e{npL>Wc!OSV8cdcjIKcssT{%~#xf{9)jes%y`y_IOiN z{9i9YK9@&iX(;}5xBLe=!^wpd_NSTp+=dNf%!T7Ymf_V=)Vp!1;$ZnwQh3pip$ z1|O2te5$MnjT(N)^8wt)2pSS&nN-E2y+J%b)>cg}ZwJ@DrhoAE0Jnbw zo6qEHn5iweB~M|VbyoW{UqKaB@8vWg7&YsWN=aqTk3EmK2;C23lIp)JW!I zxq&77GvjPn5@0gOoZ-8G#xl3Pf9F}$e@2)VyYPAHJ)y9(_bn9@VYJ5u(EeX1*wAeL zl`R-%y`D{g;Wr5;(2#!7L~~_s)6p#?uJ`MMa-)Kc9olwlrFEg^tt!%)$zx8`c+9C$scua4{=M8EOs&k=7+ElDqGUU* z9-u&9uzn#b>=E@1ojpbIIP2dU;8{elmf$usYs_uz|Kz>Yz7|*2N^r)AJB%NvLrNsV zfP!X9(C9BeA(8P)>w`jH>+)i`Gz?n2Jpb$kEEGWbx}-lke;=(ytY)PN~xoF~nj)%@#X{U`EP zTPd*sHoVcaxg(6vGy~ZhqAN$m3%9eS!Pe^im?Af$H=`=)7{3qvcM}0eQa%YnO>h9T z8erV0Q-K19;}fLkg}X^y{#m3Mc1LNbHX<$v0ef0M!C1_vf>DkPu@-JnrPO{h!n$x! z&>2yzX}p>7Hy)Dz_t(up&1{(?&-7OU{>iENl0&gYZK(Ro+H`YheVVtdd91IvAL09^ z<3s?iAAyQ}D>xl?SOi!zQnI>YD>^v7&N5 zmGp9Kw{3}P_QjL*dRRJ@*ux*(Cb(156r@I}-x?PZV{SQgsMG(c;5%k)QW3D-GzJ}# zchQ&!}?%V zJ3$tL$*fsLO|&Y4O5=WNnDdI0-AyGU$)ep*D2Fdv%E8Tn5vJ?s?UMDq)k34BjJRyP zO9l_D`^z)iMI|WYpu~<^u607N$V8bMy2t;s@P8r#01b_PD~GHqtPdUyaBHfR1X#)7 zwh^!7($Pum_x4tK&t2Mor~b*Igz3PU3?*WORF$e3=O?DQ=(ILXCD5H%XKOGFjMnp{ z%MrU-(%{#D+xBV6L`*FE5wW*p8_>6xAx&C&Z{4x+^(?9JlbT9LIaz$aj6L>=1Yj>G zfcv>vXV+Z7zyt8V6+eFy!^H4bBqVI87M4*cWY)9ecnK)grpCdkI+*BJ-#-`T_#5;b z>&8ri&pN4+z@edMaU@xGBizSj1+9H?san>lNr zINm5FbbR5houA5SGdDCrARJD3@JOb9BFo+WaSp1VPnnXg+!Tf_6xSNm>u_6MI@p`$ zzM@70`#(!Ocss)nM4zw4I=P@9C)B>ke}uE7AUjSi9@3e)&`w0tIjttda-^M@Qnl&I zT#<8Y3p+{+;4wFMt_Uf}J_9RX zW*+#Br7f@zy+mF>XE24gZhJ&e3K3F&6*I|ils83qC-|LW4UMHaLI={SAHoI?IbIROU)Yc72c>!)MbsRI}VBD?cKpR($gSCUN(@<q^DQ4&Ff9c{@A$E3$KaA21|Cn{kJN9 zrbiOqF}@s9HPuIw9rY0w)>Ca?qV8yZr*{LYa(T{U(489PRNus*o#Tc}C9uaY!6pu5 zIGDT27p?#75^+Lo;j71Bym@5E;_Ce)6%U*;QEioGtz!f2GkKMsVCt3BM@jNwqCLBq zIWtDv>aChZ{rEERR$WU37UitSL^a&$??`9a2*V9Kn_pxNZIWS85{NBU5r!)P9AN!j z&C}HB^=}!J1cHw0V7xF7=tNC@!99-h;J1EKE)9wmrE<8#x#^P)yE5$|D^&};@~Epp zyp9oTQuTV~fF|t$)VOmzZ7J26nzH_EBxpfH#bvgO_(9!`!eq8L*+vzi=)~_-AkDsg z$RsSEXhBKHRw>ifbB|U;Nl-4h&LzmUSZQkb#!|Mm&70n)yOwekR_J$o<8UPP!!g2_ z9P3Q0fJYIuSgMfd?q#H2qL9Jz7{xADt^KLQi($>zKpzvw*k7knZ$66YkqaKwGRWZw z!3(qoYkW(u$#xO!${b{0*1eli;nJMf8gu_-zS>&E z_u_Fg7dc&H9SN+Y(4Fa={FQH=32qwF#IIpifFr?2LXLl*$y+&^81tic8Kv*{E4dni zWs~cF$el`YeeEpLqX6^7N5y`?qxF(doyR)OTqJ)e-C$!_H>C|jqPN0!&9)`!%iO=>x@z;W|rKSl1mA^e!_ zw!FFgEb^^u+O4LTK6;*L3WJaz3PvFdVxX2$-+x zkrJPD6=ouqJ-XQfvb=0%znE~lIu;4UlS5Gs=m&YRhqRMwZxRf)Y>km%wU=7`w8RIt z;rk*m6zF^VKEFf-lVGNdXY3#Gb7|7*{s?2p^CLkBCFHs z6lsrVf|Mm~5+Y?}?3bz8$8Hr|v`c?-Pu0NMtZ>|<#{>h`E6e1in+Tfh?SsG=*`u`V^Kb_QqlVU@)A^dCaciM7`xGt$2LC*J{ zcB&EgZ@Fbf+)HuVkRo6*kc)(Kp=Xdz;84aa^A!{1Dvr`sv=J7Ud9|k2UV~RHEP}5BZDbY?tVSzrxk44dac}|7@Fv%A9ZbrBxv$QhJIx z80(WzY{9Epl}s#d?;omJKP*aI;V>^=gdZ7A(L>-d4_Wi_kYqbu z_M3ineJbl<7FWqPKJ_$*|8?%*oZ~yy>ou7lUr7R^*vpBVZvcLpi09M)xKnH_uF_Sw zDA%8Zeyo_0s6i)O1LC`-NxH>rvMW@NwHr>@O))6jeJ|h*cMOVzdF#SbEi?a}#97?L z+@0+%{TmBH;jBGpl!PU7orw5iR7~~y^BjVk%JBCcj$%MANrdyiGT9Tb)iRxWLRR*f zo>W(u+%pexifX@2a0C?|MHbeZOeEQ?y=>uv*WLA;6=E5|NT5X=B@>S+O`zw@9A7x1 z%T1-ldgyw}RY~tkJtj#q5||<-~!9jax(wL>>Saf3a7vyl;37spx0deJ3hh=&iS{R z15T~S+^C8rJC7NfD=b zbL=q;`0kKBNnRF^(cp+-zu!CkQ{Ct2m_mi(@GX6*cKPt*^5qlx^RZi+^Zmi)S_YAa zH@q;D24=`Nc`glXM?1Y9_gdaAn?X+=XSm(me@qwa0jvXw-{-6HO z4@)MU{E+_?eSTD(VZFs>b!#DUuYE@Rdmwiu($;t=u$~pMbk^yRZKDZ$!aKbWDl(ZM zXy?-?k3}wRooNrA7H{_5`dM*o;=N*ur#TCURZAu{#RrgR?~?` z4c2sIE;BVGD>-+A@17z^_-QoEM%V|Ji2`U zaF}W!)oB{49_a9V3zL6aE;d^lcK++0lfYt&q)QM1co-n$9Dwx)T4>mSJ0p{@ znB%rzk-E}q1GydyDYFG5XG~d2ss>Ts-%xpH@o;|Klv{8>Rxyic6NQ2L&c=g5UsmUx zftdvsohOn}JZY%wO_ZmLZiP4$dwW1GzE9v=9TDPx^df6u#RjJgeM%t&;2#9DY!WNZxvB!)8If=rg8bt9guH^vtlet z-p1QKz`-s%d6O8gD9=j;(ngs!T-OR6?iU~%d&NHVHxwWP{+zi>^^n<@`eBr7Xx@N4 z7ks6TuHK^JyFL!67f||i;XlLUIsnq-k&~L}J^DK+GoT5vVMk%`gwwT>p)Rc(6f2AK zk3PJ8MAKFJ(}V%+U%vKJ6(eCz9)RZ4wT2zcHc5xH?R5D^2_O!wO%MHA=5&JFUeA>v)PN1Og#|l)f_|sFM8r#uWxEz2xxc#ICpU;3J%r zlE`{t5yFM~ixXHeCS2J2P2^$9Zh6koy<;fl#E1WuQ11f^?>e_8(9j6>C%2P zJ!^{2i*=U;=>iIC5o4d=c&^rE98lEy5Rv|6-LpIC4CDAf?wg~*2DQq<(PlYGqgqIA zaUmqlUI>X=2c@<%s;n^b01-Ab&d zo426^ME(C*H!c8i#`-`3;4~<|gc58nr*KOVJD+%DqUY!3u3zruf!uYrxnUp_J1)CS z?Zo-bgH6oWJlfo9X#>V=PBPck6CsFrxjWQQ6T~Z%oHU#2xl1xC%~eUeI4 z?662s0DY6EKLCufbeFAj2KZO;F~_iUxF*r3@s*Itj|R>SbkZ4j z-RkgtFa<|nDu>!q8Bu*ZSkgk6@>@`Uu~+$Eet7@BsLI!|^sMTrjUu@%5)Bc4JS47- zqW}1dYji#tMKx1&NPg9Pn{i0h*9n@ho*luKGW)oROa0eMK2} zKTYpvu@m4Hut@0l@MQ5zItq4r+Zb#Tqi4BU_20w{4icKpB!!>syYM`qtPe3Z9aBP= zE^&Wk+Y2*N$=d1eOj<7P&;tdhy7)r8A%}tCwY{a4Yw>^tVRd31(Wj%54gNbIPTJm; zrEGs+2OCS}S->P6lnZZduTgg##A8-+Z62TS!Pi_$R^M6q^WG0X`%EGp8LbeBs{*L` z(IUL=R1G>17l=KWKO&JZrR`Sgk(Wzz$A@vlX>?S(@j9VOCE{Ret+i zi`q@5eHwZ@O@7HV8OcKpxPCV#LOI((D}@j?bs4>oj-Lysjx!C|<}t*GumFDTqa!WA zbYmP+=Xwf0O?PZT&CkB`l5AVZPIYlI1kNjwxq;u>8=Y__HaGWrn!FRgCcM|eN0X;x zL-F}0^5i*}|DkNH?12prmxlV`$jV@Yo9kT%JAN@=KGoA|&|S;DZwtn#@k*U2JFygs zv~T|FTvT^rUEvJQ%sR^JKBNOk+h9KyMF6&7#%*xFkPu*Uq~`imt_GVkqrmA zR#T94+G@p-i{}?@J~`fA7NlTAKdD%died)GlpU5;&KP_!mn7tA%1yJDA8YIQ7FJ(V5GTXHED5wTCo5+ zg`<2bZItS68__u#VLRDR?W(NLVd1IznJxd0o;{G}5BjV@Q@TAWxOd^o>bL>_r zpxV;+fb0d|CB1S&YXi;4iM(Lp&dZ9?u{^e0d-4RF5L|<1-bD^Zg_X9UbgQMgn4Dtc zM5WRpGIX$eH>t=leiA+C6^Yv_0@TetkKGYWgkuu?SVm6XLBAG@6Ajf(kooZS4-<{~ z7KuS*wXu#4XMsmRVATosPCs+J;BEMNJG?$b7M?uS9gAKi19hs7_Y2w$Jd+!$ zHbY^-U!#nsFSjBBnz6(?R1z4+jl%Ix%gD7$O8ibR=O?E>-(rg6uwqiiMmP3d?K-ApFMG%D4Cm(A*iKTTr^J3nSs=${cJOgM!RVQef0r+B!MxW-exKkkDgf=(1) zE@4{;6N?s}&Q*Td`+3NmIXR7vM!t#~VCJyQD3jJGT)l({;t0SDM~=jArcM!Cz?kKlgHrop#i#H3ta{vP!(XtNQcs_Jp~BHF3gH86HCLIG+Ir8c$6J{c zHhY2mI%SfLAeo$BY3-n{mCDyt@7}`cJMz)A6`a>lB`%4aj(DA}EMM}$rnCS>-Q}>L zfE*jL&T02y5XQPoo=Gx^G#j@AW1gna7ewn>!AN7_W+r7!HdL-a9v=oioK88nKR3BA z`5#efg(P_gj7^R6?+!xb1qDilg4yG~Sq^n}zHY4F@4OlrEV9)`5;4NMt8Oj=cA@2N z24b0%0T54DDO|jUXM`mq+0gF)dI7j3xJC_85lxOUe?&(o2<^;R3}74r&8i2xJ4wzW zo_kdWOZ;5o*W}NB4Ur)u@zvuqavT_?-c@p5BZeZR%C+W&DvJbD1P0FDn>MzMJ<=m~ z@kaHS;NaYwCpcUbYL%ffVF3l=LXz70sUHnQ?doQ?8F`r&9s@L1*$Buz2L30I7XbM_ z`--|&7stVzB7}Pnx-MR1m%6}iR4IQ#F6HA}253P9D?U9##`NgXgQm%jCVfjw#B3 z*qRSWG|=f}6FoszL(Sz{o*M6RQl_Rz7cq-DK-F-6TB{Q3h;crVX$Dt2tAAyC8HAR< z-FjstaL0U;+hwAj=MU?-t65<&p|`5%9ERUiJr8^W*>Z)`k9s@ zH1%NEYeOA!vEJGw&t?oH;V>14jl!yq%gE~IL8g8)GP~L94Y1~RTV$l6XDda%{giio z#0|msMi~)C83`(ak3^`E3o`--LZ5Tqu}Zp&Z{iD(w_T=(+qeIM8cgcm*kFhuuF{ez z=4Baqnl?eRgj~0>|8P2rqe68c6KIiA&bMc)HUT&9Pf{9&(=VPyU9kpe3akb=3d1Ps zIVVYrjOeYt3mvm2Uv0A3>46I%k^>W{KJMh70G7xB$5jajo(v_`ji8~t7wV(^KQ!oO-}VKuJLn7Y?crC zqisW#f*pIlB}PKc9HXdi_9o;hw%LLLPwNUaEXDEP&x#Ly$j|)x<5e>%6>1Uw!Ns{z!>H9cn11Ic3M&_*w$}r4Z?hzA(<8MJk-U=x zj*yEz6o0((z;G;QdOJr?p0z%{Lfl@Z{i`TaW>=*r|NT4>2%d=_w&A5*CS?A$6f3bZ zK%linb?Gc?wCeALRYJ<$C+PidYO@-f%x|p_nCpM0mdS69az#?NmL?lYyg3elgJRMi zY4Ir>Sk>nf=X8xyVZK}|ik$|-4K;ah?u2?x!R~>js{aqScTIP>lk1*;M~7V0;RmfR zDs3qI$o^DHftYf5v));8>C-OtptCX*9DNEN!>!Fv?&h^8I36xwK3jidwP9P-*rU*H zWqUd9Bs{LwfAV4fa75W`O}Uw58HPUf72dmxD7{Ny3??!sPy3oHlBV_{9>1c8W5AV| zSn##wO+|4o*Cca9@zaM_#pwOh^-DFMh>u^BBChP2fuObhqh#n4DIjw z8b@MN515Rucc28%_6K41a>?mHSkNHrO(EJbz=e%)K)>rc`A+a|0-iEtyXp|%rcq(rv>ho2+Re0A@|4_+k^cT2n#=k_{`b+oH)7>(6A zm^d=5PNUjFk3?kAv+}O{6G{xR6v&3&GykztHm6MBe?KF0-Tg=b8K;ZDCKEH^5Qt@I zU(}1qC;qR7ZjA*$g+IKQi3f+b3q)}!?+cyjcK@B%^fM!C>?)+YjsdR3qyc)E#%Y?P z_=CqsuU`0^o-8;O@_;a~kZidLW3K4*6W z7YR650rP-Pl!nr53nP&|pl;S%28XfSb=(VL(|Av&+oBkIC_6z{SDwK?Eu<sASP z;mt&K^H}XklSAApCvO?_K-uCXPy>#EH!5iMV>EjeM)PFQt01JM zJ2`p<1sc=90JfLh^Eu72xtf4w|0G_GGLLzs2NU15c$J5NReh#ZoEYg47$vy3KMmM1 ziN@_$5_MLjZxwb1IP29plY_sue(r2yWRV)RqofyTn@aGZk9Eznujmu=sSYZi{zr!~ z#E&5s0FVZ%Z5IhC(Nr!BI+U)v7Z@tYGknoD2ctG>ppA#sTu|P+1tBX;zLip_-k`Mf zI9>Ign@PvMSBG6UD}nP~Ip?w0tovr+ zeMcy$7hj;6I55mJkNhVKF&*1BOw+=^GaFn1IsDpZ=$5-U!=i!TtEoavvPFgGe8yNlnev z(sIxS<3i?S_6{GY>kA+oWmkr>;Sa;B3fi;4iF)vJY*>|OSE(QQM^{Uv*k4Nd7F*A1 zx%kzkYVtZ$3eY!%p+B%Z83vEFft=zNy|*vJPP#jrT}9ac^{1rLzdWJvKp#O9Wnz^Oio?K4;U)~7`lB&1s9C`%V>$V_JA9Dp{Tb=1`4*gUSW`dnG zfMJT~E=Nnf46G|LjQEEXzjV(xFC;G8toQQEi9n^d0evd9d zR_A^K$Qx8G$m^r-0mvIb>zXl{mc~w_z(D~6Mlg8=rsJ*@rOwc+Cvw^`FibVOZxiON2kbNyl4K#kI#B&a~pWO zc9Z$X<f z8W4xxl77l(&uy;R64}}KvZ1VR(ir9OjCrXTF56V;3%ptdzIky}z<#-iK^caTw88F>f!8FPAUm7u=H``Z zyW`qY*1|IT&X3M`eHDrqIaF1Y5>!_TpTHUkAGKMpAwnX*A;>%4wAK)jJezd^~v0Jst`UKEYIN zHRZ`<8OX<{f)R!#yj{-ul*wZxHlN4a(GVwA_pA+pDI@CsmrM$%B$e)opSaeeX_eMVNtef(nijp+r9Dv z8M5(9*M3`WzN?Rik5b8XyT45A=M1wbgT~g=DoJMzK8PFE-Knp@uT5y9)H^!rL?1Je zT)H7`2n7Rizf?|xw zb?cQICX!LaTQw<$-ovX2MZi6L(_fj`4;#U^*#5z1OS0KWhMU>JbZSzpEb7Sir-^u5o@Z1HdL2oWCTJRd}EG{7tWAb^nnx<-Wo|3R~yD z>g$V>iw4;Uyh)n`KE`NM-x(g78Og5x1pD`K1w!wm!Z0qpKkVVO%NNo-Q4FtVg?{C3 z`&~Tfa&h=0lKi6TFN7dBHL1{|F8CG$qrqmN;Ss<3lRsnjchZ zZ~g`xv-!)uG`-)?H2u_4rF3%XyExLD1vs{UTH&>R)rAyzT2V`J@%&mJ54@$vZz}%N zJ&XoPFc@9Mcr2yd(22z!Te`&BZNK8@`|7RdR6mANr<-&g*jNG_V9lOmA z!7G?q0Z|d_KU-3pO6uXo!8sE*o~b+TpxNpz`Cbfh^N;Ax53Z<2%A3_gZ5xCyG;mj3F2IB*UI%T6CO`Xo#eIk1a}Jc|Q%&vH zsJ<-UX+#J%w5Bvox?#B{Ts?1htm#xE&5NFqmc)m{yaKzm1nKRiFh&%K$2yU7mWhk={l(Zl&p3meR4Sz;+VL!{hpmBY(`Q7f{Ko;Q#ye{PY zxYrx;M(TPSCgwBW-2C?)JC(RE1RJ;-zqy5vVf@z&F+tGwGx=^Rw(rMprl+cG!`4v} z8JG3}U23A~Rw_qiw=~QDDnQX1c`x^eog7AY1%eydg6;=1;4i$chDK5hh3Z9P^{HUb zAd`MkzQVxCCV@6iFjDj82~X~u|N3b;C&Ik{Bs4F0?|`NNk z{)8-l%~OKq5_K-8(~2g*D#c8`)zp?x_GAPzC>r~Y%&}8_zDq#Z657X5ZpsI`jo3x&JhaO|x?h(A1(=(;K!i@wz1accQY>UZT(qjJC zt(uXf(1mXn;TCEFI4*;sZlEJ6xP781T%u70S*^-2^<z-HMT0SYCkIMB@ z$4|-RQ2de$TcKn)mUb66ha7C$CQ6xZ_|IpYOB)wZKi^!BRku@39h1-lMc?WH5st2d^;S-nm9i5+t^qQbTjS`d6J7_Ahpz6mBM_ zoS3RZ_1zJSLb?RY#AMYHo_W(xD$J76FTy{rfBl;9BllL3JN!TZE~*wv&iFY@c5$BJ zaiDim&vo)hc7EI5`SGf!NLBdI6mznYw6^)cW(sNGPJqBFV;F6!gWyBbE#s(r%+Dxh zy6y$w`lnJ|@R|5sX?gHF!`&@~yh?lTHENw)V?7Li2SKR3toUMo6-F*s(%egMhmGEC zd-hvy`YoM$`Su<6%Lj~tv>akQ^pjRiCFyeK1kDK?d)qQO`Xp?p2Vbp_2z^} zo1P>cn-?sOE=orWkZ_}cYK8y4)tdS5#{pG3biJo_`8x9vqI1p7|49%6>O`_I-6K5$ z2K|?@;@#&3iNmqn1~}|=N9ST`R;Fe`ysRoW5;@2na@+%QkI<)VZ3UM}4##8-qGW44 zfFW9B{{D+Aey{8B;=!+5&A#`ruAO(!F!%p?JkR?Fotb4m=S3Kd+#0P!IhvH@h;aDd zh!FYWoikAyi{5dNt!FmP$BnQ2lKEo3b=0;wzob1x`}^b1A{9drL9Q%|D+|$o7I`I= zoO-YaXc!nPFJngpA}RONf#79~`=4Vj=F2WrS&Ob|C*56!^lT>%mJ#*zQ63kGe~)z~ zR@wqY1jTVOmPUf3Z18JXB6}yryly5#9Xfp$5^uUU{3a(LZuNJo?^lnvtm}pvlP2FC zYH#YnuHp^_o{RkMw-7mwg-$_gX^axf3_W`Y52E+xLoZsjlb6NPU)KqtnH#;HSk$X$ z$G(CeHYd7UT&E*{h#DGAXKi;-!beoJzRn6`o3kdsFfXBiC_qgMr`ZSLLkjP0xL^C$04os~M%8VKmR+g@r$pfDyEuHr`>v&H5ad4Y!#YF@L) zObz5q&0xQrPZWZ3RpSrNjmN{C0??0Fx(;XY{p&#Jaw9rMXnPPKvT%;UYEI(#tQAe5gu zP@tpSql%q(EgzPaQ*m#iByE%PnJT-ENvY{s{3~A-KA*)`axU7&7u}5*r*(3MtJWk{ z7|aFdEfzmsQmlA4kO}zu-cD_Z-~3ii=Nz#9_j*qTD<>RJ!tkx8XMzPk#n$0eo1k+CK*`%Rb~`#J`O>0P$SYe@*1c17VmINdAbQ z_~j}nWMG&i-1qqiZDFZMJw}|UiiEgkajxEe0}5^YFd$L?nsU(m#!1~FoW%zch;dr|E9nmIs(F^jDOsKWc^x6ao0^mKZ6N!_Sq(dH@Dr%A*j^?i-D?{Y?V(_NW-h3 z0Luh7d;5dF(d?E()kxr$S`+z1E|(Re6>rjF_OW{6FVrhyt#(J@z8mjTdEZ7j<{~+A zG>FcZAF79{Rf7ThxHfa@#jf~Z!P=Mk@AkHgRY*+a=JhV$J9$k6Pcn%oKdQc5wrwo% z`h7fi6{`7U7Gr0Mhw|TX+SdAaL2~e6mq56tqb73F+#1}Jly?lz%h>X+b#Rk3`2mZ2 z*K2^1f5qm=XdR+d<}a-LsWUHS)yjiZ^4ZW6C&Re%Rabfs|Ra1F#I-PyYmx`oMw2VS#giDAsV zVc%^0w_P>5U1oLAjg zE&daTqNqDPCVDn~mDUR~(&zmWccbPLfni$at)QkIkW|mEMtMc9}Rr{zf z%ghofCAVeBnE#*WuwhZGsSc>KuAi-Wg_xo=GFBsBpmyjV=rn$QKKIofb>L{UjDc?Ltb4;Q_h49^ z$Cv1?A8CoN#!DMx4I3r-BK3pgX!6;wee=7WmF1^Ivv(yK&yMYvS<2|K8iyL8Y2@8w zg2vvncPgED)cc9*cvR&fC!tAM{Dt4GdSe(nyf{ zveob`jT#}r++|OGk@>a(hr9Oi?Y0;l+dQ3Z%4lEaIS`wB~w}j`t7pqNHN)hC5)dpY6-Io?Vi1%mlL`dLajy4 z?>};^qlOx4)Tzgj%~u%~?NRu(aE)+9*4M2NyZ6`$`Jx%v@DakBBPRMjGYn-pI{!>m zR`5O~M}#tazAtEoV%*`8?YOoNMWrgVqSEVSAvZ0$!#vGdfy>nAN+sOV?$fFZEmF6P zM0iqPee6Ko!BJDrtq=8vc!aH(+&vq9d%74`Ogd{&N$FXPUhCeO;#zj5P;YicfY*50 znO&<9*IR5p%zwgv@BY#Gp$mLYV{3mHmQ)KCPM@O|%o^h^H(rl65FJMcJlyip1s>zhH0v zmSp8nrv6A9MbVkiE9(&d=AmW04Q0;mni+@VKb5l}@D-BCgW^$8Z$gXtMnNhpC2Ti* z%P7L*bkm~U5aV6?ZosGPd}w3=wiR{PzCJ4f>P2E?oFtWAq8)-47WLrEt+n34t`F5= zp8Q60;h5lxg&7BO^4K+jN7j!n^#&g7;c!sj^_39y(P-PJRx^rd_GaH=jvy7kmG<&3 zpTjnL*6_tIG8!Sf9k9T_s|A4mlch+1^VgpF9!osrh4d2hj|gGV0}L~#x!dycZr$VS z1rkfUB%xwzF-0JE9|oT|5|Y?Mk5H$#akwfNf3IcnyZh;<1LG1n2KvmuqKbiYoq~=$ zN+jCGiL?YXW-d{iY$YoCZmX;1rt$dViL~~#%D?3~vNsDwwN2NIc8A2E&o>biua6^X z6_lUPHv6`+gUj!ZVQVU^jb$E1dLpO(FdBMUcDFE!wWhjHVv$7rUoXIG46V7%y zGUj#e98BY-{j2Zq{Wgu7kYZ}NaM=0G=U(fiCdU>UlFDE>o?JQJedrt0-r0Ut$9Cm| zeminB`ncPsro+u^HfZI1W<(+MZ+q;JYb9cjJ3;{`NVvpZx4;WLAmh3|Pkt>v3s8cw za4W&~hfZJNt7OQQs4d#vRJjHjA#A8U(F{){RjlNCgq0$xuUwVwkaaZS zuSN|sgHZqbx-ika=OQn0>qx`ev$D6H&65N+L`TO8N0A?~`76o4sC;R$PqtrEZ%bCqc|1NE`nk6hBf24cv(Nabn@&?O{E1FRDX-LEghhz)3_G04)hZ+9 z!9-r~)?{!!bEDo-OpCcrQb_mlDS08V-Ghwbf|?*R5nu`d@X2)aVyqPG^!4-c`4j8{ z#0Fdn|FDK@(-i5=07M*RG0k0_SW{E*;H_s&c_wa3{&HUL^;18J7MF>PQpY3q3$!%y z*DT1PvD7qK=L1?ZNO!@WHmr1YBnUSoabCawoih z210{5i4epSLr_Dz_Ymp!toPF@pNbmCJjYj9fKIJ2#j(u%lh;=V5&4cidqtMxUs70o z<*aY?$`zEb3@!!O#CBPdt?74m2n?NnNQY`V{zzr~C`#z(3wI6u+qGgth@Y|6&@6WF z<3?5l_cOpu6MWTO!)l|awSLRO#y{cLIeD5XD@n2xd= z$c!Aa`>teRSu?s*PRT@BTBj(F?)&23Y)(wV>VvCWKej%^u!+v-$2e^M`CPSg$1yyE z|FkpruOcIx1K)Idx@3)g4y};65M+!)U_6mtSVuH)tch81Er#_skavG>|cGMT)X-1)bY+43qjEwB1#Pkk4I?>&+;}TIe#uvEZJ> zaV^;d&DR|rSA#~j0%$!QR~&N#3?q=v^5x&cuXHg4hFYJC&kI|`eJ9OS+bmx$?06!2 z7jnDo1<#xD-L^(waep0!dF9jp$=uUhd@^k2y>bks5s8t!*TDBuA7CpjIj#SjeLW}i zYG-n@cNSLSSs~diPm6oeiR@pHwhfslZKTD<;lDH+t9lXTvP$+MgvS&|xD|VD(@eSK z`2JfLXqGzt*^TXscwSQMgl#afBq6)~Df0id_vP_aZsEUs+s0xeg<_K-DpO=0HkoBg zNo0)7GGv~KqR2dyv5;A&3?X(Ii-^d~j*85gXZP8ibMF1!zwf`d&*$_x?RTwbJ>&Oz z)_T`kZ@o3FlCmOveYg34ptYtrM|Jvy<*#9A`DXZrbbe0F^uJfTuEE>u-qLOQ+s)f* ziZkBs%;RW`w4s%Q@9%vjj^2lufzp#q5(Nu^@&*|gO)Zs=B{XWCol#`d{%6J&jAkyfY?beN3-F*w+@o#w=p6cCJ4}EkGE;~DwH`r8Hx2R+eCsuX?pDdgF@!I|{{o>JpIrcg#9i*tX&edlg{;AGz$KJ#w)=yR6TEYFj3 zEzE>~uZGQXCB*PGQp0pPRh8Qc#LWRo-L2uRYQGsD$w*#5cl~ibOjXG4o5z1T|5jV_L)SuZJlKg+~DJYtTSl{_}nP{z@CIq_7|ed=CG z+|Gve8)j|aeTKoKE#8|{@vKC{%3%e#r!9G6TE#`uo#!<#)u|Xr+%fk#FW~-c@zu}D z^Bio|l6zwh){GhM73GXR7jyS7_xk)$o71RZYJrJWWORS2wLM}sf?76t?aGsPSNc}1 zZExA!VEbTnzRx#dDCHc+EnQ0|!>BZ!Y zkwhB9cG&BLrIbFkZ8Dc|EA8Z*%J0S1@)*S{t8^u6gM}BGpQO174@z1LTVqSPU4PB# z4OKkAvDni}8R+P8xRe#&crM}en#RZ@`bqy%T|(J#sLI^-&08$1%HnT3XthT?P%HcG zfp-q(#v98HzZn!VUGz1sUP4n_hi2YrmpU`-d9wRH+2})Yv<~Shhm+Zo8jb zv6p)}A}TcA`^IyQyFA(suZzA4O&9fG?TRjM@d;k6DqT>=J_!x=)~uQ;$d&p2%-?Zy z=cnJeM25Kc;z-Z8=lm^YjOs|DFPQaGuGF+0Q>s*U(a!?G{`Db^NgH(L8AErP`?vhK zY_=bpaq*sv3!^;DM#h8aSsrplq zC4Xc5NR3PWwfzXaPUlVB64)H}P}7>1mn$U2xqEe%pQtTytZeGf7Ep;)FU_~SKXzwx zJ#Izd1of{qRc5(&DBIVS7j7rjy>iVK3g>1W-CcO~>dPgLPnF^U-NKDa^z@~#Z)>w% zm9IaazPj@E!n74x>Bz>^M%d!!!;Pb6@`}M%^SN;MHA^nfL>=2maE4Lnvl&(;tq&r4 z!oSGA`d^+)v$qn=w#?G>2xyBG>khbo?;@lBYMU|*d+@2lJH+vqc{*OT4XjtyO-9!l zrVZ1upS4UeG;YbxZ@x8Z8*s=rk-ND>fO-t1c_fi?s=!q(RM7O{>D))Wi?ez%C z*tM$On5oboDpEW3;rc^dTv2?lPqJ|i4oK9y-$Q4QvyGlVVNxmaLariqf8E&wWfcbs&i<(Y;b#S zabrSRTH9+t#9oDegeytZLf|i!Eq~mkFre6Xs{F?5?MR}B5?Dg-`q0Z$1_PEiQZJA( zqxU6Usf+gI-N11AR) znNE%zaIj1HYo5-X`g9=t;i9|w<@$Zrph0BM1Xx(MwAxB|c&*R<)^{%8swwgBB!9a+%FMgxoe=zM z%6{$_$HRwb`^ZiDX>OHpoN~Yg67~51^c-y5zByPtAoqe%g8t!OKW>zo)kbQQHjclM zQBP10GOiCfJe}eITk?kQG$%~L_FQUI^dIMxo;*jz>>8_+A~fu5-_s<+1YQaGq%p5y zu{J92cuZIxH~&1b7mgXM>(9vQt`k-CsLhXx!NyBI@9lWYapryWCy}rS)yQ(xvZ(mb zq6lu7dIy>wS*q6VtkBDiL|)@V#etNS&%)Ti?&I6E0WZ4t zIB*1_QMMAB?5SZlhq;@hvPM+H$8)~y-udQzG3^{fo`e!wU+BTu)ptVL>^^>rvz{&i zb}{7~TDJ&BUh3iyf<>#)i<tlfsJmj+vAd}oJb)Z`U&_z%jxM5ZK%jKk>}0`=Y|-HoQH`6&GQxDl81;qRZfN)M*3 z#>v^vnDdD*fg5(iT;uEBtzg>93tRmHLJeK?zn)#!9wL`MFO@=tx#A{*Q^3nZHtiZh8 zu-aEO&Yb+_)qA+3T0%Zj_wsOce$YdjE);p+b%*X) zR)y&O1m=sOVMUqkF~^2JNvG57T-pmgDbFQ7ulDvD|1xuib^l;GE%~<$zvp8%o|_Ga zmoCVhx)%Fo#nQLpY;`rc9}a)LeT;ih zxb~*2bl}_f&Am9s=(n?7O7%@2Op;6XHsCMc?2s_j(GY*ZT@!9&AvF52EYfvU|ceU*!aJODJ#TbcFkd~f zyn8RQK%oE5d^+1G-}q^6e({1{8=+Smw+&xKq>ny`VNaBbzOw)3Ljct^8Lw$N>NKzyB<3srtr^ZoeCxzE|qQ*v~u^T>KT+)3f`j<81Ok?Dw zZ5tKaFzdFcY_gfJt$Tcm<}J4{Rc@8<^NkxdEZ@KVa0NZsl_U1DmLV3m`zqvX@C{b? z-sfTirsdni^A+x5NT$EGDh6T_QDza!C|WP34+{p|bKch&Igp2$yBbc-_NmSj@as+)=hw38FA zm=zX$eBfI8*QJq`Y+Cal20}!{6^Ru=NAO-^23d-nK#vs}6e+V%`9DCB`v+T>o$y4 z`~v5{YM(Va_G-<~yb$eKLeG-v8Sa)?lqF!6QOc9)IUCS=P?K0^=WVuYH8jmd+iNSS z-@tD49DT~+S$UxtPqn^a=R+U%JZZm-{&#NMNS z%-iBsoZjGiYnehfaw@kA>8QDm$s4E|V*}nKheVfFwc`{OBl$K(Mx5AO zhL3snhiAk*vQ!ydv*{>d!9JKyP%&}NZ9Fda{wu%fmXsN$Y>8*@wU1fnPO_KR>4{|> zhco&dXU-0imwz?R<^P#el%`*P;?%w5V$EI0UhOGsBl7-wjsA0r3J#$;G?h92(hLhC zO+2vNU z?1tzgg25de1g$=`%-pA3OC9E3qlo4J` zDvPSULp6}=f6KqqJdHNv815KIu1b4Nqn><iO;6WwVzDj*woSu1FXeepaLQ5c zFvqF~tAoKpJ|^8X(mV|Fq`l8K+_D;Nt5g(=_s6N6Dcsw9GeDa*_5%XPnx-KxvVq<-Xl}BXTB=XH)FYX_{C89 zg<_H6@TV+Hr#~A_mfOXz+F!|yb@Rmhg=r<9hda9*V^dr{E>&@q`))>v+LV~ztM_J} zanr|CF6CIN9|yHaxHG!|a{{nNfCP)ZYe-ZCYkj+q=3YY>RwFkNhmuEIEmnLZ7ad9Y zk^H3m-wrYI;e6jgKEI$a>zK!});?ZdD<7}Z3L5%o7)z?3^x?yL{*e&*na9zYc<#1f zEaP_7mJ$BD5jBI%LPKSOi3qzur7Evztb(TV^)PFBxr@ z6;@$5+Jhy|`+sXRgN$^!fMe&(un1PO^v6C`{J~ z7!4D#kivF>ZZ8(p!oqh!oavBjv#M*Xg=u^MooG!2eAx4XX_VBv86W%^>dA9-OoP(f zW0e8e<)?HU?~^k;`Zv8s#96-k^IyFmOC;U3x4rDlB~*AppXT_Nm=qCiXq42Pu?AWCVCX0 z%q#ku%&}{xjGV2dV>OkbxFIXdEX2Mr&5^~Bp{-dU6I?>%3rl!dJjI6f9fr04PN zRO^QNS3helxsE8e7h&sG()HWK2-C5>d`s-8nQQy$o~Ud4qsXCN-x`jx>=2Aqxa=0o z@^^Z&rk-7+9jCT6-{dVN>L#y4F|Aw5!GB+`#(bPfSWx9s_P9Esz$^TrY4jX_D2+Vu zWG+`^M)e#jWbRM2r`Z1fmUObDURH_xpMU%!qoDcc|60DpAZVcrw4tQ>|38B6{$CX` zlxvFuZH9Bf`Dtxblx_Yl0Zho43JqcQ0@u305ZCjl8Y*7a-9nr=D<6LD;q|h=76PYN zAUr1gLlCZ9`hWWI4eiUno^S#}jj$`onHAr-(?q|Lx<7e@I3l5}3u$!f&?qPV*ZTUQ z@KX6+@C>Tw(~*qNWr2fbIM|_tkHA?2?7uq$Fc=myj$_tva(^!sek;eQ8be+h%L)RKy)^3kzg*g|0u`>?~FS%~^41sf8A zT%Np~5ipkwk&KEq4w_;`_yHm2L3__Jq6C2?8qf}5NDDYpEkOxis+=Lxn+~E23QQ!Y zH4GvCX9z~ZMrLF#(A*l3^Rm`P#3?F6sB(91o zU1>3j{U>Y~FM~Qng_#b>_fM^SfEPm35C0qC&q;hwiYWWc3phRhKYlIFrMe_-xc4CZ zE!-~s*VX~j?`%<&)I==fa9rH)UyCrxvh=+{Qe<02Gv4{v7uurtMDNLcfOE%kk<|Yw zN3nF=fOIU+Rthq7ixtPeBu#4fC(oA`+oD>w{~JXa)(T{iP4`BkLYe+2h3WRvRJhVS zm%!zJTHXE=kxQkz?G2YF{JE0~PyQOh_1ASgY;K8lMLGL_Ri+Ff?94R#a&4mqUKa0( z=x#Nz|0j?UtZkqTOYZ|MtbXlqE~S#X=UYMe~4EQjHRAJn*X z+#-*t7T+uBo8U7M2>^bhz#!4e<|B<-^tQf&dxW4eElv6PXBp3=8Mh@3&TrqkJD+{T zxUF}%RvL6f)F>$<=-sj2lC#?g(c6lv?>Ic9N;M2_Ue&$C_KR?hox}5tXJcqD%!-}a zpk~@!hhFgzvQ~EGG`{^ST|75YUh$B)NadI6V=(^lE1qAPDq)A<$!$^RWi~y3MVPZ3 z(#+FEkUu4gD8K7tzAA{b4&Exa{UgW}jnE=$l#&sA+vzvL1s*{e56s`dKg97VqnNzc^Y*D1&yE{C=5$mOFZPr5@Af5CJSTvuymdTt3J94jIoq)AFt$H8Vt$+yRe%@3v@3VHZfh~!e+MGBJcv0S zVYn7}T*AOOTr*4JtU0qjYX4`<{8)yAR>vncxGai*O!*Mu9GZ<5-gz(QYRI}%GM@R} zRM25WU&m;FC@xRTb7wl|*e>H4BFYW>7i+siI1>Nz*cR`0+Vz3>Bz-28&lXAMR$UQl#8{l8f zCiMD$3F$yUE2lF-MA7f2(EWoTo&PK9FbzAFhtTgN!sWeOzQiOFu47HQuKoq z(>StV!&K2JM{*d-o%e4q&9cwD?SaSkM=wzc?$^HbX$`LcllOq}WQihuLhneK9e|p; zo;Nvvqw~J1WUJyW1Dbkdwf)8}yi6{!X$5d_MDsB(-B5qQpi1j2B4lS~kG3E%6mqWSe7SL6U^j7)kCX(`AFvb2w0 z;W565`8NiC6Qkl|c*XbT=)Ct2i;dw0uISIpUf7JuSRNRW;|O5c}naFqu9hj@h$7jR%YCso6~Slw?(Bp zJ4jnpcZ)mttioj>T};IUyKsc)+2Jk zB|wpLS2ChDv?B+xY}{JlbOVG466A&U&A}12qU}vl+DLm&Z0IvqFmK!)ShJ8?^_SPO zmR9T#s*qqi!6qNBqz%UzXr6C-nSHJ1G$L;(gasY~8D4rq7Ypbjf_tnvDo939!GbWH zxs>NU348vqxS8NEv3u$tZUsFC#8m-~%AY|7@le}vA38LDx+BhxA46d zX8odbJ`ZW8HA=^Ak=DpCLQAKPmUeg-p%~s82^L?4`287tbi4tM!knYWtOO7=AIb5~ zqaDeOEVUU)3bln};`4vo6H2kj#k3eY0y6!>FUJujGx#h;O}wV~5$sVTFFy&oV7De{ z{FXzSBwD`{IHos{Oi~P|G3SM{(upfVJo-c+k;xclUBDiMOM>qX$m@Djtq5o`fwpf- zCefJpLzS*VIF=JdOx;i?HJdp|u*^BAxKul4Lic41QgF3h6yB473~;>g6DjtpsJ_tEh7zgSQn>VqjS$W9T@Rkq z-M=`^CeJ*a76Z8f2qM4`0XSu|)Li&DrmV9cfuJtH?9`Gs-!N;D%S(uoof-mA=#Kzh zZq!Vil8wsa%R!EwUs%IV8nV%!1HxleJ83aB@qAyU(1B&Q<+NSpLuoX7p*AMvC)Ohv zBQHqg1gpGo1ZXz(3iyL@WKUYmB76n`qfRd9K=9`v0mRllIKF*6_!g7_^}t;CD}o_X z9|Ooz>t7tLeTsf2k`BA$;4GYYA}rk_DvIbCh8{hu!p9sNHX9g6-d<~hwj<6t1PYq!pg_jMINrgb3!Bqm_5Ipr);(_g^ z)6zjOtC;@LdESMxfr3a-ngbgE&H;s2GY}M&3+rWIL*zlFR0lYsWeX0|vJJC~Y9tm7 z_t+Vp2tY9timG~Bg_iw3w~NLQ6ffV;IROUNi0U6T2%^#PG}+zr!CRsb4&t^@sMQjr zkA%?7BPoW8>ZDC3J4MwCGinmNae72TfP$9NRLq6NFhLgz%=k%0nWpdlupA88 z51{O+&K^5lo3(N@TECUAHn)nKp1gy2>n;}?@jyP9ok1yqQHRDLQLdrPj_&;_+Xp(a zCvKhOd;I5-%PU>Q*z4CU9G+f@EHOA0{-lV=NFH2F_O4f;`xc`^P{pZQLA(cAtNNiE!-| zx6bfrBBv)&F>f}R<#Imy$_&s|q)ed>JZ3ha-PBLDItFKSnF}%erBz0gJ7n+jBcNFs`sf4NC7DJ!yJ4yMD`-koeia=XO z^0YY)pH~krX!ofQ&7cgGY9hDM&Nh1VommQ;B~oNGwpVYzTUsSu3Qe1E@{EdziV>Fa zj&r2)!+0se@H{~?R+cWlZs9pQE{NFNWnz5JYybD;w?N{kN?p4KAA zh3zhO+h=ibKGn|1i3sjNkbz*eRO07(B3=OpZJkKPCtJ#ROfRkd_k@7@wYFJuwY6mK z-|U49yO=XDz82owz`%$e!*06|dNnIC@sw~D`aDcw!0KfU!eJ#9`|6k|S@RGoDnOXb z#@f>53NZT-n6-QHQi^SPONQ-w_5sJW8dlC?gh@(b>suI?s~xFW`1oad%njSNbejAL zy1po|vBxT>Oq356y?@idz)uv^c2^=ubz_aIa9UsU&&PoJN(;BpoVOq2*HsG{vc7$O zY+#Uf8pCG03XG+k27{A%@qDhOt2n)q2$H;*rBSm_;{JU+DDd%;{===imM-_9`)>kc zHa6Tp4umbZ?~38Q!H@I=wEL`)nXdu@w*nL9x=V9NvK#}+)y~*#)NNJ!jEh~PVsmez zt6*`~YZ@OG28j>AoYX6d1x z2981EhZ$n4vuvrtT`@2iJAq-p5QPfwmxdDb1g4y{UYShwxIsovD(Xn>AVA>o7{Ps* zz|mXpBVx~35wz3GSM)uT=XwmdB55PBv>?!Ws@vQykPVI2m`Dnqdk~wP!LSuzK}4Eu z>9RoJYcxN~*q9E(UcdsHc=WqQO6r=-6|17zq=8xqNx9oLtDMG^e#g8#ps7?aAzr*e zhFvhonViWb>65iILy~otB95p4Ak4?<9mh|ErDUcDCuDh%p4j>j{AR8dsc07t*1ZJZ z_M`3Pvv;;F8r*o=*5{T^*}yJo-f|2dUd-G56dkK83%WtAkER<3vFa=a^bgNuqjDZ{ zYWGgBy~I^VM0Lnn*}&RmtYy97qO} zSx^n_FmAdRCP%8Jlu4^?A+Th;QI4l$tu13!R8$Ma$Y=_3A=sLO)$_Ny+pqfLm&cA` zxSUp!)=Ck9v>=5Bz6GLdV+O%KaII ztXK)7iDUV)+l!1_vM*b6L4F?EL5SB3%s28A+J>|*22gt0fg;y}I4UdjSwQKh8&K>6 zs?8o)L=r*(!ihdy45gx|5?M?k&N>N0=;bkJYKKV*U&9ocpf~E zcBOkZiuM+wr}NX)CPdHYDO%nFQc@{aP49kwSp5hnG1-dlW$P>Mj9>pKCst?if4r-} z8`Nk9upBFFzpa04VSLVgIT9UfWt@={O?)U;rsLKbV~QjLlPiG9tyamCPTGJ}w4YC7 zUz21kt*~jDWaRMSJ8`1Dd^XRraML87-n^ehmi#aRm5&rBPXm<(q6T&07cHplat z^~@%*)#zaA>$m{oE4_);k9~3S^mt_uJ@W3@5NK-R42GSLW|<^|4kP$O3;z~ijG(3+ zAbJ4|E^G^o?!Rh(o%6dRemxQQrx&BJgdBlZj1bGBUc~At?4DT8619w+9-=3p7!^Pe zM?jF_?+A9yk9ew?+=IrT)DWb`UElm>B$t;2vRRuQOhVUhz6YcagJ z+1_lDL|xq6&_HRnLe9gp+I?X}Gl*0GOfTJx9BoK%!iK;V1(WpR+^F!((7*}2TH|-4 zlqhL6R$@Qo(1kk7Q=$kgz%o5p(JBlmUjfQIcqw7)ZCL2VrBmD5(Ic&iv?I_4A(-I6 z?szvH(DN`JI8_DAiv6|dx1B+4TZcwU_R_kp$e(=*V=@uOWL)sury1g}vy6I8oH5%S zmLnp5PP^|NIK49qre%Wy2VegJ=3N_?Q4G0D;+$n6P{CgU>j9j zJ+Mhr!22IBVdvbvvvJ>&P~mT)VEk@ebkHKu??|Uso8C0X{{+jV0EXNq1G$!w)De!) zvsqET0P^zyY@gGpf2q}3gN=UyD1E!G;EByxDCbe5tDqggc32T2=som3zT~IccTt9P zI~<1k^#O8tHXxEsVYY_m@J=l~IE`ixEpAc?KtUGtfQAT~B&mK%7z!EfIit{*keX<3+d9 zJo}8z7m-I0j{(Gc0nkla8~1C$kGB=HyfRnJi$%vIwhG~$@!y7W_Pij^01T-Xf=@g? zs)3*{a|hHjMlKA@xd$@9!2RfgJHXnfeNQD2K3``7AZ3(u%Id8SG&f>=fI8PmiZ#^>C+TH{?ZHCKUr^m zl`?X|0MwuSL}ZcJ0#LDimhf<%R>kENvx)yk(G?xzFoYndS zWh`PlGktYzCx+M*h5r1>e3%m}%@Z+NuzAHXvt_04D9d zE9bF&zlV12z@uAREG>IU>b}-~W4?z@OXvRm2qKFMBI`1tU_u#Pg)zVlDDYvp%F2rE zuL-4lc4og5O5bv66Ri?RgA+U#6!)ki_VNO+IUx3`lVa_A0Cljl9(|4G-iMIj86})z zv|q`q!Cz{-lMvUMP;6O!Fx%edTEP>bpVI4k(cl3g^*KWh{L`KvVQu+`4qux;U)shE ziYH7F?urNH{~>LEowAuh4G@C#6X1zR&Em+Ppjvh6rB$d#U{kq&lLG5)Fl%@!>h%$C zDLm6129fz_oCbq{h&zU7#E(Ey+(R7k0KsjEp!{+$(R5IeO?P*DbkM>0PK>UKfx&uk zbCBdg(2r1QwM-_cpBtFv`c)y!YfpOJFB&Xq);X?r`&BXTYeZD^5@YY@_;p(F>^7*_ zpArc)x+n<6jO7$* zHDmqp6W5bv_(=Mc7Xe;jDx+fowOL6}ge|ak3e;Z^3?Ps=cW|~7n%(t|JJf`BJFW;F z4rtek`;F`F<#TnrP^Jy8AR(z3_f1KUKADJH(KB)za_A_aQ3_0bL|Ts*1e_TpRu4Lm z_Bdxtnuhihlr-;92(Ee<3XxSeN;AYKIfXQ$lKxB}x}=Ne zA=sA)8_)fFiZE#bO}p1%2h{WD<}Tt-10+Db=O2?DWJ;1pDTVN|2gOuP69~oHkr!ll z=1({;LGB}A1Al?=OoAfBTOEp)NQi$=^x4Atb|tdnwsW`}hVPb2z<-1_A)Xn$TnU`% zs+3nlu`CR8;lg^~Y?R)2yF#(F`ZYG&mp%f{CSccl&a8@dl%Nme@r;XAt1_&fieakP z6Cln>Byk&1tz}$!x74M2n+lqYJ7uFD8C`W>n0o|rJV{DyeTs`H7)+n5`Kjh3=N4); z@&sq!)3vpDc}-UF^1LK|bCw)$Uiffr6iSN%esBPUmm#pV5fs=N?>0Y6^SQW#j)n;) zTRQlS_BK$9rvw=>DV#X7wCUR%_ZZv%Rq_PP0qMH3oI<6**G; zcEaA-Gnbcxy5gJI2FRfV62fm^Fq*qsm>%6BYs6U)OFA=cD!<>X@CZZM05Ea++$uU; z>TF+vKjn5GvFwq#87qK=?Kl9r%)oV@^vx?1Fm5BTdOB7%XH0Zu!~$HUjd3i|i*03q z!f&4h_q72ySW8Z99n5FxF=T*60VsMb-2kwbQKbhzaQ4wpQQ>D^4b1bCWhl6d-8DLf ze@;-h{yVDL^Puicxj}!Lr|;c^2PY)7`_fURvh;^sy3>@8Vl48zHztIlqjyD|$({Wm z4y>8)#pPVpqu)XZkUBnbJiW?{ckiXOYv@1{<6q$Cd!YO|Qvh|{=$w1gRd@Q;0UY(< zR8s)OK)sTO?M9uc<3^pQc9u>YeO)nc02TA;alxr^@3>9@Q!nmOv`DbZjkJ!-6=pr9~>7>Ii$3;T zfb7Zu<|NL?oUb;G8&L9|@#6#fTaVg)2LSy?IG&*CpvC;94oN@ZukS)irS=xP4RCv~ zc+_JNuY1{vbQ6_v0wV-FxlAG71?bVc``k`W`Cg+d>o$D8?E5|MxPZ$%5y}C9V7KSO zLv%V+Py!zW1!nCk-)+V-KON+fJH|ZfK1GnkzaT?;GiH|l zp@E{i*bjvRkGx)O$6o!rxK;o`4`OWZdfqYHx$bB*;}Bw7J|ia(gQ*Z@mgCgafMSiJ2%^JeP!BJa42WNzCZCZE!v z7ETF&AK!tcaDe+5cJ*1k0s-57+``Q*Ep>=gR6HZSOfzzPRaEj%lWJ=hbsEPcqDceN zxPPApU&D6S`@l*BxLTgHnrRI8@6nk(Z!C#=-w;*QaKmvg2e$~j->`C4xr~>=-hKhq zDKMRPBU6f+i6|4QLRh5g|GgABH}8jk)l19q4P_#+T?dPd#|u~v@6)av$NvH--6HxW zt;TR;Ty5BH*52Oi7XD92X%plA>M7jl4Bc-8yX}eUmp)BlZ!Y?xxUW$a+#Z@hEF70+ zle}vN^DXZw0)Dd^9dsx4BIre{&=E1BZSb*Z1>< zp7N?iYaeD2t>EoicqKX6I?IkpqS7Z(*A4)@nC3R*9=;t(vm2U7okO=LX}D}7$Y|6o zzBzf`#y#%E6uxWU8ciS1<~Rw}$$U^U=uTWjyRVMe;>~dcg1ALZ@rv$PqRzW?ddwF^ z@Rhbjiv1(ktiCzk+?P%(1KR*oqRv(T@riq94-In3R+n+h*&HbV?R~Y2%$OH#Lrs%Q zwGsJ=Q2a8(v|R`HypdJW9_G}>xYNBDO_;RUj%`MwVZE8ufeG`{2O<;=(*RjWdJ<{7 z80s4bX~?nVkJoR@0Nc~Q#1c}9sPZ##>`17OL~w$=7!EBk%Aa1^!cu?~vNX(iFDLNH zSs)6QyM?ENMSy?jmpUcyFtwK@vo3)1sa+puCNnyP5xmQQ=U57{afikiR-$I3ask?6nriFYR8D&F6U`H=6^LF9HA!3XXIEU$m z-PxxQXD?xvPY?xuaKtBqkT7ev9eW)CLi)V}6poI%R^lG4t)fCX{LGHEC5+o95r*f- zCT$_Xv(MD17X(!Bm3)-Jsex2AFf&246RBq#K3X6>2|rW~B4xv)@-Gvt2otVls7V1fp0$$&XgE6n@#&WWI;r^Z0@v^Z_8Se;Up8w_x8*DdtS%rwpbB3tz3 z2-z^Fq~eCKSImc(x++>CEnxGUG^8I)5USSOW)UJiP$e?XZM=w(38Dr*8Y?QqS(ih{ zqEX>Fk6|U2C+G-igc;8osXgxH0gHYTJGZ$(+sakc6};fXy$}Ypn3ubtMSI+hpiHHj z{)dE~kVcxa>JI$;-6B4WBbg`X+I+eh=gtMPpd-!EozZ3yQBqp|=z<&wyE<()x zFFZm*JGMZzf5R;zcZm$Q1WA1iN|~tl*pA5?r5t=P8ztDk^OL!O9zFN1GK#6opoU&F51nykp^mlO!og)My zsET--37;~XVQVNWDcAR*52n_n`xdZ3|9DPs-8DEph%e}KFcs0-n@v3gESgo;(QcEj zywWS(tN(J5j~o`g;<$e^1yMs~yJM4)lMGYJdv4(b+DBdSZq#_Q!n_8VR1)V998&Rm zxL#>JrFh=tQW}{9v4g6JU)Mfs!{u4W!nH0>D2gNxgneE&k}uG>ElNFjEv2rNy?a!q z<(N8E#m})cIXN2gTIvSiHaZQJ1{E(ya57b6^>M2DQp4b71OpMn=dEV?&r&LJoN9eT zu;vZBq@2It?PYU)v4)ASC^0f-%rJD}bKeI`8`CKAo{*_p=_?bMyF4RGF9hY{nf b29HP@D9EFJDBd}ZfIn(VT8gjb%^v(OKI6J9 literal 0 HcmV?d00001 diff --git a/packages/cli/template/nextjs-shadcn/src/app/(main)/layout.tsx b/packages/cli/template/nextjs-shadcn/src/app/(main)/layout.tsx new file mode 100644 index 00000000..57a8452b --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/app/(main)/layout.tsx @@ -0,0 +1,6 @@ +import AppShell from "@/components/AppShell/internal/AppShell"; +import React from "react"; + +export default function Layout({ children }: { children: React.ReactNode }) { + return {children}; +} diff --git a/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx b/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx new file mode 100644 index 00000000..0f180c04 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx @@ -0,0 +1,90 @@ +import { + ActionIcon, + Anchor, + AppShellFooter, + Box, + Code, + Container, + Group, + Image, + px, + Stack, + Text, + Title, +} from "@mantine/core"; +import { IconBrandGithub, IconExternalLink } from "@tabler/icons-react"; + +export default function Home() { + return ( + <> + + + ProofKit + Welcome! + + + This is the base template home page. To add more pages, components, + or other features, run the ProofKit CLI from within your project. + + __PNPM_COMMAND__ proofkit + + + To change this page, open src/app/(main)/page.tsx + + + + ProofKit Docs + + + + + + + + + + Sponsored by{" "} + + Proof+Geist + {" "} + and{" "} + + Ottomatic + + + + + + + + + + + + + + + ); +} diff --git a/packages/cli/template/nextjs-shadcn/src/app/layout.tsx b/packages/cli/template/nextjs-shadcn/src/app/layout.tsx new file mode 100644 index 00000000..6f0ff3db --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/app/layout.tsx @@ -0,0 +1,20 @@ +import { type Metadata } from "next"; +import "@/config/theme/globals.css"; + +export const metadata: Metadata = { + title: "My ProofKit App", + description: "Generated by proofkit", + icons: [{ rel: "icon", url: "/favicon.ico" }], +}; + +export default function RootLayout({ + children, +}: Readonly<{ children: React.ReactNode }>) { + return ( + + + {children} + + + ); +} diff --git a/packages/cli/template/nextjs-shadcn/src/app/navigation.tsx b/packages/cli/template/nextjs-shadcn/src/app/navigation.tsx new file mode 100644 index 00000000..887073db --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/app/navigation.tsx @@ -0,0 +1,12 @@ +import { type ProofKitRoute } from "@proofkit/cli"; + +export const primaryRoutes: ProofKitRoute[] = [ + { + label: "Dashboard", + type: "link", + href: "/", + exactMatch: true, + }, +]; + +export const secondaryRoutes: ProofKitRoute[] = []; diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppLogo.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppLogo.tsx new file mode 100644 index 00000000..f5ea4966 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppLogo.tsx @@ -0,0 +1,6 @@ +import { IconInfinity } from "@tabler/icons-react"; +import React from "react"; + +export default function AppLogo() { + return ; +} diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx new file mode 100644 index 00000000..8c4270df --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx @@ -0,0 +1,21 @@ +import { Header } from "@/components/AppShell/internal/Header"; +import { AppShell, AppShellHeader, AppShellMain } from "@mantine/core"; +import React from "react"; + +import { headerHeight } from "./config"; + +export default function MainAppShell({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + +
+ + + {children} + + ); +} diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.module.css b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.module.css new file mode 100644 index 00000000..79d81bad --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.module.css @@ -0,0 +1,40 @@ +.header { + /* height: rem(56px); */ + margin-bottom: rem(120px); + background-color: var(--mantine-color-body); + border-bottom: rem(1px) solid + light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); +} + +.inner { + /* height: rem(56px); */ + display: flex; + justify-content: space-between; + align-items: center; +} + +.link { + display: block; + line-height: 1; + padding: rem(8px) rem(12px); + border-radius: var(--mantine-radius-sm); + text-decoration: none; + color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); + font-size: var(--mantine-font-size-sm); + font-weight: 500; + cursor: pointer; + background: none; + border: none; + + @mixin hover { + background-color: light-dark( + var(--mantine-color-gray-0), + var(--mantine-color-dark-6) + ); + } + + [data-mantine-color-scheme] &[data-active] { + background-color: var(--mantine-primary-color-filled); + color: var(--mantine-color-white); + } +} diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx new file mode 100644 index 00000000..4409b1d6 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx @@ -0,0 +1,34 @@ +import { Box, Container, Group } from "@mantine/core"; + +import SlotHeaderCenter from "../slot-header-center"; +import SlotHeaderLeft from "../slot-header-left"; +import SlotHeaderRight from "../slot-header-right"; +import { headerHeight } from "./config"; +import classes from "./Header.module.css"; +import HeaderMobileMenu from "./HeaderMobileMenu"; + +export function Header() { + return ( +
+ + + + + + + + + + + + + + +
+ ); +} diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderMobileMenu.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderMobileMenu.tsx new file mode 100644 index 00000000..910104fb --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderMobileMenu.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { Burger, Menu } from "@mantine/core"; +import { useDisclosure } from "@mantine/hooks"; + +import SlotHeaderMobileMenuContent from "../slot-header-mobile-content"; + +export default function HeaderMobileMenu() { + const [opened, { toggle }] = useDisclosure(false); + + return ( + + + + + + + + + ); +} diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderNavLink.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderNavLink.tsx new file mode 100644 index 00000000..5da52246 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderNavLink.tsx @@ -0,0 +1,31 @@ +"use client"; + +import { type ProofKitRoute } from "@proofkit/cli"; +import { usePathname } from "next/navigation"; +import React from "react"; + +import classes from "./Header.module.css"; + +export default function HeaderNavLink(route: ProofKitRoute) { + const pathname = usePathname(); + + if (route.type === "function") { + return ; + } + + const isActive = route.exactMatch + ? pathname === route.href + : pathname.startsWith(route.href); + + if (route.type === "link") { + return ( + + {route.label} + + ); + } +} diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/config.ts b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/config.ts new file mode 100644 index 00000000..ded639d0 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/config.ts @@ -0,0 +1 @@ +export const headerHeight = 56; diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-center.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-center.tsx new file mode 100644 index 00000000..2de3b630 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-center.tsx @@ -0,0 +1,13 @@ +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects + * this file to exist and may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderCenter() { + return null; +} + +export default SlotHeaderCenter; diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-left.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-left.tsx new file mode 100644 index 00000000..781fcbce --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-left.tsx @@ -0,0 +1,23 @@ +import Link from "next/link"; + +import AppLogo from "../AppLogo"; + +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects this file to exist and + * may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderLeft() { + return ( + <> + + + + + ); +} + +export default SlotHeaderLeft; diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-mobile-content.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-mobile-content.tsx new file mode 100644 index 00000000..9943f8a0 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-mobile-content.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { primaryRoutes } from "@/app/navigation"; +import { Menu } from "@mantine/core"; +import { useRouter } from "next/navigation"; + +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects + * this file to exist and may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderMobileMenuContent({ + closeMenu, +}: { + closeMenu: () => void; +}) { + const router = useRouter(); + return ( + <> + {primaryRoutes.map((route) => ( + { + closeMenu(); + if (route.type === "function") { + route.onClick(); + } else if (route.type === "link") { + router.push(route.href); + } + }} + > + {route.label} + + ))} + + ); +} + +export default SlotHeaderMobileMenuContent; diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx new file mode 100644 index 00000000..6c392c95 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx @@ -0,0 +1,26 @@ +import { primaryRoutes } from "@/app/navigation"; +import { Group } from "@mantine/core"; + +import HeaderNavLink from "./internal/HeaderNavLink"; + +/** + * DO NOT REMOVE / RENAME THIS FILE + * + * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects + * this file to exist and may use it to inject content for other components. + * + * If you don't want it to be used, you may return null or an empty fragment + */ +export function SlotHeaderRight() { + return ( + <> + + {primaryRoutes.map((route) => ( + + ))} + + + ); +} + +export default SlotHeaderRight; diff --git a/packages/cli/template/nextjs-shadcn/src/config/env.ts b/packages/cli/template/nextjs-shadcn/src/config/env.ts new file mode 100644 index 00000000..3c50ef8d --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/config/env.ts @@ -0,0 +1,13 @@ +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod/v4"; + +export const env = createEnv({ + server: { + NODE_ENV: z + .enum(["development", "test", "production"]) + .default("development"), + }, + client: {}, + // For Next.js >= 13.4.4, you only need to destructure client variables: + experimental__runtimeEnv: {}, +}); diff --git a/packages/cli/template/nextjs-shadcn/src/config/theme/globals.css b/packages/cli/template/nextjs-shadcn/src/config/theme/globals.css new file mode 100644 index 00000000..0e2f76bb --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/config/theme/globals.css @@ -0,0 +1,125 @@ +/* Add global styles here */ + +@import "tailwindcss" prefix(tw); +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.145 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.145 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.985 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.396 0.141 25.723); + --destructive-foreground: oklch(0.637 0.237 25.331); + --border: oklch(0.269 0 0); + --input: oklch(0.269 0 0); + --ring: oklch(0.439 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(0.269 0 0); + --sidebar-ring: oklch(0.439 0 0); +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +@layer base { + * { + @apply tw:border-border tw:outline-ring/50; + } + body { + @apply tw:bg-background tw:text-foreground; + } +} diff --git a/packages/cli/template/nextjs-shadcn/src/config/theme/mantine-theme.ts b/packages/cli/template/nextjs-shadcn/src/config/theme/mantine-theme.ts new file mode 100644 index 00000000..890db89c --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/config/theme/mantine-theme.ts @@ -0,0 +1,22 @@ +import { createTheme, type MantineColorsTuple } from "@mantine/core"; + +// generate your own set of colors here: https://mantine.dev/colors-generator +const brandColor: MantineColorsTuple = [ + "#ffebff", + "#f5d5fb", + "#e6a8f3", + "#d779eb", + "#cb51e4", + "#c337e0", + "#c029df", + "#a91cc6", + "#9715b1", + "#84099c", +]; + +export const theme = createTheme({ + primaryColor: "brand", + colors: { + brand: brandColor, + }, +}); diff --git a/packages/cli/template/nextjs-shadcn/src/server/safe-action.ts b/packages/cli/template/nextjs-shadcn/src/server/safe-action.ts new file mode 100644 index 00000000..7f62198a --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/server/safe-action.ts @@ -0,0 +1,3 @@ +import { createSafeActionClient } from "next-safe-action"; + +export const actionClient = createSafeActionClient(); diff --git a/packages/cli/template/nextjs-shadcn/src/utils/notification-helpers.ts b/packages/cli/template/nextjs-shadcn/src/utils/notification-helpers.ts new file mode 100644 index 00000000..771fdffe --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/utils/notification-helpers.ts @@ -0,0 +1,32 @@ +import { + showNotification, + type NotificationData, +} from "@mantine/notifications"; + +export function showErrorNotification(): void; +export function showErrorNotification(props: NotificationData): void; +export function showErrorNotification(message: string): void; +export function showErrorNotification(args?: string | NotificationData): void { + const message = + typeof args === "string" ? args : "An unexpected error occurred."; + const defaultProps = typeof args === "string" ? {} : (args ?? {}); + + showNotification({ color: "red", title: "Error", message, ...defaultProps }); +} + +export function showSuccessNotification(): void; +export function showSuccessNotification(props: NotificationData): void; +export function showSuccessNotification(message: string): void; +export function showSuccessNotification( + args?: string | NotificationData +): void { + const message = typeof args === "string" ? args : "Success!"; + const defaultProps = typeof args === "string" ? {} : (args ?? {}); + + showNotification({ + color: "green", + title: "Success", + message, + ...defaultProps, + }); +} diff --git a/packages/cli/template/nextjs-shadcn/src/utils/styles.ts b/packages/cli/template/nextjs-shadcn/src/utils/styles.ts new file mode 100644 index 00000000..1f4cd38e --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/utils/styles.ts @@ -0,0 +1,6 @@ +import { clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: any[]) { + return twMerge(clsx(inputs)); +} diff --git a/packages/cli/template/nextjs-shadcn/tsconfig.json b/packages/cli/template/nextjs-shadcn/tsconfig.json new file mode 100644 index 00000000..f48e7ee6 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./src/*" + ] + }, + "target": "ES2017" + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} From 856184c64bee83963561091679887a539654aaf1 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 8 Aug 2025 21:14:34 +0000 Subject: [PATCH 3/5] Checkpoint before follow-up message Co-authored-by: eric.luce --- my-shadcn-app/.cursor/rules/cursor-rules.mdc | 88 ------- my-shadcn-app/.cursor/rules/filemaker-api.mdc | 176 ------------- .../.cursor/rules/package-manager.mdc | 65 ----- .../rules/troubleshooting-patterns.mdc | 240 ------------------ my-shadcn-app/.cursor/rules/ui-components.mdc | 57 ----- my-shadcn-app/.eslintrc.cjs | 44 ---- my-shadcn-app/.gitignore | 37 --- my-shadcn-app/.prettierrc | 3 - my-shadcn-app/README.md | 27 -- my-shadcn-app/components.json | 21 -- my-shadcn-app/next.config.ts | 12 - my-shadcn-app/package.json | 65 ----- my-shadcn-app/postcss.config.cjs | 15 -- my-shadcn-app/proofkit.json | 14 - my-shadcn-app/public/favicon.ico | Bin 32603 -> 0 bytes my-shadcn-app/public/proofkit.png | Bin 93051 -> 0 bytes my-shadcn-app/src/app/(main)/layout.tsx | 6 - my-shadcn-app/src/app/(main)/page.tsx | 90 ------- my-shadcn-app/src/app/layout.tsx | 39 --- my-shadcn-app/src/app/navigation.tsx | 12 - my-shadcn-app/src/components/AppLogo.tsx | 6 - .../components/AppShell/internal/AppShell.tsx | 21 -- .../AppShell/internal/Header.module.css | 40 --- .../components/AppShell/internal/Header.tsx | 34 --- .../AppShell/internal/HeaderMobileMenu.tsx | 27 -- .../AppShell/internal/HeaderNavLink.tsx | 31 --- .../components/AppShell/internal/config.ts | 1 - .../AppShell/slot-header-center.tsx | 13 - .../components/AppShell/slot-header-left.tsx | 23 -- .../AppShell/slot-header-mobile-content.tsx | 43 ---- .../components/AppShell/slot-header-right.tsx | 26 -- my-shadcn-app/src/config/env.ts | 13 - my-shadcn-app/src/config/theme/globals.css | 125 --------- .../src/config/theme/mantine-theme.ts | 22 -- my-shadcn-app/src/server/safe-action.ts | 3 - .../src/utils/notification-helpers.ts | 32 --- my-shadcn-app/src/utils/styles.ts | 6 - my-shadcn-app/tsconfig.json | 40 --- packages/cli/template/nextjs/.prettierrc | 3 - packages/cli/template/nextjs/README.md | 27 -- packages/cli/template/nextjs/_gitignore | 37 --- packages/cli/template/nextjs/components.json | 21 -- packages/cli/template/nextjs/next.config.ts | 12 - packages/cli/template/nextjs/package.json | 50 ---- .../cli/template/nextjs/postcss.config.cjs | 15 -- packages/cli/template/nextjs/proofkit.json | 7 - .../cli/template/nextjs/public/favicon.ico | Bin 15086 -> 0 bytes .../cli/template/nextjs/public/proofkit.png | Bin 52140 -> 0 bytes .../template/nextjs/src/app/(main)/layout.tsx | 6 - .../template/nextjs/src/app/(main)/page.tsx | 90 ------- .../cli/template/nextjs/src/app/layout.tsx | 39 --- .../template/nextjs/src/app/navigation.tsx | 12 - .../nextjs/src/components/AppLogo.tsx | 6 - .../components/AppShell/internal/AppShell.tsx | 21 -- .../AppShell/internal/Header.module.css | 40 --- .../components/AppShell/internal/Header.tsx | 34 --- .../AppShell/internal/HeaderMobileMenu.tsx | 27 -- .../AppShell/internal/HeaderNavLink.tsx | 31 --- .../components/AppShell/internal/config.ts | 1 - .../AppShell/slot-header-center.tsx | 13 - .../components/AppShell/slot-header-left.tsx | 23 -- .../AppShell/slot-header-mobile-content.tsx | 43 ---- .../components/AppShell/slot-header-right.tsx | 26 -- .../cli/template/nextjs/src/config/env.ts | 13 - .../nextjs/src/config/theme/globals.css | 125 --------- .../nextjs/src/config/theme/mantine-theme.ts | 22 -- .../template/nextjs/src/server/safe-action.ts | 3 - .../nextjs/src/utils/notification-helpers.ts | 32 --- .../cli/template/nextjs/src/utils/styles.ts | 6 - packages/cli/template/nextjs/tsconfig.json | 40 --- 70 files changed, 2342 deletions(-) delete mode 100644 my-shadcn-app/.cursor/rules/cursor-rules.mdc delete mode 100644 my-shadcn-app/.cursor/rules/filemaker-api.mdc delete mode 100644 my-shadcn-app/.cursor/rules/package-manager.mdc delete mode 100644 my-shadcn-app/.cursor/rules/troubleshooting-patterns.mdc delete mode 100644 my-shadcn-app/.cursor/rules/ui-components.mdc delete mode 100644 my-shadcn-app/.eslintrc.cjs delete mode 100644 my-shadcn-app/.gitignore delete mode 100644 my-shadcn-app/.prettierrc delete mode 100644 my-shadcn-app/README.md delete mode 100644 my-shadcn-app/components.json delete mode 100644 my-shadcn-app/next.config.ts delete mode 100644 my-shadcn-app/package.json delete mode 100644 my-shadcn-app/postcss.config.cjs delete mode 100644 my-shadcn-app/proofkit.json delete mode 100644 my-shadcn-app/public/favicon.ico delete mode 100644 my-shadcn-app/public/proofkit.png delete mode 100644 my-shadcn-app/src/app/(main)/layout.tsx delete mode 100644 my-shadcn-app/src/app/(main)/page.tsx delete mode 100644 my-shadcn-app/src/app/layout.tsx delete mode 100644 my-shadcn-app/src/app/navigation.tsx delete mode 100644 my-shadcn-app/src/components/AppLogo.tsx delete mode 100644 my-shadcn-app/src/components/AppShell/internal/AppShell.tsx delete mode 100644 my-shadcn-app/src/components/AppShell/internal/Header.module.css delete mode 100644 my-shadcn-app/src/components/AppShell/internal/Header.tsx delete mode 100644 my-shadcn-app/src/components/AppShell/internal/HeaderMobileMenu.tsx delete mode 100644 my-shadcn-app/src/components/AppShell/internal/HeaderNavLink.tsx delete mode 100644 my-shadcn-app/src/components/AppShell/internal/config.ts delete mode 100644 my-shadcn-app/src/components/AppShell/slot-header-center.tsx delete mode 100644 my-shadcn-app/src/components/AppShell/slot-header-left.tsx delete mode 100644 my-shadcn-app/src/components/AppShell/slot-header-mobile-content.tsx delete mode 100644 my-shadcn-app/src/components/AppShell/slot-header-right.tsx delete mode 100644 my-shadcn-app/src/config/env.ts delete mode 100644 my-shadcn-app/src/config/theme/globals.css delete mode 100644 my-shadcn-app/src/config/theme/mantine-theme.ts delete mode 100644 my-shadcn-app/src/server/safe-action.ts delete mode 100644 my-shadcn-app/src/utils/notification-helpers.ts delete mode 100644 my-shadcn-app/src/utils/styles.ts delete mode 100644 my-shadcn-app/tsconfig.json delete mode 100644 packages/cli/template/nextjs/.prettierrc delete mode 100644 packages/cli/template/nextjs/README.md delete mode 100644 packages/cli/template/nextjs/_gitignore delete mode 100644 packages/cli/template/nextjs/components.json delete mode 100644 packages/cli/template/nextjs/next.config.ts delete mode 100644 packages/cli/template/nextjs/package.json delete mode 100644 packages/cli/template/nextjs/postcss.config.cjs delete mode 100644 packages/cli/template/nextjs/proofkit.json delete mode 100644 packages/cli/template/nextjs/public/favicon.ico delete mode 100644 packages/cli/template/nextjs/public/proofkit.png delete mode 100644 packages/cli/template/nextjs/src/app/(main)/layout.tsx delete mode 100644 packages/cli/template/nextjs/src/app/(main)/page.tsx delete mode 100644 packages/cli/template/nextjs/src/app/layout.tsx delete mode 100644 packages/cli/template/nextjs/src/app/navigation.tsx delete mode 100644 packages/cli/template/nextjs/src/components/AppLogo.tsx delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/internal/AppShell.tsx delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/internal/Header.module.css delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/internal/Header.tsx delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/internal/HeaderMobileMenu.tsx delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/internal/HeaderNavLink.tsx delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/internal/config.ts delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/slot-header-center.tsx delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/slot-header-left.tsx delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/slot-header-mobile-content.tsx delete mode 100644 packages/cli/template/nextjs/src/components/AppShell/slot-header-right.tsx delete mode 100644 packages/cli/template/nextjs/src/config/env.ts delete mode 100644 packages/cli/template/nextjs/src/config/theme/globals.css delete mode 100644 packages/cli/template/nextjs/src/config/theme/mantine-theme.ts delete mode 100644 packages/cli/template/nextjs/src/server/safe-action.ts delete mode 100644 packages/cli/template/nextjs/src/utils/notification-helpers.ts delete mode 100644 packages/cli/template/nextjs/src/utils/styles.ts delete mode 100644 packages/cli/template/nextjs/tsconfig.json diff --git a/my-shadcn-app/.cursor/rules/cursor-rules.mdc b/my-shadcn-app/.cursor/rules/cursor-rules.mdc deleted file mode 100644 index 061da499..00000000 --- a/my-shadcn-app/.cursor/rules/cursor-rules.mdc +++ /dev/null @@ -1,88 +0,0 @@ ---- -description: | - This rule documents how to manage and organize Cursor rules. It should be included when: - 1. Creating or modifying Cursor rules - 2. Organizing documentation for the codebase - 3. Setting up new development patterns - 4. Adding project-wide conventions - 5. Managing rule file locations - 6. Updating rule descriptions or globs - 7. Working with .cursor directory structure -globs: - - ".cursor/rules/*.mdc" - - ".cursor/config/*.json" - - ".cursor/settings/*.json" -alwaysApply: true ---- -# Cursor Rules Location - -Rules for placing and organizing Cursor rule files in the repository. - - -name: cursor_rules_location -description: Standards for placing Cursor rule files in the correct directory -filters: - # Match any .mdc files - - type: file_extension - pattern: "\\.mdc$" - # Match files that look like Cursor rules - - type: content - pattern: "(?s).*?" - # Match file creation events - - type: event - pattern: "file_create" - -actions: - - type: reject - conditions: - - pattern: "^(?!\\.\\/\\.cursor\\/rules\\/.*\\.mdc$)" - message: "Cursor rule files (.mdc) must be placed in the .cursor/rules directory" - - - type: suggest - message: | - When creating Cursor rules: - - 1. Always place rule files in PROJECT_ROOT/.cursor/rules/: - ``` - .cursor/rules/ - ├── your-rule-name.mdc - ├── another-rule.mdc - └── ... - ``` - - 2. Follow the naming convention: - - Use kebab-case for filenames - - Always use .mdc extension - - Make names descriptive of the rule's purpose - - 3. Directory structure: - ``` - PROJECT_ROOT/ - ├── .cursor/ - │ └── rules/ - │ ├── your-rule-name.mdc - │ └── ... - └── ... - ``` - - 4. Never place rule files: - - In the project root - - In subdirectories outside .cursor/rules - - In any other location - - Inside of the cursor-rules.mdc file - -examples: - - input: | - # Bad: Rule file in wrong location - rules/my-rule.mdc - my-rule.mdc - .rules/my-rule.mdc - - # Good: Rule file in correct location - .cursor/rules/my-rule.mdc - output: "Correctly placed Cursor rule file" - -metadata: - priority: high - version: 1.0 - \ No newline at end of file diff --git a/my-shadcn-app/.cursor/rules/filemaker-api.mdc b/my-shadcn-app/.cursor/rules/filemaker-api.mdc deleted file mode 100644 index dd6d6716..00000000 --- a/my-shadcn-app/.cursor/rules/filemaker-api.mdc +++ /dev/null @@ -1,176 +0,0 @@ ---- -description: | - This rule provides guidance for working with the FileMaker Data API in this project. It should be included when: - 1. Working with database operations or data fetching - 2. Encountering database-related errors or type issues - 3. Making changes to FileMaker schemas or layouts - 4. Implementing new data access patterns - 5. Discussing alternative data storage solutions - 6. Working with server-side API routes or actions -globs: - - "src/**/*.ts" - - "src/**/*.tsx" - - "**/fmschema.config.mjs" - - "src/**/actions/*.ts" -alwaysApply: true ---- -# FileMaker Data API Integration - -This rule documents how the FileMaker Data API is integrated and used in the project. - - -name: filemaker_api -description: Documents FileMaker Data API integration patterns and conventions. FileMaker is the ONLY data source for this application - no SQL or other databases should be used. -filters: - - type: file_extension - pattern: "\\.(ts|tsx)$" - - type: directory - pattern: "src/server/" - - type: content - pattern: "(@proofkit/cli|ZodError|typegen)" - -data_source_policy: - exclusive_source: "FileMaker Data API" - prohibited: - - "SQL databases" - - "NoSQL databases" - - "Local storage for persistent data" - - "Direct file system storage" - reason: "All data operations must go through FileMaker to maintain data integrity and business logic" - -troubleshooting: - priority_order: - - "ALWAYS run `{package-manager} typegen` first for ANY data loading issues" - - "DO NOT check environment variables unless you have a specific error message pointing to them" - - "Check for FileMaker schema changes" - - "Verify type definitions match current schema" - - "Review Zod validation errors" - rationale: "Most data loading issues are resolved by running typegen. Environment variables are rarely the cause of data loading problems and should not be investigated unless specific error messages indicate an authentication or connection issue." - -conventions: - api_setup: - - Uses @proofkit/fmdapi package version ^5.0.0 - - Configuration in fmschema.config.mjs - - Environment variables in .env for connection details - - Type generation via `{package-manager} typegen` command - - data_access: - - ALL data operations MUST use FileMaker Data API - - Server-side only API calls via @proofkit/fmdapi - - Type-safe database operations - - Centralized error handling - - Connection pooling and session management - - No direct database connections outside FileMaker - - data_operations: - create: - - Use layout.create({ fieldData: {...} }) - - Validate input against Zod schemas - - Returns recordId of created record - - Handle duplicates via FileMaker business logic - read: - - Use layout.get({ recordId }) for single record by ID - - Use layout.find({ query, limit, offset, sort }) for multiple records - - Use layout.maybeFindFirst({ query }) for optional single record - - Support for complex queries and sorting - update: - - Use layout.update({ recordId, fieldData }) - - Follow FileMaker field naming conventions - - Respect FileMaker validation rules - delete: - - Use layout.delete({ recordId }) - - Respect FileMaker deletion rules - - Handle cascading deletes via FileMaker - query_options: - - Limit and offset for pagination - - Sort by multiple fields with ascend/descend - - Complex query criteria with operators (==, *, etc.) - - Optional type-safe responses with Zod validation - - security: - - Credentials stored in environment variables - - No direct client-side FM API access - - API routes validate authentication - - Data sanitization before queries - - All database access through FileMaker only - -type_generation: - process: - - "IMPORTANT: Running `{package-manager} typegen` solves almost all data loading problems" - - "Run `{package-manager} typegen` after any FileMaker schema changes" - - "Run `{package-manager} typegen` as first step when troubleshooting data issues" - - "Types are generated from FileMaker database schema" - - "Generated types are used in server actions and components" - - "Zod schemas validate runtime data against types" - - common_issues: - schema_changes: - symptoms: - - "No data appearing in tables" - - "ZodError during runtime" - - "Missing or renamed fields" - - "Type mismatches in responses" - - "Empty query results" - solution: "ALWAYS run `{package-manager} typegen && {package-manager} tsc` first" - important_note: "Do NOT check environment variables as a cause for data loading problems unless you have a specific known error that points to environment variables. Most data loading issues are resolved by running typegen." - - field_types: - symptoms: - - "Unexpected null values" - - "Type conversion errors" - - "Invalid date formats" - solution: "Update Zod schemas and type definitions" - - security_notes: - - "Never display, log, or commit environment variables" - - "Never check environment variable values directly" - - "Keep .env files out of version control" - - "When troubleshooting, only verify if variables exist, never their values" - -patterns: - - Server actions wrap FM API calls - - Type definitions generated from FM schema - - Error boundaries for FM API errors - - Rate limiting on API routes - - Caching strategies for frequent queries - -dependencies: - fmdapi: "@proofkit/fmdapi@^5.0.0" - proofkit: "@proofkit/cli@^1.0.0" - -keywords: - database: - - "FileMaker" - - "FMREST" - - "Database schema" - - "Field types" - - "Type generation" - - "Schema changes" - - "Exclusive data source" - - "No SQL" - - "FileMaker only" - - "Data API" - errors: - - "ZodError" - - "TypeError" - - "ValidationError" - - "Missing field" - - "Runtime error" - commands: - - "typegen" - - "tsc" - - "type checking" - - "schema update" - operations: - - "FM.create" - - "FM.find" - - "FM.get" - - "FM.update" - - "FM.delete" - - "FileMaker layout" - - "FileMaker query" - -metadata: - priority: high - version: 1.0 - \ No newline at end of file diff --git a/my-shadcn-app/.cursor/rules/package-manager.mdc b/my-shadcn-app/.cursor/rules/package-manager.mdc deleted file mode 100644 index d25da047..00000000 --- a/my-shadcn-app/.cursor/rules/package-manager.mdc +++ /dev/null @@ -1,65 +0,0 @@ ---- -description: | -globs: -alwaysApply: true ---- ---- -description: | - This rule documents the package manager configuration and usage. It should be included when: - 1. Installing dependencies - 2. Running scripts - 3. Managing project packages - 4. Running development commands - 5. Executing build or test operations -globs: - - "package.json" - - "pnpm-lock.yaml" - - ".npmrc" -alwaysApply: true ---- -# Package Manager Configuration - -This rule documents the package manager setup and usage requirements. - - -name: package_manager -description: Documents package manager configuration and usage requirements - -configuration: - name: "pnpm" - version: "latest" - commands: - install: "pnpm install" - build: "pnpm build" - dev: "pnpm dev" - typegen: "pnpm typegen" - typecheck: "pnpm tsc" - notes: "Always use pnpm instead of npm or yarn for consistency" - dev_server_guidelines: - - "Never relaunch the dev server command if it may already be running" - - "Use pnpm dev only when explicitly needed to start the server for the first time" - - "For code changes, just save the files and the server will automatically reload" - -examples: - - description: "Installing dependencies" - correct: "pnpm install" - incorrect: - - "npm install" - - "yarn install" - - - description: "Running scripts" - correct: "pnpm run script-name" - incorrect: - - "npm run script-name" - - "yarn script-name" - - - description: "Adding dependencies" - correct: "pnpm add package-name" - incorrect: - - "npm install package-name" - - "yarn add package-name" - -metadata: - priority: high - version: 1.0 - \ No newline at end of file diff --git a/my-shadcn-app/.cursor/rules/troubleshooting-patterns.mdc b/my-shadcn-app/.cursor/rules/troubleshooting-patterns.mdc deleted file mode 100644 index 797fd3cc..00000000 --- a/my-shadcn-app/.cursor/rules/troubleshooting-patterns.mdc +++ /dev/null @@ -1,240 +0,0 @@ ---- -description: | -globs: -alwaysApply: false ---- -# Troubleshooting and Maintenance Patterns - -This rule documents common issues, error patterns, and their solutions in the project. - - -name: troubleshooting_patterns -description: Documents common runtime errors, type errors, and solutions. All data operations MUST use FileMaker Data API exclusively. -filters: - - type: file_extension - pattern: "\\.(ts|tsx)$" - - type: content - pattern: "(Error|error|ZodError|TypeError|ValidationError|@proofkit/fmdapi)" - -initial_debugging_steps: - priority: "ALWAYS run `{package-manager} typegen` first for any data-related issues" - steps: - - "Run `{package-manager} typegen` to ensure types match FileMaker schema" - - "Check if error persists after typegen" - - "If error persists, check console for exact error messages" - - "Look for patterns in the troubleshooting guide below" - common_console_errors: - zod_errors: - pattern: "ZodError: [path] invalid_type..." - likely_cause: "Field name mismatch or missing field" - example: "ZodError: nameFirst expected string, got undefined" - solution: "Run typegen first, then check field names in FileMaker schema" - type_errors: - pattern: "TypeError: Cannot read property 'X' of undefined" - likely_cause: "Accessing field before data is loaded or field name mismatch" - solution: "Run typegen first, then add null checks or loading states" - network_errors: - pattern: "Failed to fetch" or "Network error" - likely_cause: "FileMaker connection issues" - solution: "Run typegen first, then check FileMaker server status and credentials" - -data_source_validation: - requirement: "All data operations must use FileMaker Data API exclusively" - first_step_for_data_issues: "ALWAYS run `{package-manager} typegen` first" - common_mistakes: - - "Attempting to use SQL queries" - - "Adding direct database connections" - - "Using local storage for persistent data" - - "Implementing alternative data stores" - - "Skipping typegen after FileMaker schema changes" - - "Using incorrect field names from old schema" - correct_approach: - - "Run typegen first" - - "Use @proofkit/fmdapi for all data operations" - - "Follow FileMaker layout and field conventions" - - "Use layout.create, layout.find, layout.get, layout.update, layout.delete" - - "Use layout.maybeFindFirst for optional records" - -error_patterns: - field_name_mismatches: - symptoms: - - "ZodError: invalid_type at path [fieldName]" - - "Property 'X' does not exist on type 'Y'" - - "TypeScript errors about missing properties" - common_examples: - - "nameFirst vs firstName" - - "lastName vs nameLast" - - "postalCode vs postal_code" - - "phoneNumber vs phone" - cause: "Mismatch between component field names and FileMaker schema" - solution: - steps: - - "Run `{package-manager} typegen` to update types" - - "Look at generated types in src/config/schemas/filemaker/" - - "Update component field names to match schema" - - "Check console for exact field name in error" - files_to_check: - - "src/config/schemas/filemaker/*.ts" - - "Component files using the fields" - - zod_validation_errors: - symptoms: - - "Runtime ZodError: invalid_type" - - "Zod schema validation failed" - - "Property not found in schema" - - "Unexpected field in response" - cause: "FileMaker database schema changes not reflected in TypeScript types" - solution: - steps: - - "Run `{package-manager} typegen` to regenerate types from FileMaker schema" - - "Run `{package-manager} tsc` to identify type mismatches" - - "Check console for exact error message" - - "Update affected components and server actions" - commands: - - "{package-manager} typegen" - - "{package-manager} tsc" - files_to_check: - - "src/server/actions/*" - - "src/server/schema/*" - - "fmschema.config.mjs" - - filemaker_connection: - symptoms: - - "ETIMEDOUT connecting to FileMaker" - - "Invalid FileMaker credentials" - - "Session token expired" - - "Layout not found" - - "Field not found in layout" - - "Invalid find criteria" - - "No data appearing or queries returning empty" - cause: "FileMaker connection, authentication, or query issues" - solution: - steps: - - "Run `{package-manager} typegen` to ensure schema is up to date" - - "Check FileMaker Server status" - - "Validate credentials and permissions" - - "Note: As an AI, you cannot directly check environment variables - always ask the user to verify them if this is determined to be the issue" - - "Verify layout names and field access" - - "Check FileMaker query syntax" - files_to_check: - - "src/server/lib/fm.ts" - - "fmschema.config.mjs" - - data_access_errors: - symptoms: - - "Invalid operation on FileMaker record" - - "Record not found" - - "Insufficient permissions" - - "Invalid find request" - cause: "Incorrect FileMaker Data API usage or permissions" - solution: - steps: - - "Run `{package-manager} typegen` to ensure schema is up to date" - - "Verify FileMaker layout privileges" - - "Check record existence before operations" - - "Validate find criteria format" - - "Use proper FM API methods" - files_to_check: - - "src/server/actions/*" - - "src/server/lib/fm.ts" - - type_errors: - symptoms: - - "Type ... is not assignable to type ..." - - "Property ... does not exist on type ..." - - "Argument of type ... is not assignable" - cause: "Mismatch between FileMaker schema and TypeScript types" - solution: - steps: - - "Run `{package-manager} typegen` to regenerate types" - - "Run `{package-manager} tsc` to identify type mismatches" - - "Update type definitions if needed" - - "Check for null/undefined handling" - commands: - - "{package-manager} typegen && {package-manager} tsc" - - data_sync_issues: - symptoms: - - "Missing fields in table" - - "Unexpected null values" - - "Fields showing as blank" - - "Type mismatches between FM and frontend" - first_step: "ALWAYS run `{package-manager} typegen` first" - cause: "Mismatch between FileMaker schema and TypeScript types, or outdated type definitions" - solution: - steps: - - "Run `{package-manager} typegen` to regenerate types from FileMaker schema" - - "Check for any type errors in the console" - - "Verify field names match exactly between FM and generated types" - - "Update components if field names have changed" - commands: - - "{package-manager} typegen" - - "{package-manager} tsc" - files_to_check: - - "src/config/schemas/filemaker/*.ts" - - "fmschema.config.mjs" - -maintenance_tasks: - schema_sync: - description: "Keep FileMaker schema and TypeScript types in sync" - frequency: "After any FileMaker schema changes" - steps: - - "Run typegen to update types" - - "Run TypeScript compiler" - - "Update affected components" - impact: "Prevents runtime errors and type mismatches" - - type_checking: - description: "Regular type checking for early error detection" - frequency: "Before deployments and after schema changes" - commands: - - "{package-manager} tsc --noEmit" - impact: "Catches type errors before runtime" - -keywords: - errors: - - "ZodError" - - "TypeError" - - "ValidationError" - - "Schema mismatch" - - "Type mismatch" - - "Runtime error" - - "Database schema" - - "Type generation" - - "FileMaker fields" - - "Missing property" - - "Invalid type" - - "Layout not found" - - "Field not found" - - "Invalid find request" - solutions: - - "typegen" - - "tsc" - - "type checking" - - "schema update" - - "validation fix" - - "error handling" - - "FM API methods" - - "FileMaker layout" - operations: - - "layout.create" - - "layout.find" - - "layout.get" - - "layout.update" - - "layout.delete" - - "layout.maybeFindFirst" - - "recordId" - - "fieldData" - - "query parameters" - - "sort options" - data_source: - - "FileMaker only" - - "No SQL" - - "FM Data API" - - "Exclusive data source" - - "@proofkit/fmdapi" - -metadata: - priority: high - version: 1.0 - \ No newline at end of file diff --git a/my-shadcn-app/.cursor/rules/ui-components.mdc b/my-shadcn-app/.cursor/rules/ui-components.mdc deleted file mode 100644 index 78ec63ad..00000000 --- a/my-shadcn-app/.cursor/rules/ui-components.mdc +++ /dev/null @@ -1,57 +0,0 @@ ---- -description: -globs: -alwaysApply: false ---- -# UI Components and Styling - -This rule documents the UI component library and styling conventions used in the project. - - -name: ui_components -description: Documents UI component library usage and styling conventions -filters: - - type: file_extension - pattern: "\\.(ts|tsx)$" - - type: directory - pattern: "src/components/" - - type: content - pattern: "@mantine/" - -conventions: - component_library: - - Mantine v7 as primary UI framework - - Tabler icons for iconography - - Mantine React Table for data grids - - Custom components extend Mantine base - - styling: - - PostCSS for processing - - Mantine theme customization - - CSS modules for component styles - - CSS variables for theming - - components: - - Atomic design principles - - Consistent prop interfaces - - Accessibility first - - Responsive design patterns - - forms: - - React Hook Form for form state - - Zod for validation schemas - - Mantine form components - - Custom form layouts - -dependencies: - mantine_core: "^7.17.0" - mantine_hooks: "^7.17.0" - mantine_dates: "^7.17.0" - mantine_notifications: "^7.17.0" - react_hook_form: "^7.54.2" - zod: "^3.24.2" - -metadata: - priority: high - version: 1.0 - \ No newline at end of file diff --git a/my-shadcn-app/.eslintrc.cjs b/my-shadcn-app/.eslintrc.cjs deleted file mode 100644 index 2c5996ec..00000000 --- a/my-shadcn-app/.eslintrc.cjs +++ /dev/null @@ -1,44 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -const config = { - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": true - }, - "plugins": [ - "@typescript-eslint" - ], - "extends": [ - "next/core-web-vitals", - "plugin:@typescript-eslint/recommended-type-checked", - "plugin:@typescript-eslint/stylistic-type-checked" - ], - "rules": { - "@typescript-eslint/array-type": "off", - "@typescript-eslint/consistent-type-definitions": "off", - "@typescript-eslint/consistent-type-imports": [ - "warn", - { - "prefer": "type-imports", - "fixStyle": "inline-type-imports" - } - ], - "@typescript-eslint/no-unused-vars": [ - "warn", - { - "argsIgnorePattern": "^_" - } - ], - "@typescript-eslint/require-await": "off", - "@typescript-eslint/no-explicit-any": "warn", - "@typescript-eslint/no-misused-promises": [ - "error", - { - "checksVoidReturn": { - "attributes": false - } - } - ], - "@typescript-eslint/no-floating-promises": "warn" - } -} -module.exports = config; \ No newline at end of file diff --git a/my-shadcn-app/.gitignore b/my-shadcn-app/.gitignore deleted file mode 100644 index 00bba9bb..00000000 --- a/my-shadcn-app/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local -.env - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/my-shadcn-app/.prettierrc b/my-shadcn-app/.prettierrc deleted file mode 100644 index b4bfed35..00000000 --- a/my-shadcn-app/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "plugins": ["prettier-plugin-tailwindcss"] -} diff --git a/my-shadcn-app/README.md b/my-shadcn-app/README.md deleted file mode 100644 index 4f416a4a..00000000 --- a/my-shadcn-app/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# ProofKit NextJS Template - -This is a [NextJS](https://nextjs.org/) project bootstrapped with `@proofkit/cli`. Learn more at [proofkit.dev](https://proofkit.dev) - -## What's next? How do I make an app with this? - -While this template is designed to be a minimal starting point, the proofkit CLI will guide you through adding additional features and pages. - -To add new things to your project, simply run the `proofkit` script from the project's root directory. - -e.g. `npm run proofkit` or `pnpm proofkit` etc. - -For more information, see the full [ProofKit documentation](https://proofkit.dev). - -## Project Structure - -ProofKit projects have an opinionated structure to help you get started and some conventions must be maintained to ensure that the CLI can properly inject new features and components. - -The `src` directory is the home for your application code. It is used for most things except for configuration and is organized as follows: - -- `app` - NextJS app router, where your pages and routes are defined -- `components` - Shared components used throughout the app -- `server` - Code that connects to backend databases and services that should not be exposed in the browser - -Anytime you see an `internal` folder, you should not modify any files inside. These files are maintained exclusively by the ProofKit CLI and changes to them may be overwritten. - -Anytime you see a componet file that begins with `slot-`, you _may_ modify the content, but do not rename, remove, or move them. These are desigend to be customized, but are still used by the CLI to inject additional content. If a slot is not needed by your app, you can have the compoment return `null` or an empty fragment: `<>` diff --git a/my-shadcn-app/components.json b/my-shadcn-app/components.json deleted file mode 100644 index 0d27c449..00000000 --- a/my-shadcn-app/components.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "style": "new-york", - "rsc": true, - "tsx": true, - "tailwind": { - "config": "", - "css": "src/config/theme/globals.css", - "baseColor": "neutral", - "cssVariables": true, - "prefix": "tw:" - }, - "aliases": { - "components": "@/components", - "utils": "@/utils/styles", - "ui": "@/components/ui", - "lib": "@/utils", - "hooks": "@/utils/hooks" - }, - "iconLibrary": "lucide" -} diff --git a/my-shadcn-app/next.config.ts b/my-shadcn-app/next.config.ts deleted file mode 100644 index 9555317e..00000000 --- a/my-shadcn-app/next.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type NextConfig } from "next"; - -// Import env here to validate during build. -import "./src/config/env"; - -const nextConfig: NextConfig = { - experimental: { - optimizePackageImports: ["@mantine/core", "@mantine/hooks"], - }, -}; - -export default nextConfig; diff --git a/my-shadcn-app/package.json b/my-shadcn-app/package.json deleted file mode 100644 index 6dbfc035..00000000 --- a/my-shadcn-app/package.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "name": "my-shadcn-app", - "version": "0.1.0", - "private": true, - "scripts": { - "build": "next build", - "deploy": "proofkit deploy", - "dev": "next dev --turbopack", - "lint": "next lint", - "proofkit": "proofkit", - "start": "next start", - "typegen": "proofkit typegen" - }, - "dependencies": { - "@hookform/resolvers": "^5.1.1", - "@mantine/core": "^7.17.0", - "@mantine/dates": "^7.17.0", - "@mantine/hooks": "^7.17.0", - "@mantine/modals": "^7.17.0", - "@mantine/notifications": "^7.17.0", - "@next-safe-action/adapter-react-hook-form": "^2.0.0", - "@radix-ui/react-slot": "^1.2.3", - "@t3-oss/env-nextjs": "^0.12.0", - "@tabler/icons-react": "^3.30.0", - "@tailwindcss/postcss": "^4.1.10", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "dayjs": "^1.11.13", - "lucide-react": "^0.518.0", - "mantine-react-table": "2.0.0-beta.9", - "next": "^15.2.3", - "next-safe-action": "^8.0.4", - "react": "19.0.0", - "react-dom": "19.0.0", - "react-hook-form": "^7.54.2", - "tailwind-merge": "^3.3.1", - "tailwindcss": "^4.1.10", - "tw-animate-css": "^1.3.4", - "zod": "^3.24.2" - }, - "devDependencies": { - "@proofkit/cli": "^1.1.6", - "@types/node": "^22", - "@types/react": "npm:types-react@19.0.12", - "@types/react-dom": "npm:types-react-dom@19.0.4", - "eslint": "^9.14.0", - "eslint-config-next": "15.2.3", - "postcss": "^8.4.41", - "postcss-preset-mantine": "^1.17.0", - "postcss-simple-vars": "^7.0.1", - "prettier": "^3.5.3", - "prettier-plugin-tailwindcss": "^0.6.12", - "typescript": "^5" - }, - "pnpm": { - "overrides": { - "@types/react": "npm:types-react@19.0.0-rc.1", - "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" - } - }, - "proofkitMetadata": { - "initVersion": "1.1.6" - }, - "packageManager": "pnpm@10.11.1" -} diff --git a/my-shadcn-app/postcss.config.cjs b/my-shadcn-app/postcss.config.cjs deleted file mode 100644 index 085a0ef9..00000000 --- a/my-shadcn-app/postcss.config.cjs +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - plugins: { - "@tailwindcss/postcss": {}, - "postcss-preset-mantine": {}, - "postcss-simple-vars": { - variables: { - "mantine-breakpoint-xs": "36em", - "mantine-breakpoint-sm": "48em", - "mantine-breakpoint-md": "62em", - "mantine-breakpoint-lg": "75em", - "mantine-breakpoint-xl": "88em", - }, - }, - }, -}; diff --git a/my-shadcn-app/proofkit.json b/my-shadcn-app/proofkit.json deleted file mode 100644 index 87c5ee11..00000000 --- a/my-shadcn-app/proofkit.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "appType": "browser", - "ui": "shadcn", - "auth": { - "type": "none" - }, - "envFile": ".env", - "dataSources": [], - "tanstackQuery": false, - "replacedMainPage": false, - "appliedUpgrades": [ - "cursorRules" - ] -} diff --git a/my-shadcn-app/public/favicon.ico b/my-shadcn-app/public/favicon.ico deleted file mode 100644 index f9227c6e68b9acab3b23c293c3174f71eb9db61d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32603 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 diff --git a/my-shadcn-app/src/app/(main)/layout.tsx b/my-shadcn-app/src/app/(main)/layout.tsx deleted file mode 100644 index 57a8452b..00000000 --- a/my-shadcn-app/src/app/(main)/layout.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import AppShell from "@/components/AppShell/internal/AppShell"; -import React from "react"; - -export default function Layout({ children }: { children: React.ReactNode }) { - return {children}; -} diff --git a/my-shadcn-app/src/app/(main)/page.tsx b/my-shadcn-app/src/app/(main)/page.tsx deleted file mode 100644 index 68340a69..00000000 --- a/my-shadcn-app/src/app/(main)/page.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { - ActionIcon, - Anchor, - AppShellFooter, - Box, - Code, - Container, - Group, - Image, - px, - Stack, - Text, - Title, -} from "@mantine/core"; -import { IconBrandGithub, IconExternalLink } from "@tabler/icons-react"; - -export default function Home() { - return ( - <> - - - ProofKit - Welcome! - - - This is the base template home page. To add more pages, components, - or other features, run the ProofKit CLI from within your project. - - pnpm proofkit - - - To change this page, open src/app/(main)/page.tsx - - - - ProofKit Docs - - - - - - - - - - Sponsored by{" "} - - Proof+Geist - {" "} - and{" "} - - Ottomatic - - - - - - - - - - - - - - - ); -} diff --git a/my-shadcn-app/src/app/layout.tsx b/my-shadcn-app/src/app/layout.tsx deleted file mode 100644 index 9512cb63..00000000 --- a/my-shadcn-app/src/app/layout.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Suspense } from "react"; -import { theme } from "@/config/theme/mantine-theme"; -import { ColorSchemeScript, MantineProvider } from "@mantine/core"; -import { ModalsProvider } from "@mantine/modals"; -import { Notifications } from "@mantine/notifications"; - -import "@mantine/core/styles.css"; -import "@mantine/notifications/styles.css"; -import "@mantine/dates/styles.css"; -import "mantine-react-table/styles.css"; -import "@/config/theme/globals.css"; - -import { type Metadata } from "next"; - -export const metadata: Metadata = { - title: "My ProofKit App", - description: "Generated by proofkit", - icons: [{ rel: "icon", url: "/favicon.ico" }], -}; - -export default function RootLayout({ - children, -}: Readonly<{ children: React.ReactNode }>) { - return ( - - - - - - - - - - {children} - - - - ); -} diff --git a/my-shadcn-app/src/app/navigation.tsx b/my-shadcn-app/src/app/navigation.tsx deleted file mode 100644 index 887073db..00000000 --- a/my-shadcn-app/src/app/navigation.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { type ProofKitRoute } from "@proofkit/cli"; - -export const primaryRoutes: ProofKitRoute[] = [ - { - label: "Dashboard", - type: "link", - href: "/", - exactMatch: true, - }, -]; - -export const secondaryRoutes: ProofKitRoute[] = []; diff --git a/my-shadcn-app/src/components/AppLogo.tsx b/my-shadcn-app/src/components/AppLogo.tsx deleted file mode 100644 index f5ea4966..00000000 --- a/my-shadcn-app/src/components/AppLogo.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { IconInfinity } from "@tabler/icons-react"; -import React from "react"; - -export default function AppLogo() { - return ; -} diff --git a/my-shadcn-app/src/components/AppShell/internal/AppShell.tsx b/my-shadcn-app/src/components/AppShell/internal/AppShell.tsx deleted file mode 100644 index 8c4270df..00000000 --- a/my-shadcn-app/src/components/AppShell/internal/AppShell.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Header } from "@/components/AppShell/internal/Header"; -import { AppShell, AppShellHeader, AppShellMain } from "@mantine/core"; -import React from "react"; - -import { headerHeight } from "./config"; - -export default function MainAppShell({ - children, -}: { - children: React.ReactNode; -}) { - return ( - - -
- - - {children} - - ); -} diff --git a/my-shadcn-app/src/components/AppShell/internal/Header.module.css b/my-shadcn-app/src/components/AppShell/internal/Header.module.css deleted file mode 100644 index 79d81bad..00000000 --- a/my-shadcn-app/src/components/AppShell/internal/Header.module.css +++ /dev/null @@ -1,40 +0,0 @@ -.header { - /* height: rem(56px); */ - margin-bottom: rem(120px); - background-color: var(--mantine-color-body); - border-bottom: rem(1px) solid - light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); -} - -.inner { - /* height: rem(56px); */ - display: flex; - justify-content: space-between; - align-items: center; -} - -.link { - display: block; - line-height: 1; - padding: rem(8px) rem(12px); - border-radius: var(--mantine-radius-sm); - text-decoration: none; - color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); - font-size: var(--mantine-font-size-sm); - font-weight: 500; - cursor: pointer; - background: none; - border: none; - - @mixin hover { - background-color: light-dark( - var(--mantine-color-gray-0), - var(--mantine-color-dark-6) - ); - } - - [data-mantine-color-scheme] &[data-active] { - background-color: var(--mantine-primary-color-filled); - color: var(--mantine-color-white); - } -} diff --git a/my-shadcn-app/src/components/AppShell/internal/Header.tsx b/my-shadcn-app/src/components/AppShell/internal/Header.tsx deleted file mode 100644 index 4409b1d6..00000000 --- a/my-shadcn-app/src/components/AppShell/internal/Header.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Box, Container, Group } from "@mantine/core"; - -import SlotHeaderCenter from "../slot-header-center"; -import SlotHeaderLeft from "../slot-header-left"; -import SlotHeaderRight from "../slot-header-right"; -import { headerHeight } from "./config"; -import classes from "./Header.module.css"; -import HeaderMobileMenu from "./HeaderMobileMenu"; - -export function Header() { - return ( -
- - - - - - - - - - - - - - -
- ); -} diff --git a/my-shadcn-app/src/components/AppShell/internal/HeaderMobileMenu.tsx b/my-shadcn-app/src/components/AppShell/internal/HeaderMobileMenu.tsx deleted file mode 100644 index 910104fb..00000000 --- a/my-shadcn-app/src/components/AppShell/internal/HeaderMobileMenu.tsx +++ /dev/null @@ -1,27 +0,0 @@ -"use client"; - -import { Burger, Menu } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; - -import SlotHeaderMobileMenuContent from "../slot-header-mobile-content"; - -export default function HeaderMobileMenu() { - const [opened, { toggle }] = useDisclosure(false); - - return ( - - - - - - - - - ); -} diff --git a/my-shadcn-app/src/components/AppShell/internal/HeaderNavLink.tsx b/my-shadcn-app/src/components/AppShell/internal/HeaderNavLink.tsx deleted file mode 100644 index 5da52246..00000000 --- a/my-shadcn-app/src/components/AppShell/internal/HeaderNavLink.tsx +++ /dev/null @@ -1,31 +0,0 @@ -"use client"; - -import { type ProofKitRoute } from "@proofkit/cli"; -import { usePathname } from "next/navigation"; -import React from "react"; - -import classes from "./Header.module.css"; - -export default function HeaderNavLink(route: ProofKitRoute) { - const pathname = usePathname(); - - if (route.type === "function") { - return ; - } - - const isActive = route.exactMatch - ? pathname === route.href - : pathname.startsWith(route.href); - - if (route.type === "link") { - return ( - - {route.label} - - ); - } -} diff --git a/my-shadcn-app/src/components/AppShell/internal/config.ts b/my-shadcn-app/src/components/AppShell/internal/config.ts deleted file mode 100644 index ded639d0..00000000 --- a/my-shadcn-app/src/components/AppShell/internal/config.ts +++ /dev/null @@ -1 +0,0 @@ -export const headerHeight = 56; diff --git a/my-shadcn-app/src/components/AppShell/slot-header-center.tsx b/my-shadcn-app/src/components/AppShell/slot-header-center.tsx deleted file mode 100644 index 2de3b630..00000000 --- a/my-shadcn-app/src/components/AppShell/slot-header-center.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * DO NOT REMOVE / RENAME THIS FILE - * - * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects - * this file to exist and may use it to inject content for other components. - * - * If you don't want it to be used, you may return null or an empty fragment - */ -export function SlotHeaderCenter() { - return null; -} - -export default SlotHeaderCenter; diff --git a/my-shadcn-app/src/components/AppShell/slot-header-left.tsx b/my-shadcn-app/src/components/AppShell/slot-header-left.tsx deleted file mode 100644 index 781fcbce..00000000 --- a/my-shadcn-app/src/components/AppShell/slot-header-left.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import Link from "next/link"; - -import AppLogo from "../AppLogo"; - -/** - * DO NOT REMOVE / RENAME THIS FILE - * - * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects this file to exist and - * may use it to inject content for other components. - * - * If you don't want it to be used, you may return null or an empty fragment - */ -export function SlotHeaderLeft() { - return ( - <> - - - - - ); -} - -export default SlotHeaderLeft; diff --git a/my-shadcn-app/src/components/AppShell/slot-header-mobile-content.tsx b/my-shadcn-app/src/components/AppShell/slot-header-mobile-content.tsx deleted file mode 100644 index 9943f8a0..00000000 --- a/my-shadcn-app/src/components/AppShell/slot-header-mobile-content.tsx +++ /dev/null @@ -1,43 +0,0 @@ -"use client"; - -import { primaryRoutes } from "@/app/navigation"; -import { Menu } from "@mantine/core"; -import { useRouter } from "next/navigation"; - -/** - * DO NOT REMOVE / RENAME THIS FILE - * - * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects - * this file to exist and may use it to inject content for other components. - * - * If you don't want it to be used, you may return null or an empty fragment - */ -export function SlotHeaderMobileMenuContent({ - closeMenu, -}: { - closeMenu: () => void; -}) { - const router = useRouter(); - return ( - <> - {primaryRoutes.map((route) => ( - { - closeMenu(); - if (route.type === "function") { - route.onClick(); - } else if (route.type === "link") { - router.push(route.href); - } - }} - > - {route.label} - - ))} - - ); -} - -export default SlotHeaderMobileMenuContent; diff --git a/my-shadcn-app/src/components/AppShell/slot-header-right.tsx b/my-shadcn-app/src/components/AppShell/slot-header-right.tsx deleted file mode 100644 index 6c392c95..00000000 --- a/my-shadcn-app/src/components/AppShell/slot-header-right.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { primaryRoutes } from "@/app/navigation"; -import { Group } from "@mantine/core"; - -import HeaderNavLink from "./internal/HeaderNavLink"; - -/** - * DO NOT REMOVE / RENAME THIS FILE - * - * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects - * this file to exist and may use it to inject content for other components. - * - * If you don't want it to be used, you may return null or an empty fragment - */ -export function SlotHeaderRight() { - return ( - <> - - {primaryRoutes.map((route) => ( - - ))} - - - ); -} - -export default SlotHeaderRight; diff --git a/my-shadcn-app/src/config/env.ts b/my-shadcn-app/src/config/env.ts deleted file mode 100644 index 3c50ef8d..00000000 --- a/my-shadcn-app/src/config/env.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { createEnv } from "@t3-oss/env-nextjs"; -import { z } from "zod/v4"; - -export const env = createEnv({ - server: { - NODE_ENV: z - .enum(["development", "test", "production"]) - .default("development"), - }, - client: {}, - // For Next.js >= 13.4.4, you only need to destructure client variables: - experimental__runtimeEnv: {}, -}); diff --git a/my-shadcn-app/src/config/theme/globals.css b/my-shadcn-app/src/config/theme/globals.css deleted file mode 100644 index 0e2f76bb..00000000 --- a/my-shadcn-app/src/config/theme/globals.css +++ /dev/null @@ -1,125 +0,0 @@ -/* Add global styles here */ - -@import "tailwindcss" prefix(tw); -@import "tw-animate-css"; - -@custom-variant dark (&:is(.dark *)); - -:root { - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --destructive-foreground: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --radius: 0.625rem; - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.145 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.145 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.985 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.396 0.141 25.723); - --destructive-foreground: oklch(0.637 0.237 25.331); - --border: oklch(0.269 0 0); - --input: oklch(0.269 0 0); - --ring: oklch(0.439 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(0.269 0 0); - --sidebar-ring: oklch(0.439 0 0); -} - -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-destructive-foreground: var(--destructive-foreground); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); -} - -@layer base { - * { - @apply tw:border-border tw:outline-ring/50; - } - body { - @apply tw:bg-background tw:text-foreground; - } -} diff --git a/my-shadcn-app/src/config/theme/mantine-theme.ts b/my-shadcn-app/src/config/theme/mantine-theme.ts deleted file mode 100644 index 890db89c..00000000 --- a/my-shadcn-app/src/config/theme/mantine-theme.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createTheme, type MantineColorsTuple } from "@mantine/core"; - -// generate your own set of colors here: https://mantine.dev/colors-generator -const brandColor: MantineColorsTuple = [ - "#ffebff", - "#f5d5fb", - "#e6a8f3", - "#d779eb", - "#cb51e4", - "#c337e0", - "#c029df", - "#a91cc6", - "#9715b1", - "#84099c", -]; - -export const theme = createTheme({ - primaryColor: "brand", - colors: { - brand: brandColor, - }, -}); diff --git a/my-shadcn-app/src/server/safe-action.ts b/my-shadcn-app/src/server/safe-action.ts deleted file mode 100644 index 7f62198a..00000000 --- a/my-shadcn-app/src/server/safe-action.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createSafeActionClient } from "next-safe-action"; - -export const actionClient = createSafeActionClient(); diff --git a/my-shadcn-app/src/utils/notification-helpers.ts b/my-shadcn-app/src/utils/notification-helpers.ts deleted file mode 100644 index 771fdffe..00000000 --- a/my-shadcn-app/src/utils/notification-helpers.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { - showNotification, - type NotificationData, -} from "@mantine/notifications"; - -export function showErrorNotification(): void; -export function showErrorNotification(props: NotificationData): void; -export function showErrorNotification(message: string): void; -export function showErrorNotification(args?: string | NotificationData): void { - const message = - typeof args === "string" ? args : "An unexpected error occurred."; - const defaultProps = typeof args === "string" ? {} : (args ?? {}); - - showNotification({ color: "red", title: "Error", message, ...defaultProps }); -} - -export function showSuccessNotification(): void; -export function showSuccessNotification(props: NotificationData): void; -export function showSuccessNotification(message: string): void; -export function showSuccessNotification( - args?: string | NotificationData -): void { - const message = typeof args === "string" ? args : "Success!"; - const defaultProps = typeof args === "string" ? {} : (args ?? {}); - - showNotification({ - color: "green", - title: "Success", - message, - ...defaultProps, - }); -} diff --git a/my-shadcn-app/src/utils/styles.ts b/my-shadcn-app/src/utils/styles.ts deleted file mode 100644 index 1f4cd38e..00000000 --- a/my-shadcn-app/src/utils/styles.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { clsx } from "clsx"; -import { twMerge } from "tailwind-merge"; - -export function cn(...inputs: any[]) { - return twMerge(clsx(inputs)); -} diff --git a/my-shadcn-app/tsconfig.json b/my-shadcn-app/tsconfig.json deleted file mode 100644 index f48e7ee6..00000000 --- a/my-shadcn-app/tsconfig.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "compilerOptions": { - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": [ - "./src/*" - ] - }, - "target": "ES2017" - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/packages/cli/template/nextjs/.prettierrc b/packages/cli/template/nextjs/.prettierrc deleted file mode 100644 index b4bfed35..00000000 --- a/packages/cli/template/nextjs/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "plugins": ["prettier-plugin-tailwindcss"] -} diff --git a/packages/cli/template/nextjs/README.md b/packages/cli/template/nextjs/README.md deleted file mode 100644 index 4f416a4a..00000000 --- a/packages/cli/template/nextjs/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# ProofKit NextJS Template - -This is a [NextJS](https://nextjs.org/) project bootstrapped with `@proofkit/cli`. Learn more at [proofkit.dev](https://proofkit.dev) - -## What's next? How do I make an app with this? - -While this template is designed to be a minimal starting point, the proofkit CLI will guide you through adding additional features and pages. - -To add new things to your project, simply run the `proofkit` script from the project's root directory. - -e.g. `npm run proofkit` or `pnpm proofkit` etc. - -For more information, see the full [ProofKit documentation](https://proofkit.dev). - -## Project Structure - -ProofKit projects have an opinionated structure to help you get started and some conventions must be maintained to ensure that the CLI can properly inject new features and components. - -The `src` directory is the home for your application code. It is used for most things except for configuration and is organized as follows: - -- `app` - NextJS app router, where your pages and routes are defined -- `components` - Shared components used throughout the app -- `server` - Code that connects to backend databases and services that should not be exposed in the browser - -Anytime you see an `internal` folder, you should not modify any files inside. These files are maintained exclusively by the ProofKit CLI and changes to them may be overwritten. - -Anytime you see a componet file that begins with `slot-`, you _may_ modify the content, but do not rename, remove, or move them. These are desigend to be customized, but are still used by the CLI to inject additional content. If a slot is not needed by your app, you can have the compoment return `null` or an empty fragment: `<>` diff --git a/packages/cli/template/nextjs/_gitignore b/packages/cli/template/nextjs/_gitignore deleted file mode 100644 index 00bba9bb..00000000 --- a/packages/cli/template/nextjs/_gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local -.env - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/packages/cli/template/nextjs/components.json b/packages/cli/template/nextjs/components.json deleted file mode 100644 index 0d27c449..00000000 --- a/packages/cli/template/nextjs/components.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "style": "new-york", - "rsc": true, - "tsx": true, - "tailwind": { - "config": "", - "css": "src/config/theme/globals.css", - "baseColor": "neutral", - "cssVariables": true, - "prefix": "tw:" - }, - "aliases": { - "components": "@/components", - "utils": "@/utils/styles", - "ui": "@/components/ui", - "lib": "@/utils", - "hooks": "@/utils/hooks" - }, - "iconLibrary": "lucide" -} diff --git a/packages/cli/template/nextjs/next.config.ts b/packages/cli/template/nextjs/next.config.ts deleted file mode 100644 index 9555317e..00000000 --- a/packages/cli/template/nextjs/next.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type NextConfig } from "next"; - -// Import env here to validate during build. -import "./src/config/env"; - -const nextConfig: NextConfig = { - experimental: { - optimizePackageImports: ["@mantine/core", "@mantine/hooks"], - }, -}; - -export default nextConfig; diff --git a/packages/cli/template/nextjs/package.json b/packages/cli/template/nextjs/package.json deleted file mode 100644 index 70024ab7..00000000 --- a/packages/cli/template/nextjs/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "template", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev --turbopack", - "build": "next build", - "start": "next start", - "lint": "next lint", - "proofkit": "proofkit", - "typegen": "proofkit typegen", - "deploy": "proofkit deploy" - }, - "dependencies": { - "@hookform/resolvers": "^5.1.1", - "@next-safe-action/adapter-react-hook-form": "^2.0.0", - "next-safe-action": "^8.0.4", - "react-hook-form": "^7.54.2", - "@tabler/icons-react": "^3.30.0", - "@mantine/core": "^7.17.0", - "@mantine/dates": "^7.17.0", - "@mantine/hooks": "^7.17.0", - "@mantine/modals": "^7.17.0", - "@mantine/notifications": "^7.17.0", - "mantine-react-table": "2.0.0-beta.9", - "@t3-oss/env-nextjs": "^0.12.0", - "dayjs": "^1.11.13", - "next": "^15.2.3", - "react": "19.0.0", - "react-dom": "19.0.0", - "zod": "^3.24.2" - }, - "devDependencies": { - "@types/node": "^20", - "@types/react": "npm:types-react@19.0.12", - "@types/react-dom": "npm:types-react-dom@19.0.4", - "eslint": "^9.14.0", - "eslint-config-next": "15.2.3", - "postcss": "^8.4.41", - "postcss-preset-mantine": "^1.17.0", - "postcss-simple-vars": "^7.0.1", - "typescript": "^5" - }, - "pnpm": { - "overrides": { - "@types/react": "npm:types-react@19.0.0-rc.1", - "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" - } - } -} diff --git a/packages/cli/template/nextjs/postcss.config.cjs b/packages/cli/template/nextjs/postcss.config.cjs deleted file mode 100644 index 085a0ef9..00000000 --- a/packages/cli/template/nextjs/postcss.config.cjs +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - plugins: { - "@tailwindcss/postcss": {}, - "postcss-preset-mantine": {}, - "postcss-simple-vars": { - variables: { - "mantine-breakpoint-xs": "36em", - "mantine-breakpoint-sm": "48em", - "mantine-breakpoint-md": "62em", - "mantine-breakpoint-lg": "75em", - "mantine-breakpoint-xl": "88em", - }, - }, - }, -}; diff --git a/packages/cli/template/nextjs/proofkit.json b/packages/cli/template/nextjs/proofkit.json deleted file mode 100644 index 6aca1027..00000000 --- a/packages/cli/template/nextjs/proofkit.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "auth": { "type": "none" }, - "envFile": ".env", - "appType": "browser", - "ui": "shadcn", - "appliedUpgrades": ["shadcn", "cursorRules"] -} diff --git a/packages/cli/template/nextjs/public/favicon.ico b/packages/cli/template/nextjs/public/favicon.ico deleted file mode 100644 index ba9355b8d3f888ad3a93c0f254b6776a0c2aed92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 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 DtPcMKfsh_-A)LFM)6iMLm_0IRoy0b^RZ#+}< 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 b29HP@D9EFJDBd}ZfIn(VT8gjb%^v(OKI6J9 diff --git a/packages/cli/template/nextjs/src/app/(main)/layout.tsx b/packages/cli/template/nextjs/src/app/(main)/layout.tsx deleted file mode 100644 index 57a8452b..00000000 --- a/packages/cli/template/nextjs/src/app/(main)/layout.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import AppShell from "@/components/AppShell/internal/AppShell"; -import React from "react"; - -export default function Layout({ children }: { children: React.ReactNode }) { - return {children}; -} diff --git a/packages/cli/template/nextjs/src/app/(main)/page.tsx b/packages/cli/template/nextjs/src/app/(main)/page.tsx deleted file mode 100644 index 0f180c04..00000000 --- a/packages/cli/template/nextjs/src/app/(main)/page.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { - ActionIcon, - Anchor, - AppShellFooter, - Box, - Code, - Container, - Group, - Image, - px, - Stack, - Text, - Title, -} from "@mantine/core"; -import { IconBrandGithub, IconExternalLink } from "@tabler/icons-react"; - -export default function Home() { - return ( - <> - - - ProofKit - Welcome! - - - This is the base template home page. To add more pages, components, - or other features, run the ProofKit CLI from within your project. - - __PNPM_COMMAND__ proofkit - - - To change this page, open src/app/(main)/page.tsx - - - - ProofKit Docs - - - - - - - - - - Sponsored by{" "} - - Proof+Geist - {" "} - and{" "} - - Ottomatic - - - - - - - - - - - - - - - ); -} diff --git a/packages/cli/template/nextjs/src/app/layout.tsx b/packages/cli/template/nextjs/src/app/layout.tsx deleted file mode 100644 index 9512cb63..00000000 --- a/packages/cli/template/nextjs/src/app/layout.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Suspense } from "react"; -import { theme } from "@/config/theme/mantine-theme"; -import { ColorSchemeScript, MantineProvider } from "@mantine/core"; -import { ModalsProvider } from "@mantine/modals"; -import { Notifications } from "@mantine/notifications"; - -import "@mantine/core/styles.css"; -import "@mantine/notifications/styles.css"; -import "@mantine/dates/styles.css"; -import "mantine-react-table/styles.css"; -import "@/config/theme/globals.css"; - -import { type Metadata } from "next"; - -export const metadata: Metadata = { - title: "My ProofKit App", - description: "Generated by proofkit", - icons: [{ rel: "icon", url: "/favicon.ico" }], -}; - -export default function RootLayout({ - children, -}: Readonly<{ children: React.ReactNode }>) { - return ( - - - - - - - - - - {children} - - - - ); -} diff --git a/packages/cli/template/nextjs/src/app/navigation.tsx b/packages/cli/template/nextjs/src/app/navigation.tsx deleted file mode 100644 index 887073db..00000000 --- a/packages/cli/template/nextjs/src/app/navigation.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { type ProofKitRoute } from "@proofkit/cli"; - -export const primaryRoutes: ProofKitRoute[] = [ - { - label: "Dashboard", - type: "link", - href: "/", - exactMatch: true, - }, -]; - -export const secondaryRoutes: ProofKitRoute[] = []; diff --git a/packages/cli/template/nextjs/src/components/AppLogo.tsx b/packages/cli/template/nextjs/src/components/AppLogo.tsx deleted file mode 100644 index f5ea4966..00000000 --- a/packages/cli/template/nextjs/src/components/AppLogo.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { IconInfinity } from "@tabler/icons-react"; -import React from "react"; - -export default function AppLogo() { - return ; -} diff --git a/packages/cli/template/nextjs/src/components/AppShell/internal/AppShell.tsx b/packages/cli/template/nextjs/src/components/AppShell/internal/AppShell.tsx deleted file mode 100644 index 8c4270df..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/internal/AppShell.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Header } from "@/components/AppShell/internal/Header"; -import { AppShell, AppShellHeader, AppShellMain } from "@mantine/core"; -import React from "react"; - -import { headerHeight } from "./config"; - -export default function MainAppShell({ - children, -}: { - children: React.ReactNode; -}) { - return ( - - -
- - - {children} - - ); -} diff --git a/packages/cli/template/nextjs/src/components/AppShell/internal/Header.module.css b/packages/cli/template/nextjs/src/components/AppShell/internal/Header.module.css deleted file mode 100644 index 79d81bad..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/internal/Header.module.css +++ /dev/null @@ -1,40 +0,0 @@ -.header { - /* height: rem(56px); */ - margin-bottom: rem(120px); - background-color: var(--mantine-color-body); - border-bottom: rem(1px) solid - light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); -} - -.inner { - /* height: rem(56px); */ - display: flex; - justify-content: space-between; - align-items: center; -} - -.link { - display: block; - line-height: 1; - padding: rem(8px) rem(12px); - border-radius: var(--mantine-radius-sm); - text-decoration: none; - color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); - font-size: var(--mantine-font-size-sm); - font-weight: 500; - cursor: pointer; - background: none; - border: none; - - @mixin hover { - background-color: light-dark( - var(--mantine-color-gray-0), - var(--mantine-color-dark-6) - ); - } - - [data-mantine-color-scheme] &[data-active] { - background-color: var(--mantine-primary-color-filled); - color: var(--mantine-color-white); - } -} diff --git a/packages/cli/template/nextjs/src/components/AppShell/internal/Header.tsx b/packages/cli/template/nextjs/src/components/AppShell/internal/Header.tsx deleted file mode 100644 index 4409b1d6..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/internal/Header.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Box, Container, Group } from "@mantine/core"; - -import SlotHeaderCenter from "../slot-header-center"; -import SlotHeaderLeft from "../slot-header-left"; -import SlotHeaderRight from "../slot-header-right"; -import { headerHeight } from "./config"; -import classes from "./Header.module.css"; -import HeaderMobileMenu from "./HeaderMobileMenu"; - -export function Header() { - return ( -
- - - - - - - - - - - - - - -
- ); -} diff --git a/packages/cli/template/nextjs/src/components/AppShell/internal/HeaderMobileMenu.tsx b/packages/cli/template/nextjs/src/components/AppShell/internal/HeaderMobileMenu.tsx deleted file mode 100644 index 910104fb..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/internal/HeaderMobileMenu.tsx +++ /dev/null @@ -1,27 +0,0 @@ -"use client"; - -import { Burger, Menu } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; - -import SlotHeaderMobileMenuContent from "../slot-header-mobile-content"; - -export default function HeaderMobileMenu() { - const [opened, { toggle }] = useDisclosure(false); - - return ( - - - - - - - - - ); -} diff --git a/packages/cli/template/nextjs/src/components/AppShell/internal/HeaderNavLink.tsx b/packages/cli/template/nextjs/src/components/AppShell/internal/HeaderNavLink.tsx deleted file mode 100644 index 5da52246..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/internal/HeaderNavLink.tsx +++ /dev/null @@ -1,31 +0,0 @@ -"use client"; - -import { type ProofKitRoute } from "@proofkit/cli"; -import { usePathname } from "next/navigation"; -import React from "react"; - -import classes from "./Header.module.css"; - -export default function HeaderNavLink(route: ProofKitRoute) { - const pathname = usePathname(); - - if (route.type === "function") { - return ; - } - - const isActive = route.exactMatch - ? pathname === route.href - : pathname.startsWith(route.href); - - if (route.type === "link") { - return ( - - {route.label} - - ); - } -} diff --git a/packages/cli/template/nextjs/src/components/AppShell/internal/config.ts b/packages/cli/template/nextjs/src/components/AppShell/internal/config.ts deleted file mode 100644 index ded639d0..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/internal/config.ts +++ /dev/null @@ -1 +0,0 @@ -export const headerHeight = 56; diff --git a/packages/cli/template/nextjs/src/components/AppShell/slot-header-center.tsx b/packages/cli/template/nextjs/src/components/AppShell/slot-header-center.tsx deleted file mode 100644 index 2de3b630..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/slot-header-center.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * DO NOT REMOVE / RENAME THIS FILE - * - * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects - * this file to exist and may use it to inject content for other components. - * - * If you don't want it to be used, you may return null or an empty fragment - */ -export function SlotHeaderCenter() { - return null; -} - -export default SlotHeaderCenter; diff --git a/packages/cli/template/nextjs/src/components/AppShell/slot-header-left.tsx b/packages/cli/template/nextjs/src/components/AppShell/slot-header-left.tsx deleted file mode 100644 index 781fcbce..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/slot-header-left.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import Link from "next/link"; - -import AppLogo from "../AppLogo"; - -/** - * DO NOT REMOVE / RENAME THIS FILE - * - * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects this file to exist and - * may use it to inject content for other components. - * - * If you don't want it to be used, you may return null or an empty fragment - */ -export function SlotHeaderLeft() { - return ( - <> - - - - - ); -} - -export default SlotHeaderLeft; diff --git a/packages/cli/template/nextjs/src/components/AppShell/slot-header-mobile-content.tsx b/packages/cli/template/nextjs/src/components/AppShell/slot-header-mobile-content.tsx deleted file mode 100644 index 9943f8a0..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/slot-header-mobile-content.tsx +++ /dev/null @@ -1,43 +0,0 @@ -"use client"; - -import { primaryRoutes } from "@/app/navigation"; -import { Menu } from "@mantine/core"; -import { useRouter } from "next/navigation"; - -/** - * DO NOT REMOVE / RENAME THIS FILE - * - * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects - * this file to exist and may use it to inject content for other components. - * - * If you don't want it to be used, you may return null or an empty fragment - */ -export function SlotHeaderMobileMenuContent({ - closeMenu, -}: { - closeMenu: () => void; -}) { - const router = useRouter(); - return ( - <> - {primaryRoutes.map((route) => ( - { - closeMenu(); - if (route.type === "function") { - route.onClick(); - } else if (route.type === "link") { - router.push(route.href); - } - }} - > - {route.label} - - ))} - - ); -} - -export default SlotHeaderMobileMenuContent; diff --git a/packages/cli/template/nextjs/src/components/AppShell/slot-header-right.tsx b/packages/cli/template/nextjs/src/components/AppShell/slot-header-right.tsx deleted file mode 100644 index 6c392c95..00000000 --- a/packages/cli/template/nextjs/src/components/AppShell/slot-header-right.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { primaryRoutes } from "@/app/navigation"; -import { Group } from "@mantine/core"; - -import HeaderNavLink from "./internal/HeaderNavLink"; - -/** - * DO NOT REMOVE / RENAME THIS FILE - * - * You may CUSTOMIZE the content of this file, but the ProofKit CLI expects - * this file to exist and may use it to inject content for other components. - * - * If you don't want it to be used, you may return null or an empty fragment - */ -export function SlotHeaderRight() { - return ( - <> - - {primaryRoutes.map((route) => ( - - ))} - - - ); -} - -export default SlotHeaderRight; diff --git a/packages/cli/template/nextjs/src/config/env.ts b/packages/cli/template/nextjs/src/config/env.ts deleted file mode 100644 index 3c50ef8d..00000000 --- a/packages/cli/template/nextjs/src/config/env.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { createEnv } from "@t3-oss/env-nextjs"; -import { z } from "zod/v4"; - -export const env = createEnv({ - server: { - NODE_ENV: z - .enum(["development", "test", "production"]) - .default("development"), - }, - client: {}, - // For Next.js >= 13.4.4, you only need to destructure client variables: - experimental__runtimeEnv: {}, -}); diff --git a/packages/cli/template/nextjs/src/config/theme/globals.css b/packages/cli/template/nextjs/src/config/theme/globals.css deleted file mode 100644 index 0e2f76bb..00000000 --- a/packages/cli/template/nextjs/src/config/theme/globals.css +++ /dev/null @@ -1,125 +0,0 @@ -/* Add global styles here */ - -@import "tailwindcss" prefix(tw); -@import "tw-animate-css"; - -@custom-variant dark (&:is(.dark *)); - -:root { - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --destructive-foreground: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --radius: 0.625rem; - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.145 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.145 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.985 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.396 0.141 25.723); - --destructive-foreground: oklch(0.637 0.237 25.331); - --border: oklch(0.269 0 0); - --input: oklch(0.269 0 0); - --ring: oklch(0.439 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(0.269 0 0); - --sidebar-ring: oklch(0.439 0 0); -} - -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-destructive-foreground: var(--destructive-foreground); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); -} - -@layer base { - * { - @apply tw:border-border tw:outline-ring/50; - } - body { - @apply tw:bg-background tw:text-foreground; - } -} diff --git a/packages/cli/template/nextjs/src/config/theme/mantine-theme.ts b/packages/cli/template/nextjs/src/config/theme/mantine-theme.ts deleted file mode 100644 index 890db89c..00000000 --- a/packages/cli/template/nextjs/src/config/theme/mantine-theme.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createTheme, type MantineColorsTuple } from "@mantine/core"; - -// generate your own set of colors here: https://mantine.dev/colors-generator -const brandColor: MantineColorsTuple = [ - "#ffebff", - "#f5d5fb", - "#e6a8f3", - "#d779eb", - "#cb51e4", - "#c337e0", - "#c029df", - "#a91cc6", - "#9715b1", - "#84099c", -]; - -export const theme = createTheme({ - primaryColor: "brand", - colors: { - brand: brandColor, - }, -}); diff --git a/packages/cli/template/nextjs/src/server/safe-action.ts b/packages/cli/template/nextjs/src/server/safe-action.ts deleted file mode 100644 index 7f62198a..00000000 --- a/packages/cli/template/nextjs/src/server/safe-action.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createSafeActionClient } from "next-safe-action"; - -export const actionClient = createSafeActionClient(); diff --git a/packages/cli/template/nextjs/src/utils/notification-helpers.ts b/packages/cli/template/nextjs/src/utils/notification-helpers.ts deleted file mode 100644 index 771fdffe..00000000 --- a/packages/cli/template/nextjs/src/utils/notification-helpers.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { - showNotification, - type NotificationData, -} from "@mantine/notifications"; - -export function showErrorNotification(): void; -export function showErrorNotification(props: NotificationData): void; -export function showErrorNotification(message: string): void; -export function showErrorNotification(args?: string | NotificationData): void { - const message = - typeof args === "string" ? args : "An unexpected error occurred."; - const defaultProps = typeof args === "string" ? {} : (args ?? {}); - - showNotification({ color: "red", title: "Error", message, ...defaultProps }); -} - -export function showSuccessNotification(): void; -export function showSuccessNotification(props: NotificationData): void; -export function showSuccessNotification(message: string): void; -export function showSuccessNotification( - args?: string | NotificationData -): void { - const message = typeof args === "string" ? args : "Success!"; - const defaultProps = typeof args === "string" ? {} : (args ?? {}); - - showNotification({ - color: "green", - title: "Success", - message, - ...defaultProps, - }); -} diff --git a/packages/cli/template/nextjs/src/utils/styles.ts b/packages/cli/template/nextjs/src/utils/styles.ts deleted file mode 100644 index 1f4cd38e..00000000 --- a/packages/cli/template/nextjs/src/utils/styles.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { clsx } from "clsx"; -import { twMerge } from "tailwind-merge"; - -export function cn(...inputs: any[]) { - return twMerge(clsx(inputs)); -} diff --git a/packages/cli/template/nextjs/tsconfig.json b/packages/cli/template/nextjs/tsconfig.json deleted file mode 100644 index f48e7ee6..00000000 --- a/packages/cli/template/nextjs/tsconfig.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "compilerOptions": { - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": [ - "./src/*" - ] - }, - "target": "ES2017" - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts" - ], - "exclude": [ - "node_modules" - ] -} From 4820e09b88f189a7c326150cee8558ff3ff97f93 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 8 Aug 2025 21:17:58 +0000 Subject: [PATCH 4/5] Remove Mantine dependencies and migrate to Tailwind CSS styling Co-authored-by: eric.luce --- .../cli/template/nextjs-shadcn/next.config.ts | 6 +- .../template/nextjs-shadcn/postcss.config.cjs | 10 -- .../nextjs-shadcn/src/app/(main)/page.tsx | 121 ++++++++---------- .../components/AppShell/internal/AppShell.tsx | 17 ++- .../AppShell/internal/Header.module.css | 33 ++--- .../components/AppShell/internal/Header.tsx | 27 ++-- .../AppShell/internal/HeaderMobileMenu.tsx | 34 +++-- .../AppShell/slot-header-mobile-content.tsx | 14 +- .../components/AppShell/slot-header-right.tsx | 13 +- .../src/config/theme/mantine-theme.ts | 22 ---- .../src/utils/notification-helpers.ts | 31 +---- 11 files changed, 117 insertions(+), 211 deletions(-) delete mode 100644 packages/cli/template/nextjs-shadcn/src/config/theme/mantine-theme.ts diff --git a/packages/cli/template/nextjs-shadcn/next.config.ts b/packages/cli/template/nextjs-shadcn/next.config.ts index 9555317e..5a07c277 100644 --- a/packages/cli/template/nextjs-shadcn/next.config.ts +++ b/packages/cli/template/nextjs-shadcn/next.config.ts @@ -3,10 +3,6 @@ import { type NextConfig } from "next"; // Import env here to validate during build. import "./src/config/env"; -const nextConfig: NextConfig = { - experimental: { - optimizePackageImports: ["@mantine/core", "@mantine/hooks"], - }, -}; +const nextConfig: NextConfig = {}; export default nextConfig; diff --git a/packages/cli/template/nextjs-shadcn/postcss.config.cjs b/packages/cli/template/nextjs-shadcn/postcss.config.cjs index 085a0ef9..483f3785 100644 --- a/packages/cli/template/nextjs-shadcn/postcss.config.cjs +++ b/packages/cli/template/nextjs-shadcn/postcss.config.cjs @@ -1,15 +1,5 @@ module.exports = { plugins: { "@tailwindcss/postcss": {}, - "postcss-preset-mantine": {}, - "postcss-simple-vars": { - variables: { - "mantine-breakpoint-xs": "36em", - "mantine-breakpoint-sm": "48em", - "mantine-breakpoint-md": "62em", - "mantine-breakpoint-lg": "75em", - "mantine-breakpoint-xl": "88em", - }, - }, }, }; diff --git a/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx b/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx index 0f180c04..39212573 100644 --- a/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx +++ b/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx @@ -1,90 +1,69 @@ -import { - ActionIcon, - Anchor, - AppShellFooter, - Box, - Code, - Container, - Group, - Image, - px, - Stack, - Text, - Title, -} from "@mantine/core"; import { IconBrandGithub, IconExternalLink } from "@tabler/icons-react"; export default function Home() { return ( <> - - - +
+ ProofKit - Welcome! +

Welcome!

- +

This is the base template home page. To add more pages, components, or other features, run the ProofKit CLI from within your project. - - __PNPM_COMMAND__ proofkit +

+ + __PNPM_COMMAND__ proofkit + - - To change this page, open src/app/(main)/page.tsx - - - + To change this page, open src/app/(main)/page.tsx +

+ +
+ + ); } diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx index 8c4270df..fc3f6873 100644 --- a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx @@ -1,7 +1,5 @@ -import { Header } from "@/components/AppShell/internal/Header"; -import { AppShell, AppShellHeader, AppShellMain } from "@mantine/core"; import React from "react"; - +import { Header } from "@/components/AppShell/internal/Header"; import { headerHeight } from "./config"; export default function MainAppShell({ @@ -10,12 +8,13 @@ export default function MainAppShell({ children: React.ReactNode; }) { return ( - - +
+
- - - {children} - +
+
+ {children} +
+
); } diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.module.css b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.module.css index 79d81bad..2733308e 100644 --- a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.module.css +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.module.css @@ -1,13 +1,10 @@ .header { - /* height: rem(56px); */ - margin-bottom: rem(120px); - background-color: var(--mantine-color-body); - border-bottom: rem(1px) solid - light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); + margin-bottom: 7.5rem; + background-color: var(--pk-header-bg, transparent); + border-bottom: 1px solid var(--pk-border, rgba(0,0,0,0.08)); } .inner { - /* height: rem(56px); */ display: flex; justify-content: space-between; align-items: center; @@ -16,25 +13,21 @@ .link { display: block; line-height: 1; - padding: rem(8px) rem(12px); - border-radius: var(--mantine-radius-sm); + padding: 0.5rem 0.75rem; + border-radius: 0.375rem; text-decoration: none; - color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); - font-size: var(--mantine-font-size-sm); + color: inherit; + font-size: 0.875rem; font-weight: 500; cursor: pointer; background: none; border: none; +} - @mixin hover { - background-color: light-dark( - var(--mantine-color-gray-0), - var(--mantine-color-dark-6) - ); - } +.link:hover { + background-color: rgba(0, 0, 0, 0.05); +} - [data-mantine-color-scheme] &[data-active] { - background-color: var(--mantine-primary-color-filled); - color: var(--mantine-color-white); - } +[data-theme="dark"] .link:hover { + background-color: rgba(255, 255, 255, 0.06); } diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx index 4409b1d6..eedce969 100644 --- a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx @@ -1,5 +1,3 @@ -import { Box, Container, Group } from "@mantine/core"; - import SlotHeaderCenter from "../slot-header-center"; import SlotHeaderLeft from "../slot-header-left"; import SlotHeaderRight from "../slot-header-right"; @@ -10,25 +8,20 @@ import HeaderMobileMenu from "./HeaderMobileMenu"; export function Header() { return (
- - +
+
- +
- - +
+
- - +
+
- - - +
+
+
); } diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderMobileMenu.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderMobileMenu.tsx index 910104fb..ac2a2e2b 100644 --- a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderMobileMenu.tsx +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/HeaderMobileMenu.tsx @@ -1,27 +1,25 @@ "use client"; -import { Burger, Menu } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; - +import { useState } from "react"; import SlotHeaderMobileMenuContent from "../slot-header-mobile-content"; export default function HeaderMobileMenu() { - const [opened, { toggle }] = useDisclosure(false); + const [opened, setOpened] = useState(false); return ( - - - - - - - - +
+ + {opened && ( +
+ setOpened(false)} /> +
+ )} +
); } diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-mobile-content.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-mobile-content.tsx index 9943f8a0..f63d0365 100644 --- a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-mobile-content.tsx +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-mobile-content.tsx @@ -1,7 +1,6 @@ "use client"; import { primaryRoutes } from "@/app/navigation"; -import { Menu } from "@mantine/core"; import { useRouter } from "next/navigation"; /** @@ -19,11 +18,11 @@ export function SlotHeaderMobileMenuContent({ }) { const router = useRouter(); return ( - <> +
{primaryRoutes.map((route) => ( - { closeMenu(); if (route.type === "function") { @@ -33,10 +32,11 @@ export function SlotHeaderMobileMenuContent({ } }} > - {route.label} - + {route.icon} + {route.label} + ))} - +
); } diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx index 6c392c95..989fecaf 100644 --- a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx @@ -1,5 +1,4 @@ import { primaryRoutes } from "@/app/navigation"; -import { Group } from "@mantine/core"; import HeaderNavLink from "./internal/HeaderNavLink"; @@ -13,13 +12,11 @@ import HeaderNavLink from "./internal/HeaderNavLink"; */ export function SlotHeaderRight() { return ( - <> - - {primaryRoutes.map((route) => ( - - ))} - - +
+ {primaryRoutes.map((route) => ( + + ))} +
); } diff --git a/packages/cli/template/nextjs-shadcn/src/config/theme/mantine-theme.ts b/packages/cli/template/nextjs-shadcn/src/config/theme/mantine-theme.ts deleted file mode 100644 index 890db89c..00000000 --- a/packages/cli/template/nextjs-shadcn/src/config/theme/mantine-theme.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createTheme, type MantineColorsTuple } from "@mantine/core"; - -// generate your own set of colors here: https://mantine.dev/colors-generator -const brandColor: MantineColorsTuple = [ - "#ffebff", - "#f5d5fb", - "#e6a8f3", - "#d779eb", - "#cb51e4", - "#c337e0", - "#c029df", - "#a91cc6", - "#9715b1", - "#84099c", -]; - -export const theme = createTheme({ - primaryColor: "brand", - colors: { - brand: brandColor, - }, -}); diff --git a/packages/cli/template/nextjs-shadcn/src/utils/notification-helpers.ts b/packages/cli/template/nextjs-shadcn/src/utils/notification-helpers.ts index 771fdffe..dc0dd7c8 100644 --- a/packages/cli/template/nextjs-shadcn/src/utils/notification-helpers.ts +++ b/packages/cli/template/nextjs-shadcn/src/utils/notification-helpers.ts @@ -1,32 +1,15 @@ -import { - showNotification, - type NotificationData, -} from "@mantine/notifications"; - export function showErrorNotification(): void; -export function showErrorNotification(props: NotificationData): void; export function showErrorNotification(message: string): void; -export function showErrorNotification(args?: string | NotificationData): void { - const message = - typeof args === "string" ? args : "An unexpected error occurred."; - const defaultProps = typeof args === "string" ? {} : (args ?? {}); - - showNotification({ color: "red", title: "Error", message, ...defaultProps }); +export function showErrorNotification(args?: string): void { + const message = typeof args === "string" ? args : "An unexpected error occurred."; + // TODO: Replace with your preferred toast library + if (typeof window !== "undefined") console.error(message); } export function showSuccessNotification(): void; -export function showSuccessNotification(props: NotificationData): void; export function showSuccessNotification(message: string): void; -export function showSuccessNotification( - args?: string | NotificationData -): void { +export function showSuccessNotification(args?: string): void { const message = typeof args === "string" ? args : "Success!"; - const defaultProps = typeof args === "string" ? {} : (args ?? {}); - - showNotification({ - color: "green", - title: "Success", - message, - ...defaultProps, - }); + // TODO: Replace with your preferred toast library + if (typeof window !== "undefined") console.log(message); } From a22676cd3358e8277960fb7ab7b2a9db8e6113e7 Mon Sep 17 00:00:00 2001 From: Eric Luce <37158449+eluce2@users.noreply.github.com> Date: Sat, 9 Aug 2025 09:00:38 -0500 Subject: [PATCH 5/5] fix template --- packages/cli/src/helpers/createProject.ts | 1 + .../src/installers/dependencyVersionMap.ts | 11 +++ .../template/nextjs-shadcn/components.json | 2 +- .../nextjs-shadcn/src/app/(main)/page.tsx | 97 ++++++++++++++----- .../template/nextjs-shadcn/src/app/layout.tsx | 24 ++++- .../components/AppShell/internal/AppShell.tsx | 7 +- .../components/AppShell/internal/Header.tsx | 7 +- .../components/AppShell/slot-header-right.tsx | 4 +- .../src/components/providers.tsx | 13 +++ .../src/components/theme-provider.tsx | 11 +++ .../src/config/theme/globals.css | 73 +++++++------- 11 files changed, 180 insertions(+), 70 deletions(-) create mode 100644 packages/cli/template/nextjs-shadcn/src/components/providers.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/theme-provider.tsx diff --git a/packages/cli/src/helpers/createProject.ts b/packages/cli/src/helpers/createProject.ts index 32231e27..9966dbb3 100644 --- a/packages/cli/src/helpers/createProject.ts +++ b/packages/cli/src/helpers/createProject.ts @@ -45,6 +45,7 @@ export const createBareProject = async ({ "tailwind-merge", "tailwindcss", "tw-animate-css", + "next-themes", ] as AvailableDependencies[]; const SHADCN_BASE_DEV_DEPS = [ "prettier", diff --git a/packages/cli/src/installers/dependencyVersionMap.ts b/packages/cli/src/installers/dependencyVersionMap.ts index 13df7f69..59edbdd3 100644 --- a/packages/cli/src/installers/dependencyVersionMap.ts +++ b/packages/cli/src/installers/dependencyVersionMap.ts @@ -88,5 +88,16 @@ export const dependencyVersionMap = { // Icons (for shadcn/ui) "lucide-react": "^0.518.0", + + // Mantine UI + "@mantine/core": "^7.15.0", + "@mantine/dates": "^7.15.0", + "@mantine/hooks": "^7.15.0", + "@mantine/modals": "^7.15.0", + "@mantine/notifications": "^7.15.0", + "mantine-react-table": "^2.0.0", + + // Theme utilities + "next-themes": "^0.4.6", } as const; export type AvailableDependencies = keyof typeof dependencyVersionMap; diff --git a/packages/cli/template/nextjs-shadcn/components.json b/packages/cli/template/nextjs-shadcn/components.json index 0d27c449..7cccc384 100644 --- a/packages/cli/template/nextjs-shadcn/components.json +++ b/packages/cli/template/nextjs-shadcn/components.json @@ -8,7 +8,7 @@ "css": "src/config/theme/globals.css", "baseColor": "neutral", "cssVariables": true, - "prefix": "tw:" + "prefix": "" }, "aliases": { "components": "@/components", diff --git a/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx b/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx index 39212573..5c9443b3 100644 --- a/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx +++ b/packages/cli/template/nextjs-shadcn/src/app/(main)/page.tsx @@ -1,8 +1,55 @@ -import { IconBrandGithub, IconExternalLink } from "@tabler/icons-react"; +"use client"; + +import { + IconBrandGithub, + IconExternalLink, + IconCopy, + IconCheck, + IconTerminal, +} from "@tabler/icons-react"; +import { Button } from "@/components/ui/button"; +import { useState } from "react"; + +function InlineSnippet({ command }: { command: string }) { + const [copied, setCopied] = useState(false); + + const onCopy = () => { + if (typeof window === "undefined" || !navigator.clipboard?.writeText) + return; + navigator.clipboard.writeText(command).then( + () => { + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }, + () => {}, + ); + }; + + return ( +
+
+ +
+ + {command} + +
+ +
+
+ ); +} export default function Home() { return ( - <> +
ProofKit -

Welcome!

+

Welcome!

-

+

This is the base template home page. To add more pages, components, or other features, run the ProofKit CLI from within your project.

- - __PNPM_COMMAND__ proofkit - -

+ + +

To change this page, open src/app/(main)/page.tsx

- - +
+ ); } diff --git a/packages/cli/template/nextjs-shadcn/src/app/layout.tsx b/packages/cli/template/nextjs-shadcn/src/app/layout.tsx index 6f0ff3db..70a51fc1 100644 --- a/packages/cli/template/nextjs-shadcn/src/app/layout.tsx +++ b/packages/cli/template/nextjs-shadcn/src/app/layout.tsx @@ -7,13 +7,31 @@ export const metadata: Metadata = { icons: [{ rel: "icon", url: "/favicon.ico" }], }; +import { Geist, Geist_Mono } from "next/font/google"; + +import Providers from "@/components/providers"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + export default function RootLayout({ children, -}: Readonly<{ children: React.ReactNode }>) { +}: Readonly<{ + children: React.ReactNode; +}>) { return ( - - {children} + + {children} ); diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx index fc3f6873..33ccb2df 100644 --- a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx @@ -8,8 +8,11 @@ export default function MainAppShell({ children: React.ReactNode; }) { return ( -
-
+
+
diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx index eedce969..a302ecce 100644 --- a/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx @@ -7,8 +7,11 @@ import HeaderMobileMenu from "./HeaderMobileMenu"; export function Header() { return ( -
-
+
+
diff --git a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx index 989fecaf..afe06352 100644 --- a/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx +++ b/packages/cli/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx @@ -1,6 +1,7 @@ import { primaryRoutes } from "@/app/navigation"; import HeaderNavLink from "./internal/HeaderNavLink"; +import { ModeToggle } from "../mode-toggle"; /** * DO NOT REMOVE / RENAME THIS FILE @@ -12,10 +13,11 @@ import HeaderNavLink from "./internal/HeaderNavLink"; */ export function SlotHeaderRight() { return ( -
+
{primaryRoutes.map((route) => ( ))} +
); } diff --git a/packages/cli/template/nextjs-shadcn/src/components/providers.tsx b/packages/cli/template/nextjs-shadcn/src/components/providers.tsx new file mode 100644 index 00000000..a101d447 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/providers.tsx @@ -0,0 +1,13 @@ +"use client"; + +import { ThemeProvider } from "./theme-provider"; +import { Toaster } from "./ui/sonner"; + +export default function Providers({ children }: { children: React.ReactNode }) { + return ( + + {children} + + + ); +} diff --git a/packages/cli/template/nextjs-shadcn/src/components/theme-provider.tsx b/packages/cli/template/nextjs-shadcn/src/components/theme-provider.tsx new file mode 100644 index 00000000..6459132f --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/theme-provider.tsx @@ -0,0 +1,11 @@ +"use client"; + +import { ThemeProvider as NextThemesProvider } from "next-themes"; +import type * as React from "react"; + +export function ThemeProvider({ + children, + ...props +}: React.ComponentProps) { + return {children}; +} diff --git a/packages/cli/template/nextjs-shadcn/src/config/theme/globals.css b/packages/cli/template/nextjs-shadcn/src/config/theme/globals.css index 0e2f76bb..5a886a5a 100644 --- a/packages/cli/template/nextjs-shadcn/src/config/theme/globals.css +++ b/packages/cli/template/nextjs-shadcn/src/config/theme/globals.css @@ -1,11 +1,16 @@ /* Add global styles here */ -@import "tailwindcss" prefix(tw); +@import "tailwindcss"; @import "tw-animate-css"; -@custom-variant dark (&:is(.dark *)); +@theme { + --font-sans: + "Inter", "Geist", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", + "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +} :root { + --radius: 0.625rem; --background: oklch(1 0 0); --foreground: oklch(0.145 0 0); --card: oklch(1 0 0); @@ -21,7 +26,6 @@ --accent: oklch(0.97 0 0); --accent-foreground: oklch(0.205 0 0); --destructive: oklch(0.577 0.245 27.325); - --destructive-foreground: oklch(0.577 0.245 27.325); --border: oklch(0.922 0 0); --input: oklch(0.922 0 0); --ring: oklch(0.708 0 0); @@ -30,7 +34,6 @@ --chart-3: oklch(0.398 0.07 227.392); --chart-4: oklch(0.828 0.189 84.429); --chart-5: oklch(0.769 0.188 70.08); - --radius: 0.625rem; --sidebar: oklch(0.985 0 0); --sidebar-foreground: oklch(0.145 0 0); --sidebar-primary: oklch(0.205 0 0); @@ -48,35 +51,38 @@ --card-foreground: oklch(0.985 0 0); --popover: oklch(0.145 0 0); --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.985 0 0); + --primary: oklch(0.85 0 0); --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.396 0.141 25.723); - --destructive-foreground: oklch(0.637 0.237 25.331); - --border: oklch(0.269 0 0); - --input: oklch(0.269 0 0); - --ring: oklch(0.439 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(0.269 0 0); - --sidebar-ring: oklch(0.439 0 0); + --secondary: oklch(0.2 0 0); + --secondary-foreground: oklch(0.9 0 0); + --muted: oklch(0.2 0 0); + --muted-foreground: oklch(0.78 0 0); + --accent: oklch(0.22 0 0); + --accent-foreground: oklch(0.9 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.27 0 0); + --input: oklch(0.27 0 0); + --ring: oklch(0.52 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.18 0 0); + --sidebar-foreground: oklch(0.97 0 0); + --sidebar-primary: var(--primary); + --sidebar-primary-foreground: var(--primary-foreground); + --sidebar-accent: oklch(0.22 0 0); + --sidebar-accent-foreground: oklch(0.9 0 0); + --sidebar-border: oklch(0.27 0 0); + --sidebar-ring: oklch(0.52 0 0); } @theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); @@ -92,7 +98,6 @@ --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); - --color-destructive-foreground: var(--destructive-foreground); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); @@ -101,10 +106,6 @@ --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); --color-sidebar: var(--sidebar); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar-primary: var(--sidebar-primary); @@ -117,9 +118,9 @@ @layer base { * { - @apply tw:border-border tw:outline-ring/50; + @apply border-border outline-ring/50; } body { - @apply tw:bg-background tw:text-foreground; + @apply bg-background text-foreground; } }