commit 87ca5af765d2be237a2b396b8412d7906890d6a8 Author: luciano Date: Wed Apr 29 12:10:08 2026 +0200 chore: initial monorepo scaffold Setup pnpm workspaces with apps/{web,api} placeholders and shared packages: tsconfig, eslint-config, shared, ui, db. Includes Prettier, ESLint, Husky pre-commit, lint-staged, EditorConfig, VSCode settings. Co-Authored-By: Claude Opus 4.7 (1M context) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8c52ff9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..6b74dc9 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,14 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + extends: ['@ketopath/eslint-config'], + ignorePatterns: [ + 'node_modules/', + 'dist/', + 'build/', + '.next/', + 'out/', + 'coverage/', + 'pnpm-lock.yaml', + ], +}; diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..618169c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +* text=auto eol=lf + +*.docx binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.pdf binary + +pnpm-lock.yaml linguist-generated=true -diff diff --git a/.github/workflows/.gitkeep b/.github/workflows/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb2b88a --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Dependencies +node_modules/ +.pnpm-store/ + +# Build output +dist/ +build/ +.next/ +out/ +.turbo/ + +# Test / coverage +coverage/ +.nyc_output/ + +# Env files (NEVER commit) +.env +.env.* +!.env.example + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# OS +.DS_Store +Thumbs.db + +# Editor +.idea/ +*.swp +*.swo + +# TypeScript +*.tsbuildinfo + +# Misc +.cache/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..cb2c84d --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +pnpm lint-staged diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..c49db3b --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +engine-strict=true +auto-install-peers=true +node-linker=isolated diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..2dbbe00 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20.11.1 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..1916473 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,14 @@ +node_modules/ +.pnpm-store/ +dist/ +build/ +.next/ +out/ +.turbo/ +coverage/ +pnpm-lock.yaml +*.docx +*.pdf + +# User-authored project doc — preserve exact formatting +CLAUDE.md diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..dea6315 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "singleQuote": true, + "semi": true, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 2, + "arrowParens": "always", + "endOfLine": "lf", + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..063ad39 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "eslint.workingDirectories": [{ "pattern": "apps/*" }, { "pattern": "packages/*" }], + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": true, + "files.eol": "\n" +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..2014ad2 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,208 @@ +# KetoPath + +> Web app responsive multi-utente per la gestione personalizzata di chetogenica e digiuno intermittente, con piani alimentari adattivi, tracking peso/progressi, gestione del digiuno e lista della spesa automatica. + +Questo file viene letto automaticamente da Claude Code a ogni sessione. Tienilo aggiornato con le decisioni architetturali e di prodotto. + +--- + +## Vision + +Trasformare la chetogenica e il digiuno intermittente da diete temporanee a stili di vita strutturati, accompagnando ogni utente dalla prima settimana di adattamento al mantenimento per la vita. + +Il documento di prodotto completo è in `docs/PRD_KetoPath.docx`. Quando devi prendere decisioni di prodotto non banali, leggilo prima di proporre soluzioni. + +--- + +## Tech stack + +**Frontend** +- Next.js 14 (App Router) + TypeScript strict mode +- Tailwind CSS + shadcn/ui per i componenti +- TanStack Query per data fetching client-side +- Zustand per stato globale leggero +- Zod per validazione form e tipi runtime + +**Backend** +- Node.js + Fastify + TypeScript +- Prisma come ORM +- Auth gestita via Clerk (no roll-your-own) + +**Database & infrastruttura** +- PostgreSQL 15+ come DB principale +- Redis per cache, sessioni e queue di job +- Cloudflare R2 per storage foto progress +- SendGrid per email transazionali +- Firebase Cloud Messaging per push web + +**Hosting & DevOps** +- Vercel per il frontend Next.js +- Render o Fly.io per il backend Fastify +- GitHub Actions per CI/CD +- PostHog (self-hosted) per analytics +- Sentry per error tracking + +--- + +## Repository structure + +``` +ketopath/ +├── apps/ +│ ├── web/ # Next.js frontend (App Router) +│ └── api/ # Fastify backend +├── packages/ +│ ├── db/ # Prisma schema, client, migrations +│ ├── shared/ # Tipi TS, utility e logica di dominio condivisa +│ └── ui/ # Componenti UI riusabili (estensione shadcn/ui) +├── docs/ +│ ├── PRD_KetoPath.docx +│ └── decisions/ # ADR (Architecture Decision Records) +├── .github/workflows/ +└── CLAUDE.md # questo file +``` + +Usa un monorepo con pnpm workspaces o Turborepo. Tutto in TypeScript. + +--- + +## Convenzioni di codice + +- **TypeScript strict mode** sempre. Mai `any` senza commento `// eslint-disable-next-line` motivato. +- **File**: `kebab-case.tsx` per i moduli, `PascalCase.tsx` per i componenti React esposti. +- **Componenti React**: function components + hooks, no class components. +- **Naming**: + - Variabili e funzioni: `camelCase` + - Componenti, tipi e interfacce: `PascalCase` + - Costanti globali: `SCREAMING_SNAKE_CASE` +- **Commit message**: Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`, ecc.). +- **Linting**: ESLint + Prettier, formattazione automatica al pre-commit con husky + lint-staged. +- **Test**: Vitest per unit test, Playwright per E2E. Coverage minima 70% sui moduli di dominio (calcoli BMR, macros, fasi). + +--- + +## Pattern di codice da preferire + +- **Server Components** di default in Next.js; `"use client"` solo dove serve interattività. +- **Server Actions** per mutazioni semplici di form, API routes per logica più complessa. +- **Suspense + Error Boundary** per ogni feature. +- **Form**: React Hook Form + Zod resolver. Mai validazione manuale. +- **Date**: usa `date-fns`. Mai `Date.parse` o stringhe ad-hoc. +- **DB queries**: Prisma client. Niente raw SQL se non strettamente necessario, e in quel caso commenta perché. +- **Optimistic updates** per le azioni utente frequenti (segnare un pasto come consumato, spuntare un articolo della lista spesa). + +--- + +## Conoscenza di dominio + +Il dominio dell'app ha alcuni concetti chiave che devi conoscere prima di scrivere codice: + +- **3 Fasi del percorso utente**: + - `INTENSIVE` (giorni 1-30/45) — deficit calorico aggressivo, IF stretto + - `TRANSITION` (giorni 31-90) — reverse dieting, calorie in salita + - `MAINTENANCE` (per sempre) — 14:10, regola 80/20, soglia di allarme +- **Calcolo calorie** con formula Mifflin-St Jeor: + - Uomini: `BMR = 10 × peso(kg) + 6.25 × altezza(cm) − 5 × età + 5` + - Donne: `BMR = 10 × peso(kg) + 6.25 × altezza(cm) − 5 × età − 161` + - TDEE = BMR × fattore attività (1.2 / 1.375 / 1.55 / 1.725) +- **Macros target per fase**: + - Carboidrati netti: 5-10% in Phase 1, sale in Phase 2-3 + - Proteine: 1.5-1.8 g/kg di peso ideale + - Grassi: il resto +- **Protocolli di digiuno**: enum `FASTING_PROTOCOL = 14_10 | 16_8 | 18_6 | 20_4 | ESE_24 | FIVE_TWO` +- **Esclusioni alimentari**: ogni `Ingredient` ha `exclusion_groups` (es. `lactose`, `fish`, `nuts`); ogni `Recipe` eredita le esclusioni dai suoi ingredienti + +Quando implementi una nuova funzionalità, mappa sempre prima a quale fase appartiene e quali macros/vincoli rispetta. + +--- + +## Comandi comuni + +```bash +# Sviluppo +pnpm dev # Avvia frontend + backend in parallelo +pnpm dev:web # Solo Next.js +pnpm dev:api # Solo Fastify + +# Build & deploy +pnpm build # Build di tutti i package +pnpm start # Avvia in production mode + +# Database +pnpm db:migrate # prisma migrate dev +pnpm db:studio # Apre Prisma Studio +pnpm db:seed # Popola DB con dati di test + +# Quality +pnpm lint # ESLint +pnpm format # Prettier +pnpm typecheck # tsc --noEmit +pnpm test # Vitest +pnpm test:e2e # Playwright +``` + +--- + +## Vincoli non negoziabili + +- **Lingua UI di default: italiano**. Tutti i testi user-facing in italiano. Predisporre i18n con `next-intl` per l'eventuale internazionalizzazione futura. +- **Mobile-first responsive**: ogni pagina deve essere progettata e testata prima a 375px di larghezza. +- **GDPR by design**: i dati di salute (peso, misure, foto, sintomi) rientrano nell'art. 9 GDPR. Crittografia at-rest sul DB, niente log dei dati sanitari, consenso esplicito. +- **Disclaimer medico** sempre visibile in onboarding, nelle pagine di calcolo calorico e nelle pagine di tracking. Testo da concordare con un medico advisor. +- **Privacy first**: niente tracking di terze parti senza consenso, no Google Analytics di default. Se proprio servono analytics, usa PostHog self-hosted con cookie-less mode. +- **Accessibilità WCAG 2.1 AA**: tutto il contenuto navigabile da tastiera, contrasto colori sufficiente, alt text sulle immagini, semantica HTML corretta. + +--- + +## Cosa NON fare mai + +- Salvare password in chiaro (Clerk gestisce auth, non implementarla a mano). +- Loggare dati di salute fuori dal DB cifrato. +- Usare `eval()` o `new Function()` con input utente. +- Disabilitare feature di sicurezza (CSP, CORS, rate limiting) per "comodità di sviluppo". +- Fare claim medici sui prodotti o suggerire farmaci/integratori specifici. +- Esportare dati utente in chiaro senza autenticazione e log dell'export. +- Fare commit di file `.env`, chiavi API, dump di database. +- Usare librerie deprecate o senza manutenzione attiva (controlla l'ultimo commit prima di aggiungere una dipendenza). + +--- + +## Workflow consigliato per Claude Code + +Quando ti chiedo una nuova funzionalità, segui questo flusso: + +1. **Domanda di chiarimento** se il task non è completamente specificato. +2. **Lettura preventiva**: leggi i file pertinenti prima di proporre modifiche, non scrivere codice "alla cieca". +3. **Plan mode** per task non banali: presentami un piano in 5-10 punti prima di toccare il codice. +4. **Implementazione progressiva**: feature piccole, commit frequenti, ogni commit verde (lint + test passano). +5. **Diff esplicito**: mostrami sempre i diff prima di applicare modifiche a file critici (`prisma/schema.prisma`, `package.json`, file di config). +6. **Test**: per ogni nuova logica di dominio (calcoli macros, fasi, vincoli) scrivi anche unit test. +7. **Documentazione**: aggiorna il README e questo CLAUDE.md quando introduci pattern nuovi o cambi decisioni architetturali. + +--- + +## Decisioni architetturali aperte (da prendere insieme) + +Queste decisioni non sono ancora finalizzate. Se le tocchi, aprire un ADR in `docs/decisions/`. + +- [ ] Stripe vs Lemon Squeezy per il payment provider +- [ ] PostHog self-hosted vs Mixpanel per analytics di prodotto +- [ ] Render vs Fly.io vs AWS ECS per l'hosting backend +- [ ] Strategia di seeding del database ricette (manuale vs scraping autorizzato vs LLM-assisted) +- [ ] Localizzazione: i18n da subito o solo italiano per MVP? +- [ ] App mobile nativa post-MVP: React Native o Expo? + +--- + +## Riferimenti + +- PRD completo: `docs/PRD_KetoPath.docx` +- Documentazione Next.js: https://nextjs.org/docs +- Documentazione Prisma: https://www.prisma.io/docs +- Documentazione Clerk: https://clerk.com/docs +- shadcn/ui: https://ui.shadcn.com +- GDPR e dati sanitari: https://www.garanteprivacy.it/ + +--- + +*Ultimo aggiornamento: aprile 2026. Modifica questo file ogni volta che cambia una decisione architetturale o un pattern di codice.* diff --git a/README.md b/README.md new file mode 100644 index 0000000..b0342d0 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# KetoPath + +Web app responsive multi-utente per la gestione personalizzata di chetogenica e digiuno intermittente. + +> Vedi `CLAUDE.md` per le convenzioni di progetto e `docs/PRD_KetoPath.docx` per il PRD completo. + +## Prerequisiti + +- Node.js `>=20.11` (vedi `.nvmrc`) +- pnpm `>=9` (`corepack enable && corepack prepare pnpm@latest --activate`) + +## Getting started + +```bash +pnpm install +pnpm typecheck +pnpm lint +pnpm format:check +``` + +## Struttura del monorepo + +``` +apps/ + web/ # Next.js 14 frontend (da scaffoldare) + api/ # Fastify backend (da scaffoldare) +packages/ + shared/ # Tipi e utility di dominio + ui/ # Componenti UI riusabili + db/ # Prisma client (da scaffoldare) + tsconfig/ # tsconfig presets condivisi + eslint-config/ # ESLint config condivisa +docs/ + PRD_KetoPath.docx +``` + +## Script disponibili + +- `pnpm dev` — avvia tutte le app in parallelo +- `pnpm dev:web` / `pnpm dev:api` — avvia singola app +- `pnpm build` — build di produzione +- `pnpm lint` / `pnpm lint:fix` — ESLint +- `pnpm format` / `pnpm format:check` — Prettier +- `pnpm typecheck` — `tsc -b` su tutto il monorepo +- `pnpm test` — Vitest (unit test) +- `pnpm test:e2e` — Playwright (E2E) diff --git a/apps/api/.gitkeep b/apps/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/web/.gitkeep b/apps/web/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/PRD_KetoPath.docx b/docs/PRD_KetoPath.docx new file mode 100644 index 0000000..ac85332 Binary files /dev/null and b/docs/PRD_KetoPath.docx differ diff --git a/package.json b/package.json new file mode 100644 index 0000000..5293a18 --- /dev/null +++ b/package.json @@ -0,0 +1,48 @@ +{ + "name": "ketopath", + "version": "0.0.0", + "private": true, + "description": "KetoPath monorepo — web app per la gestione di chetogenica e digiuno intermittente", + "packageManager": "pnpm@9.12.0", + "engines": { + "node": ">=20.11", + "pnpm": ">=9" + }, + "scripts": { + "dev": "pnpm --parallel --filter \"./apps/*\" dev", + "dev:web": "pnpm --filter @ketopath/web dev", + "dev:api": "pnpm --filter @ketopath/api dev", + "build": "pnpm --filter \"./apps/*\" build", + "start": "pnpm --filter \"./apps/*\" start", + "lint": "eslint . --max-warnings=0", + "lint:fix": "eslint . --fix", + "format": "prettier --write .", + "format:check": "prettier --check .", + "typecheck": "tsc -b", + "test": "pnpm --filter \"./packages/*\" --filter \"./apps/*\" -r --if-present test", + "test:e2e": "pnpm --filter @ketopath/web test:e2e", + "prepare": "husky" + }, + "devDependencies": { + "@types/node": "^20.12.7", + "@typescript-eslint/eslint-plugin": "^7.7.0", + "@typescript-eslint/parser": "^7.7.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "husky": "^9.0.11", + "lint-staged": "^15.2.2", + "prettier": "^3.2.5", + "prettier-plugin-tailwindcss": "^0.5.14", + "typescript": "5.4.5" + }, + "lint-staged": { + "*.{ts,tsx,js,jsx,cjs,mjs}": [ + "eslint --fix --max-warnings=0", + "prettier --write" + ], + "*.{json,md,yml,yaml,css}": [ + "prettier --write" + ] + } +} diff --git a/packages/db/.eslintrc.cjs b/packages/db/.eslintrc.cjs new file mode 100644 index 0000000..2ad14cf --- /dev/null +++ b/packages/db/.eslintrc.cjs @@ -0,0 +1,5 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + extends: ['@ketopath/eslint-config/node.cjs'], +}; diff --git a/packages/db/package.json b/packages/db/package.json new file mode 100644 index 0000000..ebdd467 --- /dev/null +++ b/packages/db/package.json @@ -0,0 +1,19 @@ +{ + "name": "@ketopath/db", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit", + "lint": "eslint src --max-warnings=0" + }, + "devDependencies": { + "@ketopath/eslint-config": "workspace:*", + "@ketopath/tsconfig": "workspace:*" + } +} diff --git a/packages/db/src/index.ts b/packages/db/src/index.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/packages/db/src/index.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json new file mode 100644 index 0000000..5100b45 --- /dev/null +++ b/packages/db/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@ketopath/tsconfig/node.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "composite": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/eslint-config/index.cjs b/packages/eslint-config/index.cjs new file mode 100644 index 0000000..e6c0688 --- /dev/null +++ b/packages/eslint-config/index.cjs @@ -0,0 +1,65 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: false, + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + plugins: ['@typescript-eslint', 'import'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:import/recommended', + 'plugin:import/typescript', + 'prettier', + ], + settings: { + 'import/resolver': { + typescript: { + alwaysTryTypes: true, + }, + node: true, + }, + }, + rules: { + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, + ], + '@typescript-eslint/consistent-type-imports': [ + 'error', + { prefer: 'type-imports', fixStyle: 'inline-type-imports' }, + ], + 'import/order': [ + 'error', + { + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + 'newlines-between': 'always', + alphabetize: { order: 'asc', caseInsensitive: true }, + }, + ], + 'import/no-default-export': 'off', + }, + overrides: [ + { + files: ['*.cjs', '*.config.js', '*.config.mjs'], + env: { node: true }, + rules: { + '@typescript-eslint/no-var-requires': 'off', + }, + }, + ], + ignorePatterns: [ + 'node_modules/', + 'dist/', + 'build/', + '.next/', + 'out/', + 'coverage/', + '*.config.js', + '*.config.cjs', + '*.config.mjs', + ], +}; diff --git a/packages/eslint-config/nextjs.cjs b/packages/eslint-config/nextjs.cjs new file mode 100644 index 0000000..921a567 --- /dev/null +++ b/packages/eslint-config/nextjs.cjs @@ -0,0 +1,8 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: [require.resolve('./index.cjs'), 'next/core-web-vitals'], + rules: { + 'react/no-unescaped-entities': 'off', + '@next/next/no-html-link-for-pages': 'off', + }, +}; diff --git a/packages/eslint-config/node.cjs b/packages/eslint-config/node.cjs new file mode 100644 index 0000000..ccb5b24 --- /dev/null +++ b/packages/eslint-config/node.cjs @@ -0,0 +1,11 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: [require.resolve('./index.cjs')], + env: { + node: true, + es2022: true, + }, + rules: { + 'no-console': ['warn', { allow: ['warn', 'error', 'info'] }], + }, +}; diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json new file mode 100644 index 0000000..9e54eb0 --- /dev/null +++ b/packages/eslint-config/package.json @@ -0,0 +1,14 @@ +{ + "name": "@ketopath/eslint-config", + "version": "0.0.0", + "private": true, + "main": "index.cjs", + "files": [ + "index.cjs", + "nextjs.cjs", + "node.cjs" + ], + "peerDependencies": { + "eslint": "^8.57.0" + } +} diff --git a/packages/shared/.eslintrc.cjs b/packages/shared/.eslintrc.cjs new file mode 100644 index 0000000..2aed780 --- /dev/null +++ b/packages/shared/.eslintrc.cjs @@ -0,0 +1,5 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + extends: ['@ketopath/eslint-config'], +}; diff --git a/packages/shared/package.json b/packages/shared/package.json new file mode 100644 index 0000000..5fb63ef --- /dev/null +++ b/packages/shared/package.json @@ -0,0 +1,19 @@ +{ + "name": "@ketopath/shared", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit", + "lint": "eslint src --max-warnings=0" + }, + "devDependencies": { + "@ketopath/eslint-config": "workspace:*", + "@ketopath/tsconfig": "workspace:*" + } +} diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/packages/shared/src/index.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json new file mode 100644 index 0000000..da4abf6 --- /dev/null +++ b/packages/shared/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@ketopath/tsconfig/base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "composite": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/tsconfig/base.json b/packages/tsconfig/base.json new file mode 100644 index 0000000..f654913 --- /dev/null +++ b/packages/tsconfig/base.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Base", + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ESNext", + "moduleResolution": "Bundler", + "esModuleInterop": true, + "resolveJsonModule": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + + "strict": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + "noImplicitOverride": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "incremental": true + } +} diff --git a/packages/tsconfig/nextjs.json b/packages/tsconfig/nextjs.json new file mode 100644 index 0000000..368cdea --- /dev/null +++ b/packages/tsconfig/nextjs.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Next.js", + "extends": "./base.json", + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "jsx": "preserve", + "allowJs": true, + "noEmit": true, + "plugins": [{ "name": "next" }] + } +} diff --git a/packages/tsconfig/node.json b/packages/tsconfig/node.json new file mode 100644 index 0000000..c946605 --- /dev/null +++ b/packages/tsconfig/node.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Node.js 20", + "extends": "./base.json", + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "types": ["node"] + } +} diff --git a/packages/tsconfig/package.json b/packages/tsconfig/package.json new file mode 100644 index 0000000..1483b34 --- /dev/null +++ b/packages/tsconfig/package.json @@ -0,0 +1,10 @@ +{ + "name": "@ketopath/tsconfig", + "version": "0.0.0", + "private": true, + "files": [ + "base.json", + "nextjs.json", + "node.json" + ] +} diff --git a/packages/ui/.eslintrc.cjs b/packages/ui/.eslintrc.cjs new file mode 100644 index 0000000..2aed780 --- /dev/null +++ b/packages/ui/.eslintrc.cjs @@ -0,0 +1,5 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + extends: ['@ketopath/eslint-config'], +}; diff --git a/packages/ui/package.json b/packages/ui/package.json new file mode 100644 index 0000000..e73e505 --- /dev/null +++ b/packages/ui/package.json @@ -0,0 +1,19 @@ +{ + "name": "@ketopath/ui", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit", + "lint": "eslint src --max-warnings=0" + }, + "devDependencies": { + "@ketopath/eslint-config": "workspace:*", + "@ketopath/tsconfig": "workspace:*" + } +} diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/packages/ui/src/index.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json new file mode 100644 index 0000000..43101dd --- /dev/null +++ b/packages/ui/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@ketopath/tsconfig/base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "composite": true, + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "jsx": "preserve" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..885d597 Binary files /dev/null and b/pnpm-lock.yaml differ diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..e9b0dad --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - 'apps/*' + - 'packages/*' diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2425989 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "files": [], + "references": [ + { "path": "./packages/shared" }, + { "path": "./packages/ui" }, + { "path": "./packages/db" } + ] +}