Javis OS
Javis OS는 기업가를 돕는 에이전시 AI로, 업무를 지원하고 함께 성장합니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Next.js frontend for the Klever Tracker GPS fleet platform. It talks to the existing Klever Tracker GraphQL API (Laravel + Lighthouse).
../implementation-plan.md, Phase 1 (Foundation, Auth & Users)../api-alignment.md../design.md, ../ui-demo.htmlRequires Node.js 24+.
npm install
cp .env.example .env.local # then edit
npm run dev # http://localhost:3000
The real API currently sits behind an HTTP basic-auth lock (api-alignment.md B1). For sign-in, forgot and reset password, put that lock's credentials in KLEVER_BASIC_AUTH_USER / KLEVER_BASIC_AUTH_PASSWORD. They're sent only on requests without a login token, because the lock and the token share the Authorization header. Requests made after sign-in carry the token instead, so they stay blocked until the backend team removes the lock or switches it to an IP allow-list. Without credentials, set KLEVER_MOCK=true to develop against the built-in mock. Sign in with [email protected] / Demo@12345. The reset-password mock link is /en/reset-password?token=demo-reset-token&[email protected]. The mock is ignored in production builds.
| Command | What it does |
|---|---|
npm run dev | Dev server |
npm run build / npm start | Production build and server |
npm run lint | ESLint |
npm run typecheck | Generate route types, then tsc --noEmit |
npm test | Unit tests (Vitest) |
npm run test:e2e | End-to-end tests (Playwright, against the mock API) |
npm run codegen | Typed GraphQL documents from schema.graphql (once the backend shares it, B2) |
The Klever API issues a bearer token that never expires. The browser never sees it:
src/lib/auth/actions.ts). It calls the login mutation and stores the token in an HttpOnly, SameSite=Lax cookie (Secure in production)./api/graphql on the same origin (src/app/api/graphql/route.ts). The handler checks the Origin header, reads the cookie, adds Authorization: Bearer … and forwards the request to Klever.kleverRequest() (src/lib/graphql/klever.ts).src/proxy.ts (Next.js 16's renamed middleware) sends signed-out visitors to /[locale]/login?next=…. It only checks that the cookie exists; the API authorises every request.Unauthenticated. response clears the cookie and sends the user back to login.Logout clears the cookie. It can't revoke the token on the server until the backend adds a logout mutation (B4).
/heatmap)Shows where one or more vehicles spent their time over a period of up to 31 days (at most 50 vehicles).
The Klever API has no aggregate query, so the Next.js server builds the heatmap. GET /api/heatmap (src/app/api/heatmap/route.ts) validates the query (src/lib/heatmap/request.ts). It checks every vehicle against the company's own vehicles / devices lists, because Klever scopes by token. Then it pages through positionHistory 1,000 fixes at a time and aggregates on the server (src/lib/heatmap/service.ts, aggregate.ts). The browser only receives { total_points, cell_count, bounds, cells: [{ lat, lng, weight }] }, capped at 5,000 cells. Fixes are cached per session for 5 minutes, so zooming re-aggregates without calling Klever again. Selections over 300,000 points get a 422 asking for a shorter period.
Before weighting, the server drops bad fixes: missing coordinates, (0,0), and single-fix jumps that would need more than 300 km/h. Points are snapped to a grid of about 8 screen pixels at the current zoom. Each cell returns the centroid of its points and the sum of their weights.
| Weight mode | Weight of each GPS fix | Good for |
|---|---|---|
density | 1 | Where the vehicle reported most. Busy roads show up as much as stops, because trackers report more often while moving. |
dwell | Seconds until that vehicle's next fix (SQL: LEAD(recorded_at) OVER (PARTITION BY vehicle ORDER BY recorded_at)), capped at 30 minutes | Where the vehicle actually spent its time. The cap stops a tracker that was offline or asleep for hours from creating a fake hotspot at its last position. |
idle | Same as dwell, but only for fixes with ignition on and speed below 3 km/h | Engine-on waiting: queues, drop-offs with the engine running, idling at sites. |
The map is Google Maps (@vis.gl/react-google-maps) with a deck.gl HeatmapLayer through GoogleMapsOverlay, not the deprecated google.maps.visualization.HeatmapLayer. The map refetches when the zoom settles on a level with a different grid size (debounced by 500 ms).
In mock mode (KLEVER_MOCK=true), src/lib/heatmap/demo-tracks.ts generates repeatable routes for vehicles 1–3 across Dubai and Sharjah from 1 September 2026 onward. They include parking and idling stops, traffic crawls, a three-hour device-offline gap (vehicle 2) and a few bad fixes (vehicle 3).
Not available yet: a company picker for platform staff (the API has no cross-company scope, A1). Passing company_id returns a 422.
src/
app/
[locale]/ root layout (en | ar, sets dir), fonts, providers
(auth)/ login, forgot-password, reset-password
(app)/ signed-in shell (sidebar + top bar), dashboard
api/graphql/route.ts same-origin GraphQL proxy (BFF)
components/ ui/ primitives (shadcn/ui style), shell/, theme and locale switches
i18n/ next-intl routing, navigation, request config
lib/
auth/ Server Actions and Zod schemas
graphql/ server client, browser client, error mapping, operations, mock
session.ts cookie helpers (server only)
proxy.ts locale routing + optimistic auth redirect
messages/en.json, ar.json all UI text
e2e/ Playwright tests
<Suspense>. Read node_modules/next/dist/docs/ before using an API you haven't used in this version.next/root-params ([locale] is the root segment). Use Link, useRouter and redirect from @/i18n/navigation.src/app/globals.css. Use logical utilities (ms-, pe-, start-) so layouts flip for Arabic.{ data, paginatorInfo }; relations are plain IDs; JSON fields are strings; timestamps are UTC; another company's row returns null; a permission block returns "Forbidden.".classifyGraphQLErrors / classifyHttpResponse and are shown with the errors.* messages.