feat: Full project management application scaffold
Complete architecture for a ClickUp/Notion/Miro-class project management app:
- Turborepo monorepo with Next.js 15, TypeScript, PostgreSQL (Drizzle ORM)
- Object-centered database schema (everything is an Object: tasks, projects, docs, whiteboards)
- NextAuth v5 authentication with credentials + OAuth providers
- tRPC v11 API layer with full CRUD for objects, properties, relations, templates, search
- Three-panel UI: collapsible sidebar, center content area, push-in right panel
- Purple/teal theme with light/dark mode via Shadcn/ui + Tailwind CSS
- Multiple views: List, Kanban board (dnd-kit), Table (spreadsheet), Embedded iframe
- TipTap rich text editor with slash commands, custom blocks (callout, toggle, mention, embed, divider), AI block
- Real-time collaboration via Yjs + Hocuspocus with presence/cursors
- tldraw whiteboard with custom shape cards (task, document, project)
- MCP server exposing all app data/tools for AI agents
- AI chat panel, editor AI slash commands, Cmd+K command palette
- Template system with built-in templates (Bug Report, Meeting Notes, Sprint)
- Full-text search with result highlighting
- Docker Compose for full-stack deployment (web + collab + postgres + redis)
Made-with: Cursor
2026-03-26 23:39:16 -04:00
|
|
|
"use client";
|
|
|
|
|
|
feat: ECHODO app shell, Coolify deploy, Authentik + Umami
Bundles in-flight ECHODO work with the Coolify deployment configuration:
App
- New routes: ai, forms, planner, settings (templates/types), teams,
doc detail, whiteboard detail
- New components: app shell rework (icon-rail, top-header), forms
builder/renderer/responses, types manager, objects creation dialog,
card primitive, form + overview views
- New tRPC routers: favorites, forms, types, workspaces; updates to
health and objects routers
- Markdown backlog sync (packages/database) + cursor-sync schema/migrations
- Schema additions: forms, types, favorites, markdown_backlog, cursor_sync
- Initial Drizzle migrations checked in
Deployment
- docker/docker-compose.coolify.yml: drops bundled Postgres/Redis
(uses CT 102 shared services), removes host port mappings, adds
Coolify SERVICE_FQDN_* magic vars for web + collab
- .env.example rewritten as the full ECHODO/Coolify variable manifest
- NextAuth gains an Authentik OIDC provider (gated on env presence)
- Root layout injects Umami tracking script when configured;
metadata title flipped to ECHODO
Security
- .gitignore expanded to exclude AGENT-DEPLOY.md, .env.*, secrets/,
credentials.*, *.key, *.crt, *.pem, ssh keys
Made-with: Cursor
2026-04-26 15:34:34 -04:00
|
|
|
import { useMemo } from "react";
|
|
|
|
|
|
|
|
|
|
import { api } from "@/lib/trpc";
|
feat: Full project management application scaffold
Complete architecture for a ClickUp/Notion/Miro-class project management app:
- Turborepo monorepo with Next.js 15, TypeScript, PostgreSQL (Drizzle ORM)
- Object-centered database schema (everything is an Object: tasks, projects, docs, whiteboards)
- NextAuth v5 authentication with credentials + OAuth providers
- tRPC v11 API layer with full CRUD for objects, properties, relations, templates, search
- Three-panel UI: collapsible sidebar, center content area, push-in right panel
- Purple/teal theme with light/dark mode via Shadcn/ui + Tailwind CSS
- Multiple views: List, Kanban board (dnd-kit), Table (spreadsheet), Embedded iframe
- TipTap rich text editor with slash commands, custom blocks (callout, toggle, mention, embed, divider), AI block
- Real-time collaboration via Yjs + Hocuspocus with presence/cursors
- tldraw whiteboard with custom shape cards (task, document, project)
- MCP server exposing all app data/tools for AI agents
- AI chat panel, editor AI slash commands, Cmd+K command palette
- Template system with built-in templates (Bug Report, Meeting Notes, Sprint)
- Full-text search with result highlighting
- Docker Compose for full-stack deployment (web + collab + postgres + redis)
Made-with: Cursor
2026-03-26 23:39:16 -04:00
|
|
|
|
|
|
|
|
export type SortDirection = "asc" | "desc";
|
|
|
|
|
|
|
|
|
|
export interface ViewFilter {
|
|
|
|
|
field: string;
|
|
|
|
|
operator: "eq" | "neq" | "contains" | "gt" | "lt" | "in" | "isEmpty" | "isNotEmpty";
|
|
|
|
|
value: unknown;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ViewSort {
|
|
|
|
|
field: string;
|
|
|
|
|
direction: SortDirection;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ViewConfig {
|
|
|
|
|
filters: ViewFilter[];
|
|
|
|
|
sorts: ViewSort[];
|
|
|
|
|
groupBy: string | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ViewObject {
|
|
|
|
|
id: string;
|
|
|
|
|
type: string;
|
|
|
|
|
title: string;
|
|
|
|
|
status: string | null;
|
|
|
|
|
icon: string | null;
|
|
|
|
|
sortOrder: number;
|
|
|
|
|
parentId: string | null;
|
|
|
|
|
createdAt: string;
|
|
|
|
|
updatedAt: string;
|
|
|
|
|
assignees?: { user: { id: string; name: string | null; avatarUrl: string | null } }[];
|
|
|
|
|
propertyValues?: { propertyDefinition: { id: string; name: string; fieldType: string }; value: unknown }[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applyFilters(objects: ViewObject[], filters: ViewFilter[]): ViewObject[] {
|
|
|
|
|
return objects.filter((obj) =>
|
|
|
|
|
filters.every((f) => {
|
|
|
|
|
const val = f.field === "status" ? obj.status : f.field === "title" ? obj.title : null;
|
|
|
|
|
if (f.operator === "eq") return val === f.value;
|
|
|
|
|
if (f.operator === "neq") return val !== f.value;
|
|
|
|
|
if (f.operator === "contains" && typeof val === "string" && typeof f.value === "string")
|
|
|
|
|
return val.toLowerCase().includes(f.value.toLowerCase());
|
|
|
|
|
if (f.operator === "isEmpty") return !val;
|
|
|
|
|
if (f.operator === "isNotEmpty") return !!val;
|
|
|
|
|
return true;
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getField(obj: ViewObject, field: string): unknown {
|
|
|
|
|
return (obj as unknown as Record<string, unknown>)[field];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applySorts(objects: ViewObject[], sorts: ViewSort[]): ViewObject[] {
|
|
|
|
|
if (sorts.length === 0) return objects;
|
|
|
|
|
return [...objects].sort((a, b) => {
|
|
|
|
|
for (const s of sorts) {
|
|
|
|
|
const aVal = getField(a, s.field) ?? "";
|
|
|
|
|
const bVal = getField(b, s.field) ?? "";
|
|
|
|
|
const cmp = String(aVal).localeCompare(String(bVal));
|
|
|
|
|
if (cmp !== 0) return s.direction === "asc" ? cmp : -cmp;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applyGroupBy(objects: ViewObject[], groupBy: string | null): Record<string, ViewObject[]> {
|
|
|
|
|
if (!groupBy) return { "All Items": objects };
|
|
|
|
|
const groups: Record<string, ViewObject[]> = {};
|
|
|
|
|
for (const obj of objects) {
|
|
|
|
|
const key = String(getField(obj, groupBy) ?? "No Value");
|
|
|
|
|
if (!groups[key]) groups[key] = [];
|
|
|
|
|
groups[key].push(obj);
|
|
|
|
|
}
|
|
|
|
|
return groups;
|
|
|
|
|
}
|
|
|
|
|
|
feat: ECHODO app shell, Coolify deploy, Authentik + Umami
Bundles in-flight ECHODO work with the Coolify deployment configuration:
App
- New routes: ai, forms, planner, settings (templates/types), teams,
doc detail, whiteboard detail
- New components: app shell rework (icon-rail, top-header), forms
builder/renderer/responses, types manager, objects creation dialog,
card primitive, form + overview views
- New tRPC routers: favorites, forms, types, workspaces; updates to
health and objects routers
- Markdown backlog sync (packages/database) + cursor-sync schema/migrations
- Schema additions: forms, types, favorites, markdown_backlog, cursor_sync
- Initial Drizzle migrations checked in
Deployment
- docker/docker-compose.coolify.yml: drops bundled Postgres/Redis
(uses CT 102 shared services), removes host port mappings, adds
Coolify SERVICE_FQDN_* magic vars for web + collab
- .env.example rewritten as the full ECHODO/Coolify variable manifest
- NextAuth gains an Authentik OIDC provider (gated on env presence)
- Root layout injects Umami tracking script when configured;
metadata title flipped to ECHODO
Security
- .gitignore expanded to exclude AGENT-DEPLOY.md, .env.*, secrets/,
credentials.*, *.key, *.crt, *.pem, ssh keys
Made-with: Cursor
2026-04-26 15:34:34 -04:00
|
|
|
export function useViewData(
|
|
|
|
|
config: ViewConfig,
|
|
|
|
|
workspaceId?: string,
|
|
|
|
|
parentId?: string | null,
|
|
|
|
|
) {
|
|
|
|
|
const { data, isLoading: queryLoading } = api.objects.list.useQuery(
|
|
|
|
|
{ workspaceId: workspaceId!, parentId: parentId ?? undefined, limit: 200 },
|
|
|
|
|
{ enabled: Boolean(workspaceId) },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const objects: ViewObject[] = useMemo(() => {
|
|
|
|
|
if (!data?.objects) return [];
|
|
|
|
|
return data.objects.map((row) => ({
|
|
|
|
|
id: row.id,
|
|
|
|
|
type: row.type,
|
|
|
|
|
title: row.title,
|
|
|
|
|
status: row.status,
|
|
|
|
|
icon: row.icon,
|
|
|
|
|
sortOrder: row.sortOrder,
|
|
|
|
|
parentId: row.parentId,
|
|
|
|
|
createdAt:
|
|
|
|
|
row.createdAt instanceof Date ? row.createdAt.toISOString() : String(row.createdAt),
|
|
|
|
|
updatedAt:
|
|
|
|
|
row.updatedAt instanceof Date ? row.updatedAt.toISOString() : String(row.updatedAt),
|
|
|
|
|
}));
|
|
|
|
|
}, [data?.objects]);
|
feat: Full project management application scaffold
Complete architecture for a ClickUp/Notion/Miro-class project management app:
- Turborepo monorepo with Next.js 15, TypeScript, PostgreSQL (Drizzle ORM)
- Object-centered database schema (everything is an Object: tasks, projects, docs, whiteboards)
- NextAuth v5 authentication with credentials + OAuth providers
- tRPC v11 API layer with full CRUD for objects, properties, relations, templates, search
- Three-panel UI: collapsible sidebar, center content area, push-in right panel
- Purple/teal theme with light/dark mode via Shadcn/ui + Tailwind CSS
- Multiple views: List, Kanban board (dnd-kit), Table (spreadsheet), Embedded iframe
- TipTap rich text editor with slash commands, custom blocks (callout, toggle, mention, embed, divider), AI block
- Real-time collaboration via Yjs + Hocuspocus with presence/cursors
- tldraw whiteboard with custom shape cards (task, document, project)
- MCP server exposing all app data/tools for AI agents
- AI chat panel, editor AI slash commands, Cmd+K command palette
- Template system with built-in templates (Bug Report, Meeting Notes, Sprint)
- Full-text search with result highlighting
- Docker Compose for full-stack deployment (web + collab + postgres + redis)
Made-with: Cursor
2026-03-26 23:39:16 -04:00
|
|
|
|
|
|
|
|
const processed = useMemo(() => {
|
|
|
|
|
let result = applyFilters(objects, config.filters);
|
|
|
|
|
result = applySorts(result, config.sorts);
|
|
|
|
|
const grouped = applyGroupBy(result, config.groupBy);
|
|
|
|
|
return { items: result, grouped };
|
|
|
|
|
}, [objects, config]);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
items: processed.items,
|
|
|
|
|
grouped: processed.grouped,
|
feat: ECHODO app shell, Coolify deploy, Authentik + Umami
Bundles in-flight ECHODO work with the Coolify deployment configuration:
App
- New routes: ai, forms, planner, settings (templates/types), teams,
doc detail, whiteboard detail
- New components: app shell rework (icon-rail, top-header), forms
builder/renderer/responses, types manager, objects creation dialog,
card primitive, form + overview views
- New tRPC routers: favorites, forms, types, workspaces; updates to
health and objects routers
- Markdown backlog sync (packages/database) + cursor-sync schema/migrations
- Schema additions: forms, types, favorites, markdown_backlog, cursor_sync
- Initial Drizzle migrations checked in
Deployment
- docker/docker-compose.coolify.yml: drops bundled Postgres/Redis
(uses CT 102 shared services), removes host port mappings, adds
Coolify SERVICE_FQDN_* magic vars for web + collab
- .env.example rewritten as the full ECHODO/Coolify variable manifest
- NextAuth gains an Authentik OIDC provider (gated on env presence)
- Root layout injects Umami tracking script when configured;
metadata title flipped to ECHODO
Security
- .gitignore expanded to exclude AGENT-DEPLOY.md, .env.*, secrets/,
credentials.*, *.key, *.crt, *.pem, ssh keys
Made-with: Cursor
2026-04-26 15:34:34 -04:00
|
|
|
isLoading: queryLoading,
|
feat: Full project management application scaffold
Complete architecture for a ClickUp/Notion/Miro-class project management app:
- Turborepo monorepo with Next.js 15, TypeScript, PostgreSQL (Drizzle ORM)
- Object-centered database schema (everything is an Object: tasks, projects, docs, whiteboards)
- NextAuth v5 authentication with credentials + OAuth providers
- tRPC v11 API layer with full CRUD for objects, properties, relations, templates, search
- Three-panel UI: collapsible sidebar, center content area, push-in right panel
- Purple/teal theme with light/dark mode via Shadcn/ui + Tailwind CSS
- Multiple views: List, Kanban board (dnd-kit), Table (spreadsheet), Embedded iframe
- TipTap rich text editor with slash commands, custom blocks (callout, toggle, mention, embed, divider), AI block
- Real-time collaboration via Yjs + Hocuspocus with presence/cursors
- tldraw whiteboard with custom shape cards (task, document, project)
- MCP server exposing all app data/tools for AI agents
- AI chat panel, editor AI slash commands, Cmd+K command palette
- Template system with built-in templates (Bug Report, Meeting Notes, Sprint)
- Full-text search with result highlighting
- Docker Compose for full-stack deployment (web + collab + postgres + redis)
Made-with: Cursor
2026-03-26 23:39:16 -04:00
|
|
|
total: processed.items.length,
|
|
|
|
|
};
|
|
|
|
|
}
|