Native Shell
Native Shell은 모든 플랫폼의 앱 안에서 만들어지는 AI UI입니다
Nuxt UI 기반 전문 대시보드 템플릿으로 다중 페이지·데이터 시각화·포괄적 관리 기능을 제공해 강력한 관리자 인터페이스를 만들 수 있습니다
A professional dashboard template built with Nuxt UI, featuring multiple pages, data visualization, and comprehensive management capabilities for creating powerful admin interfaces.
개발 도구TypeScript · VueGitHub @adme-dev온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기XeroFlow Agency — internal operations dashboard for digital marketing agencies. Work management, client portal, Xero financials, ad spend tracking, real-time chat, and AI-powered insights. Built with Nuxt 4, Nuxt UI v4, Neon Postgres, and Cloudflare.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Internal operations dashboard for a digital marketing agency. Manages work (boards, Kanban, timeline, calendar), clients, projects, financials (Xero integration, EOM invoicing, ad spend tracking), real-time chat, AI-powered insights, and a client portal.
CRM hybrid search release operations are fail closed. Commands default to preview, require Node 24.18.0 and a clean frozen artifact, and verify signed environment resource readback before any release action. Production resource provisioning, migration, dormant deployment, client indexing, shadow, and assist are six separate approvals. See CRM search staged rollout; Task 18 tooling is dry-run only and does not deploy or provision resources.
<script setup>, TypeScript)@iconify-json/lucide@internationalized/date@neondatabase/serverless)xero-node) — accounting integrationnitro.preset: 'cloudflare_pages')@cf/meta/llama-3.1-8b-instruct)app/
components/ # Auto-imported Vue components (nested folders become prefixes)
composables/ # Auto-imported composables (useFetch, useAuth, useChat, etc.)
layouts/ # Page layouts (agency.vue, portal.vue)
middleware/ # Route middleware (auth.global.ts, portal-auth.ts)
pages/ # File-based routing
agency/ # Staff-facing pages (boards, clients, chat, AI, time tracking)
portal/ # Client portal pages (projects, approvals, invoices)
auth/ # Authentication pages
types/ # TypeScript types (index.ts for runtime, index.d.ts for extended)
server/
api/
agency/ # Staff API endpoints (JWT auth via requireAuth)
portal/ # Client API endpoints (cookie auth via requireClientAuth)
database/
schema*.sql # Base schema files (~28 domain schemas)
migrations/ # Numbered migrations (001–025)
utils/ # Server utilities (db.ts, auth.ts, clientAuth.ts, etc.)
workers/
ai-agent-worker/ # Proactive AI analysis worker
board-events/ # BoardRoom Durable Object (real-time board collaboration)
chat-rooms/ # ChatRoom Durable Object (real-time chat)
email-worker/ # Inbound email processing (Cloudflare Email Routing)
agency-workflows/ # Durable Cloudflare Workflows orchestration
.nvmrc)git clone https://github.com/adme-dev/dashboard.git
cd dashboard
pnpm install
cp .env.example .env
Populate .env with the values described below.
| Variable | Description |
|---|---|
DATABASE_URL | Neon Postgres connection string |
XERO_CLIENT_ID | OAuth client ID from Xero developer portal |
XERO_CLIENT_SECRET | OAuth client secret |
XERO_REDIRECT_URI | Callback path (/api/xero/callback) |
SESSION_SECRET | Random string for cookie/session signing |
GROQ_API | Groq API key for AI features |
RESEND_API_KEY | Resend API key for transactional email |
EMAIL_FROM | Sender address for outbound email |
APP_URL | Application URL (http://localhost:3000 for dev) |
Optional variables for Cloudflare services (R2, KV, Queues, AI, Vectorize) are documented in .env.example. Local dev works without them via graceful degradation.
Run the base schema followed by migrations against your Neon database:
# Run base schema (start with schema.sql, then domain schemas as needed)
psql $DATABASE_URL -f server/database/schema.sql
# Run migrations in order
psql $DATABASE_URL -f server/database/migrations/001-board-groups.sql
# ... through 025-ai-chat-pins.sql
pnpm dev
The app starts on http://localhost:3000. Cloudflare bindings (KV, Queues, AI, Vectorize, Durable Objects) are optional in dev — features degrade gracefully when unavailable.
| Command | Description |
|---|---|
pnpm dev | Start dev server on port 3000 |
pnpm build | Production build (uses --max-old-space-size=8192) |
pnpm preview | Preview production build locally |
pnpm test | Run Vitest tests |
pnpm lint | Lint with ESLint |
pnpm typecheck | Run Nuxt type checking |
pnpm graphify:rebuild | Rebuild local Graphify architecture artifacts |
pnpm readiness:agency-workflows | Run Workflows cutover readiness checks |
The project is configured for Cloudflare Pages via wrangler.toml.
Connect the repo in the Cloudflare dashboard under Workers & Pages > Create > Pages > Connect to Git.
Set build command to pnpm build and output directory to dist.
Add environment variables in Settings > Variables and Secrets for both preview and production.
Cloudflare bindings (KV, Queues, AI, Vectorize, Durable Objects) are configured in wrangler.toml.
To deploy from the CLI, use the guarded repository command:
pnpm deploy:production
Do not run a raw wrangler pages deploy command from this repository. The guarded command verifies that both the repository configuration and deployment target are exactly agency-dashboard; it refuses any other Pages project. See the Pages cross-deployment incident.
# KV namespace for caching
npx wrangler kv namespace create CACHE
# Queue for background jobs
npx wrangler queues create agency-jobs
npx wrangler queues create agency-jobs-dlq
# Vectorize index for semantic search
npx wrangler vectorize create agency-search --dimensions=768 --metric=cosine
Durable Objects (ChatRoom, BoardRoom) are deployed as separate workers under workers/.
Each worker under workers/ has its own wrangler.toml and deploys independently:
cd workers/chat-rooms && npx wrangler deploy
cd workers/board-events && npx wrangler deploy
cd workers/email-worker && npx wrangler deploy
cd workers/ai-agent-worker && npx wrangler deploy
requireAuth(event) — returns User or throws 401. Use requireRole(event, ['admin', 'owner']) for RBAC.client_session_token) via requireClientAuth(event) — returns ServerClientUser with .clientId and .permissions.server/api/agency/, client endpoints under server/api/portal/.// Typical API endpoint
export default defineEventHandler(async (event) => {
const user = await requireAuth(event)
const id = getRouterParam(event, 'id')
const body = await readBody(event)
const query = getQuery(event)
const rows = await queryRows('SELECT ...', [id])
return rows
})
Server utilities use the Nitro double-tilde alias:
import { queryRows } from '~~/server/utils/db' // correct
import { queryRows } from '~/server/utils/db' // wrong
// Reads (reactive, SSR-compatible)
const { data } = await useFetch('/api/agency/tasks')
// Mutations
await $fetch('/api/agency/tasks', { method: 'POST', body: { ... } })
// User feedback
const toast = useToast()
toast.add({ title: 'Saved', color: 'success' })
Types must be defined in app/types/index.ts (not .d.ts) to be importable at runtime. TypeScript resolves .ts over .d.ts.
nuxi build can crash with memory exhaustion. The build script already uses --max-old-space-size=8192 but may still fail on constrained machines.index.d.ts instead of index.ts. Running pnpm typecheck will surface these — they don't block the build.Originally based on the Nuxt UI Dashboard template. Extended and maintained by the ADME engineering group.