Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ MONGODB_DATABASE=kalori_db
# ===================
# Logto Auth (Local Development)
# ===================
LOGTO_ENDPOINT=http://localhost:3301
LOGTO_ADMIN_ENDPOINT=http://localhost:3302
LOGTO_PORT=3301
LOGTO_ADMIN_PORT=3302
LOGTO_ENDPOINT=http://localhost:3001
LOGTO_ADMIN_ENDPOINT=http://localhost:3002

# Logto App Credentials (from Admin Console)
LOGTO_APP_ID=
LOGTO_APP_SECRET=

# Logto Database (Postgres - Local)
LOGTO_DB_USER=logto
Expand All @@ -25,7 +27,12 @@ LOGTO_DB_NAME=logto
# ===================
NEXT_PUBLIC_API_URL=http://localhost:4000
BACKEND_PORT=4000
BACKEND_BASE_URL=http://localhost:4000
FRONTEND_PORT=3000
FRONTEND_URL=http://localhost:3000

# Session Secret (for express-session)
SESSION_SECRET=

# ============================================
# PRODUCTION (VPS 72.62.74.47) - Copy to .env.production
Expand All @@ -38,8 +45,8 @@ FRONTEND_PORT=3000
# MONGODB_DATABASE=kalori_db

# Logto Production (logto-auth on Coolify)
# LOGTO_ENDPOINT=http://logto-dkgs8kco00440g4cg4goksoc.72.62.74.47.sslip.io
# LOGTO_ADMIN_ENDPOINT=http://logto-admin-dkgs8kco00440g4cg4goksoc.72.62.74.47.sslip.io
# LOGTO_ENDPOINT=
# LOGTO_ADMIN_ENDPOINT=
# LOGTO_DB_USER=zen0
# LOGTO_DB_NAME=logto
# LOGTO_DB_PASSWORD=<your-logto-password>
20 changes: 20 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dependencies
node_modules

# Build outputs
dist
.next
build
coverage

# Turbo
.turbo

# Lock files
pnpm-lock.yaml
package-lock.json
yarn.lock

