# CLAUDE.md - LogShip ERP Nuxt Frontend
## Project Overview
**LogShip ERP** is an enterprise resource planning web application built with **Nuxt 3** and **Vue 3 Composition API**. It connects to an **iDempiere** ERP backend via REST API. The app also integrates with Strapi (CMS/media), Laravel, PostgREST, Elasticsearch, DHL, Sendcloud, Shopify, and PlentyOne.
- **App Name:** LogShip WMS / ERP Solutions
- **Company:** LogYou
- **Production URL:** https://app.logship.de
- **Dev URL:** https://dev-app.logship.de
---
## Tech Stack
| Layer | Technology |
|-------|-----------|
| Framework | Nuxt 3.17+ (Vue 3.5+, Composition API, `
```
### Create Page Pattern
```vue
```
---
## Component Patterns
### Form Component Pattern
**Naming:** `components/[domain]/[Entity]Form.vue`
```vue
```
### Action Component Pattern (AG Grid context menu)
**Naming:** `components/[domain]/[Entity]Action.vue`
```vue
```
### Detail Record Tab Pattern
**Naming:** `components/[domain]/[Entity]DetailRecord.vue`
Manages sub-tabs for complex entity views (e.g., Partner → Locations, Bank Accounts, Users).
---
## State Management
**NO Pinia/Vuex.** All state uses Nuxt's `useState()` in `composables/states.ts`:
```typescript
export const useSideBar = () => useState('sideBar', () => false)
export const useTabs = () => useState('tabs', () => [{ link: '/', text: 'Home', active: true }])
export const usePrintPreview = () => useState('printPreview', () => false)
export const usePrintParam = () => useState('printParam', () => {})
// ... 33 total state composables
```
**State persistence strategy:**
- **Cookies:** Auth data, user, org, role, language (persistent, cross-tab)
- **localStorage:** Theme (`logship_theme`), language (`logship_lang`), tabs, scanner preference
- **sessionStorage:** Detail record active tab
- **useState:** UI runtime state (sidebar, modals, active menus)
---
## Data Fetching
### Client-side (pages/components)
```typescript
// SSR-safe initial data load
const { data, pending, error, refresh } = await useFetch('/api/endpoint', {
headers: useRequestHeaders(['cookie']) // ALWAYS include cookies for auth
})
// Client-side mutations
const res = await $fetch('/api/endpoint', {
method: 'POST',
headers: useRequestHeaders(['cookie']),
body: { /* data */ }
})
```
### Server-side (API routes)
```typescript
// Using fetchHelper (for iDempiere)
const res = await fetchHelper(event, 'models/c_bpartner?$filter=...', 'GET', token, null)
// Using event.context.fetch (middleware-provided, auto-handles cookies)
const res = await event.context.fetch('models/c_bpartner?$filter=...', 'GET', token, null)
// Other backend helpers
const res = await postgrestHelper(event, '/rpc/function_name', 'POST', body)
const res = await strapiHelper(event, 'endpoint', 'GET', null)
const res = await laravelHelper(event, 'api/endpoint', 'POST', body)
const res = await elasticHelper(event, 'index/_search', 'POST', body)
```
---
## Layouts
| Layout | Usage | Components |
|--------|-------|-----------|
| `app` | Default authenticated pages | NavBar + SideBar + TabBar + Footer |
| `admin` | Admin panel | NavBarAdmin + SideBarAdmin |
| `org` | Organization selection | NavBarOrg + SideBarOrg |
| `auth` / `new-auth` | Login/register pages | Centered form |
| `mobile` | Mobile routes (`/mobile/*`) | Portrait-locked, landscape warning |
| `tracking` | Public tracking page | Minimal layout |
| `new-dash` | New dashboard | TopMegaBar + NewSideBar + MainNavigationMenu |
**Usage in pages:**
```typescript
definePageMeta({ layout: 'admin' })
```
---
## Middleware
- **`auth.ts`** — Checks `/api/idempiere-auth/authenticated`; redirects to `/signin` if not authenticated. Mobile pages fall back to cookie check on network errors.
- **`guest.ts`** — Redirects authenticated users away from signin/register pages.
- **`org.ts`** — Organization context check (currently disabled/commented out).
**Page usage:**
```typescript
definePageMeta({ middleware: ['auth', 'org'] })
```
---
## Styling Conventions
- **Primary CSS:** Bulma classes (`field`, `label`, `input`, `button is-primary`, `columns`, `column`)
- **Theme variables:** `--theme-bg-primary`, `--theme-bg-secondary`, `--theme-text-primary`, `--theme-border`, etc.
- **Dark mode:** CSS variables switch values; classes `.dark` / `[data-mode="dark"]`
- **Scoped styles:** Use `