# Generated files
*.min.js
*.min.css
12 changes: 12 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"semi": true,
"trailingComma": "es5",
"singleQuote": false,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "always",
"endOfLine": "lf"
}
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,13 @@ The app is deployed using [Coolify](https://coolify.io/) to a self-hosted server
1. Fork the repository
2. Create branch from `dev` (not `main`)
3. Make your changes
4. Run `pnpm typecheck` to verify
5. Submit PR to `dev` branch
6. Wait for review
4. **Run `pnpm lint:fix` to auto-fix issues**
5. Run `pnpm typecheck` to verify types
6. Submit PR to `dev` branch
7. Wait for review

> [!TIP]
> See [docs/linting.md](docs/linting.md) for full linting guide.

### Commit Convention

Expand Down
6 changes: 2 additions & 4 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,11 @@ services:
container_name: kal-logto
entrypoint: ["sh", "-c", "npm run cli db seed -- --swe && npm start"]
ports:
- "${LOGTO_PORT:-3301}:3001"
- "${LOGTO_ADMIN_PORT:-3302}:3002"
- "3001:3001"
- "3002:3002"
environment:
- TRUST_PROXY_HEADER=1
- DB_URL=postgres://${LOGTO_DB_USER}:${LOGTO_DB_PASSWORD}@postgres:5432/${LOGTO_DB_NAME}
- ENDPOINT=${LOGTO_ENDPOINT}
- ADMIN_ENDPOINT=${LOGTO_ADMIN_ENDPOINT}
depends_on:
postgres:
condition: service_healthy
Expand Down
81 changes: 81 additions & 0 deletions docs/linting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Linting & Code Formatting

This monorepo uses **ESLint** for linting and **Prettier** for code formatting.

## Quick Commands

```bash
# Check for lint issues
pnpm lint

# Auto-fix lint issues
pnpm lint:fix

# Format all files with Prettier
pnpm format

# Check formatting without fixing
pnpm format:check
```

## Before Pushing Code

> [!IMPORTANT]
> **Always run `pnpm lint:fix` before pushing your changes!**

```bash
# 1. Auto-fix lint issues
pnpm lint:fix

# 2. Format code
pnpm format

# 3. Verify build
pnpm build
```

## What Gets Auto-Fixed

| Issue | Auto-fixable |
| ----------------------- | ------------- |
| Import ordering | ✅ Yes |
| Duplicate imports | ✅ Yes |
| Consistent type imports | ✅ Yes |
| Code formatting | ✅ Yes |
| Unused variables | ❌ Manual fix |
| Type errors | ❌ Manual fix |

## Configuration Files

| File | Purpose |
| ------------------- | --------------------------- |
| `eslint.config.mjs` | ESLint rules (flat config) |
| `.prettierrc` | Prettier formatting options |
| `.prettierignore` | Files to skip formatting |

## VS Code Integration

For auto-fix on save, add to `.vscode/settings.json`:

```json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}
```

Recommended extensions:

- **ESLint** (`dbaeumer.vscode-eslint`)
- **Prettier** (`esbenp.prettier-vscode`)

## Package-Specific Linting

```bash
# Lint a specific package
pnpm --filter kal-frontend lint
pnpm --filter kal-backend lint:fix
```
202 changes: 202 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import eslint from "@eslint/js";
import tseslint from "@typescript-eslint/eslint-plugin";
import tsparser from "@typescript-eslint/parser";
import importPlugin from "eslint-plugin-import";
import reactPlugin from "eslint-plugin-react";
import reactHooksPlugin from "eslint-plugin-react-hooks";
import prettierConfig from "eslint-config-prettier";
import globals from "globals";

export default [
// Global ignores
{
ignores: [
"**/node_modules/**",
"**/dist/**",
"**/.next/**",
"**/build/**",
"**/.turbo/**",
"**/coverage/**",
"**/*.config.js",
"**/*.config.mjs",
"**/*.config.cjs",
"**/migrate-mongo-config.js",
"**/migrate-mongo-config.cjs",
"**/migrations/**/*.js",
"**/postcss.config.js",
"**/tailwind.config.ts",
],
},

// Base ESLint recommended rules
eslint.configs.recommended,

// TypeScript files configuration (backend/shared - Node.js)
{
files: [
"packages/kal-backend/**/*.ts",
"packages/kal-db/**/*.ts",
"packages/kal-shared/**/*.ts",
],
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
globals: {
...globals.node,
...globals.es2021,
},
},
plugins: {
"@typescript-eslint": tseslint,
import: importPlugin,
},
rules: {
// TypeScript rules
"@typescript-eslint/no-unused-vars": [
"warn",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/consistent-type-imports": [
"warn",
{ prefer: "type-imports" },
],

// General rules
"no-console": "off",
"no-debugger": "warn",
"no-unused-vars": "off",

// Import rules
"import/order": [
"warn",
{
groups: [
"builtin",
"external",
"internal",
"parent",
"sibling",
"index",
],
"newlines-between": "always",
alphabetize: { order: "asc", caseInsensitive: true },
},
],
"import/no-duplicates": "warn",
},
},

// React/Next.js TypeScript files (frontend)
{
files: ["packages/kal-frontend/**/*.ts", "packages/kal-frontend/**/*.tsx"],
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
globals: {
...globals.browser,
...globals.node,
...globals.es2021,
React: "readonly",
},
},
plugins: {
"@typescript-eslint": tseslint,
import: importPlugin,
react: reactPlugin,
"react-hooks": reactHooksPlugin,
},
settings: {
react: {
version: "detect",
},
},
rules: {
// TypeScript rules
"@typescript-eslint/no-unused-vars": [
"warn",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/consistent-type-imports": [
"warn",
{ prefer: "type-imports" },
],

// General rules
"no-console": ["warn", { allow: ["warn", "error", "info"] }],
"no-debugger": "warn",
"no-unused-vars": "off",

// React rules
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
"react/jsx-uses-react": "off",
"react/jsx-uses-vars": "error",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",

// Import rules
"import/order": [
"warn",
{
groups: [
"builtin",
"external",
"internal",
"parent",
"sibling",
"index",
],
"newlines-between": "always",
alphabetize: { order: "asc", caseInsensitive: true },
},
],
"import/no-duplicates": "warn",
},
},

// JavaScript files configuration
{
files: ["**/*.js", "**/*.mjs", "**/*.cjs"],
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
globals: {
...globals.node,
...globals.browser,
...globals.es2021,
},
},
rules: {
"no-unused-vars": [
"warn",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
},
],
"no-console": "off",
},
},

// Disable formatting rules (handled by Prettier)
prettierConfig,
];
Loading